WhizzML Reference Manual

4.5 Numbers

4.5.1 Numerical type predicates

Predicates checking whether any value is a number, integer or real.

(number? obj) \(\rightarrow \) boolean
(integer? obj) \(\rightarrow \) boolean
(real? obj) \(\rightarrow \) boolean

(integer? 0.0) ;; => false
(real? "hello!") ;; => false
(real? 1) ;; => true
(integer? 1) ;; => true

4.5.2 Arithmetic operators

The basic arithmetic operators take one or more arguments and are represented by their usual symbols:

(+ num1 …) \(\rightarrow \) number
(- num1 …) \(\rightarrow \) number
(* num1 …) \(\rightarrow \) number
(/ num1 …) \(\rightarrow \) number

Division raises error code -10 if division by zero. If passed only one argument, / computes its inverse.

In addition, the standard library includes the following binary and unary operators on numbers:

(rem int1 int2) \(\rightarrow \) integer

Computes the remainder of dividing int1 by int2. Raises error code -10 if the latter is zero.

(div int1 int2) \(\rightarrow \) integer

Computes the integer division num1 by int2. Raises error code -10 if the latter is zero.

(sqrt num1) \(\rightarrow \) number

Computes the square root of its argument. Raises error code -30 if passed a negative number.

(+ 1) ;; => 1
(+ 1 -1) ;; => 0
(- 23.8 18.2) ;; => 42.0
(/ 2) ;; => 0.5
(/ 1 2 3) ;; => 0.16666667
(rem 23 3) ;; => 2
(div 45 7) ;; => 6
(sqrt 24) ;; => 4.898979485566356
(sqrt 0.144) ;; => 0.3794733192202055

4.5.3 Numeric coercion and parsing

The following operators act on any number, returning an integer in all cases:

(abs num) \(\rightarrow \) integer

The absolute value of its argument.

(ceil num) \(\rightarrow \) integer

The ceiling, that is, the lowest integer greater than or equal to the given value.

(floor num) \(\rightarrow \) integer

The floor of a number is the biggest integer less than or equal to the given number.

(round num) \(\rightarrow \) integer

Rounding finds the integer value that is closest to the given number.

(abs -21) ;; => 21
(abs 3.0) ;; => 3.0
(ceil 23.3) ;; => 24
(ceil -128.2) ;; => -128
(floor 12.8) ;; => 12
(floor -12.3) ;; => -13
(round 1.2) ;; => 1
(round 1.5) ;; => 2

(read-number str) \(\rightarrow \) number

The standard library provides read-number to parse a string representing a number, using any of the accepted number literal expressions in WhizzML. This procedure raises error code -30 (domain error) if passed a string that cannot be parsed.

(read-number "0.1232") ;; => 0.1232
(read-number "0.1232a") ;; => Error
(read-number "-32") ;; => -32
(read-number "0x32") ;; => 50 (hexadecimal notation)
(read-number "032") ;; => 26 (octal notation)
(read-number "2r111") ;; => 7 (explicit base)
(read-number "3/2") ;; => 3/2 (rational number)

4.5.4 Comparisons

(< num1 …) \(\rightarrow \) boolean
(<= num1 …) \(\rightarrow \) boolean
(> num1 …) \(\rightarrow \) boolean
(>= num1 …) \(\rightarrow \) boolean

Comparison operators (like, e.g. <) are multivariadic and can take more than two arguments, so that, say, (< x y z) is equivalent to (and (< x y) (< y z)), or the mathematical expression x < y < z.

(< 1 2) ;; => true
(<= 0 0 3) ;; => true
(> -19 -18) ;; => false
(> -19 -20 -21) ;; => true
(<= 1 1 2 2 2 3 4 44) ;; => true
(< 0) ;; => true
(< -1) ;; => true
(< 12.343) ;; => true

Comparison operators can also take a single argument, in which case they always evaluate to true

Convenience predicates for direct comparison to zero and parity are also provided:

(zero? num) \(\rightarrow \) boolean
(positive? num) \(\rightarrow \) boolean
(negative? num) \(\rightarrow \) boolean
(even? int) \(\rightarrow \) boolean
(odd? int) \(\rightarrow \) boolean

(zero? 0) ;; => true
(zero? 0.0) ;; => true
(zero? -2) ;; => false
(positive? 0) ;; => false
(positive? 0.1) ;; => true
(negative? 0) ;; => false
(negative? 0.0) ;; => false
(even? 0) ;; => true
(odd? 3) ;; => true

Furthermore, WhizzML provides procedures for computing the maximum and minimum of any number of arguments:

(min num1 …) \(\rightarrow \) number
(max num1 …) \(\rightarrow \) number

(max 10) ;; => 10
(max -1 -20.0 30 10.2) ;; => 10
(min -1.1) ;; => -1.1
(min (sqrt 2) (sqrt 3)) ;; =>  1.4142135623730951

4.5.5 Transcedental functions

Common non-algebraic functions on numbers are also available:

(log num) \(\rightarrow \) number
(log2 num) \(\rightarrow \) number
(log10 num) \(\rightarrow \) number

Logarithms in base \(e\), 2 and 10. These procedures take a positive number as argument, and raise error code -30 otherwise.

(pow num1 num2) \(\rightarrow \) number
(exp num1) \(\rightarrow \) number

The general power function returns \(num1^{num2}\), and exp uses \(e\) as its base, computing \(e^{num1}\).

(sin num1) \(\rightarrow \) number
(cos num1) \(\rightarrow \) number
(tan num1) \(\rightarrow \) number

Standard trigonometric functions: sine, cosine and tanget. For all of them, num1 is an angle in radians. We also provide their inverses:

(asin num1) \(\rightarrow \) number
(acos num1) \(\rightarrow \) number
(atan num1) \(\rightarrow \) number

Both asin and acos take a number in the interval \([1, -1]\), raising error code -30 otherwise.

(to-degress num1) \(\rightarrow \) number
(to-radians num1) \(\rightarrow \) number

Conversion functions from radians to degrees and vice versa.

(sinh num1) \(\rightarrow \) number
(cosh num1) \(\rightarrow \) number
(tanh num1) \(\rightarrow \) number

These are the standard hyperbolic functions.

(gamma num1) \(\rightarrow \) number

The gamma function for real-valued arguments is also available. Note that it is undefined for non-positive integer arguments (including 0).

(log 2) ;; => 0.6931471805599453
(log (exp 1)) ;; => 1.0
(pow 4 (/ 1 2)) ;; => 2.0
(+ (pow (sin 1.2) 2) (pow (cos 1.2) 2)) ;; => 1.0
(tan (atan -1.2)) ;; => -1.2
(sinh 23.32) ;; => 6.709919691913042E9
(gamma 2) ;; => 1.0000000000000002

4.5.6 Random number generators

Each instance of a WhizzML runtime has an implicit random number generator (RNG). The random number series generated by this RNG are accesible via the following standard procedures omitting the optional argument rnd-id in all cases.

(rand [rng-id]) \(\rightarrow \) number
(rand-range num1 num2 [rng-id]) \(\rightarrow \) number
(rand-int num1 [rng-id]) \(\rightarrow \) integer
(set-rng-seed obj [rng-id]) \(\rightarrow \) boolean

The rand procedure generates a random number in the interval \([0, 1]\), whereas rand-range uses the range \([\mathrm{num1}, \mathrm{num2}]\) (with both ends arbitrary numbers). Finally, rand-int returns an integer between 0 and its argument.

The implicit RNG is seeded at random every time a virtual machine is started, so that two runs of the same program using the functions above will in general obtain different number sequences from the generator. To produce deterministic results, you can seed the RNG using set-rng-seed and providing any WhizzML value as seed.

(rand) ;; => 0.5778650511056185
(rand-int 2313) ;; => 501
(rand-range -10 3) ;; => 1.4949024706147611
(set-rng-seed "a seed")  ;; => true

Instead of using the implicit RNG, you can create your own RNG instances via create-rng, and use the returned identifier as the rng argument in the functions above.

(create-rng [obj]) \(\rightarrow \) rng-id

The value returned by create-rng is a unique identifier for the RNG just created.

(define rng-id (create-rng 42))  ;; any value can be used as seed
(rand rng-id)  ;; => 0.13599370513111353
(rand-int 100 rng-id) ;; => 59
(rand-int 100 rng-id) ;; => 10
(rand-range -10 10 rng-id) ;; => -2.855083905160427
(set-rng-seed rng-id "whizzml")  ;; => true

You should treat the random indentifier value as an opaque token. Everytime the seed of an RNG is set, the generator starts over, even if the seed is the same that was used before.

Typically, if you are writing a library that uses random numbers and want to make it deterministic, you will be using in it your own RNG, created via create-rng with an appropriate key. In that way, you won’t interfere with other libraries or scripts using the library at hand, nor get affected by other code setting the implicit RNG’s seed.

4.5.7 Basic statistics

(mean list) \(\rightarrow \) number
(variance list) \(\rightarrow \) number
(stdev list) \(\rightarrow \) number
(chi-squared-test num int) \(\rightarrow \) number

mean computes the mean value of a list of numbers, variance their variance and stdev their standard deviation. chi-squared-test returns the p-value for a given value and degrees of freedom.

mean will raise error code -20 if passed an empty list, and both variance and stdev signal code -25 if passed a list with less than two numbers. chi-squared-test will raise error code -20 if the first argument is negative, or the second argument is either non-positive or non-integer.