shift/count_bits
Definition: | object res = shift_bits(object n, integer shift_distance) |
Description: |
Moves the bits in the input value by the specified distance.
n: The value(s) whose bits will be be moved. shift_distance: number of bits to be moved by. Returns: atom(s) containing a 32-bit integer. A single atom in n yields a single atom result, otherwise the result is a sequence with the same shape as n, consisting of 32-bit integers. Note the builtin << and >> operators are nothing to do with this routine, more strictly atom-only, implemented as lhs*power(2,rhs) and floor(lhs/power(2,rhs)) respectively, don’t impose any 32-bit limits, and inlined for efficiency. By inlined I just mean the front-end emits the exact same IL it would were the longhand versions found in the source code. |
pwa/p2js: | Supported. |
Comments: |
If n is a sequence, each element is shifted. The value(s) in n are first truncated to a 32-bit integer. The output is truncated to a 32-bit integer. Vacated bits are replaced with zero. If shift_distance is negative, the bits in n are moved left. If shift_distance is positive, the bits in n are moved right. If shift_distance is zero, the bits in n are not moved. |
Auxillary functions: |
object result = count_bits(object n[, integer nFrame=2]) A simple implementation of Kernigans bit counter, eg count_bits(0b00100001) returns 2, with just the two iterations of the loop, although while n exceeds the limits of a native integer/and_bits() it resorts to a slightly slower single-bit test/shift method, which it also does when presented with any fractional values (for example 1/256 has a bit count of exactly 1). The nFrame parameter is intended for internal/recursive use, on sequences and eg 256.00390625, and should be ignored. As per shift_bits, a single atom yields an integer result, otherwise the result is a sequence with the same shape as n, consisting of small integers (0..53/63). Note that the checking to ensure the parameter(s) have not exceeded native 53/63 bit precision limits, which w/could of course make the results pretty much meaningless, may yet need some further improvement. See also mpz_popcount(), which has no such limits and quite effectively disuades me from wanting to try anything clever with negative parameter(s), other than deliberately crash. As far as I am aware there is no such function as mpfr_popcount(), though you might be able to do something with an mpq of 1/256 (etc), that is by using mpz_popcount on the numerator and denominator, not that I’ve tried. Lastly note that count_bits() specifically returns -1 for [-]inf/nan. |
Example: |
?shift_bits(7,-3) --==> 56 (==7*8) ?shift_bits(0,-9) --==> 0 ?shift_bits(4,-7) --==> 512 (==4*128) ?shift_bits(8,-4) --==> 128 (==8*16) ?shift_bits(0xFE427AAC,-7) --==> 557667840 (==0x213D5600) ?shift_bits(0xFE427AAC,-8) --==> 1115335680 (==#427AAC00) ?shift_bits(-7,-3) --==> -56 (==0xFFFFFFC8) ?shift_bits(131,0) --==> 131 ?shift_bits(184.464,0) --==> 184 ?shift_bits(999_999_999_999_999,0) --==> -1530494977 (==0xA4C67FFF) ?shift_bits(184,3) --==> 23 (==184/8) ?shift_bits(48,2) --==> 12 (==48/4) ?shift_bits(121,3) --==> 15 (==floor(121/8)) ?shift_bits(0xFE427AAC, 7) --==> 33326325 (==0x01FC84F5) ?shift_bits(-7,3) --==> 536870911 (==0x1FFFFFFF) ?shift_bits({48,121},2) --==> {12,30} |
Implementation: | See builtins\shift_bits.e (an autoinclude) for details of the actual implementation. |