#################### # helper functions # #################### fn mshift { shift echo $* } fn reverse { switch($#*) { case 1 echo $1 case * echo `{reverse `{mshift $*}} $1 } } fn split { n = $1 shift if(~ $n '') { echo $* | sed 's/(.)/\1 /g' } if not{ echo $* | sed 's/'^$n^'/ /g' } } fn join { echo $* | sed 's/ //g' } fn length { echo $#* } fn pad { } #################### fn and1 { switch($#*) { case 2 if(~ $1 1 && ~ $2 1) { echo 1 } if not{ echo 0 } case 1 echo NaN } } fn and { { switch($#*) { case 2 n = (`{split '' $2}) * = (`{split '' $1}) while(! ~ $#* 0) { echo -n `{and1 $1 $n(1)}^' ' shift n = `{mshift $n} } } }| sed 's/ $//;s/ //g' } fn or1 { switch($#*) { case 2 if(~ $1 0 && ~ $2 0) { echo 0 } if not{ echo 1 } } } fn or { { switch($#*) { case 2 n = (`{split '' $2}) * = (`{split '' $1}) while(! ~ $#* 0) { echo -n `{or1 $1 $n(1)}^' ' shift n = `{mshift $n} } } }| sed 's/ $//;s/ //g' } fn cmp1 { n = '' switch($1) { case 0 switch($2) { case 0 n = 0 case 1 n = 1 } case 1 switch($2) { case 0 n = -1 case 1 n = 0 } case * n = NaN } echo $n } fn cmpb { res = 0 switch($#*) { case 2 one = `{split '' $1} two = `{split '' $2} if(~ $#one $#two) { while(! ~ $#one 0 && ~ $res 0) { res = `{cmp1 $one(1) $two(1)} one = `{mshift $one} two = `{mshift $two} } echo $res } if not { while(! ~ $#one 0 && ! ~ $#two 0) { one = `{mshift $one} two = `{mshift $two} } if(! ~ $#one 0) { echo -1 } if not { echo 1 } } } } fn cmp { switch($#*) { case 2 cmpb `{tobin $1} `{tobin $2} } } fn modtwo1 { switch ($1) { case 2 4 6 8 0 n = 0 case 1 3 5 7 9 n = 1 case * n = NaN } echo $n } fn modtwo-long { n = $* modtwo1 $n($#n) } fn modtwo { modtwo-long `{split '' $1} } fn divtwo1 { switch ($1) { case 0 n = 0 case 1 n = (0 1) case 2 n = 1 case 3 n = (1 1) case 4 n = 2 case 5 n = (2 1) case 6 n = 3 case 7 n = (3 1) case 8 n = 4 case 9 n = (4 1) case 10 n = 5 case 11 n = (5 1) case 12 n = 6 case 13 n = (6 1) case 14 n = 7 case 15 n = (7 1) case 16 n = 8 case 17 n = (8 1) case 18 n = 9 case 19 n = (9 1) } echo $n } fn divtwo-long { switch($#*) { case 1 n = (`{divtwo1 $1}) echo $n(1) case * n = (`{divtwo1 $1}) switch($#n) { case 1 echo $n(1) `{divtwo-long `{mshift $*}} case 2 z = (`{mshift $*}) echo $n(1) `{divtwo-long $n(2)^$z(1) `{mshift $z}} } } } fn divtwo { divtwo-long `{split '' $1} |sed 's/ //g;s/^0+(.+)/\1/' } fn addone1 { switch ($1) { case 0 n = 1 case 1 n = 2 case 2 n = 3 case 3 n = 4 case 4 n = 5 case 5 n = 6 case 6 n = 7 case 7 n = 8 case 8 n = 9 case 9 n = (0 1) case * n = NaN } echo $n } fn addone-long { # big-endian z = `{split '' $1} switch($#*) { case 1 n = (`{addone1 $z}) switch($#n) { case 1 echo $n `{mshift $*} case 2 echo $n(1) $n(2) } case * n = `{addone1 $z} switch($#n) { case 1 echo -n $n(1) `{mshift $*} case 2 nz = `{mshift $*} echo -n $n(1) `{addone-long $nz(1)^$n(2) `{mshift $nz}} } } } fn addone { join `{reverse `{addone-long `{reverse `{split '' $1}}}} } fn multwo1 { switch ($1) { case 0 n = 0 case 1 n = 2 case 2 n = 4 case 3 n = 6 case 4 n = 8 case 5 n = (0 1) case 6 n = (2 1) case 7 n = (4 1) case 8 n = (6 1) case 9 n = (8 1) } if(~ $#* 2) { switch($#n) { case 2 n = (`{addone1 $n(1)} $n(2)) case 1 n = `{addone $n} } } echo $n } fn multwo-long { # big-endian z = `{split '' $1} switch($#*) { case 1 n = `{multwo1 $z} switch($#n) { case 1 echo $n case 2 echo $n(1) $n(2) } case * n = `{multwo1 $z} nn = `{mshift $*} switch($#n) { case 1 echo $n `{multwo-long $nn} case 2 echo $n(1) `{multwo-long $nn(1)^$n(2) `{mshift $nn}} } } } fn multwo { join `{reverse `{multwo-long `{reverse `{split '' $1}}}} } fn tobin-long { n = `{divtwo $1} if(! ~ $n 0) { echo -n `{tobin-long `{divtwo $1}} `{modtwo $1} } if not { modtwo $1 } } fn tobin { join `{tobin-long $1} } fn padb { # pad the first binary number with zeros until # it becomes as long as the second # # user must ensure that the first argument is # numerically less than the second one = `{split '' $1} two = `{split '' $2} while(! ~ $#one $#two) { one = ('0' $one) } echo `{join $one} } fn todec-long { # rear-endian switch ($#*) { case 1 switch($1) { case 1 echo -n 1 case * echo -n NaN # can not end with a zero } case * switch ($1) { case 0 multwo `{todec-long `{mshift $*} } case 1 addone `{multwo `{todec-long `{mshift $*} } } } } } fn todec { switch($1) { case 0 echo 0 case * join `{reverse `{todec-long `{reverse `{split '' $1}}}} } } #################################################### fn andip1 { switch($#*) { case 2 ns = `{tobin $1} nn = `{tobin $2} switch(`{cmpb $nn $ns}) { case -1 ns = `{padb $ns $nn} case 1 nn = `{padb $nn $ns} } r = `{and $ns $nn} todec `{echo $r |sed 's/^0+(.+)$/\1/'} case * echo NaN } } fn andip { { n = (`{split '\.' $2 }) * = (`{split '\.' $1 }) if(~ $#n $#*) { while(! ~ $#* 0) { echo -n `{andip1 $n(1) $1}^' ' shift n = `{mshift $n} } } if not { echo 'number of quads must match' } }| sed 's/ $//;s/ /./g' }