- we have a great documentation site now! cljdoc now hosts a full port of the original scmutils reference manual. All code snippets in the ported refman now work. I've also distributed many of the sections in the reference manual into more topically organized sections in the cljdoc site, so give those a browse and keep your eye out for more expansion there.
Okay, on to the beefy changelog.
A quick note: After the work below,
v/nullity?
renamed tov/zero?
, andv/unity?
renamed tov/one?
#180. This affects the names listed in the CHANGELOG entries below.
This release brings us closer to the interface provided by scmutils
.
PR #193 brings:
g/dot-product
, for scalars, differentials, structures, functions and row/column matricesg/inner-product
for scalars, structures, functions and row/column matricesg/outer-product
for functions, structures of length 3 and matrices, between a row and a column onlyg/cross-product
now works for row/column matrices in addition to structures (and functions that accept these)
PR sicmutils/sicmutils#169 brings:
g/exp2
,g/exp10
for exponents with base 2 and 10g/log2
, for base 2 logarithmsg/log10
for base 10 logsg/gcd
andg/lcm
are now exposed insicmutils.env
#178 introduces:
g/dimension
for scalars (always 1), structures and matrices (square, column and row)g/trace
returns the trace for square matrices and square structures
We now expose the following additional trigonometric functions in sicmutils.generic
(courtesy of sicmutils/sicmutils#154):
cosh
: hyperbolic cosinesinh
: hyperbolic sinetanh
: hyperbolic tangent, ie sinh/coshsech
: hyperbolic secant, ie 1/coshcsch
: hyperbolic secant, ie 1/sinhacosh
: inverse hyperbolic cosine, ie,(= x (cosh (acosh x)))
asinh
: inverse hyperbolic sine, ie,(= x (sinh (asinh x)))
atanh
: inverse hyperbolic tangent, ie,(= x (tanh (atanh x)))
These three methods existed in sicmutils.env
, but not as extensible generics. Now they're fully extensible:
cot
: cotangent, ie 1/tansec
: secant, ie 1/coscsc
: cosecant, ie 1/sin
These all work with:
- real and complex numbers
- power series (missing a few implementations, operators and matrices are missing the same ones for this reason)
- matrices (square matrices return their power series expansions)
- operators (power series expansion of the operator)
- functions (where they create composition)
- symbolic expressions
- Derivatives and dual numbers! The new functions all work with
D
, the forward-mode automatic differentiation operator.
Additionally, four methods that lived in sicmutils.generic
are now exposed as generics:
real-part
imag-part
angle
conjugate
These now work on:
-
all numeric types, including symbolic expressions.
-
functions
-
structures (only
magnitude
andconjugate
)magnitude
formerly didn't handle structures containing complex numbers by taking a proper inner product. This is fixed as of #168
-
PR #189 introduces:
g/make-rectangular
, (build a complex number from real and imaginary parts)g/make-polar
(build a complex number from radius and angle)- note that these work with real numbers, symbolic numbers, functions and any combination of these.
These work with functions, real numbers and symbolic expressions (and any mix of the three).
literal-matrix
fn generates a symbolic matrix (sicmutils/sicmutils#169)literal
,literal-up
andliteral-down
generate symbolic structures (sicmutils/sicmutils#169)
This release (courtesy of #168) brings the numeric tower in line with the scmutils tower. Prior to this release, all numbers, including complex, descended from ::x/numerical-expression
. Symbolic expressions also derived from this type! The problem this causes is that all of generic implementations for the number types default to the symbolic functions.
If I don't specify a g/sec
method for numbers, for example, then (g/sec 12)
returns a symbolic (/ 1 (cos 12))
, instead of actually evaluating the expression.
The fix comes from these changes:
-
::v/number
now means, "the numeric tower ascending from integer -> rational -> real -> complex numbers. All of these types now respondtrue
tov/number?
(prior to this release, Complex numbers did NOT!) -
::v/real
now means, "anything in the numeric tower except Complex". These all respond true tov/real?
-
::x/numeric-expression
has changed to::x/numeric
, and now means "anything that responds to::"v/number
, plus symbolic expressions, which now clearly represent any number in the numeric tower. Query for these withv/scalar?
I can now make some comments that clear up my former misunderstandings:
-
The
sicmutils.abstract.number
(I'll call thisan
here) namespace is responsible for installing generic implementations of all numeric methods for symbolic expressions and "literal numbers". -
the
an/literal-number
constructor promotes a number, symbol or symbolic expression up to:xx/numeric
, which means that any operation you perform on it will pass it through the symbolic expressions defined insicmutils.numsymb
. A few notes on these expressions:-
They will try to preserve exactness, but if they can't - ie, if you do something like
(cos (an/literal-number 2.2))
- the system will return-.588
. If you call(cos (an/literal-number 2))
, you'll get the expression(cos 2)
, preserving exactness. -
Symbols are automatically interpreted as "literal numbers".
-
The only ways to make a proper symbolic expression that works with the generics are:
- Use the explicit
an/literal-number
constructor - pass a symbol to any generic arithmetic function
- perform any unary or binary arithmetic operation on an existing symbolic expression.
- Use the explicit
-
an/abstract-number?
returns true for symbolic expressions, anything wrapped inliteral-number
or symbols. -
literal-number?
only returns true for explicitly wrapped things and symbolic expressions, not symbols. -
use
v/real?
,v/number?
andv/scalar?
to query the numeric tower.
-
-
If you want to compare literal numbers and an expression like
(an/literal-number 12)
, usev/=
. In Clojurescript, this will work with the built in=
as well, since equality is implemented with a protocol that we can extend. For example:
(v/= 12 (literal-number 12))
;;=> true
(= 12 (literal-number 12))
;; true in cljs, false in clj
If you keep the literal on the left side of =
, this will work in both systems, since we've overridden the =
implementation for literals:
(= (literal-number 12) 12)
;;=> true in both languages
This paves the way for the other abstract types that exist in scmutils
, like matrices, up and down tuples.
-
expose
bootstrap-repl!
to Clojurescript, so that this is available in self-hosted CLJS (sicmutils/sicmutils#157) -
modified
infix.cljc
to wrap forms indisplaystyle
and add proper carriage returns inside structures (sicmutils/sicmutils#157) -
add
multidimensional-minimize
to thesicmutils.env
namespace (sicmutils/sicmutils#157) -
add more
sqrt
simplification rules to allow square roots to cancel out across a division boundary, with or without products in the numerator and denominator (sicmutils/sicmutils#160) -
fix NPE bug that appears in nelder-mead, when callback isn't supplied (sicmutils/sicmutils#162)
-
Add
sqrt-expand
andsqrt-contract
, to allow simplifications to push inside of square roots (sicmutils/sicmutils#163) -
speed up power series multiplication by skipping work when either head term is zero (sicmutils/sicmutils#166)
-
File moves:
sicmutils.polynomial-gcd
=>sicmutils.polynomial.gcd
sicmutils.polynomial-factor
=>sicmutils.polynomial.factor
sicmutils.rules
=>sicmutils.simplify.rules
sicmutils.analyze
=>sicmutils.expression.analyze
sicmutils.infix
=>sicmutils.expression.render
sicmutils.numerical.compile
=>sicmutils.expression.compile
-
sicmutils.env/one?
now exposes/aliasessicmutils.value/unity?
#154 -
Fixed #93 by adding an explicit
g/invert
implementation for polynomials in the rational fn namespace. The fix lives in #169. -
added
sicmutils.value/sqrt-machine-epsilon
(#170) -
fixed issues in
function.cljc
andoperator.cljc
where the ClojurescriptIFn
-invoke
arguments shadowed either thethis
operator, or some parameter name in the deftype (#169) -
g/sqrt
now maintains precision with Clojurescript's rational numbers.(g/sqrt #sicm/ratio 9/4)
for example returns#sicm/ratio 3/2
. (#168) -
g/determinant
andg/transpose
now act as identity for everything in the numeric tower, plus symbolic expressions (#168) -
sicmutils.expression.Expression
is nowsicmutils.expression.Literal
; it has a newmeta
field, and is adeftype
instead of adefrecord
. (#168)- To get the internal expression, use
x/expression-of
instead of:expression
. - to access the
type
field, usex/literal-type
instead of:type
- To get the internal expression, use
-
2-arity
g/atan
,g/cross-product
andg/gcd
now work for functions (#168) -
Literal
now responds appropriately tov/unity?
andv/nullity?
if it wraps a numerical "0" or "1".v/exact?
now returns true if the literal wraps an exact number (#168) -
x/variables-in
now works with wrapped expressions; no more need to explicitly unwrap (#168) -
x/walk-expression
renamedx/evaluate
(#168) -
The new
x/substitute
performs substitutions on an unwrapped expression (#168) -
x/compare
returns a comparator that works with unwrapped symbolic expression trees (#168). The rules are that that types have the following ordering: -
empty sequence is < anything (except another empty seq)
-
real < symbol < string < sequence
-
sequences compare element-by-element
-
Any types NOT in this list compare using hashes
-
g/transpose
now works properly for functions that act as linear maps. The defining relation is:
(= (((transpose f) g) 'x)
(g (f x)))
-
added
g/determinant
implementation to functions (#171) -
Moved all
literal-function
machinery and definitions tosicmutils.abstract.function
(#171).sicmutils.function
now contains only the generic method implementations for clojure functions and multimethods. -
Switched inheritance order for functions;
:sicmutils.abstract.function/function
(used to be:sicmutils.function/function
) now inherits from::v/function
instead of the other way around. (#171) -
Enhanced the
g/simplify
behavior for core functions that overlap with generic functions (+
,-
,*
,/
,mod
,quot
,rem
,neg?
). These now freeze to the same symbols as their generic counterparts. (#173) -
Add support for the hyperbolic trig functions
sinh
,cosh
,tanh
,atanh
,asinh
andacosh
tosicmutils.expression.render/->Javascript
. (#174) -
Add support for the hyperbolic trig functions
atanh
,asinh
andacosh
tosicmutils.expression.compile
. (#175) -
matrix.cljc
gainsm/nth-col
andm/diagonal
(#178 introduces:) -
As of #178 introduces:, we have three new kinds for matrices. Square matrices return
::m/square-matrix
, and columns and rows return::m/column-matrix
and::row-matrix
respectively. These all derive from::m/matrix
. This makes it easier to register methods or test specifically for these cases. We've also addedm/column?
andm/row?
predicates to check for these cases. -
#185 specializes all matrix operations that return power series (trig operations and
g/exp
to::square-matrix
). -
#184 modifies
v/exact?
on functions;((v/exact? f) x) == (v/exact? (f x))
now, instead of false as before.literal-function
forms now have a correctv/one-like
implementation. -
clojure Vars now respond to function algebra (#184). All functions implement
g/negative?
,g/abs
,g/quotient
,g/remainder
,g/modulo
,g/dimension
andg/exact-divide
, responding to the appropriate arities. -
sicmutils.complex/complex
can now take any real type in its constructor, vs only numbers (#184). -
modint
instances now implementv/freeze?
:(sicmutils.modint/make 1 2)
freezes to that(modint 1 2)
. (#185). -
v/eq
renamed tov/=
. (#186). -
v/zero-like
on matrices now fills entries with appropriatev/zero-like
versions of their existing types (#188) -
v/Value
gainsidentity-like
andidentity
(#188). These are aliased intosicmutils.env
. Implementations are installed on:- all numeric types, symbolic expressions,
Differential
(they return 1 of the appropriate type) - native and abstract functions, vars (they return an identity function)
- operators (return an identity operator, same as
one-like
) - matrices (identity matrix, only works with
::m/square-matrix
) Polynomial
(only works on monomials for now, returns an identity polynomial)RationalFunction
(returns the identity poly divided by unit poly, so only works on monomials by extension)ModInt
(returns the same asone-like
)Series
andPowerSeries
(returns[0 1 0 0 0 0...]
). This is slightly suspect in the case ofSeries
, sinceSeries
, unlikePowerSeries
, are general infinite sequences and not necessarily interpreted as polynomials. This decision followsscmutils
convention.
- all numeric types, symbolic expressions,
-
sicmutils.complex/I
aliasesi
(#189) -
matrix.cljc
has a newby-cols
(analogous tom/by-rows
), androw
to generate a row matrix (analagous tocolumn
). #197 Also inmatrix.cljc
:num-rows
,num-cols
access the row or column number without inspecting the deftype variables directlyfmap-indexed
, likefmap
but receivesi
andj
indices as second and third arguments. -with-substituted-row
, for swapping out a single row in a matrixsubmatrix
generates a submatrix from low and high row and colsmatrix-some
renamed tosome
: make sure to use a namespace prefix to avoid clashing withclojure.core/some
.- new-matrix constructor
by-cols
(analogous toby-rows
, takes a sequence of columns) row
constructor takes a sequence of values and returns a row matrix.by-rows*
,by-cols*
,row*
andcolumn*
are non-variadic versions of those functions. If you already have a sequence of rows, columns or elements, prefer these.up->row-matrix
=>down->row-matrix
androw-matrix->up
=>row-matrix->down
. A row is analogous to adown
, so we make a change to reflect this.g/cross-product
between twodown
structures now returns adown
.make-zero
generates a zero-valued matrix of the supplied dimensions.make-diagonal
generates a diagonal matrix containing the values of the supplied sequence.m/identity-like
returns an identity matrix (given a square matrix) with entries of identical type, but set appropriately to zero or one. This is installed asv/one-like
andv/identity-like
.v/identity?
now returns true for identity matrices, false otherwise.v/one?
returnsfalse
for identity matrices! If it didn't,(* 2 (I 10))
would return2
, sinceone?
signals multiplicative identity.
-
sicmutils.structure/up
andsicmutils.structure/down
now have analogouss/up*
ands/down*
functions. These behave identically, but are non-variadic. If you already have a sequence you'd like to transform, prefer these (#197). -
sicmutils.value/kind-predicate
takes some item and returns a predicate that returns true if its argument has the same type (or inherits from it) (#197). -
sicmutils.function/arg-shift
andsicmutils.function/arg-scale
take functions and return new functions that shift and scale their arguments (respectively) by the originally supplied shifts (#197). -
sicmutils.generic/factorial
computes the factorial of the supplied integern
. (#197). -
Many new functions and constants exposed in
sicmutils.env
via #197:-pi
joinspi
as a constants:generate
,m:generate
,vector:generate
to generate matrices, structures and vectorsconstant-series
, fromseries/constant
seq:print
andseq:pprint
matrix-by-cols
,row-matrix
,v:make-basis-unit
- aliases for
sicmutils.function
'sarity
,arg-shift
,arg-scale
dimension
,factorial
aliased fromsicmutils.generic
derivative
aliased fromsicmutils.calculus.derivative
submatrix
,up->column-matrix
,down->row-matrix
,row-matrix->{down,vector}
,column-matrix->{up,vector}
aliased fromsicmutils.matrix
D-numeric
fromsicmutils.numerical.derivative
brent-min
,brent-max
,golden-section-min
,golden-section-max
nelder-mead
sum
from `sicmutils.util.aggregatekind-predicate
fromsicmutils.value
-
Structures and matrices both gain the ability to do native
get-in
,assoc-in
andempty
. These work as expected, like a potentially nested vector. (#193) -
matrix.cljc
gainsup->row-matrix
,up->column-matrix
,row-matrix->up
,column-matrix->up
(#193) -
structure.cljc
gains many features in (#193):kronecker
andbasis-unit
for generating potentially infinite basis sequences- the ability to conj new items onto a structure:
(conj (up 1 2) 3) => (up 1 2 3)
- The structure-preserving
map-chain
takes a 2-arg function and presents it with each element of a deeply nested structure, along with a vector of its "chain", the path into its location. The fn's return becomes the new item at that location. structure->prototype
generates a same-shape structure as its argument, with symbolic entries that display their location (preserving orientation).typical-object
returns a structure of the same shape and orientation ass
, generated by substituting gensymmed symbols in for each entry.compatible-zero
returns a structure compatible for multiplication withs
down to 0.transpose-outer
returns a new structure with the same orientation as the first element ofs
, filled with elements of the same orientation ass
. Each element is generating by taking the first element of each entry ins
, the the second, etc... In that sense this is similar to a traditional matrix transpose.dot-product
takes the dot product of two structures. They must be the same top-level orientation and dimension; beyond that, their entries are pairwise-multiplied and summed.inner-product
is the same, but the left structure is conjugated first.outer-product
now works multiple levels deep.vector-outer-product
andvector-inner-product
are similar, but only enforce the top-level length; all internal structures are NOT flattened and must be compatible forg/*
.compatible-for-contraction?
now searches recursively down into a structure; previously it only checked the top level.- The new
*allow-incompatible-multiplication*
dynamic variable is set totrue
by default. Set it false to force a setting where, when you multiply structures, they must be:- opposite orientation
- every element of the right entry must be compatible for contraction with the left
- structure multiplication with scalars, etc now respects ordering, just in case any multiplication is not commutative.
sicmutils.generators
now holds generators forup
,down
, andstructure
generators; these produce potentially deeply nested structures.up1
,down1
andstructure1
generate only one level deep. Mix and match! Seestructure_test.cljc
for many examples of how to use these.