# 3a: signed and modular ints ### `++fe` :: modulo bloq Modulo bloq Core containing XX Accepts ------- `a` is a `++bloq`. Source ------ |_ a=bloq ### `++dif` Produces the difference between two atoms in the modular basis representation. Accepts ------- `a` is a `++bloq`. `b` is an atom. `c` is an atom. Produces -------- A `@s` Source ------ ++ dif |=([b/@ c/@] (sit (sub (add out (sit b)) (sit c)))) Examples -------- > (~(dif fe 3) 63 64) 255 > (~(dif fe 3) 5 10) 251 > (~(dif fe 3) 0 1) 255 > (~(dif fe 0) 9 10) 1 > (~(dif fe 0) 9 11) 0 > (~(dif fe 0) 9 12) 1 > (~(dif fe 2) 9 12) 13 > (~(dif fe 2) 63 64) 15 ------------------------------------------------------------------------ ### `++inv` Invert mod field Inverts the order of the modular field. Accepts ------- `b` is a `++bloq`. Produces -------- An atom. Source ------ ++ inv |=(b/@ (sub (dec out) (sit b))) Examples -------- > (~(inv fe 3) 255) 0 > (~(inv fe 3) 256) 255 > (~(inv fe 3) 0) 255 > (~(inv fe 3) 1) 254 > (~(inv fe 3) 2) 253 > (~(inv fe 3) 55) 200 ------------------------------------------------------------------------ ### `++net` Reverse bytes Revereses bytes within block. Accepts ------- `b` is a `++bloq`. Produces -------- An atom. Source ------ ++ net |= b/@ ^- @ => .(b (sit b)) ?: (lte a 3) b =+ c=(dec a) %+ con (lsh c 1 $(a c, b (cut c [0 1] b))) $(a c, b (cut c [1 1] b)) Examples -------- > (~(net fe 3) 64) 64 > (~(net fe 3) 128) 128 > (~(net fe 3) 255) 255 > (~(net fe 3) 256) 0 > (~(net fe 3) 257) 1 > (~(net fe 3) 500) 244 > (~(net fe 3) 511) 255 > (~(net fe 3) 512) 0 > (~(net fe 3) 513) 1 > (~(net fe 3) 0) 0 > (~(net fe 3) 1) 1 > (~(net fe 0) 1) 1 > (~(net fe 0) 2) 0 > (~(net fe 0) 3) 1 > (~(net fe 6) 1) 72.057.594.037.927.936 > (~(net fe 6) 2) 144.115.188.075.855.872 > (~(net fe 6) 3) 216.172.782.113.783.808 > (~(net fe 6) 4) 288.230.376.151.711.744 > (~(net fe 6) 5) 360.287.970.189.639.680 > (~(net fe 6) 6) 432.345.564.227.567.616 > (~(net fe 6) 7) 504.403.158.265.495.552 > (~(net fe 6) 512) 562.949.953.421.312 > (~(net fe 6) 513) 72.620.543.991.349.248 ------------------------------------------------------------------------ ### `++out` Max integer value The maximum integer value that the current block can store. Accepts ------- A `++bloq`. Produces -------- An atom. Source ------ ++ out (bex (bex a)) Examples -------- > ~(out fe 0) 2 > ~(out fe 1) 4 > ~(out fe 2) 16 > ~(out fe 3) 256 > ~(out fe 4) 65.536 > ~(out fe 10) \/179.769.313.486.231.590.772.930.519.078.902.473.361.797.697.894.230.657.\/ 273.430.081.157.732.675.805.500.963.132.708.477.322.407.536.021.120.113. 879.871.393.357.658.789.768.814.416.622.492.847.430.639.474.124.377.767. 893.424.865.485.276.302.219.601.246.094.119.453.082.952.085.005.768.838. 150.682.342.462.881.473.913.110.540.827.237.163.350.510.684.586.298.239. 947.245.938.479.716.304.835.356.329.624.224.137.216 \/ \/ ------------------------------------------------------------------------ ### `++rol` Roll left Roll `d` to the left by `c` `b`-sized blocks. Accepts ------- `a` is a `++bloq`. `b` is a `++bloq`. `c` is an atom. `d` is an atom. Produces -------- An atom. Source ------ ++ rol |= [b/bloq c/@ d/@] ^- @ :: roll left =+ e=(sit d) =+ f=(bex (sub a b)) =+ g=(mod c f) (sit (con (lsh b g e) (rsh b (sub f g) e))) Examples -------- > `@ux`(~(rol fe 6) 4 3 0xabac.dedf.1213) 0x1213.0000.abac.dedf > `@ux`(~(rol fe 6) 4 2 0xabac.dedf.1213) 0xdedf.1213.0000.abac > `@t`(~(rol fe 5) 3 1 'dfgh') 'hdfg' > `@t`(~(rol fe 5) 3 2 'dfgh') 'ghdf' > `@t`(~(rol fe 5) 3 0 'dfgh') 'dfgh' ------------------------------------------------------------------------ ### `++ror` Roll right Roll `d` to the right by `c` `b`-sized blocks. Accepts ------- `a` is a `++bloq`. `b` is a `++bloq`. `c` is an atom. `d` is an atom. Produces -------- An atom. Source ------ ++ ror |= {b/bloq c/@ d/@} ^- @ :: roll right =+ e=(sit d) =+ f=(bex (sub a b)) =+ g=(mod c f) (sit (con (rsh b g e) (lsh b (sub f g) e))) Examples -------- > `@ux`(~(ror fe 6) 4 1 0xabac.dedf.1213) 0x1213.0000.abac.dedf > `@ux`(~(ror fe 6) 3 5 0xabac.dedf.1213) 0xacde.df12.1300.00ab > `@ux`(~(ror fe 6) 3 3 0xabac.dedf.1213) 0xdf12.1300.00ab.acde > `@t`(~(rol fe 5) 3 0 'hijk') 'hijk' > `@t`(~(rol fe 5) 3 1 'hijk') 'khij' > `@t`(~(rol fe 5) 3 2 'hijk') 'jkhi' ------------------------------------------------------------------------ ### `++sum` Sum Sum two numbers in this modular field. Accepts ------- `a` is a `++bloq`. `b` is an atom. `c` is an atom. Produces -------- An atom. Source ------ ++ sum |=([b/@ c/@] (sit (add b c))) :: wrapping add Examples -------- > (~(sum fe 3) 10 250) 4 > (~(sum fe 0) 0 1) 1 > (~(sum fe 0) 0 2) 0 > (~(sum fe 2) 14 2) 0 > (~(sum fe 2) 14 3) 1 > (~(sum fe 4) 10.000 256) 10.256 > (~(sum fe 4) 10.000 100.000) 44.464 ### `++sit` Atom in mod block representation Produce an atom in the current modular block representation. Accepts ------- `a` is a `++bloq`. `b` is an atom. Produces -------- An atom. Source ------ ++ sit |=(b/@ (end a 1 b)) :: enforce modulo Examples -------- > (~(sit fe 3) 255) 255 > (~(sit fe 3) 256) 0 > (~(sit fe 3) 257) 1 > (~(sit fe 2) 257) 1 > (~(sit fe 2) 10.000) 0 > (~(sit fe 2) 100) 4 > (~(sit fe 2) 19) 3 > (~(sit fe 2) 17) 1 > (~(sit fe 0) 17) 1 > (~(sit fe 0) 0) 0 > (~(sit fe 0) 1) 1 *** ### `++si` ++ si !: :: signed integer |% Container core for the signed integer functions. ------------------------------------------------------------------------ ### `++abs` Absolute value Produces the absolute value of a signed integer. Accepts ------- `a` is a signed integer, `@s`. Produces -------- An atom. Source ------ ++ abs |=(a/@s (add (end 0 1 a) (rsh 0 1 a))) :: absolute value Examples -------- > (abs:si -2) 2 > (abs:si -10.000) 10.000 > (abs:si --2) 2 ------------------------------------------------------------------------ ### `++dif` Difference Produces the difference between two signed integers `b` and `c`. Accepts ------- `a` is a signed integer, `@s`. `b` is a signed integer, `@s`. Produces -------- A `@s`. Source ------ ++ dif |= [a/@s b/@s] :: subtraction (sum a (new !(syn b) (abs b))) Examples -------- > (dif:si --10 -7) --17 > (dif:si --10 --7) --3 > (dif:si `@s`0 --7) -7 > (dif:si `@s`0 `@s`7) --4 ------------------------------------------------------------------------ ### `++dul` Modulus Produces the modulus of two signed integers. Accepts ------- `a` is a signed integer, `@s`. `b` is an atom. Produces -------- An atom. Source ------ ++ dul |= [a/@s b/@] :: modulus =+(c=(old a) ?:(-.c (mod +.c b) (sub b +.c))) Examples -------- > (dul:si --9 3) 0 > (dul:si --9 4) 1 > (dul:si --9 5) 4 > (dul:si --9 6) 3 > (dul:si --90 --10) 10 ------------------------------------------------------------------------ ### `++fra` Divide Produces the quotient of two signed integers. Accepts ------- `a` is a signed integer, `@s`. `b` is a signed integer, `@s`. Produces -------- An atom. Source ------ ++ fra |= [a/@s b/@s] :: divide (new =(0 (mix (syn a) (syn b))) (div (abs a) (abs b))) Examples -------- > (fra:si --10 -2) -5 > (fra:si -20 -5) --4 ------------------------------------------------------------------------ ### `++new` Signed integer Produces a signed integer from a loobean sign value `a` and an atom `b`. Accepts ------- `a` is a loobean. `b` is an atom. Produces -------- A `@s` Source ------ ++ new |= [a/? b/@] :: [sign value] to @s `@s`?:(a (mul 2 b) ?:(=(0 b) 0 +((mul 2 (dec b))))) Examples -------- > (new:si [& 10]) --10 > (new:si [| 10]) -10 > (new:si [%.y 7]) --7 ------------------------------------------------------------------------ ### `++old` sign value Produces the cell `[sign value]` representations of a signed integer. Accepts ------- `a` is a `@s`. Produces -------- A cell of a boolean and an atom. Source ------ ++ old |=(a/@s [(syn a) (abs a)]) :: [sign value] Examples -------- > (old:si 7) ! type-fail ! exit > (old:si -7) [%.n 7] > (old:si --7) [%.y 7] > (old:si `@s`7) [%.n 4] > (old:si -0) [%.y 0] ------------------------------------------------------------------------ ### `++pro` Multiply Produces the product of two signed integers. Accepts ------- `a` is a `@s`. `b` is a `@s`. Produces -------- A `@s`. Source ------ ++ pro |= [a/@s b/@s] :: multiplication (new =(0 (mix (syn a) (syn b))) (mul (abs a) (abs b))) Examples -------- > (pro:si -4 --2) -8 > (pro:si -4 -2) --8 > (pro:si --10.000.000 -10) -100.000.000 > (pro:si -1.337 --0) --0 ------------------------------------------------------------------------ ### `++rem` Remainder Produces the remainder from a division of two signed integers. Accepts ------- `a` is a `@s`. `b` is a `@s`. Produces -------- A `@sd`. Source ------ ++ rem |=([a/@s b/@s] (dif a (pro b (fra a b)))) :: remainder Examples -------- > (rem:si -10 -4) -2 > (rem:si --10 --4) --2 > (rem:si --10 -4) --2 > (rem:si --7 --3) --1 > (rem:si --0 --10.000) --0 ------------------------------------------------------------------------ ### `++sum` Add Sum two signed integers. Accepts ------- `b` is a `@s`. `c` is a signed integer `@s`. Produces -------- A `@s`. Source ------ ++ sum |= [a/@s b/@s] :: addition ~| %si-sum =+ [c=(old a) d=(old b)] ?: -.c ?: -.d (new & (add +.c +.d)) ?: (gte +.c +.d) (new & (sub +.c +.d)) (new | (sub +.d +.c)) ?: -.d ?: (gte +.c +.d) (new | (sub +.c +.d)) (new & (sub +.d +.c)) (new | (add +.c +.d)) Examples -------- > (sum:si --10 --10) --20 > (sum:si --10 -0) --10 > (sum:si -10 -7) -17 > (sum:si -10 --7) -3 ------------------------------------------------------------------------ ### `++sun` Signed from unsigned Produces a signed integer from an unsigned integer. Note that the result must be manually cast to some `@s` odor to be inferred as an unsigned integer in the type system. Accepts ------- `a` is a `@u`. Produces -------- A `@s`. Source ------ ++ sun |=(a/@u (mul 2 a)) :: @u to @s Examples -------- > `@s`10 --5 > (sun:si 10) 20 > `@s`(sun:si 10) --10 > `@sd`(sun:si 10) --10 > `@sd`(sun:si 12.345) --12.345 ------------------------------------------------------------------------ ### `++syn` Sign Produce the sign of a signed integer, where `&` is posiitve, and `|` is negative. Accepts ------- `a` is a `@s`. Produces -------- A boolean. Source ------ ++ syn |=(a/@s =(0 (end 0 1 a))) :: sign test Examples -------- > (syn:si -2) %.n > (syn:si --2) %.y > (syn:si -0) %.y ------------------------------------------------------------------------ ### `++cmp` Compare Compare two signed integers. Accepts ------- `b` is a `@s`. `c` is a `@s`. Produces -------- A `@s`. Source ------ ++ cmp |= [a/@s b/@s] :: compare ^- @s ?: =(a b) --0 ?: (syn a) ?: (syn b) ?: (gth a b) --1 -1 --1 ?: (syn b) -1 ?: (gth a b) -1 --1 Examples -------- > (cmp:si --10 --10) --0 > (cmp:si --10 -0) --1 > (cmp:si -10 -7) -1 > (cmp:si -10 --7) -1 *** ### `++egcd` GCD ++ egcd !: :: schneier's egcd |= {a/@ b/@} =+ si =+ [c=(sun a) d=(sun b)] =+ [u=[c=(sun 1) d=--0] v=[c=--0 d=(sun 1)]] |- ^- {d/@ u/@s v/@s} ?: =(--0 c) [(abs d) d.u d.v] :: ?> ?& =(c (sum (pro (sun a) c.u) (pro (sun b) c.v))) :: =(d (sum (pro (sun a) d.u) (pro (sun b) d.v))) :: == =+ q=(fra d c) %= $ c (dif d (pro q c)) d c u [(dif d.u (pro q c.u)) c.u] v [(dif d.v (pro q c.v)) c.v] == :: Greatest common denominator > (egcd 20 15) [d=5 u=2 v=1] > (egcd 24 16) [d=8 u=2 v=1] > (egcd 7 5) [d=1 u=3 v=6] > (egcd (shaf ~ %ham) (shaf ~ %sam)) [ d=1 u=59.983.396.314.566.203.239.184.568.129.921.874.787 v=38.716.650.351.034.402.960.165.718.823.532.275.722 ] ***