This site is a static rendering of the Trac instance that was used by R7RS-WG1 for its work on R7RS-small (PDF), which was ratified in 2013. For more information, see Home. For a version of this page that may be more recent, see BitwiseCowan in WG2's repo for R7RS-large.

Bitwise­Cowan

cowan
2016-08-09 02:16:23
6history
source

Bitwise arithmetic procedures

This proposal is based mainly on SRFI 33, with some changes and additions from Olin's late revisions to SRFI 33 (which were never consummated) and from SRFI 60.

Abstract

Scheme has no standard procedures for performing bitwise logical operations on integers, which is a problem for authors of portable code. This SRFI proposes a coherent and comprehensive set of these functions; it is accompanied by a reference implementation of the spec in terms of a set of seven core operators. The sample implementation is portable, as efficient as practical with pure Scheme arithmetic (it is worthwhile replacing certain primitive operations with C or assembly language if possible), and open source. The precise semantics of these operators is almost never an issue. A consistent, portable set of names and parameter conventions, however, is. Hence this SRFI.

Among the applications of bitwise operations are: hashing, Galois-field 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.

Procedure index

bitwise-not bitwise-and bitwise-ior bitwise-xor bitwise-eqv bitwise-nand bitwise-nor bitwise-andc1 bitwise-andc2 bitwise-orc1 bitwise-orc2 arithmetic-shift bit-count integer-length bitwise-if bit-set? any-bit-set? every-bit-set? first-set-bit bit-field bit-field-any? bit-field-every? bit-field-clear bit-field-replace bit-field-replace-corresponding bit-field-rotate bit-field-reverse integer->list list->integer bits fold for-each unfold

Rationale

General design principles

Differences from Common Lisp

The core of this design design mirrors the structure of Common Lisp's pretty closely. Here are some differences:

Changes to SRFI 33 names

BitwiseCowan retains SRFI 33 names for procedures adapted from SRFI 33, with these exceptions:

SRFI 60

SRFI 60 includes five procedures that do not have SRFI 33 equivalents. They are incorporated into this SRFI as follows:

SRFI 133

The following procedures are inspired by SRFI 133: bit-swap, bit-field-fill, bit-field-append, bitwise-fold, bitwise-for-each, bitwise-unfold.

Specification

In the following procedure specifications all parameters are exact integers; unless otherwise indicated, all return values are exact integers. It is an error to pass values of other types as arguments to these functions.

Bitstrings are represented by integers, using a two's-complement encoding of the bitstring. Thus every integer represents a semi-infinite bitstring, having either a finite number of zeros (negative integers) or a finite number of ones (non-negative integers). The bits of a bitstring are numbered from the rightmost/least-significant bit: bit !#0 is the rightmost or 20 bit, bit !#1 is the next or 21 bit, and so forth.

Basic operations

(bitwise-not i) -> exact-integer

Bitwise logical negation.

(bitwise-not 10) => -11 (bitwise-not -37) => 36

The following ten procedures correspond to the useful set of non-trivial two-argument boolean functions. For each such function, the corresponding bitwise operator maps that function across a pair of bitstrings in a bit-wise fashion.

The core idea of this group of functions is this bitwise "lifting" of the set of dyadic boolean functions to bitstring parameters.

(bitwise-and i ...) -> exact-integer
(bitwise-ior i ...) -> exact-integer
(bitwise-xor i ...) -> exact-integer
(bitwise-eqv i ...) -> exact-integer

These operations are associative. When passed no arguments, the procedures return the identity values -1, 0, 0, and -1 respectively.

The bitwise-eqv procedure produces the negation of the bitwise-xor procedure. When applied to three arguments, it does not produce a 1 bit everywhere that a, b and c all agree. That is, it does not produce

(bitwise-ior (bitwise-and a b c) (bitwise-and (bitwise-not a) (bitwise-not b) (bitwise-not c)))

Rather, it produces (bitwise-eqv a (bitwise-eqv b c)) or the equivalent (bitwise-eqv (bitwise-eqv a b) c).

(bitwise-ior 3 10) => 11 (bitwise-and 11 26) => 10 (bitwise-xor 3 10) => 9 (bitwise-eqv 37 12) => -42 (bitwise-and 37 12) => 4

(bitwise-nand i j) -> exact-integer
(bitwise-nor i j) -> exact-integer
(bitwise-andc1 i j) -> exact-integer
(bitwise-andc2 i j) -> exact-integer
(bitwise-orc1 i j) -> exact-integer
(bitwise-orc2 i j) -> exact-integer

These operations are not associative.

(bitwise-nand 11 26) => -11 (bitwise-nor 11 26) => -28 (bitwise-andc1 11 26) => 16 (bitwise-andc2 11 26) => 1 (bitwise-orc1 11 26) => -2 (bitwise-orc2 11 26) => -17

Integer operations

(arithmetic-shift i count) -> exact-integer

Arithmetic left shift when count>0; right shift when count<0.

(arithmetic-shift 8 2) => 32 (arithmetic-shift 4 0) => 4 (arithmetic-shift 8 -1) => 4 (arithmetic-shift -100000000000000000000000000000000 -100) => -79

(bit-count i) -> nonnegative-exact-integer

Population count of 1's (i >= 0) or 0's (i < 0).

(bit-count 0) => 0 (bit-count -1) => 0 (bit-count 7) => 3 (bit-count 13) => 3 ;Two's-complement binary: ...0001101 (bit-count -13) => 2 ;Two's-complement binary: ...1110011 (bit-count 30) => 4 ;Two's-complement binary: ...0011110 (bit-count -30) => 4 ;Two's-complement binary: ...1100010 (bit-count (expt 2 100)) => 1 (bit-count (- (expt 2 100))) => 100 (bit-count (- (1+ (expt 2 100)))) => 1

(integer-length i) -> nonnegative-exact-integer

The number of bits needed to represent i, i.e.

(ceiling (/ (log (if (negative? integer) (- integer) (+ 1 integer))) (log 2)))

(integer-length 0) => 0 (integer-length 1) => 1 (integer-length -1) => 0 (integer-length 7) => 3 (integer-length -7) => 3 (integer-length 8) => 4 (integer-length -8) => 3 This is equivalent to: (bitwise-ior (bitwise-and (bitwise-not mask) i) (bitwise-and mask j)) As always, the rightmost/least-significant bit in i is bit 0. (bit-set? 1 1) => false (bit-set? 0 1) => true (bit-set? 3 10) => true (bit-set? 1000000 -1) => true (bit-set? 2 6) => true (bit-set? 0 6) => false return (not (zero? (bitwise-and ''test-bits i'')))` (first-set-bit 1) => 0 (first-set-bit 2) => 1 (first-set-bit 0) => -1 (first-set-bit 40) => 3 (first-set-bit -28) => 2 (first-set-bit (expt 2 99)) => 99 (first-set-bit (expt -2 99)) => 99 The initial value of r When The values returned by proc are discarded. Returns Otherwise, apply mapper Then get a new state Note that it is an infinite generator. SRFI 33 was never finalized, but is a comprehensive proposal. SRFI 60 (based on SLIB) is smaller but has a few procedures of its own; some of its procedures have both native (often CL) and SRFI 33 names. R6RS is a subset of SRFI 60, but all procedure names begin with a bitwise- prefix. BitwiseCowan adopts this change. Consequently, they are not quite compatible across specifications. Note that copy-bit-field corresponds to different procedures in SRFI 33 and SRFI 60.