diff --git a/libmath/desk/lib/complex.hoon b/libmath/desk/lib/complex.hoon index 6d76cfb..d9d4b24 100644 --- a/libmath/desk/lib/complex.hoon +++ b/libmath/desk/lib/complex.hoon @@ -20,18 +20,17 @@ :: additive copies later. Complex has no total order, so there is :: intentionally no gth/gte/lth/lte -- only equ/neq. :: -:: TODO (PENCILLED IN -- complex transcendentals, follow-on to the %unum -:: transcendental work). This lib currently provides arithmetic + abs/conj/ -:: re/im/pak only. To let Saloon's Tier B (exp/sin/cos/log/sqrt/...) accept -:: %cplx rays the way it now accepts %unum, each width door needs the complex -:: elementary functions, then a %cplx branch in saloon +trans-scalar/+fun-scalar -:: (mirroring the %unum branch). Closed forms over the real component ops: -:: cexp(a+bi) = e^a * (cos b + i sin b) -:: clog(a+bi) = log|z| + i*atan2(b, a) (needs a real atan2) -:: csqrt(z) = sqrt((|z|+a)/2) + i*sgn(b)*sqrt((|z|-a)/2) -:: csin/ccos via the real sin/cos/sinh/cosh, cpow via cexp(w*clog z) -:: Depends on the real transcendentals (which #18's Chebyshev rewrite will -:: harden); accuracy will inherit whatever the real layer provides. +:: Complex elementary functions (cexp/clog/csqrt/csin/ccos/ctan/cpow) compose +:: real component transcendentals. To keep this lib self-contained -- like +:: /lib/unum, /lib/fixed, /lib/twoc, with no dependency on /lib/math -- each +:: width door carries its OWN real exp/sin/cos/log/atan as naive Taylor/AGM +:: series over the stdlib component float door, at a fixed term count (the same +:: approach as /lib/math and /lib/unum; #18's Chebyshev rewrite would upgrade +:: those in lockstep). Closed forms: +:: cexp(a+bi) = e^a (cos b + i sin b) +:: clog(a+bi) = log|z| + i atan2(b, a) +:: csqrt(z) = sqrt((|z|+a)/2) + i sgn(b) sqrt((|z|-a)/2) +:: csin/ccos via real sin/cos and cosh/sinh; ctan = csin/ccos; cpow = cexp(w clog z) :: |% +$ rounding-mode ?(%n %u %d %z) @@ -202,6 +201,132 @@ :: %.y :: Source ++ neq |=([p=@ q=@] =(| (equ p q))) + :: + :: Transcendental / elementary functions. Self-contained real @rs series + :: (naive Taylor/AGM, fixed term counts -- accurate near the expansion point, + :: matching /lib/math and /lib/unum); component arithmetic stays on stdlib +rs. + :: + ++ rpi `@rs`.3.1415927 :: pi at @rs + ++ rexp + |= x=@rs ^- @rs + =/ s .1 =/ t .1 =/ n=@ 1 + |- ?: (gth n 20) s + =. t (~(mul rs rnd) t (~(div rs rnd) x (~(sun rs rnd) n))) + $(n +(n), s (~(add rs rnd) s t)) + ++ rsin + |= x=@rs ^- @rs + =/ t x =/ s x =/ n=@ 1 + |- ?: (gth n 20) s + =/ k (^mul 2 n) + =. t (~(sub rs rnd) .0 (~(mul rs rnd) t (~(div rs rnd) (~(mul rs rnd) x x) (~(mul rs rnd) (~(sun rs rnd) k) (~(sun rs rnd) +(k)))))) + $(n +(n), s (~(add rs rnd) s t)) + ++ rcos + |= x=@rs ^- @rs + =/ t .1 =/ s .1 =/ n=@ 1 + |- ?: (gth n 20) s + =/ k (^mul 2 n) + =. t (~(sub rs rnd) .0 (~(mul rs rnd) t (~(div rs rnd) (~(mul rs rnd) x x) (~(mul rs rnd) (~(sun rs rnd) (dec k)) (~(sun rs rnd) k))))) + $(n +(n), s (~(add rs rnd) s t)) + ++ rlog + |= x=@rs ^- @rs + ?: =(`@rs`.0 x) `@rs`0xff80.0000 :: log 0 = -inf + =/ y (~(div rs rnd) (~(sub rs rnd) x .1) (~(add rs rnd) x .1)) + =/ y2 (~(mul rs rnd) y y) =/ s y =/ t y =/ n=@ 1 + |- ?: (gth n 30) (~(mul rs rnd) .2 s) + =. t (~(mul rs rnd) t y2) + =/ c (~(div rs rnd) .1 (~(sun rs rnd) +((^mul 2 n)))) + $(n +(n), s (~(add rs rnd) s (~(mul rs rnd) c t))) + ++ ratan :: single-arg arctan (Gauss AGM) + |= x=@rs ^- @rs + =/ rt (~(sqt rs rnd) (~(add rs rnd) .1 (~(mul rs rnd) x x))) + =/ a (~(div rs rnd) .1 rt) =/ b .1 =/ n=@ 0 + |- ?: (gth n 40) (~(div rs rnd) x (~(mul rs rnd) rt b)) + =/ ai (~(mul rs rnd) .0.5 (~(add rs rnd) a b)) + $(n +(n), a ai, b (~(sqt rs rnd) (~(mul rs rnd) ai b))) + ++ ratn :: atan2(y, x) + |= [y=@rs x=@rs] ^- @rs + ?: (~(gth rs rnd) x .0) (ratan (~(div rs rnd) y x)) + ?: &((~(lth rs rnd) x .0) (~(gte rs rnd) y .0)) (~(add rs rnd) (ratan (~(div rs rnd) y x)) rpi) + ?: &((~(lth rs rnd) x .0) (~(lth rs rnd) y .0)) (~(sub rs rnd) (ratan (~(div rs rnd) y x)) rpi) + ?: (~(gth rs rnd) y .0) (~(div rs rnd) rpi .2) + ?: (~(lth rs rnd) y .0) (~(sub rs rnd) .0 (~(div rs rnd) rpi .2)) + .0 + :: +cexp: @cs -> @cs + :: + :: Complex exponential e^z = e^a (cos b + i sin b) for z = a + bi. + :: Examples + :: > (~(cexp cs:complex %n) 0x4000.0000.3f80.0000) :: exp(1+2i) + :: 0x401e.30c5.bf90.cb4e + :: Source + ++ cexp + |= p=@ + ^- @ + =/ ea (rexp (re p)) + (pak (~(mul rs rnd) ea (rcos (im p))) (~(mul rs rnd) ea (rsin (im p)))) + :: +clog: @cs -> @cs + :: + :: Principal complex logarithm ln(z) = ln|z| + i*atan2(b, a). + :: Source + ++ clog + |= p=@ + ^- @ + =/ a (re p) + =/ b (im p) + =/ mag (~(sqt rs rnd) (~(add rs rnd) (~(mul rs rnd) a a) (~(mul rs rnd) b b))) + (pak (rlog mag) (ratn b a)) + :: +csqrt: @cs -> @cs + :: + :: Principal complex square root: sqrt((|z|+a)/2) + i*sgn(b)*sqrt((|z|-a)/2), + :: with the imaginary sign taken from b (the principal branch). + :: Source + ++ csqrt + |= p=@ + ^- @ + =/ a (re p) + =/ b (im p) + =/ mag (~(sqt rs rnd) (~(add rs rnd) (~(mul rs rnd) a a) (~(mul rs rnd) b b))) + =/ re- (~(sqt rs rnd) (~(div rs rnd) (~(add rs rnd) mag a) .2)) + =/ im- (~(sqt rs rnd) (~(div rs rnd) (~(sub rs rnd) mag a) .2)) + (pak re- ?:((~(lth rs rnd) b .0) (fneg im-) im-)) + :: +csin: @cs -> @cs + :: + :: Complex sine sin(z) = sin(a)cosh(b) + i cos(a)sinh(b), with cosh/sinh built + :: from the real exponential. + :: Source + ++ csin + |= p=@ + ^- @ + =/ a (re p) + =/ b (im p) + =/ eb (rexp b) + =/ enb (rexp (fneg b)) + =/ csh (~(div rs rnd) (~(add rs rnd) eb enb) .2) + =/ snh (~(div rs rnd) (~(sub rs rnd) eb enb) .2) + (pak (~(mul rs rnd) (rsin a) csh) (~(mul rs rnd) (rcos a) snh)) + :: +ccos: @cs -> @cs + :: + :: Complex cosine cos(z) = cos(a)cosh(b) - i sin(a)sinh(b). + :: Source + ++ ccos + |= p=@ + ^- @ + =/ a (re p) + =/ b (im p) + =/ eb (rexp b) + =/ enb (rexp (fneg b)) + =/ csh (~(div rs rnd) (~(add rs rnd) eb enb) .2) + =/ snh (~(div rs rnd) (~(sub rs rnd) eb enb) .2) + (pak (~(mul rs rnd) (rcos a) csh) (fneg (~(mul rs rnd) (rsin a) snh))) + :: +ctan: @cs -> @cs + :: + :: Complex tangent tan(z) = sin(z) / cos(z). + :: Source + ++ ctan |=(p=@ (div (csin p) (ccos p))) + :: +cpow: [@cs @cs] -> @cs + :: + :: Complex power z^w = exp(w * ln z) (principal branch). + :: Source + ++ cpow |=([p=@ q=@] (cexp (mul q (clog p)))) -- :: +cd: complex-double (@cd), two @rd (64-bit) components. :: @@ -370,6 +495,129 @@ :: %.y :: Source ++ neq |=([p=@ q=@] =(| (equ p q))) + :: + :: Transcendental / elementary functions. Self-contained real @rd series + :: (naive Taylor/AGM, fixed term counts -- accurate near the expansion point, + :: matching /lib/math and /lib/unum); component arithmetic stays on stdlib +rs. + :: + ++ rpi `@rd`.~3.14159265358979 :: pi at @rd + ++ rexp + |= x=@rd ^- @rd + =/ s .~1 =/ t .~1 =/ n=@ 1 + |- ?: (gth n 20) s + =. t (~(mul rd rnd) t (~(div rd rnd) x (~(sun rd rnd) n))) + $(n +(n), s (~(add rd rnd) s t)) + ++ rsin + |= x=@rd ^- @rd + =/ t x =/ s x =/ n=@ 1 + |- ?: (gth n 20) s + =/ k (^mul 2 n) + =. t (~(sub rd rnd) .~0 (~(mul rd rnd) t (~(div rd rnd) (~(mul rd rnd) x x) (~(mul rd rnd) (~(sun rd rnd) k) (~(sun rd rnd) +(k)))))) + $(n +(n), s (~(add rd rnd) s t)) + ++ rcos + |= x=@rd ^- @rd + =/ t .~1 =/ s .~1 =/ n=@ 1 + |- ?: (gth n 20) s + =/ k (^mul 2 n) + =. t (~(sub rd rnd) .~0 (~(mul rd rnd) t (~(div rd rnd) (~(mul rd rnd) x x) (~(mul rd rnd) (~(sun rd rnd) (dec k)) (~(sun rd rnd) k))))) + $(n +(n), s (~(add rd rnd) s t)) + ++ rlog + |= x=@rd ^- @rd + ?: =(`@rd`.~0 x) `@rd`0xfff0.0000.0000.0000 + =/ y (~(div rd rnd) (~(sub rd rnd) x .~1) (~(add rd rnd) x .~1)) + =/ y2 (~(mul rd rnd) y y) =/ s y =/ t y =/ n=@ 1 + |- ?: (gth n 30) (~(mul rd rnd) .~2 s) + =. t (~(mul rd rnd) t y2) + =/ c (~(div rd rnd) .~1 (~(sun rd rnd) +((^mul 2 n)))) + $(n +(n), s (~(add rd rnd) s (~(mul rd rnd) c t))) + ++ ratan :: single-arg arctan (Gauss AGM) + |= x=@rd ^- @rd + =/ rt (~(sqt rd rnd) (~(add rd rnd) .~1 (~(mul rd rnd) x x))) + =/ a (~(div rd rnd) .~1 rt) =/ b .~1 =/ n=@ 0 + |- ?: (gth n 40) (~(div rd rnd) x (~(mul rd rnd) rt b)) + =/ ai (~(mul rd rnd) .~0.5 (~(add rd rnd) a b)) + $(n +(n), a ai, b (~(sqt rd rnd) (~(mul rd rnd) ai b))) + ++ ratn :: atan2(y, x) + |= [y=@rd x=@rd] ^- @rd + ?: (~(gth rd rnd) x .~0) (ratan (~(div rd rnd) y x)) + ?: &((~(lth rd rnd) x .~0) (~(gte rd rnd) y .~0)) (~(add rd rnd) (ratan (~(div rd rnd) y x)) rpi) + ?: &((~(lth rd rnd) x .~0) (~(lth rd rnd) y .~0)) (~(sub rd rnd) (ratan (~(div rd rnd) y x)) rpi) + ?: (~(gth rd rnd) y .~0) (~(div rd rnd) rpi .~2) + ?: (~(lth rd rnd) y .~0) (~(sub rd rnd) .~0 (~(div rd rnd) rpi .~2)) + .~0 + :: +cexp: @cd -> @cd + :: + :: Complex exponential e^z = e^a (cos b + i sin b) for z = a + bi. + :: Source + ++ cexp + |= p=@ + ^- @ + =/ ea (rexp (re p)) + (pak (~(mul rd rnd) ea (rcos (im p))) (~(mul rd rnd) ea (rsin (im p)))) + :: +clog: @cd -> @cd + :: + :: Principal complex logarithm ln(z) = ln|z| + i*atan2(b, a). + :: Source + ++ clog + |= p=@ + ^- @ + =/ a (re p) + =/ b (im p) + =/ mag (~(sqt rd rnd) (~(add rd rnd) (~(mul rd rnd) a a) (~(mul rd rnd) b b))) + (pak (rlog mag) (ratn b a)) + :: +csqrt: @cd -> @cd + :: + :: Principal complex square root: sqrt((|z|+a)/2) + i*sgn(b)*sqrt((|z|-a)/2), + :: with the imaginary sign taken from b (the principal branch). + :: Source + ++ csqrt + |= p=@ + ^- @ + =/ a (re p) + =/ b (im p) + =/ mag (~(sqt rd rnd) (~(add rd rnd) (~(mul rd rnd) a a) (~(mul rd rnd) b b))) + =/ re- (~(sqt rd rnd) (~(div rd rnd) (~(add rd rnd) mag a) .~2)) + =/ im- (~(sqt rd rnd) (~(div rd rnd) (~(sub rd rnd) mag a) .~2)) + (pak re- ?:((~(lth rd rnd) b .~0) (fneg im-) im-)) + :: +csin: @cd -> @cd + :: + :: Complex sine sin(z) = sin(a)cosh(b) + i cos(a)sinh(b), with cosh/sinh built + :: from the real exponential. + :: Source + ++ csin + |= p=@ + ^- @ + =/ a (re p) + =/ b (im p) + =/ eb (rexp b) + =/ enb (rexp (fneg b)) + =/ csh (~(div rd rnd) (~(add rd rnd) eb enb) .~2) + =/ snh (~(div rd rnd) (~(sub rd rnd) eb enb) .~2) + (pak (~(mul rd rnd) (rsin a) csh) (~(mul rd rnd) (rcos a) snh)) + :: +ccos: @cd -> @cd + :: + :: Complex cosine cos(z) = cos(a)cosh(b) - i sin(a)sinh(b). + :: Source + ++ ccos + |= p=@ + ^- @ + =/ a (re p) + =/ b (im p) + =/ eb (rexp b) + =/ enb (rexp (fneg b)) + =/ csh (~(div rd rnd) (~(add rd rnd) eb enb) .~2) + =/ snh (~(div rd rnd) (~(sub rd rnd) eb enb) .~2) + (pak (~(mul rd rnd) (rcos a) csh) (fneg (~(mul rd rnd) (rsin a) snh))) + :: +ctan: @cd -> @cd + :: + :: Complex tangent tan(z) = sin(z) / cos(z). + :: Source + ++ ctan |=(p=@ (div (csin p) (ccos p))) + :: +cpow: [@cd @cd] -> @cd + :: + :: Complex power z^w = exp(w * ln z) (principal branch). + :: Source + ++ cpow |=([p=@ q=@] (cexp (mul q (clog p)))) -- :: +ch: complex-half (@ch), two @rh (16-bit) components. :: @@ -536,6 +784,129 @@ :: %.y :: Source ++ neq |=([p=@ q=@] =(| (equ p q))) + :: + :: Transcendental / elementary functions. Self-contained real @rh series + :: (naive Taylor/AGM, fixed term counts -- accurate near the expansion point, + :: matching /lib/math and /lib/unum); component arithmetic stays on stdlib +rs. + :: + ++ rpi `@rh`.~~3.14159 :: pi at @rh + ++ rexp + |= x=@rh ^- @rh + =/ s .~~1 =/ t .~~1 =/ n=@ 1 + |- ?: (gth n 20) s + =. t (~(mul rh rnd) t (~(div rh rnd) x (~(sun rh rnd) n))) + $(n +(n), s (~(add rh rnd) s t)) + ++ rsin + |= x=@rh ^- @rh + =/ t x =/ s x =/ n=@ 1 + |- ?: (gth n 20) s + =/ k (^mul 2 n) + =. t (~(sub rh rnd) .~~0 (~(mul rh rnd) t (~(div rh rnd) (~(mul rh rnd) x x) (~(mul rh rnd) (~(sun rh rnd) k) (~(sun rh rnd) +(k)))))) + $(n +(n), s (~(add rh rnd) s t)) + ++ rcos + |= x=@rh ^- @rh + =/ t .~~1 =/ s .~~1 =/ n=@ 1 + |- ?: (gth n 20) s + =/ k (^mul 2 n) + =. t (~(sub rh rnd) .~~0 (~(mul rh rnd) t (~(div rh rnd) (~(mul rh rnd) x x) (~(mul rh rnd) (~(sun rh rnd) (dec k)) (~(sun rh rnd) k))))) + $(n +(n), s (~(add rh rnd) s t)) + ++ rlog + |= x=@rh ^- @rh + ?: =(`@rh`.~~0 x) `@rh`0xfc00 + =/ y (~(div rh rnd) (~(sub rh rnd) x .~~1) (~(add rh rnd) x .~~1)) + =/ y2 (~(mul rh rnd) y y) =/ s y =/ t y =/ n=@ 1 + |- ?: (gth n 30) (~(mul rh rnd) .~~2 s) + =. t (~(mul rh rnd) t y2) + =/ c (~(div rh rnd) .~~1 (~(sun rh rnd) +((^mul 2 n)))) + $(n +(n), s (~(add rh rnd) s (~(mul rh rnd) c t))) + ++ ratan :: single-arg arctan (Gauss AGM) + |= x=@rh ^- @rh + =/ rt (~(sqt rh rnd) (~(add rh rnd) .~~1 (~(mul rh rnd) x x))) + =/ a (~(div rh rnd) .~~1 rt) =/ b .~~1 =/ n=@ 0 + |- ?: (gth n 40) (~(div rh rnd) x (~(mul rh rnd) rt b)) + =/ ai (~(mul rh rnd) .~~0.5 (~(add rh rnd) a b)) + $(n +(n), a ai, b (~(sqt rh rnd) (~(mul rh rnd) ai b))) + ++ ratn :: atan2(y, x) + |= [y=@rh x=@rh] ^- @rh + ?: (~(gth rh rnd) x .~~0) (ratan (~(div rh rnd) y x)) + ?: &((~(lth rh rnd) x .~~0) (~(gte rh rnd) y .~~0)) (~(add rh rnd) (ratan (~(div rh rnd) y x)) rpi) + ?: &((~(lth rh rnd) x .~~0) (~(lth rh rnd) y .~~0)) (~(sub rh rnd) (ratan (~(div rh rnd) y x)) rpi) + ?: (~(gth rh rnd) y .~~0) (~(div rh rnd) rpi .~~2) + ?: (~(lth rh rnd) y .~~0) (~(sub rh rnd) .~~0 (~(div rh rnd) rpi .~~2)) + .~~0 + :: +cexp: @ch -> @ch + :: + :: Complex exponential e^z = e^a (cos b + i sin b) for z = a + bi. + :: Source + ++ cexp + |= p=@ + ^- @ + =/ ea (rexp (re p)) + (pak (~(mul rh rnd) ea (rcos (im p))) (~(mul rh rnd) ea (rsin (im p)))) + :: +clog: @ch -> @ch + :: + :: Principal complex logarithm ln(z) = ln|z| + i*atan2(b, a). + :: Source + ++ clog + |= p=@ + ^- @ + =/ a (re p) + =/ b (im p) + =/ mag (~(sqt rh rnd) (~(add rh rnd) (~(mul rh rnd) a a) (~(mul rh rnd) b b))) + (pak (rlog mag) (ratn b a)) + :: +csqrt: @ch -> @ch + :: + :: Principal complex square root: sqrt((|z|+a)/2) + i*sgn(b)*sqrt((|z|-a)/2), + :: with the imaginary sign taken from b (the principal branch). + :: Source + ++ csqrt + |= p=@ + ^- @ + =/ a (re p) + =/ b (im p) + =/ mag (~(sqt rh rnd) (~(add rh rnd) (~(mul rh rnd) a a) (~(mul rh rnd) b b))) + =/ re- (~(sqt rh rnd) (~(div rh rnd) (~(add rh rnd) mag a) .~~2)) + =/ im- (~(sqt rh rnd) (~(div rh rnd) (~(sub rh rnd) mag a) .~~2)) + (pak re- ?:((~(lth rh rnd) b .~~0) (fneg im-) im-)) + :: +csin: @ch -> @ch + :: + :: Complex sine sin(z) = sin(a)cosh(b) + i cos(a)sinh(b), with cosh/sinh built + :: from the real exponential. + :: Source + ++ csin + |= p=@ + ^- @ + =/ a (re p) + =/ b (im p) + =/ eb (rexp b) + =/ enb (rexp (fneg b)) + =/ csh (~(div rh rnd) (~(add rh rnd) eb enb) .~~2) + =/ snh (~(div rh rnd) (~(sub rh rnd) eb enb) .~~2) + (pak (~(mul rh rnd) (rsin a) csh) (~(mul rh rnd) (rcos a) snh)) + :: +ccos: @ch -> @ch + :: + :: Complex cosine cos(z) = cos(a)cosh(b) - i sin(a)sinh(b). + :: Source + ++ ccos + |= p=@ + ^- @ + =/ a (re p) + =/ b (im p) + =/ eb (rexp b) + =/ enb (rexp (fneg b)) + =/ csh (~(div rh rnd) (~(add rh rnd) eb enb) .~~2) + =/ snh (~(div rh rnd) (~(sub rh rnd) eb enb) .~~2) + (pak (~(mul rh rnd) (rcos a) csh) (fneg (~(mul rh rnd) (rsin a) snh))) + :: +ctan: @ch -> @ch + :: + :: Complex tangent tan(z) = sin(z) / cos(z). + :: Source + ++ ctan |=(p=@ (div (csin p) (ccos p))) + :: +cpow: [@ch @ch] -> @ch + :: + :: Complex power z^w = exp(w * ln z) (principal branch). + :: Source + ++ cpow |=([p=@ q=@] (cexp (mul q (clog p)))) -- :: +cq: complex-quad (@cq), two @rq (128-bit) components. :: @@ -703,5 +1074,128 @@ :: %.y :: Source ++ neq |=([p=@ q=@] =(| (equ p q))) + :: + :: Transcendental / elementary functions. Self-contained real @rq series + :: (naive Taylor/AGM, fixed term counts -- accurate near the expansion point, + :: matching /lib/math and /lib/unum); component arithmetic stays on stdlib +rs. + :: + ++ rpi `@rq`.~~~3.14159265358979323846 :: pi at @rq + ++ rexp + |= x=@rq ^- @rq + =/ s .~~~1 =/ t .~~~1 =/ n=@ 1 + |- ?: (gth n 20) s + =. t (~(mul rq rnd) t (~(div rq rnd) x (~(sun rq rnd) n))) + $(n +(n), s (~(add rq rnd) s t)) + ++ rsin + |= x=@rq ^- @rq + =/ t x =/ s x =/ n=@ 1 + |- ?: (gth n 20) s + =/ k (^mul 2 n) + =. t (~(sub rq rnd) .~~~0 (~(mul rq rnd) t (~(div rq rnd) (~(mul rq rnd) x x) (~(mul rq rnd) (~(sun rq rnd) k) (~(sun rq rnd) +(k)))))) + $(n +(n), s (~(add rq rnd) s t)) + ++ rcos + |= x=@rq ^- @rq + =/ t .~~~1 =/ s .~~~1 =/ n=@ 1 + |- ?: (gth n 20) s + =/ k (^mul 2 n) + =. t (~(sub rq rnd) .~~~0 (~(mul rq rnd) t (~(div rq rnd) (~(mul rq rnd) x x) (~(mul rq rnd) (~(sun rq rnd) (dec k)) (~(sun rq rnd) k))))) + $(n +(n), s (~(add rq rnd) s t)) + ++ rlog + |= x=@rq ^- @rq + ?: =(`@rq`.~~~0 x) `@rq`0xffff.0000.0000.0000.0000.0000.0000.0000 + =/ y (~(div rq rnd) (~(sub rq rnd) x .~~~1) (~(add rq rnd) x .~~~1)) + =/ y2 (~(mul rq rnd) y y) =/ s y =/ t y =/ n=@ 1 + |- ?: (gth n 30) (~(mul rq rnd) .~~~2 s) + =. t (~(mul rq rnd) t y2) + =/ c (~(div rq rnd) .~~~1 (~(sun rq rnd) +((^mul 2 n)))) + $(n +(n), s (~(add rq rnd) s (~(mul rq rnd) c t))) + ++ ratan :: single-arg arctan (Gauss AGM) + |= x=@rq ^- @rq + =/ rt (~(sqt rq rnd) (~(add rq rnd) .~~~1 (~(mul rq rnd) x x))) + =/ a (~(div rq rnd) .~~~1 rt) =/ b .~~~1 =/ n=@ 0 + |- ?: (gth n 40) (~(div rq rnd) x (~(mul rq rnd) rt b)) + =/ ai (~(mul rq rnd) .~~~0.5 (~(add rq rnd) a b)) + $(n +(n), a ai, b (~(sqt rq rnd) (~(mul rq rnd) ai b))) + ++ ratn :: atan2(y, x) + |= [y=@rq x=@rq] ^- @rq + ?: (~(gth rq rnd) x .~~~0) (ratan (~(div rq rnd) y x)) + ?: &((~(lth rq rnd) x .~~~0) (~(gte rq rnd) y .~~~0)) (~(add rq rnd) (ratan (~(div rq rnd) y x)) rpi) + ?: &((~(lth rq rnd) x .~~~0) (~(lth rq rnd) y .~~~0)) (~(sub rq rnd) (ratan (~(div rq rnd) y x)) rpi) + ?: (~(gth rq rnd) y .~~~0) (~(div rq rnd) rpi .~~~2) + ?: (~(lth rq rnd) y .~~~0) (~(sub rq rnd) .~~~0 (~(div rq rnd) rpi .~~~2)) + .~~~0 + :: +cexp: @cq -> @cq + :: + :: Complex exponential e^z = e^a (cos b + i sin b) for z = a + bi. + :: Source + ++ cexp + |= p=@ + ^- @ + =/ ea (rexp (re p)) + (pak (~(mul rq rnd) ea (rcos (im p))) (~(mul rq rnd) ea (rsin (im p)))) + :: +clog: @cq -> @cq + :: + :: Principal complex logarithm ln(z) = ln|z| + i*atan2(b, a). + :: Source + ++ clog + |= p=@ + ^- @ + =/ a (re p) + =/ b (im p) + =/ mag (~(sqt rq rnd) (~(add rq rnd) (~(mul rq rnd) a a) (~(mul rq rnd) b b))) + (pak (rlog mag) (ratn b a)) + :: +csqrt: @cq -> @cq + :: + :: Principal complex square root: sqrt((|z|+a)/2) + i*sgn(b)*sqrt((|z|-a)/2), + :: with the imaginary sign taken from b (the principal branch). + :: Source + ++ csqrt + |= p=@ + ^- @ + =/ a (re p) + =/ b (im p) + =/ mag (~(sqt rq rnd) (~(add rq rnd) (~(mul rq rnd) a a) (~(mul rq rnd) b b))) + =/ re- (~(sqt rq rnd) (~(div rq rnd) (~(add rq rnd) mag a) .~~~2)) + =/ im- (~(sqt rq rnd) (~(div rq rnd) (~(sub rq rnd) mag a) .~~~2)) + (pak re- ?:((~(lth rq rnd) b .~~~0) (fneg im-) im-)) + :: +csin: @cq -> @cq + :: + :: Complex sine sin(z) = sin(a)cosh(b) + i cos(a)sinh(b), with cosh/sinh built + :: from the real exponential. + :: Source + ++ csin + |= p=@ + ^- @ + =/ a (re p) + =/ b (im p) + =/ eb (rexp b) + =/ enb (rexp (fneg b)) + =/ csh (~(div rq rnd) (~(add rq rnd) eb enb) .~~~2) + =/ snh (~(div rq rnd) (~(sub rq rnd) eb enb) .~~~2) + (pak (~(mul rq rnd) (rsin a) csh) (~(mul rq rnd) (rcos a) snh)) + :: +ccos: @cq -> @cq + :: + :: Complex cosine cos(z) = cos(a)cosh(b) - i sin(a)sinh(b). + :: Source + ++ ccos + |= p=@ + ^- @ + =/ a (re p) + =/ b (im p) + =/ eb (rexp b) + =/ enb (rexp (fneg b)) + =/ csh (~(div rq rnd) (~(add rq rnd) eb enb) .~~~2) + =/ snh (~(div rq rnd) (~(sub rq rnd) eb enb) .~~~2) + (pak (~(mul rq rnd) (rcos a) csh) (fneg (~(mul rq rnd) (rsin a) snh))) + :: +ctan: @cq -> @cq + :: + :: Complex tangent tan(z) = sin(z) / cos(z). + :: Source + ++ ctan |=(p=@ (div (csin p) (ccos p))) + :: +cpow: [@cq @cq] -> @cq + :: + :: Complex power z^w = exp(w * ln z) (principal branch). + :: Source + ++ cpow |=([p=@ q=@] (cexp (mul q (clog p)))) -- -- diff --git a/libmath/desk/tests/lib/complex-edge.hoon b/libmath/desk/tests/lib/complex-edge.hoon new file mode 100644 index 0000000..b8b9e94 --- /dev/null +++ b/libmath/desk/tests/lib/complex-edge.hoon @@ -0,0 +1,99 @@ +:: /tests/lib/complex-edge -- %cplx transcendental edge cases (@cs). +:: +:: Exercises the origin, the real and imaginary axes, the csqrt/clog branch cut +:: (-1, +-i), the csqrt sign branch, the clog(0) singularity, and the naive- +:: series breakdown at large arguments. All values validated against numpy +:: complex64. +:: +/+ *test, complex +|% +++ s cs:complex +++ z00 `@`0x0 :: 0+0i +++ z10 `@`0x3f80.0000 :: 1+0i +++ zt0 `@`0x4120.0000 :: 10+0i +++ z0i `@`0x3f80.0000.0000.0000 :: 0+1i +++ z0n `@`0xbf80.0000.0000.0000 :: 0-1i +++ zn1 `@`0xbf80.0000 :: -1+0i +++ z11 `@`0x3f80.0000.3f80.0000 :: 1+1i +++ z34 `@`0x4080.0000.4040.0000 :: 3+4i +++ z0t `@`0x4120.0000.0000.0000 :: 0+10i +:: cexp: origin -> 1, real axis (e, 1/e), imaginary axis (cos1 + i sin1), off-axis. +++ test-cexp-origin (expect-eq !>(`@`0x3f80.0000) !>((~(cexp s %n) z00))) +++ test-cexp-1 (expect-eq !>(`@`0x402d.f855) !>((~(cexp s %n) z10))) +++ test-cexp-neg1 (expect-eq !>(`@`0x3ebc.5ab0) !>((~(cexp s %n) zn1))) +++ test-cexp-i (expect-eq !>(`@`0x3f57.6aa4.3f0a.5140) !>((~(cexp s %n) z0i))) +++ test-cexp-1p1i (expect-eq !>(`@`0x4012.6408.3fbb.fe2a) !>((~(cexp s %n) z11))) +++ test-cexp-3p4i (expect-eq !>(`@`0xc173.366f.c152.0f81) !>((~(cexp s %n) z34))) +:: clog: the singularity (log 0 = -inf) and the branch cut at -1 (iπ) and +-i. +++ test-clog-zero (expect-eq !>(`@`0xff80.0000) !>((~(clog s %n) z00))) +++ test-clog-neg1 (expect-eq !>(`@`0x4049.0fdb.0000.0000) !>((~(clog s %n) zn1))) +++ test-clog-i (expect-eq !>(`@`0x3fc9.0fdb.0000.0000) !>((~(clog s %n) z0i))) +++ test-clog-neg-i (expect-eq !>(`@`0xbfc9.0fdb.0000.0000) !>((~(clog s %n) z0n))) +:: csqrt: branch cut sqrt(-1) = i, and the sign branch sqrt(-i) = 0.707 - 0.707i. +++ test-csqrt-neg1 (expect-eq !>(`@`0x3f80.0000.0000.0000) !>((~(csqrt s %n) zn1))) +++ test-csqrt-neg-i (expect-eq !>(`@`0xbf35.04f3.3f35.04f3) !>((~(csqrt s %n) z0n))) +:: csin/ccos on the imaginary axis -> real sinh/cosh. +++ test-csin-i (expect-eq !>(`@`0x3f96.6cff.0000.0000) !>((~(csin s %n) z0i))) +++ test-ccos-i (expect-eq !>(`@`0x3fc5.83ab) !>((~(ccos s %n) z0i))) +:: KNOWN LIMITATION: the naive Taylor/AGM series diverges from the true value +:: far from the origin -- exp(10) is ~21991 here vs the true ~22026 (~0.16% +:: low), csin(0+10i) ~ i*10989 vs true ~ i*11013. Locked as regression (NOT as +:: correctness); #18's Chebyshev rewrite would tighten these. +++ test-cexp-large (expect-eq !>(`@`0x46ab.cef6) !>((~(cexp s %n) zt0))) +++ test-csin-large (expect-eq !>(`@`0x462b.b42b.0000.0000) !>((~(csin s %n) z0t))) +:: +:: Same edges across the other widths: @cd (double), @ch (half), @cq (quad). +:: Origin, the csqrt/clog branch cut at -1, the clog(0)=-inf singularity, the +:: csqrt sign branch at -i, and the imaginary axis (csin -> sinh). +++ d cd:complex +++ h ch:complex +++ q cq:complex +++ d00 `@`0x0 +++ dn1 `@`0xbff0.0000.0000.0000 +++ d0i `@`0x3ff0.0000.0000.0000.0000.0000.0000.0000 +++ d0n `@`0xbff0.0000.0000.0000.0000.0000.0000.0000 +++ h00 `@`0x0 +++ hn1 `@`0xbc00 +++ h0i `@`0x3c00.0000 +++ h0n `@`0xbc00.0000 +++ q00 `@`0x0 +++ qn1 `@`0xbfff.0000.0000.0000.0000.0000.0000.0000 +++ test-cd-cexp-origin (expect-eq !>(`@`0x3ff0.0000.0000.0000) !>((~(cexp d %n) d00))) +++ test-cd-csqrt-neg1 (expect-eq !>(`@`0x3ff0.0000.0000.0000.0000.0000.0000.0000) !>((~(csqrt d %n) dn1))) +++ test-cd-clog-neg1 (expect-eq !>(`@`0x4009.21fb.5444.2d11.0000.0000.0000.0000) !>((~(clog d %n) dn1))) +++ test-cd-clog-zero (expect-eq !>(`@`0xfff0.0000.0000.0000) !>((~(clog d %n) d00))) +++ test-cd-csqrt-neg-i (expect-eq !>(`@`0xbfe6.a09e.667f.3bcd.3fe6.a09e.667f.3bcd) !>((~(csqrt d %n) d0n))) +++ test-cd-csin-i (expect-eq !>(`@`0x3ff2.cd9f.c44e.b983.0000.0000.0000.0000) !>((~(csin d %n) d0i))) +++ test-ch-cexp-origin (expect-eq !>(`@`0x3c00) !>((~(cexp h %n) h00))) +++ test-ch-csqrt-neg1 (expect-eq !>(`@`0x3c00.0000) !>((~(csqrt h %n) hn1))) +++ test-ch-clog-zero (expect-eq !>(`@`0xfc00) !>((~(clog h %n) h00))) +++ test-ch-csqrt-neg-i (expect-eq !>(`@`0xb9a8.39a8) !>((~(csqrt h %n) h0n))) +++ test-ch-csin-i (expect-eq !>(`@`0x3cb2.0000) !>((~(csin h %n) h0i))) +++ test-cq-cexp-origin (expect-eq !>(`@`0x3fff.0000.0000.0000.0000.0000.0000.0000) !>((~(cexp q %n) q00))) +++ test-cq-csqrt-neg1 + (expect-eq !>(`@`0x3fff.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000) !>((~(csqrt q %n) qn1))) +++ test-cq-clog-zero (expect-eq !>(`@`0xffff.0000.0000.0000.0000.0000.0000.0000) !>((~(clog q %n) q00))) +:: +:: cpow edge cases (@cs): z^0 = 1, integer powers, the branch sqrt via ^0.5, +:: and the 0^w corner. +++ cs2 `@`0x4000.0000 :: 2+0i +++ csi `@`0x3f80.0000.0000.0000 :: 0+1i +++ csn1 `@`0xbf80.0000 :: -1+0i +++ cwh `@`0x3f00.0000 :: 0.5+0i +++ test-cpow-pow0 (expect-eq !>(`@`0x3f80.0000) !>((~(cpow s %n) cs2 z00))) :: 2^0 = 1 +++ test-cpow-pow2 (expect-eq !>(`@`0x4080.0000) !>((~(cpow s %n) cs2 cs2))) :: 2^2 = 4 +++ test-cpow-i2 (expect-eq !>(`@`0xb182.92c0.bf80.0000) !>((~(cpow s %n) csi cs2))) :: i^2 = -1 (+~0i) +++ test-cpow-neg1-half (expect-eq !>(`@`0x3f7f.ffff.b386.2919) !>((~(cpow s %n) csn1 cwh))) :: (-1)^0.5 = i +:: KNOWN LIMITATION: 0^2 should be 0, but cpow = exp(w*clog z) routes through +:: clog(0)=-inf and exp(-inf) (which the naive series cannot represent), so it +:: yields NaN. Locked as a documented corner, not as correctness. +++ test-cpow-zero-pow2 (expect-eq !>(`@`0x7fc0.0000.7fc0.0000) !>((~(cpow s %n) z00 cs2))) +:: +:: Rounding modes propagate through the complex ops: cexp(1+2i) gives four +:: distinct bit patterns under %n / %u / %d / %z. +++ z12 `@`0x4000.0000.3f80.0000 :: 1+2i +++ test-cexp-rnd-n (expect-eq !>(`@`0x401e.30c5.bf90.cb4e) !>((~(cexp s %n) z12))) +++ test-cexp-rnd-u (expect-eq !>(`@`0x401e.30d9.bf90.cb53) !>((~(cexp s %u) z12))) +++ test-cexp-rnd-d (expect-eq !>(`@`0x401e.30bd.bf90.cb53) !>((~(cexp s %d) z12))) +++ test-cexp-rnd-z (expect-eq !>(`@`0x401e.30bd.bf90.cb46) !>((~(cexp s %z) z12))) +-- diff --git a/libmath/desk/tests/lib/complex-fns.hoon b/libmath/desk/tests/lib/complex-fns.hoon new file mode 100644 index 0000000..024b395 --- /dev/null +++ b/libmath/desk/tests/lib/complex-fns.hoon @@ -0,0 +1,35 @@ +:: /tests/lib/complex-fns -- complex elementary functions. +:: +:: Expected values are the lib's own self-contained series outputs, validated +:: against numpy (complex64 / complex128) to display precision, e.g. +:: cexp(1+2i) = -1.1312 + 2.4717i, clog = 0.8047 + 1.1071i, csqrt = 1.2720 + +:: 0.7862i, csin = 3.1658 + 1.9596i, ccos = 2.0327 - 3.0519i, ctan = 0.0338 + +:: 1.0148i, (1+2i)^2 = -3 + 4i. Inputs: z = 1+2i at each width. +:: +/+ *test, complex +|% +++ s cs:complex +++ d cd:complex +++ h ch:complex +++ q cq:complex +++ zs `@`0x4000.0000.3f80.0000 +++ zd `@`0x4000.0000.0000.0000.3ff0.0000.0000.0000 +++ zh `@`0x4000.3c00 +++ zq `@`0x4000.0000.0000.0000.0000.0000.0000.0000.3fff.0000.0000.0000.0000.0000.0000.0000 +:: @cs (single): the full set; cpow uses w = 2+0i, so (1+2i)^2 = -3+4i. +++ test-cs-cexp (expect-eq !>(`@`0x401e.30c5.bf90.cb4e) !>((~(cexp s %n) zs))) +++ test-cs-clog (expect-eq !>(`@`0x3f8d.b70a.3f4e.0210) !>((~(clog s %n) zs))) +++ test-cs-csqrt (expect-eq !>(`@`0x3f49.4138.3fa2.d18a) !>((~(csqrt s %n) zs))) +++ test-cs-csin (expect-eq !>(`@`0x3ffa.d435.404a.9c1e) !>((~(csin s %n) zs))) +++ test-cs-ccos (expect-eq !>(`@`0xc043.524b.4002.1823) !>((~(ccos s %n) zs))) +++ test-cs-ctan (expect-eq !>(`@`0x3f81.e4c1.3d0a.7f5c) !>((~(ctan s %n) zs))) +++ test-cs-cpow (expect-eq !>(`@`0x4080.0004.c03f.fff5) !>((~(cpow s %n) zs `@`0x4000.0000))) +:: @cd (double): exp/log/sqrt -- matches numpy complex128 to ~15 digits. +++ test-cd-cexp (expect-eq !>(`@`0x4003.c618.a227.4afe.bff2.1969.c495.3cd3) !>((~(cexp d %n) zd))) +++ test-cd-clog (expect-eq !>(`@`0x3ff1.b6e1.92eb.be45.3fe9.c041.f7ed.8d33) !>((~(clog d %n) zd))) +++ test-cd-csqrt (expect-eq !>(`@`0x3fe9.2826.ef25.8d1b.3ff4.5a31.46a8.8456) !>((~(csqrt d %n) zd))) +:: @ch (half) + @cq (quad): cexp spot check across the remaining widths. +++ test-ch-cexp (expect-eq !>(`@`0x40f1.bc86) !>((~(cexp h %n) zh))) +++ test-cq-cexp + (expect-eq !>(`@`0x4000.3c61.8a22.74af.d5ad.4589.2de9.748d.bfff.2196.9c49.53cd.175c.75fb.0c1e.697d) !>((~(cexp q %n) zq))) +-- diff --git a/libmath/desk/tests/lib/unum-edge.hoon b/libmath/desk/tests/lib/unum-edge.hoon new file mode 100644 index 0000000..92729e7 --- /dev/null +++ b/libmath/desk/tests/lib/unum-edge.hoon @@ -0,0 +1,59 @@ +:: /tests/lib/unum-edge -- posit (%unum) transcendental edge cases. +:: +:: Exact identities, sign, NaR propagation, domain -> NaR, and the naive-series +:: breakdown / saturation at large arguments. Mostly at posit32 (rps), with a +:: posit8 (rpb) cross-width spot. Posits round-to-nearest-even, so there is no +:: rounding-mode variation to sweep. +:: +/+ *test, unum +|% +++ u rps:unum +++ b rpb:unum +++ nar `@`0x8000.0000 +++ s1 (sun:rps:unum 1) +++ s4 (sun:rps:unum 4) +++ s5 (sun:rps:unum 5) +++ sa (sun:rps:unum 10) +++ sb (sun:rps:unum 50) +++ sc (sun:rps:unum 100) +++ n1 (neg:rps:unum (sun:rps:unum 1)) +:: exact identities (correctly rounded; series accurate near 0) +++ test-exp0 (expect-eq !>(`@`0x4000.0000) !>((exp:u 0x0))) :: exp 0 = 1 +++ test-cos0 (expect-eq !>(`@`0x4000.0000) !>((cos:u 0x0))) :: cos 0 = 1 +++ test-sin0 (expect-eq !>(`@`0x0) !>((sin:u 0x0))) :: sin 0 = 0 +++ test-tan0 (expect-eq !>(`@`0x0) !>((tan:u 0x0))) +++ test-log1 (expect-eq !>(`@`0x0) !>((log:u s1))) :: log 1 = 0 +++ test-sqt0 (expect-eq !>(`@`0x0) !>((sqt:u 0x0))) +++ test-sqt1 (expect-eq !>(`@`0x4000.0000) !>((sqt:u s1))) +++ test-sqt4 (expect-eq !>(`@`0x4800.0000) !>((sqt:u s4))) :: sqrt 4 = 2 +++ test-fact0 (expect-eq !>(`@`0x4000.0000) !>((factorial:u 0x0))) :: 0! = 1 +++ test-fact5 (expect-eq !>(`@`0x6b80.0000) !>((factorial:u s5))) :: 5! = 120 +++ test-atan0 (expect-eq !>(`@`0x0) !>((atan:u 0x0))) +++ test-asin0 (expect-eq !>(`@`0x0) !>((asin:u 0x0))) +++ test-acos1 (expect-eq !>(`@`0x0) !>((acos:u s1))) :: acos 1 = 0 +:: sign +++ test-exp-n1 (expect-eq !>(`@`0x33c5.ab1c) !>((exp:u n1))) :: 1/e +++ test-atan-n1 (expect-eq !>(`@`0xc36f.0255) !>((atan:u n1))) :: -pi/4 (atan is odd) +:: NaR propagation +++ test-exp-nar (expect-eq !>(`@`0x8000.0000) !>((exp:u nar))) +++ test-sin-nar (expect-eq !>(`@`0x8000.0000) !>((sin:u nar))) +++ test-sqt-nar (expect-eq !>(`@`0x8000.0000) !>((sqt:u nar))) +++ test-fact-nar (expect-eq !>(`@`0x8000.0000) !>((factorial:u nar))) +:: domain -> NaR +++ test-sqt-neg (expect-eq !>(`@`0x8000.0000) !>((sqt:u n1))) :: sqrt(-1) = NaR +:: posit8 cross-width spot: identity + NaR propagation (-1 @rpb = 0xc0) +++ test-rpb-exp0 (expect-eq !>(`@`0x40) !>((exp:b 0x0))) :: exp 0 = 1 +++ test-rpb-exp-nar (expect-eq !>(`@`0x80) !>((exp:b 0x80))) +++ test-rpb-sqt-neg (expect-eq !>(`@`0x80) !>((sqt:b 0xc0))) :: sqrt(-1) = NaR +:: KNOWN LIMITATION: the naive Taylor series diverges far from the origin. +:: exp(10) ~ 21991 vs true 22026; exp(50)/exp(100) saturate near maxpos rather +:: than tracking the true value; sin(10) blows up to a huge magnitude instead +:: of staying in [-1, 1] (no range reduction). log (atanh form) holds up +:: better -- log(100) ~ 4.605. Locked as regression, NOT correctness; #18's +:: Chebyshev rewrite (range reduction) would fix these. +++ test-exp10 (expect-eq !>(`@`0x7a57.9ded) !>((exp:u sa))) +++ test-exp50 (expect-eq !>(`@`0x7ffe.1b02) !>((exp:u sb))) +++ test-exp100 (expect-eq !>(`@`0x7fff.f02b) !>((exp:u sc))) +++ test-sin10 (expect-eq !>(`@`0xc74b.a64a) !>((sin:u sa))) +++ test-log100 (expect-eq !>(`@`0x50e9.b7f7) !>((log:u sc))) +-- diff --git a/saloon/desk/lib/saloon.hoon b/saloon/desk/lib/saloon.hoon index dc4d5f9..cc755cb 100644 --- a/saloon/desk/lib/saloon.hoon +++ b/saloon/desk/lib/saloon.hoon @@ -405,6 +405,16 @@ %4 ?-(fun %neg neg:rph:unum, %factorial factorial:rph:unum, %exp exp:rph:unum, %sin sin:rph:unum, %cos cos:rph:unum, %tan tan:rph:unum, %log log:rph:unum, %log-10 log-10:rph:unum, %log-2 log-2:rph:unum, %sqrt sqt:rph:unum, %cbrt cbrt:rph:unum) %3 ?-(fun %neg neg:rpb:unum, %factorial factorial:rpb:unum, %exp exp:rpb:unum, %sin sin:rpb:unum, %cos cos:rpb:unum, %tan tan:rpb:unum, %log log:rpb:unum, %log-10 log-10:rpb:unum, %log-2 log-2:rpb:unum, %sqrt sqt:rpb:unum, %cbrt cbrt:rpb:unum) == + :: + :: complex (/lib/complex): bloq 5/6/7/8 = ch/cs/cd/cq. Real-only / ordered + :: functions (factorial, log-10, log-2, cbrt) are undefined on complex. + %cplx + ?+ bloq !! + %8 ?-(fun %neg ~(neg cq:complex rnd), %exp ~(cexp cq:complex rnd), %sin ~(csin cq:complex rnd), %cos ~(ccos cq:complex rnd), %tan ~(ctan cq:complex rnd), %log ~(clog cq:complex rnd), %sqrt ~(csqrt cq:complex rnd), %factorial |=(@ !!), %log-10 |=(@ !!), %log-2 |=(@ !!), %cbrt |=(@ !!)) + %7 ?-(fun %neg ~(neg cd:complex rnd), %exp ~(cexp cd:complex rnd), %sin ~(csin cd:complex rnd), %cos ~(ccos cd:complex rnd), %tan ~(ctan cd:complex rnd), %log ~(clog cd:complex rnd), %sqrt ~(csqrt cd:complex rnd), %factorial |=(@ !!), %log-10 |=(@ !!), %log-2 |=(@ !!), %cbrt |=(@ !!)) + %6 ?-(fun %neg ~(neg cs:complex rnd), %exp ~(cexp cs:complex rnd), %sin ~(csin cs:complex rnd), %cos ~(ccos cs:complex rnd), %tan ~(ctan cs:complex rnd), %log ~(clog cs:complex rnd), %sqrt ~(csqrt cs:complex rnd), %factorial |=(@ !!), %log-10 |=(@ !!), %log-2 |=(@ !!), %cbrt |=(@ !!)) + %5 ?-(fun %neg ~(neg ch:complex rnd), %exp ~(cexp ch:complex rnd), %sin ~(csin ch:complex rnd), %cos ~(ccos ch:complex rnd), %tan ~(ctan ch:complex rnd), %log ~(clog ch:complex rnd), %sqrt ~(csqrt ch:complex rnd), %factorial |=(@ !!), %log-10 |=(@ !!), %log-2 |=(@ !!), %cbrt |=(@ !!)) + == == :: kind :: +$ binary-ops $? %pow-n @@ -453,6 +463,14 @@ %4 ?-(fun %pow-n pow-n:rph:unum, %pow pow:rph:unum) %3 ?-(fun %pow-n pow-n:rpb:unum, %pow pow:rpb:unum) == + :: complex: z^w via +cpow (both rays complex); integer +pow-n undefined. + %cplx + ?+ bloq.meta !! + %8 ?-(fun %pow ~(cpow cq:complex rnd), %pow-n |=([@ @] !!)) + %7 ?-(fun %pow ~(cpow cd:complex rnd), %pow-n |=([@ @] !!)) + %6 ?-(fun %pow ~(cpow cs:complex rnd), %pow-n |=([@ @] !!)) + %5 ?-(fun %pow ~(cpow ch:complex rnd), %pow-n |=([@ @] !!)) + == == :: kind :: +| %linalg diff --git a/saloon/desk/tests/lib/saloon-cplx.hoon b/saloon/desk/tests/lib/saloon-cplx.hoon new file mode 100644 index 0000000..4def9fa --- /dev/null +++ b/saloon/desk/tests/lib/saloon-cplx.hoon @@ -0,0 +1,27 @@ +:: Saloon Tier-B transcendentals over %cplx (complex) rays. Verifies the +:: trans-scalar/fun-scalar %cplx dispatch reaches /lib/complex per width. +:: Expected values are the same series outputs checked in /tests/lib/complex-fns +:: (validated vs numpy). Inputs: z = 1+2i at @cs (bloq 6) and @ch (bloq 5). +:: +/- ls=lagoon +/+ *test, *saloon, *lagoon +|% +:: a 1-element %cplx ray at bloq .b holding packed complex pattern .p +++ ur |=([b=@ p=@] ^-(ray:ls (en-ray:(lake %n) [[~[1] b %cplx ~] ~[p]]))) +++ hd |=(a=ray:ls ^-(@ -:(ravel:(lake %n) a))) +++ sad (sake %n .1e-5) :: %n rounding (bare +sa default rnd is not %n) +++ z6 `@`0x4000.0000.3f80.0000 :: 1+2i @cs +++ w26 `@`0x4000.0000 :: 2+0i @cs +++ z5 `@`0x4000.3c00 :: 1+2i @ch +++ test-cplx-exp-cs (expect-eq !>(`@`0x401e.30c5.bf90.cb4e) !>((hd (exp:sad (ur 6 z6))))) +++ test-cplx-log-cs (expect-eq !>(`@`0x3f8d.b70a.3f4e.0210) !>((hd (log:sad (ur 6 z6))))) +++ test-cplx-sqrt-cs (expect-eq !>(`@`0x3f49.4138.3fa2.d18a) !>((hd (sqrt:sad (ur 6 z6))))) +++ test-cplx-sin-cs (expect-eq !>(`@`0x3ffa.d435.404a.9c1e) !>((hd (sin:sad (ur 6 z6))))) +++ test-cplx-cos-cs (expect-eq !>(`@`0xc043.524b.4002.1823) !>((hd (cos:sad (ur 6 z6))))) +++ test-cplx-tan-cs (expect-eq !>(`@`0x3f81.e4c1.3d0a.7f5c) !>((hd (tan:sad (ur 6 z6))))) +++ test-cplx-pow-cs (expect-eq !>(`@`0x4080.0004.c03f.fff5) !>((hd (pow:sad (ur 6 z6) (ur 6 w26))))) +++ test-cplx-exp-ch (expect-eq !>(`@`0x40f1.bc86) !>((hd (exp:sad (ur 5 z5))))) +:: real-only / ordered functions are undefined on complex -> crash. +++ test-cplx-factorial-crashes (expect-fail |.((factorial:sad (ur 6 z6)))) +++ test-cplx-cbrt-crashes (expect-fail |.((cbrt:sad (ur 6 z6)))) +--