`mailto:srfi-60@srfi.schemers.org`

.
See instructions
here to subscribe to the list. You can access previous messages via the
archive of the mailing list.

- Received: 2005/01/03
- Draft: 2005/01/03 - 2005/03/03

- hashing;
- Galois-field[2] calculations of error-detecting and error-correcting codes;
- cryptography and ciphers;
- pseudo-random number generation;
- register-transfer-level modeling of digital logic designs;
- Fast-Fourier transforms;
- packing and unpacking numbers in persistant data structures;
- space-filling curves with applications to dimension reduction and sparse multi-dimensional database indexes; and
- generating approximate seed values for root-finders and transcendental function algorithms.

The discussions of the withdrawn SRFI-33: "Integer Bitwise-operation Library" seemed to founder on consistency of procedure names and arity; and on perceived competition with the boolean arrays of SRFI-47.

I have implemented both logical number operations and boolean arrays; and have not been conflicted as to their application. I used boolean arrays to construct very fast indexes for database tables having millions of records. To avoid running out of RAM, creation of megabit arrays should be explicit; so the boolean array procedures put their results into a passed array. In contrast, these procedures are purely functional.

In the Bitwise Operations, rather than striving for orthogonal completeness, I have concentrated on a nearly minimal set of bitwise logical functions sufficient to support the uses listed above.

Although any two of `logior`, `logxor`, and
`logand` (in combination with `lognot`) are sufficient
to generate all the two-input logic functions, having these three
means that any nontrivial two-input logical function can be
synthesized using just one of these two-input primaries with zero or
one calls to `lognot`.

`bitwise-if` is what SRFI-33 calls `bitwise-merge`.

The SRFI-33 aliases: `bitwise-ior`, `bitwise-xor`,
`bitwise-and`, `bitwise-not`, and `bit-count` are
also provided.

`log2-binary-factors` is a useful function which is simple but
non-obvious:

(define (log2-binary-factors n) (+ -1 (integer-length (logand n (- n)))))

I have changed to `copy-bit-field` argument order to be
consistent with the other Field of Bits procedures: the
`start` and `end` index arguments are last.
This makes them analogous to the argument order to `substring`
and SRFI-47 arrays, which took their cue from `substring`.

These `start` and `end` index arguments are not
compatible with SRFI-33's `size` and `position`
arguments (occurring first) in its `bit-field` procedures.
Both define `copy-bit-field`; the arguments and purposes being
incompatible.

A procedure in slib/logical.scm, `logical:rotate`, rotated a
given number of low-order bits by a given number of bits. This
function was quite servicable, but I could not name it adequately. I
have replaced it with `rotate-bit-field` with the addition of a
`start` argument. This new function rotates a given field
(from positions `start` to `end`) within an integer;
leaving the rest unchanged.

Another problematic name was `logical:ones`, which generated an
integer with the least significant `k` bits set. Calls to
`bit-field` could have replaced its uses . But the definition
was so short that I just replaced its uses with:

(lognot (ash -1k))

The `bit-reverse` procedure was then the only one which took a
`width` argument. So I replaced it with
`reverse-bit-field`.

The Lamination functions were moved to slib/phil-spc.scm.

__Function:__**logand***n1 ...*__Function:__**bitwise-and***n1 ...*-
Returns the integer which is the bit-wise AND of the integer
arguments.
Example:

(number->string (logand #b1100 #b1010) 2) => "1000"

__Function:__**logior***n1 ...*__Function:__**bitwise-ior***n1 ...*-
Returns the integer which is the bit-wise OR of the integer arguments.
Example:

(number->string (logior #b1100 #b1010) 2) => "1110"

__Function:__**logxor***n1 ...*__Function:__**bitwise-xor***n1 ...*-
Returns the integer which is the bit-wise XOR of the integer
arguments.
Example:

(number->string (logxor #b1100 #b1010) 2) => "110"

__Function:__**lognot***n*__Function:__**bitwise-not***n*-
Returns the integer which is the 2s-complement of the integer argument.
Example:

(number->string (lognot #b10000000) 2) => "-10000001" (number->string (lognot #b0) 2) => "-1"

__Function:__**bitwise-if***mask n0 n1*-
Returns an integer composed of some bits from integer
`n0`and some from integer`n1`. A bit of the result is taken from`n0`if the corresponding bit of integer`mask`is 1 and from`n1`if that bit of`mask`is 0.

__Function:__**logtest***j k*-
(logtest j k) == (not (zero? (logand j k))) (logtest #b0100 #b1011) => #f (logtest #b0100 #b0111) => #t

__Function:__**logcount***n*__Function:__**bit-count***n*-
Returns the number of bits in integer
`n`. If integer is positive, the 1-bits in its binary representation are counted. If negative, the 0-bits in its two's-complement binary representation are counted. If 0, 0 is returned.Example:

(logcount #b10101010) => 4 (logcount 0) => 0 (logcount -2) => 1

__Function:__**integer-length***n*-
Returns the number of bits neccessary to represent
`n`.Example:

(integer-length #b10101010) => 8 (integer-length 0) => 0 (integer-length #b1111) => 4

__Function:__**log2-binary-factors***n*-
Returns the number of factors of two of integer
`n`. This value is also the bit-index of the least-significant``1'`bit in`n`.(require 'printf) (do ((idx 0 (+ 1 idx))) ((> idx 16)) (printf "%s(%3d) ==> %-5d %s(%2d) ==> %-5d\n" 'log2-binary-factors (- idx) (log2-binary-factors (- idx)) 'log2-binary-factors idx (log2-binary-factors idx))) -| log2-binary-factors( 0) ==> -1 log2-binary-factors( 0) ==> -1 log2-binary-factors( -1) ==> 0 log2-binary-factors( 1) ==> 0 log2-binary-factors( -2) ==> 1 log2-binary-factors( 2) ==> 1 log2-binary-factors( -3) ==> 0 log2-binary-factors( 3) ==> 0 log2-binary-factors( -4) ==> 2 log2-binary-factors( 4) ==> 2 log2-binary-factors( -5) ==> 0 log2-binary-factors( 5) ==> 0 log2-binary-factors( -6) ==> 1 log2-binary-factors( 6) ==> 1 log2-binary-factors( -7) ==> 0 log2-binary-factors( 7) ==> 0 log2-binary-factors( -8) ==> 3 log2-binary-factors( 8) ==> 3 log2-binary-factors( -9) ==> 0 log2-binary-factors( 9) ==> 0 log2-binary-factors(-10) ==> 1 log2-binary-factors(10) ==> 1 log2-binary-factors(-11) ==> 0 log2-binary-factors(11) ==> 0 log2-binary-factors(-12) ==> 2 log2-binary-factors(12) ==> 2 log2-binary-factors(-13) ==> 0 log2-binary-factors(13) ==> 0 log2-binary-factors(-14) ==> 1 log2-binary-factors(14) ==> 1 log2-binary-factors(-15) ==> 0 log2-binary-factors(15) ==> 0 log2-binary-factors(-16) ==> 4 log2-binary-factors(16) ==> 4

__Function:__**logbit?***index n*__Function:__**bit-set?***index n*-
(logbit? index n) == (logtest (expt 2 index) n) (logbit? 0 #b1101) => #t (logbit? 1 #b1101) => #f (logbit? 2 #b1101) => #t (logbit? 3 #b1101) => #t (logbit? 4 #b1101) => #f

__Function:__**copy-bit***index from bit*-
Returns an integer the same as
`from`except in the`index`th bit, which is 1 if`bit`is`#t`

and 0 if`bit`is`#f`

.Example:

(number->string (copy-bit 0 0 #t) 2) => "1" (number->string (copy-bit 2 0 #t) 2) => "100" (number->string (copy-bit 2 #b1111 #f) 2) => "1011"

__Function:__**bit-field***n start end*-
Returns the integer composed of the
`start`(inclusive) through`end`(exclusive) bits of`n`. The`start`th bit becomes the 0-th bit in the result.Example:

(number->string (bit-field #b1101101010 0 4) 2) => "1010" (number->string (bit-field #b1101101010 4 9) 2) => "10110"

__Function:__**copy-bit-field***to from start end*-
Returns an integer the same as
`to`except possibly in the`start`(inclusive) through`end`(exclusive) bits, which are the same as those of`from`. The 0-th bit of`from`becomes the`start`th bit of the result.Example:

(number->string (copy-bit-field #b1101101010 0 0 4) 2) => "1101100000" (number->string (copy-bit-field #b1101101010 -1 0 4) 2) => "1101101111" (number->string (copy-bit-field #b110100100010000 -1 5 9) 2) => "110100111110000"

__Function:__**ash***n count*__Function:__**arithmetic-shift***n count*-
Returns an integer equivalent to
`(inexact->exact (floor (*`

.`n`(expt 2`count`))))Example:

(number->string (ash #b1 3) 2) => "1000" (number->string (ash #b1010 -1) 2) => "101"

__Function:__**rotate-bit-field***n count start end*-
Returns
`n`with the bit-field from`start`to`end`cyclically permuted by`count`bits towards high-order.Example:

(number->string (rotate-bit-field #b0100 3 0 4) 2) => "10" (number->string (rotate-bit-field #b0100 -1 0 4) 2) => "10" (number->string (rotate-bit-field #b110100100010000 -1 5 9) 2) => "110100010010000" (number->string (rotate-bit-field #b110100100010000 1 5 9) 2) => "110100000110000"

__Function:__**reverse-bit-field***n start end*-
Returns
`n`with the order of bits`start`to`end`reversed.(number->string (reverse-bit-field #xa7 0 8) 16) => "e5"

__Function:__**integer->list***k len*__Function:__**integer->list***k*-
`integer->list`

returns a list of`len`booleans corresponding to each bit of the given integer. #t is coded for each 1; #f for 0. The`len`argument defaults to`(integer-length`

.`k`) __Function:__**list->integer***list*-
`list->integer`

returns an integer formed from the booleans in the list`list`, which must be a list of booleans. A 1 bit is coded for each #t; a 0 bit for #f.`integer->list`

and`list->integer`

are inverses so far as`equal?`

is concerned.

__Function:__**booleans->integer***bool1 ...*-
Returns the integer coded by the
`bool1`... arguments.

A *Gray code* is an ordering of non-negative integers in which
exactly one bit differs between each pair of successive elements. There
are multiple Gray codings. An n-bit Gray code corresponds to a
Hamiltonian cycle on an n-dimensional hypercube.

Gray codes find use communicating incrementally changing values between asynchronous agents. De-laminated Gray codes comprise the coordinates of Peano-Hilbert space-filling curves.

__Function:__**integer->gray-code***k*-
Converts
`k`to a Gray code of the same`integer-length`

as`k`. __Function:__**gray-code->integer***k*-
Converts the Gray code
`k`to an integer of the same`integer-length`

as`k`.For any non-negative integer

`k`,(eqv? k (gray-code->integer (integer->gray-code k)))

__Function:__**=***k1 k2*__Function:__**gray-code<?***k1 k2*__Function:__**gray-code>?***k1 k2*__Function:__**gray-code<=?***k1 k2*__Function:__**gray-code>=?***k1 k2*-
These procedures return #t if their Gray code arguments are
(respectively): equal, monotonically increasing, monotonically
decreasing, monotonically nondecreasing, or monotonically nonincreasing.
For any non-negative integers

`k1`and`k2`, the Gray code predicate of`(integer->gray-code k1)`

and`(integer->gray-code k2)`

will return the same value as the corresponding predicate of`k1`and`k2`.

This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Scheme Request For Implementation process or editors, except as needed for the purpose of developing SRFIs in which case the procedures for copyrights defined in the SRFI process must be followed, or as required to translate it into languages other than English.

The limited permissions granted above are perpetual and will not be revoked by the authors or their successors or assigns.

This document and the information contained herein is provided on an "AS IS" basis and THE AUTHOR AND THE SRFI EDITORS DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.

Editor: David Van Horn Last modified: Mon Jan 10 13:35:35 EST 2005