(.module: [library [lux #* [abstract [hash (#+ Hash)] [enum (#+ Enum)] [interval (#+ Interval)] [monoid (#+ Monoid)] [equivalence (#+ Equivalence)] [codec (#+ Codec)] [predicate (#+ Predicate)] ["." order (#+ Order)]] [control ["." try (#+ Try)]] [data [text (#+ Char)] ["." maybe]]]] ["." // #_ ["#." nat] ["#." i64]]) (def: #export (= reference sample) {#.doc "Int(eger) equivalence."} (-> Int Int Bit) ("lux i64 =" reference sample)) (def: #export (< reference sample) {#.doc "Int(eger) less-than."} (-> Int Int Bit) ("lux i64 <" reference sample)) (def: #export (<= reference sample) {#.doc "Int(eger) less-than or equal."} (-> Int Int Bit) (if ("lux i64 <" reference sample) #1 ("lux i64 =" reference sample))) (def: #export (> reference sample) {#.doc "Int(eger) greater-than."} (-> Int Int Bit) ("lux i64 <" sample reference)) (def: #export (>= reference sample) {#.doc "Int(eger) greater-than or equal."} (-> Int Int Bit) (if ("lux i64 <" sample reference) #1 ("lux i64 =" reference sample))) (template [ ] [(def: #export (Predicate Int) ( +0))] [..> positive?] [..< negative?] [..= zero?] ) (template [ ] [(def: #export ( left right) {#.doc } (-> Int Int Int) (if ( right left) left right))] [min ..< "Int(eger) minimum."] [max ..> "Int(eger) maximum."] ) (template [ ] [(def: #export ( param subject) {#.doc } (-> Int Int Int) ( param subject))] [+ "lux i64 +" "Int(eger) addition."] [- "lux i64 -" "Int(eger) substraction."] [* "lux i64 *" "Int(eger) multiplication."] [/ "lux i64 /" "Int(eger) division."] [% "lux i64 %" "Int(eger) remainder."] ) (def: #export (/% param subject) (-> Int Int [Int Int]) [(../ param subject) (..% param subject)]) (def: #export (negate value) (-> Int Int) (..- value +0)) (def: #export (abs x) (-> Int Int) (if (..< +0 x) (..* -1 x) x)) (def: #export (signum x) (-> Int Int) (cond (..= +0 x) +0 (..< +0 x) -1 ## else +1)) ## https://rob.conery.io/2018/08/21/mod-and-remainder-are-not-the-same/ (def: #export (mod divisor dividend) (All [m] (-> Int Int Int)) (let [remainder (..% divisor dividend)] (if (or (and (..< +0 divisor) (..> +0 remainder)) (and (..> +0 divisor) (..< +0 remainder))) (..+ divisor remainder) remainder))) (def: #export even? (-> Int Bit) (|>> (..% +2) ("lux i64 =" +0))) (def: #export odd? (-> Int Bit) (|>> ..even? not)) (def: #export (gcd a b) {#.doc "Greatest Common Divisor."} (-> Int Int Int) (case b +0 a _ (gcd b (..% b a)))) (def: #export (co-prime? a b) (-> Int Int Bit) (..= +1 (..gcd a b))) ## https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm (def: #export (extended_gcd a b) {#.doc "Extended euclidean algorithm."} (-> Int Int [[Int Int] Int]) (loop [x +1 x1 +0 y +0 y1 +1 a1 a b1 b] (case b1 +0 [[x y] a1] _ (let [q (/ b1 a1)] (recur x1 (- (* q x1) x) y1 (- (* q y1) y) b1 (- (* q b1) a1)))))) (def: #export (lcm a b) {#.doc "Least Common Multiple."} (-> Int Int Int) (case [a b] (^or [_ +0] [+0 _]) +0 _ (|> a (/ (gcd a b)) (* b)) )) (def: #export frac (-> Int Frac) (|>> "lux i64 f64")) (implementation: #export equivalence (Equivalence Int) (def: = ..=)) (implementation: #export order (Order Int) (def: &equivalence ..equivalence) (def: < ..<)) (implementation: #export enum (Enum Int) (def: &order ..order) (def: succ inc) (def: pred dec)) ## TODO: Find out why the numeric literals fail during JS compilation. (implementation: #export interval (Interval Int) (def: &enum ..enum) (def: top ## +9,223,372,036,854,775,807 (let [half (//i64.left_shift 62 +1)] (+ half (dec half)))) (def: bottom ## -9,223,372,036,854,775,808 (//i64.left_shift 63 +1))) (template [ ] [(implementation: #export (Monoid Int) (def: identity ) (def: compose ))] [addition ..+ +0] [multiplication ..* +1] [maximum ..max (\ ..interval bottom)] [minimum ..min (\ ..interval top)] ) (def: -sign "-") (def: +sign "+") (template [ ] [(implementation: #export (Codec Text Int) (def: (encode value) (if (..< +0 value) (|> value inc ..negate .nat inc (\ encode) ("lux text concat" ..-sign)) (|> value .nat (\ encode) ("lux text concat" ..+sign)))) (def: (decode repr) (let [input_size ("lux text size" repr)] (if (//nat.> 1 input_size) (case ("lux text clip" 0 1 repr) (^ (static ..+sign)) (|> repr ("lux text clip" 1 (dec input_size)) (\ decode) (\ try.functor map .int)) (^ (static ..-sign)) (|> repr ("lux text clip" 1 (dec input_size)) (\ decode) (\ try.functor map (|>> dec .int ..negate dec))) _ (#try.Failure )) (#try.Failure )))))] [binary //nat.binary "Invalid binary syntax for Int: "] [octal //nat.octal "Invalid octal syntax for Int: "] [decimal //nat.decimal "Invalid syntax for Int: "] [hex //nat.hex "Invalid hexadecimal syntax for Int: "] ) (implementation: #export hash (Hash Int) (def: &equivalence ..equivalence) (def: hash .nat)) (def: #export (right_shift parameter subject) {#.doc "Signed/arithmetic bitwise right-shift."} (-> Nat Int Int) (//i64.or (//i64.and //i64.sign subject) (//i64.right_shift parameter subject)))