Expand/Shrink

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.
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.