(.using [library [lux (.full) ["_" test (.only Test)] ["@" target] ["[0]" ffi] [abstract [monad (.only do)] [\\specification ["$[0]" equivalence] ["$[0]" hash] ["$[0]" order] ["$[0]" monoid] ["$[0]" codec]]] [data ["[0]" bit ("[1]#[0]" equivalence)]] [macro ["[0]" template]] [math ["[0]" random (.only Random)]]]] [\\library ["[0]" / [// (.full) ["n" nat] ["i" int] ["r" rev] ["[0]" i64]]]]) (def: random (Random Frac) (# random.monad each (|>> (i.% +1,000,000) i.frac) random.int)) (def: constant Test (do random.monad [sample random.safe_frac] (all _.and (_.coverage [/.biggest] (/.<= /.biggest sample)) (_.coverage [/.positive_infinity] (/.< /.positive_infinity sample)) (_.coverage [/.smallest] (bit#= (/.positive? sample) (/.>= /.smallest sample))) (_.coverage [/.negative_infinity] (/.> /.negative_infinity sample)) (_.coverage [/.not_a_number /.not_a_number?] (and (/.not_a_number? /.not_a_number) (not (or (/.= /.not_a_number sample) (/.not_a_number? sample))))) ))) (def: predicate Test (do [! random.monad] [sample ..random shift (# ! each /.abs ..random)] (all _.and (_.coverage [/.negative?] (bit#= (/.negative? sample) (/.< +0.0 sample))) (_.coverage [/.positive?] (bit#= (/.positive? sample) (/.> +0.0 sample))) (_.coverage [/.zero?] (bit#= (/.zero? sample) (/.= +0.0 sample))) (_.coverage [/.approximately?] (and (/.approximately? /.smallest sample sample) (/.approximately? (/.+ +1.0 shift) sample (/.+ shift sample)))) (_.coverage [/.number?] (and (not (/.number? /.not_a_number)) (not (/.number? /.positive_infinity)) (not (/.number? /.negative_infinity)) (/.number? sample))) ))) (def: conversion Test (all _.and (do [! random.monad] [expected (# ! each (n.% 1,000,000) random.nat)] (_.coverage [/.nat] (|> expected n.frac /.nat (n.= expected)))) (do [! random.monad] [expected (# ! each (i.% +1,000,000) random.int)] (_.coverage [/.int] (|> expected i.frac /.int (i.= expected)))) (do [! random.monad] [expected (# ! each (|>> (i64.left_shifted 52) .rev) random.nat)] (_.coverage [/.rev] (|> expected r.frac /.rev (r.= expected)))) )) (def: signature Test (`` (all _.and (_.for [/.equivalence /.=] ($equivalence.spec /.equivalence random.safe_frac)) (_.for [/.hash] ($hash.spec /.hash random.frac)) (_.for [/.order /.<] ($order.spec /.order random.safe_frac)) (~~ (template [ ] [(_.for [ ] ($monoid.spec /.equivalence ..random))] [/.+ /.addition] [/.* /.multiplication] [/.min /.minimum] [/.max /.maximum] )) (~~ (template [] [(_.for [] ($codec.spec /.equivalence random.safe_frac))] [/.binary] [/.octal] [/.decimal] [/.hex] )) ))) (with_expansions [ (these (ffi.import: java/lang/Double "[1]::[0]" ("static" doubleToRawLongBits [double] long) ("static" longBitsToDouble [long] double)))] (for @.old (these ) @.jvm (these ) (these))) (def: margin_of_error +0.0000001) (def: (trigonometric_symmetry forward backward angle) (-> (-> Frac Frac) (-> Frac Frac) Frac Bit) (let [normal (|> angle forward backward)] (|> normal forward backward (/.approximately? ..margin_of_error normal)))) (def: test|math Test (all _.and (do [! random.monad] [.let [~= (/.approximately? ..margin_of_error)] angle (|> random.safe_frac (# ! each (/.* /.tau)))] (all _.and (_.coverage [/.sin /.asin] (trigonometric_symmetry /.sin /.asin angle)) (_.coverage [/.cos /.acos] (trigonometric_symmetry /.cos /.acos angle)) (_.coverage [/.tan /.atan] (trigonometric_symmetry /.tan /.atan angle)) (_.coverage [/.tau] (and (and (~= +0.0 (/.sin /.tau)) (~= +1.0 (/.cos /.tau))) (and (~= +0.0 (/.sin (/./ +2.0 /.tau))) (~= -1.0 (/.cos (/./ +2.0 /.tau)))) (and (~= +1.0 (/.sin (/./ +4.0 /.tau))) (~= +0.0 (/.cos (/./ +4.0 /.tau)))) (and (~= -1.0 (/.sin (/.* +3.0 (/./ +4.0 /.tau)))) (~= +0.0 (/.cos (/.* +3.0 (/./ +4.0 /.tau))))) (let [x2+y2 (/.+ (/.pow +2.0 (/.sin angle)) (/.pow +2.0 (/.cos angle)))] (~= +1.0 x2+y2)))) (_.coverage [/.pi] (~= (/./ +2.0 /.tau) /.pi)) )) (do [! random.monad] [sample (|> random.safe_frac (# ! each (/.* +1000.0)))] (all _.and (_.coverage [/.ceil] (let [ceil'd (/.ceil sample)] (and (|> ceil'd /.int i.frac (/.= ceil'd)) (/.>= sample ceil'd) (/.<= +1.0 (/.- sample ceil'd))))) (_.coverage [/.floor] (let [floor'd (/.floor sample)] (and (|> floor'd /.int i.frac (/.= floor'd)) (/.<= sample floor'd) (/.<= +1.0 (/.- floor'd sample))))) (_.coverage [/.round] (let [round'd (/.round sample)] (and (|> round'd /.int i.frac (/.= round'd)) (/.<= +1.0 (/.abs (/.- sample round'd)))))) (_.coverage [/.root_2] (let [sample (/.abs sample)] (|> sample /.root_2 (/.pow +2.0) (/.approximately? ..margin_of_error sample)))) (_.coverage [/.root_3] (|> sample /.root_3 (/.pow +3.0) (/.approximately? ..margin_of_error sample))) )) (do [! random.monad] [.let [~= (/.approximately? ..margin_of_error)] sample (# ! each (/.* +10.0) random.safe_frac) power (# ! each (|>> (n.% 10) ++ n.frac) random.nat)] (all _.and (_.coverage [/.exp /.log] (|> sample /.exp /.log (/.approximately? +0.000000000000001 sample))) (_.coverage [/.e] (~= +1.0 (/.log /.e))) (_.coverage [/.pow /.log_by] (let [sample (/.abs sample)] (|> sample (/.pow power) (/.log_by sample) (~= power)))) )) (do [! random.monad] [.let [~= (/.approximately? ..margin_of_error)] angle (# ! each (/.* /.tau) random.safe_frac) sample (# ! each /.abs random.safe_frac) big (# ! each (/.* +1,000,000,000.00) random.safe_frac)] (template.let [(odd! ) [(_.coverage [] (~= (/.opposite ( angle)) ( (/.opposite angle))))] (even! ) [(_.coverage [] (~= ( angle) ( (/.opposite angle))))] (inverse! ) [(_.coverage [ ] (~= ( ) ( (/./ +1.0))))]] (all _.and (odd! /.sinh) (even! /.cosh) (odd! /.tanh) (odd! /.coth) (even! /.sech) (odd! /.csch) (inverse! /.acosh /.asech sample) (inverse! /.asinh /.acsch sample) (inverse! /.atanh /.acoth big) ))) (do [! random.monad] [x (# ! each (|>> (/.* +10.0) /.abs) random.safe_frac) y (# ! each (|>> (/.* +10.0) /.abs) random.safe_frac)] (_.coverage [/.hypotenuse] (let [h (/.hypotenuse x y)] (and (/.>= x h) (/.>= y h))))) (do [! random.monad] [.let [~= (/.approximately? ..margin_of_error) tau/4 (/./ +4.0 /.tau)] x (# ! each (/.* tau/4) random.safe_frac) y (# ! each (/.* tau/4) random.safe_frac)] (_.coverage [/.atan_2] (let [expected (/.atan_2 x y) actual (if (/.> +0.0 x) (/.atan (/./ x y)) (if (/.< +0.0 y) (/.- /.pi (/.atan (/./ x y))) (/.+ /.pi (/.atan (/./ x y)))))] (and (~= expected actual) (~= tau/4 (/.atan_2 +0.0 (/.abs y))) (~= (/.opposite tau/4) (/.atan_2 +0.0 (/.opposite (/.abs y)))) (/.not_a_number? (/.atan_2 +0.0 +0.0)))))) (do [! random.monad] [of (# ! each (|>> (n.% 10) ++) random.nat)] (_.coverage [/.factorial] (and (n.= 1 (/.factorial 0)) (|> (/.factorial of) (n.% of) (n.= 0))))) )) (def: .public test Test (<| (_.covering /._) (_.for [.Frac]) (all _.and (do random.monad [left random.safe_frac right random.safe_frac] (all _.and (_.coverage [/.>] (bit#= (/.> left right) (/.< right left))) (_.coverage [/.<= /.>=] (bit#= (/.<= left right) (/.>= right left))) )) (do random.monad [sample random.safe_frac] (all _.and (_.coverage [/.-] (and (/.= +0.0 (/.- sample sample)) (/.= sample (/.- +0.0 sample)) (/.= (/.opposite sample) (/.- sample +0.0)))) (_.coverage [/./] (and (/.= +1.0 (/./ sample sample)) (/.= sample (/./ +1.0 sample)))) (_.coverage [/.abs] (bit#= (/.> sample (/.abs sample)) (/.negative? sample))) (_.coverage [/.signum] (/.= (/.abs sample) (/.* (/.signum sample) sample))) )) (do random.monad [left (random.only (|>> (/.= +0.0) not) ..random) right ..random] (all _.and (_.coverage [/.%] (let [rem (/.% left right) div (|> right (/.- rem) (/./ left))] (/.= right (|> div (/.* left) (/.+ rem))))) (_.coverage [/./%] (let [[div rem] (/./% left right)] (and (/.= div (/./ left right)) (/.= rem (/.% left right))))) (_.coverage [/.mod] (or (and (/.= +0.0 (/.% left right)) (/.= +0.0 (/.mod left right))) (and (/.= (/.signum left) (/.signum (/.mod left right))) (/.= (/.signum right) (/.signum (/.% left right))) (if (/.= (/.signum left) (/.signum right)) (/.= (/.% left right) (/.mod left right)) (/.= (/.+ left (/.% left right)) (/.mod left right)))))) )) (with_expansions [ (all _.and (let [test (is (-> Frac Bit) (function (_ value) (n.= (.nat (ffi.of_long (java/lang/Double::doubleToRawLongBits (ffi.as_double value)))) (/.bits value))))] (do random.monad [sample random.frac] (_.coverage [/.bits] (and (test sample) (test /.biggest) (test /.smallest) (test /.not_a_number) (test /.positive_infinity) (test /.negative_infinity))))) (do random.monad [sample random.i64] (_.coverage [/.of_bits] (let [expected (ffi.of_double (java/lang/Double::longBitsToDouble (ffi.as_long sample))) actual (/.of_bits sample)] (or (/.= expected actual) (and (/.not_a_number? expected) (/.not_a_number? actual)))))) )] (for @.old @.jvm (let [test (is (-> Frac Bit) (function (_ expected) (let [actual (|> expected /.bits /.of_bits)] (or (/.= expected actual) (and (/.not_a_number? expected) (/.not_a_number? actual))))))] (do random.monad [sample random.frac] (_.coverage [/.bits /.of_bits] (and (test sample) (test /.biggest) (test /.smallest) (test /.not_a_number) (test /.positive_infinity) (test /.negative_infinity))))))) (do random.monad [expected random.safe_frac] (_.coverage [/.opposite] (let [subtraction! (/.= +0.0 (/.+ (/.opposite expected) expected)) inverse! (|> expected /.opposite /.opposite (/.= expected))] (and subtraction! inverse!)))) ..constant ..predicate ..conversion ..signature ..test|math )))