# Math Library

The definitions provided by this library operate on numbers or streams of numbers providing statistics or other mathematical evaluations.

## Functions

Many of the functions here are implemented in Perl. The definitions are examples of how some of these might be implemented in Dallycot.

### abs

(x: Numeric) → Numeric

Returns the absolute value of a numeric datum.

#### Examples

``````abs(-1) = 1
abs(0) = 0
abs(1) = 1
``````

#### Implementation

This is implemented natively.

``````(x) :> (
(x < 0) : -x
(     ) : x
)
``````

### arc-tan

(y: Numeric, x: Numeric, units -> “degrees”, accuracy -> 40) → Numeric

#### Implementation

This is implemented natively.

### binomial

(n: Numeric, k: Numeric) → Numeric

Returns the binomial coefficient n over k. The binomial coefficient can be used to generate Pascal’s Triangle.

#### Examples

##### Boundary conditions

When the second argument is zero or when both arguments are the same value, the `binomial` is one.

``````binomial(n, 0) = 1
binomial(n, n) = 1
``````
##### Fourth row of Pascal’s Triangle

The first five rows of the triangle are:

``````      1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
``````

The fourth row (starting at zero) is then:

``````binomial(4, 0) = 1
binomial(4, 1) = 4
binomial(4, 2) = 6
binomial(4, 3) = 4
binomial(4, 4) = 1
``````

#### Implementation

This is implemented natively.

``````(n, k) :> factorial(n) div ( factorial(k) * factorial(n - k) )
``````

### ceil

(x: Numeric) → Numeric

Returns the smallest integer greater than or equal to the given number.

#### Examples

``````ceil(1.23) = 2
ceil(-1.23) = -1
ceil(1) = 1
ceil(-1) = -1
``````

#### Implementation

This is implemented natively.

### cos

(angle: Numeric, units -> “degrees”, accuracy -> 40) → Numeric

Calculates the cosine of an angle. The `units` may be `degrees`, `radians`, or `gradians`. The calculation will be done to `accuracy` digits.

#### Examples

``````cos(90) = 0
cos(60) = 1/2
cos(0) = 1

cos(89, accuracy -> 3) = 7/400
cos(89, accuracy -> 3, units -> "radians") = 841/1000
``````

#### Implementation

This is implemented natively.

### count-and-sum

(s: [Numeric]) → [<Numeric, Numeric>]

Returns a stream of duples (count and sum) produced by counting and summing each element in the input stream.

#### Examples

``````count-and-sum(1..) = [ <1,1>, <2,3>, <3,6>, <4,10>, <5,15>, <6,21>, ... ]
count-and-sum(primes) = [ <1,1>, <2,3>, <3,6>, <4,11>, <5,18>, ... ]
``````

#### Implementation

``````foldl(
<0,0>,
(
),
_
)
``````

### differences

(s: [Numeric]) → [Numeric]

Returns a stream of numbers representing the difference between successive elements in the input numeric stream.

#### Examples

``````differences(1..) = [ -1, -1, -1, ... ]
differences(primes) = [ -1, -1, -2, -2, -4, -2, ... ]
``````

#### Implementation

``````(
diff := y-combinator(
(self, sh, st) :> (
(?sh and ?st) : [ sh - st', self(self, st', st...) ]
(?sh        ) : [ sh ]
(           ) : [    ]
)
);
{ diff(#', #...) }
)
``````

### divisible-by?

(n: Numeric, d: Numeric) → Boolean

Returns `true` if the numerator (n) is divisible by the denominator (d).

#### Examples

``````divisible-by?(10, 3) = false
divisible-by?(123, 3) = true
divisible-by?(3, 1) = true
divisible-by?(1, 3) = false
``````

#### Implementation

This is implemented natively.

``````(n, d) :> n mod d = 0
``````

### even?

(x: Numeric) → Boolean

Returns `true` if the given number is even.

#### Examples

``````even? @ 1.. = [ false, true, false, true, false, true, ... ]
even?(123) = false
even?(0) = true
even?(1.23) = false
``````

#### Implementation

This is implemented natively.

``````divisible-by?(_, 2)
``````

### factorial

(n: Numeric) → Numeric

Calculates the factorial (n!) of a number.

#### Examples

``````factorial(1) = 1
factorial(3) = 6
factorial @ 1.. = [ 1, 2, 6, 24, 120, 720, ... ]
``````

#### Implementation

This is implemented natively.

``````(n) :> (
(n > 1) : last(product(2..n))
(n = 1) : 1
(     ) : 0
)
``````

### fibonacci

(n: Numeric) → Numeric

#### Implementation

``````(n) :> fibonacci-sequence[n]
``````

### floor

(x: Numeric) → Numeric

Returns the largest integer less than or equal to the given number.

#### Examples

``````floor(1.23) = 1
floor(1) = 1
floor(-1) = -1
floor(-1.23) = -2
``````

#### Implementation

This is implemented natively.

### gcd

(*x: Numeric) → Numeric

Calculates the greatest common divisor shared by two or more numbers.

#### Examples

``````gcd(63, 42) = 21
gcd(64, 42) = 2
gcd(65, 42) = 1
``````

#### Implementation

This is implemented natively.

For two arguments, this is equivalent to the following:

``````y-combinator(
(self, a, b) :> (
(a = 0) : b
(b = 0) : a
(a > b) : self(self, a mod b, b)
(     ) : self(self, a, b mod a)
)
)
``````

### golden-ration

(accuracy: Numeric = 40) → Numeric

Provides a numerical approximation of phi, the golden ration, to the desired accuracy. Defaults to 40 digits.

#### Examples

``````golden-ratio(1) = 2
golden-ratio(2) = 8/5
golden-ratio(3) = 81/50
golden-ratio(9) = 161803399/100000000
``````

#### Implementation

This is implemented natively.

``````(accuracy) :>
(1 + sqrt(5, accuracy -> accuracy)) / 2
``````

### lcm

(*x: Numeric) → Numeric

Calculates the least common multiple of two or more numbers.

#### Examples

``````lcm(63, 42) = 126
lcm(64, 42) = 1344
lcm(65, 42) = 2730
``````

#### Implementation

This is implemented natively.

For two arguments, this is equivalent to:

``````(x, y) :> x * y div gcd(x,y)
``````

### leonardo

#### Implementation

``````(n) :> leonardo-sequence[n]
``````

### make-evens

() → [ 2, 4, 6, … ]

Creates a new stream consisting of the positive, non-zero even integers.

This is useful when you need a stream of even numbers and want to garbage collect the stream after using it.

#### Examples

``````make-evens() = [ 2, 4, 6, ... ]
``````

#### Implementation

``````() :> ({ # * 2 } @ 1..)
``````

### make-odds

() → [ 1, 3, 5, … ]

Creates a new stream consisting of the positive, non-zero even integers.

This is useful when you need a stream of odd numbers and want to garbage collect the stream after using it.

#### Examples

``````make-odds() = [ 1, 3, 5, ... ]
``````

#### Implementation

``````() :> ({ # * 2 + 1} @ 0..)
``````

### max

(s: [Numeric]) → [Numeric]

Given a stream of numbers, `max` returns a new stream representing the maximum number seen up to that point in the input stream.

#### Examples

``````max(primes) = primes
max(1..) = 1..
max([1,3,5,3,1]) = [ 1, 3, 5, 5, 5 ]
``````

#### Implementation

``````foldl1({(
(#1 > #2) : #1
(       ) : #2
)}/2, _)
``````

### mean

(s: [Numeric]) → [Numeric]

Given a stream of numbers, `mean` returns a new stream representing the mean of the numbers seen up to that point in the input stream.

#### Examples

``````mean([1, 3, 5, 3, 1]) = [ 1, 2, 3, 3, 13/5 ]
mean(1..) = [ 1, 3/2, 2, 5/2, 3, ... ]
``````

#### Implementation

``````{ #[2] div #[1] } @ count-and-sum
``````

### min

(s: [Numeric]) → [Numeric]

Given a stream of numbers, `min` returns a new stream representing the minimum number seen up to that point in the input stream.

#### Examples

``````min(primes) = [ 1, 1, 1, ... ]
min(1..) = [ 1, 1, 1, ... ]
min([1,3,5,3,1]) = [ 1, 1, 1, 1, 1 ]
min([-1, -3, -5, -3, -1]) = [ -1, -3, -5, -5, -5 ]
``````

#### Implementation

``````foldl1({(
(#1 < #2) : #1
(       ) : #2
)}/2, _)
``````

### odd?

(x: Numeric) → Boolean

Returns `true` if the given number is odd.

#### Examples

``````odd? @ 1.. = [ true, false, true, false, true, false, ... ]
odd?(123) = true
odd?(0) = false
odd?(1.23) = false
``````

#### Implementation

This is implemented natively.

``````~even?
``````

### pi

(accuracy: Numeric = 40) → Numeric

Provides a numerical approximation of PI to the desired accuracy. Defaults to 40 digits.

#### Examples

``````pi(1) = 3
pi(2) = 31/10
pi(3) = 157/50
pi(9) = 62831853/20000000
``````

#### Implementation

This is implemented natively.

### prime

(n: Numeric) → Numeric

#### Implementation

``````(n) :> primes[n]
``````

### product

(s: [Numeric]) → [Numeric]

Transforms a stream of numbers into a stream of cumulative products.

#### Examples

``````product(1..) = [ 1, 2, 6, 24, 120, ... ]
product(primes) = [ 1, 2, 6, 30, 180, ... ]
product([1, 3, 5, 3, 1]) = [ 1, 3, 15, 45, 135, 135 ]
``````

#### Implementation

``````foldl(1, { #1 * #2 }/2, _)
``````

### random

(spec: Numeric|<Numeric,Numeric>) → Numeric

Creates a pseudo-random integer up to the number given or in the range given by a vector of numbers. The upper bound must be greater than zero.

#### Examples

``````0 <= random(10) <= 10
20 <= random(<20,40>) <= 40
``````

#### Implementation

This is implemented natively.

### sin

(angle: Numeric, units -> “degrees”, accuracy -> 40) :> Numeric

Calculates the sine of an angle. The `units` may be `degrees`, `radians`, or `gradians`. The calculation will be done to `accuracy` digits.

#### Examples

``````sin(0) = 0
sin(30) = 1/2
sin(90) = 1

sin(1, accuracy -> 3) = 7/400
sin(1, accuracy -> 3, units -> "radians") = 841/1000
``````

#### Implementation

This is implemented natively.

### sum

(s: [Numeric]) → [Numeric]

Transforms a stream of numbers into a stream of cumulative sums.

#### Examples

``````sum(1..) = [ 1, 3, 6, 10, 15, ... ]
sum(primes) = [ 1, 3, 6, 11, 18, ... ]
sum([1, 3, 5, 3, 1]) = [ 1, 4, 9, 12, 13 ]
``````

#### Implementation

``````foldl(0, { #1 + #2 }/2, _)
``````

### tan

(angle: Numeric, units -> “degrees”, accuracy -> 40) :> Numeric

Calculates the tangent of an angle. The `units` may be `degrees`, `radians`, or `gradians`. The calculation will be done to `accuracy` digits.

#### Examples

``````sin(0) = 0
sin(30) = 1/2
sin(90) = 1

sin(1, accuracy -> 3) = 7/400
sin(1, accuracy -> 3, units -> "radians") = 841/1000
``````

#### Implementation

``````(angle, units -> "degrees", accuracy -> 40) :> (
sin(angle, units -> units, accuracy -> accuracy) div
cos(angle, units -> units, accuracy -> accuracy)
)
``````

### weighted-count-and-sum

(s: [<Numeric, Numeric>]) → [<Numeric, Numeric>]

Transforms a stream of duples (weight and number) into a stream of duples containing the sum of weights and sum of weighted numbers.

#### Examples

 A (4 pts) 4 B (3 pts) 9 C (2 pts) 15 D (1 pts) 8 F (0 pts) 2

then we can calculate the class average:

``````mean @ weighted-count-and-sum([<4, 4>, <9, 3>, <15, 2>, <8, 1>, <2, 0>])
= mean @ [ <4, 16>, <13, 43>, <28, 73>, <36, 81>, <38, 81> ]
= [ 4, 43/13, 73/28, 9/4, 81/38 ]
``````

Dallycot uses rationals for all numbers, so the final average for the class is around 2.131 (the sequence in floating point numbers: [ 4, 3.307, 2.607, 2.250, 2.131] ).

#### Implementation

``````foldl(
<0,0>,
),
_
)
``````

## Streams

### evens

#### Implementation

``````make-evens()
``````

### factorials

#### Implementation

``````factorial @ 1..
``````

### fibonacci-sequence

#### Implementation

``````[ 1,
1,
y-combinator(
(self, a, b) :>
[ a + b, self(self, b, a + b) ]
)(1, 1)
]
``````

### leonardo-sequence

#### Implementation

``````[ 1,
1,
y-combinator(
(self, a, b) :>
[ a + b + 1, self(self, b, a + b + 1) ]
)(1, 1)
]
``````

### odds

#### Implementation

``````make-odds()
``````

### primes

#### Implementation

``````[ 1,
2,
y-combinator(
(self, s) :>
[ s', self(self, ~divisible-by?(_, s') % s...) ]
)(make-odds()...)
]
``````

### twin-primes

#### Implementation

``````{ #[2] - #[1] = 2 } % (primes Z primes...)
``````