egison-3.5.2: lib/core/number.egi
;;;;;
;;;;;
;;;;; Number
;;;;;
;;;;;
;;;
;;; Natural Numbers
;;;
(define $nat
(matcher
{[,$n []
{[$tgt (if (eq? tgt n) {[]} {})]}]
[<o> []
{[0 {[]}]
[_ {}]}]
[<s $> nat
{[$tgt (match (compare tgt 0) ordering
{[<greater> {(- tgt 1)}]
[_ {}]})]}]
[$ [something]
{[$tgt {tgt}]}]
}))
(define $nats {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 @(map (+ 100 $) nats)})
(define $nats0 {0 @nats})
(define $odds {1 @(map (+ $ 2) odds)})
(define $evens {2 @(map (+ $ 2) evens)})
(define $primes
(letrec {[$next-primes
(lambda [$primes1 $k]
(let {[$primes2 (while (lte? $ (floor (sqrt (itof (* 6 (+ k 1)))))) primes1)]}
(match [(any (lambda [$p] (eq? (remainder (+ (* 6 k) 1) p) 0)) primes2)
(any (lambda [$p] (eq? (remainder (+ (* 6 k) 5) p) 0)) primes2)]
[bool bool]
{[[,#f ,#f] {(+ (* 6 k) 1) (+ (* 6 k) 5) @(next-primes {@primes1 (+ (* 6 k) 1) (+ (* 6 k) 5)} (+ k 1))}]
[[,#f ,#t] {(+ (* 6 k) 1) @(next-primes {@primes1 (+ (* 6 k) 1)} (+ k 1))}]
[[,#t ,#f] {(+ (* 6 k) 5) @(next-primes {@primes1 (+ (* 6 k) 5)} (+ k 1))}]
[[,#t ,#t] (next-primes primes1 (+ k 1))]
})))]}
{2 3 5 @(next-primes {2 3 5} 1)}))
(define $find-factor
(lambda [$n]
(match primes (list integer)
{[<join _ <cons (& ?(divisor? n $) $x) _>> x]})))
(define $prime-factorization
(match-lambda integer
{[,1 {}]
[$n (let {[$p (find-factor n)]}
{p @(prime-factorization (quotient n p))})]}))
(define $p-f prime-factorization)
(define $pfs (map (lambda [$n] [n (p-f n)]) nats))
(define $pfs-n
(lambda [$n]
(match-all pfs (list [integer (list integer)])
[<join _ <cons [$m (loop $i [1 n] <cons $p_i ...> <nil>)] _>> [m (map (lambda [$i] p_i) (between 1 n))]])))
(define $prime?
(lambda [$n]
(if (eq? n 1)
#f
(eq? (rac (while (lte? $ n) primes)) n))))
;;;
;;; Integers
;;;
(define $integer builtin-data-matcher)
(define $power
(lambda [$x $n]
(foldl * 1 (take n (repeat1 x)))))
(define $mod
(lambda [$m]
(matcher
{[,$n []
{[$tgt (if (eq? (modulo tgt m) (modulo n m))
{[]}
{})]}]
[$ [something]
{[$tgt {tgt}]}]
})))
(define $even?
(lambda [$n]
(eq? 0 (modulo n 2))))
(define $odd?
(lambda [$n]
(eq? 1 (modulo n 2))))
(define $between?
(lambda [$m $n $x]
(and (lte? m x) (lte? x n))))
(define $sum
(lambda [$xs]
(foldl + 0 xs)))
(define $product
(lambda [$xs]
(foldl * 1 xs)))
(define $fib
(lambda [$n]
(letrec {[$fib1 (lambda [$n $ret1 $ret2]
(match n nat
{[<o> ret2]
[<s <o>> ret1]
[<s $n1> (fib1 (- n 1) (+ ret1 ret2) ret1)]
}))]}
(fib1 n 1 1))))
(define $fibs (map fib nats0))
(define $divisor?
(lambda [$n $d]
(eq? 0 (remainder n d))))
(define $gcd
(lambda [$ns]
(match ns (multiset integer)
{[<cons $n <nil>> n]
[<cons (& ,(min ns) $m) $rs>
(gcd {m @(delete 0 (map (lambda [$r] (modulo r m)) rs))})]})))
(define $fact
(lambda [$n]
(foldl * 1 (between 1 n))))
(define $perm
(lambda [$n $r]
(foldl * 1 (between (- n (- r 1)) n))))
(define $comb
(lambda [$n $r]
(/ (perm n r)
(fact r))))
;;;
;;; Float Numbers
;;;
(define $float builtin-data-matcher)
;;;
;;; Decimal Fractions
;;;
(define $decimal (algebraic-data-matcher {<df integer (list integer)>}))
(define $decimal' (algebraic-data-matcher {<df' integer (list integer) (list integer)>}))
(define $rtod-helper
(lambda [$m $n]
(let {[$q (quotient (* m 10) n)]
[$r (remainder (* m 10) n)]}
{[q r] @(rtod-helper r n)})))
(define $rtod
(lambda [$x]
(let {[$m (numerator x)]
[$n (denominator x)]}
(let {[$q (quotient m n)]
[$r (remainder m n)]}
<Df q (map (lambda [$x $y] x) (rtod-helper r n))>))))
(define $rtod'
(lambda [$x]
(let {[$m (numerator x)]
[$n (denominator x)]}
(let {[$q (quotient m n)]
[$r (remainder m n)]}
(let {[[$s $c] (match (rtod-helper r n) (list [integer integer])
{[<join $s <cons $x <join $c <cons ,x _>>>> [s {x @c}]]})]}
<Df' q (map (lambda [$x $y] x) s) (map (lambda [$x $y] x) c)>)))))
(define $show-decimal
(lambda [$n $x]
(match (rtod x) decimal
{[<df $q $sc> (foldl S.append (S.append (show q) ".") (map show (take n sc)))]})))
(define $show-decimal'
(lambda [$x]
(match (rtod' x) decimal'
{[<df' $q $s $c> (foldl S.append "" {(S.append (show q) ".") @(map show s) " " @(map show c) " ..."})]})))
;;;
;;; Continued Fraction
;;;
(define $regular-continued-fraction
(lambda [$as]
(+ (car as)
(foldr (lambda [$a $r] (/ 1 (+ a r)))
0
(cdr as)))))
(define $continued-fraction
(match-lambda [(list integer) (list integer)]
{[[<cons $a $as> <cons $b $bs>]
(+ a (/ b (continued-fraction as bs)))]
[[<cons $a <nil>> <nil>] a]}))