# 2c: bit arithmetic ### `++bex` Binary exponent Computes the result of `2^a`, producing an atom. Accepts ------- `a` is an atom. Produces -------- An atom. Source ------ ++ bex :: binary exponent ~/ %bex |= a/@ ^- @ ?: =(0 a) 1 (mul 2 $(a (dec a))) Examples -------- > (bex 4) 16 > (bex (add 19 1)) 1.048.576 > (bex 0) 1 *** ### `++can` Assemble Produces an atom from a list `b` of length-value pairs `p` and `q`, where `p` is the length in bloqs of size `a`, and `q` is an atomic value. Accepts ------- `a` is a block size (see `++bloq`). `b` is a `++list` of length value pairs, `p` and `q`. Produces -------- An atom. Source ------ ++ can :: assemble ~/ %can |= [a/bloq b/(list [p=@ q=@])] ^- @ ?~ b 0 (mix (end a p.i.b q.i.b) (lsh a p.i.b $(b t.b))) Examples -------- > `@ub`(can 3 ~[[1 1]]) 0b1 > `@ub`(can 0 ~[[1 255]]) 0b1 > `@ux`(can 3 [3 0xc1] [1 0xa] ~) 0xa00.00c1 > `@ux`(can 3 [3 0xc1] [1 0xa] [1 0x23] ~) 0x23.0a00.00c1 > `@ux`(can 4 [3 0xc1] [1 0xa] [1 0x23] ~) 0x23.000a.0000.0000.00c1 > `@ux`(can 3 ~[[1 'a'] [2 'bc']]) 0x63.6261 *** ### `++cat` Concatenate Concatenates two atoms, `b` and `c`, according to bloq size `a`, producing an atom. Accepts ------- `a` is a block size (see `++bloq`). `b` is an atom. `c` is an atom. Produces -------- An atom. Source ------ ++ cat :: concatenate ~/ %cat |= {a/bloq b/@ c/@} (add (lsh a (met a b) c) b) Examples -------- > `@ub`(cat 3 1 0) 0b1 > `@ub`(cat 0 1 1) 0b11 > `@ub`(cat 0 2 1) 0b110 > `@ub`(cat 2 1 1) 0b1.0001 > `@ub`256 0b1.0000.0000 > `@ub`255 0b1111.1111 > `@ub`(cat 3 256 255) 0b1111.1111.0000.0001.0000.0000 > `@ub`(cat 2 256 255) 0b1111.1111.0001.0000.0000 > (cat 3 256 255) 16.711.936 *** ### `++cut` Slice Slices `c` blocks of size `a` that are `b` blocks from the end of `d`. Accepts ------- `a` is a block size (see ++bloq). `b` is an atom. `c` is an atom. Produces -------- An atom. Source ------ ++ cut :: slice ~/ %cut |= {a/bloq {b/@u c/@u} d/@} (end a c (rsh a b d)) Examples -------- > (cut 0 [1 1] 2) 1 > (cut 0 [2 1] 4) 1 > `@t`(cut 3 [0 3] 'abcdefgh') 'abc' > `@t`(cut 3 [1 3] 'abcdefgh') 'bcd' > `@ub`(cut 0 [0 3] 0b1111.0000.1101) 0b101 > `@ub`(cut 0 [0 6] 0b1111.0000.1101) 0b1101 > `@ub`(cut 0 [4 6] 0b1111.0000.1101) 0b11.0000 > `@ub`(cut 0 [3 6] 0b1111.0000.1101) 0b10.0001 *** ### `++end` Tail Produces an atom by taking the last `b` blocks of size `a` from `c`. Accepts ------- `a` is a block size (see `++bloq`). `b` is an atom. `c` is an atom. Produces -------- An atom. Source ------ ++ end :: tail ~/ %end |= {a/bloq b/@u c/@} (mod c (bex (mul (bex a) b))) Examples -------- > `@ub`12 0b1100 > `@ub`(end 0 3 12) 0b100 > (end 0 3 12) 4 > `@ub`(end 1 3 12) 0b1100 > (end 1 3 12) 12 > `@ux`'abc' 0x63.6261 > `@ux`(end 3 2 'abc') 0x6261 > `@t`(end 3 2 'abc') 'ab' *** ### `++fil` Fill bloqstream Produces an atom by repeating `c` for `b` blocks of size `a`. Accepts ------- `a` is a block size (see `++bloq`). `b` is an atom. `c` is an atom. Produces -------- An atom. Source ------ ++ fil :: fill bloqstream |= {a/bloq b/@u c/@} =+ n=0 =+ d=c |- ^- @ ?: =(n b) (rsh a 1 d) $(d (add c (lsh a 1 d)), n +(n)) Examples -------- > `@t`(fil 3 5 %a) 'aaaaa' > `@t`(fil 5 10 %ceeb) 'ceebceebceebceebceebceebceebceebceebceeb' > `@t`(fil 4 10 %eced) 'ʇʇʇʇʇʇʇʇʇʇed' > `@tas`(fil 4 10 %bf) %bfbfbfbfbfbfbfbfbfbf *** ### `++lsh` Left-shift Produces an atom by left-shifting `c` by `b` blocks of size `a`. Accepts ------- `a` is a block size (see `++bloq`). `b` is an atom. `c` is an atom. Produces -------- An atom. Source ------ ++ lsh :: left-shift ~/ %lsh |= {a/bloq b/@u c/@} (mul (bex (mul (bex a) b)) c) Examples -------- > `@ub`1 0b1 > `@ub`(lsh 0 1 1) 0b10 > (lsh 0 1 1) 2 > `@ub`255 0b1111.1111 > `@ub`(lsh 3 1 255) 0b1111.1111.0000.0000 > (lsh 3 1 255) 65.280 *** ### `++met` Measure Computes the number of blocks of size `a` in `b`, producing an atom. `a` is a block size (see `++bloq`). `b` is an atom. Source ------ ++ met :: measure ~/ %met |= {a/bloq b/@} ^- @ =+ c=0 |- ?: =(0 b) c $(b (rsh a 1 b), c +(c)) Examples -------- > (met 0 1) 1 > (met 0 2) 2 > (met 3 255) 1 > (met 3 256) 2 > (met 3 'abcde') 5 *** ### `++rap` Assemble non-zero Concatenates a list of atoms `b` using blocksize `a`, producing an atom. Accepts ------- `a` is a block size (see `++bloq`). `b` is a `++list` of atoms. Produces -------- An atom. Source ------ ++ rap :: assemble nonzero ~/ %rap |= {a/bloq b/(list @)} ^- @ ?~ b 0 (cat a i.b $(b t.b)) Examples -------- > `@ub`(rap 2 (limo [1 2 3 4 ~])) 0b100.0011.0010.0001 > `@ub`(rap 1 (limo [1 2 3 4 ~])) 0b1.0011.1001 > (rap 0 (limo [0 0 0 ~])) 0 > (rap 0 (limo [1 0 1 ~])) 3 *** ### `++rep` Assemble single Produces an atom by assembling a list of atoms `b` using block size `a`. Accepts ------- `a` is a block size (see `++bloq`). `b` is a list of atoms. Produces -------- An atom. Source ------ ++ rep :: assemble single ~/ %rep |= {a/bloq b/(list @)} ^- @ =+ c=0 |- ?~ b 0 (con (lsh a c (end a 1 i.b)) $(c +(c), b t.b)) Examples -------- > `@ub`(rep 2 (limo [1 2 3 4 ~])) 0b100.0011.0010.0001 > (rep 0 (limo [0 0 1 ~])) 4 > (rep 0 (limo [0 0 0 1 ~])) 8 > (rep 0 (limo [0 1 0 0 ~])) 2 > (rep 0 (limo [0 1 0 1 ~])) 10 > (rep 0 (limo [0 1 0 1 0 1 ~])) 42 > `@ub`42 0b10.1010 *** ### `++rip` Disassemble Produces a list of atoms from the bits of `b` using block size `a`. Accepts ------- `a` is a block size (see `++bloq`). `b` is an atom. Produces -------- A list of atoms. Source ------ ++ rip :: disassemble ~/ %rip |= {a/bloq b/@} ^- (list @) ?: =(0 b) ~ [(end a 1 b) $(b (rsh a 1 b))] Examples -------- > `@ub`155 0b1001.1011 > (rip 0 155) ~[1 1 0 1 1 0 0 1] > (rip 2 155) ~[11 9] > (rip 1 155) ~[3 2 1 2] > `@ub`256 0b1.0000.0000 > (rip 0 256) ~[0 0 0 0 0 0 0 0 1] > (rip 2 256) ~[0 0 1] > (rip 3 256) ~[0 1] *** ### `++rsh` Right-shift Right-shifts `c` by `b` blocks of size `a`, producing an atom. Accepts ------- `a` is a block size (see `++bloq`). `b` is an atom. `c` is an atom. Produces -------- An atom. Source ------ ++ rsh :: right-shift ~/ %rsh |= {a/bloq b/@u c/@} (div c (bex (mul (bex a) b))) Examples -------- > `@ub`145 0b1001.0001 > `@ub`(rsh 1 1 145) 0b10.0100 > (rsh 1 1 145) 36 > `@ub`(rsh 2 1 145) 0b1001 > (rsh 2 1 145) 9 > `@ub`10 0b1010 > `@ub`(rsh 0 1 10) 0b101 > (rsh 0 1 10) 5 > `@ux`'abc' 0x63.6261 > `@t`(rsh 3 1 'abc') 'bc' > `@ux`(rsh 3 1 'abc') 0x6362 *** ### `++swp` Reverse block order Switches little endian to big and vice versa: produces an atom by reversing the block order of `b` using block size `a`. Accepts ------- `a` is a block size (see `++bloq`). `b` is an atom. Produces -------- An atom Source ------ ++ swap |=({a/bloq b/@} (rep a (flop (rip a b)))) :: reverse bloq order Examples -------- > `@ub`24 0b1.1000 > (swap 0 24) 3 > `@ub`3 0b11 > (swap 0 0) 0 > (swap 0 128) 1 *** ### `++xeb` Binary logarithm Computes the base-2 logarithm of `a`, producing an atom. Accepts ------- `a` is an atom. Produces -------- An atom. Source ------ ++ xeb :: binary logarithm ~/ %xeb |= a/@ ^- @ (met 0 a) Examples -------- > (xeb 31) 5 > (xeb 32) 6 > (xeb 49) 6 > (xeb 0) 0 > (xeb 1) 1 > (xeb 2) 2 ***