Dallycot

A linked open code engine

View project on GitHub

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>,
  (
    (pad, element) :> <pad[1] + 1, pad[2] + element>
  ),
  _  
)

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

Assuming we have a gradebook with the following grade distribution:

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>,
  ((pad, element) :>
    <pad[1] + element[1], pad[2] + element[1] * element[2]>
  ),
  _
)

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...)