Implementations guaranteed not to be optimally efficient:
Edit: Fixed a mistake in bringing out-of-period numbers into period in sin and cos
(= pi 3.141592653589793238)
(= 2*pi (* 2 pi))
(def signum (n)
(if (> n 0)
1
(< n 0)
-1
0))
(def floor (x)
(if (< x 0)
(- (trunc x) 1)
(trunc x)))
(def ceil (x)
(if (< x 0)
(trunc x)
(+ (trunc x) 1)))
(defmemo fac (n)
(if (is n 0)
1
(* n (fac (- n 1)))))
;Existing mod only accepts integers. Left intact as "modulo"
;This mod copies the behavior of Ruby's mod
(def mod (dividend divisor)
"Returns the remainder from dividing dividend by divisor.
Adds divisor once more if they are of different signs so that the result is always of the same sign as divisor."
(if (is divisor 0)
(error "modulo undefined for 0")
(isnt (signum dividend) (signum divisor))
(+ divisor (- dividend (* divisor (trunc (/ dividend divisor)))))
(- dividend (* divisor (trunc (/ dividend divisor))))))
(def sin (x)
"Returns the sine of x in radians."
(let x (let red (mod x 2*pi)
(if (> (abs red) pi)
(- red (* (signum red) 2*pi))
red))
;Taylor polynomial; 0.0 is to cast to float
(- (+ 0.0 x (/ (expt x 5) (fac 5)) (/ (expt x 9) (fac 9)))
(/ (expt x 3) (fac 3)) (/ (expt x 7) (fac 7)))))
(def cos (x)
"Returns the cosine of x in radians."
(let x (let red (mod x 2*pi)
(if (> (abs red) pi)
(- red (* (signum red) 2*pi))
red))
;Taylor polynomial
(- (+ 1.0 (/ (expt x 4) (fac 4)) (/ (expt x 8) (fac 8)))
(/ (expt x 2) (fac 2)) (/ (expt x 6) (fac 6)))))
(def tan (x)
"Returns the tangent of x in radians."
;Lazy definition
(/ (sin x) (cos x)))
(def int? (x)
"Returns whether x is an integer"
(is (mod x 1.0) 0.0))
(defmemo prime (n)
"Returns the nth prime. 2 is the 0th prime."
(if (< n 0)
nil
(is n 0)
2
(let prev-primes (map prime (range 0 (- n 1)))
((afn (i)
(if (no (breakable:each p prev-primes ;Each always returns nil, so a break returns t
(if (int? (/ i p))
(break t))))
i
(self (+ i 1))))
(+ 1 (last prev-primes))))))
(def prime-factorization (n)
"Returns a list each prime up to the greatest prime in n paired with the power of that prime in n.
E.g.: (prime-factorization 20) returns ((2 2) (3 0) (5 1)).
Use (reduce * (map [apply expt _] ...)) to change a prime factorization into the number."
(rev:accum keep
(let p-ord 0
(while (> n 1)
(with (p (prime p-ord)
pow 0)
(until (isnt (mod n p) 0)
(++ pow)
(zap [/ _ p] n))
(keep (list p pow)))
(++ p-ord)))))
(def gcd (x y)
"Returns the greatest common divisor of x and y."
(reduce * (map [apply expt _]
(map (fn (a b)
(list (car a) (min (cadr a) (cadr b))))
(prime-factorization x) (prime-factorization y)))))
(def lcm (x y)
"Returns the least common multiple of x and y."
(/ (* x y) (gcd x y)))
