Arithmetic libraries

This section describes Scheme's libraries for more specialized numerical operations: fixnum and flonum arithmetic, as well as bitwise operations on exact integer objects.

Bitwise operations

A number of procedures operate on the binary two's-complement representations of exact integer objects: Bit positions within an exact integer object are counted from the right, i.e. bit 0 is the least significant bit. Some procedures allow extracting bit fields, i.e., number objects representing subsequences of the binary representation of an exact integer object. Bit fields are always positive, and always defined using a finite number of bits.

Fixnums

On Sagittarius Scheme, fixnum is 30 bits or 62 bits depending on platform. On 32 bits platform it fixnum is 30 bits, and 64 bits platform it is 62 bits. However, non 32 bits platform is not well tested so if you find a bug please send a report.

This section uses fx, fx1 fx2, etc., as parameter names for arguments that must be fixnums.

Function fixnum? obj

[R6RS] Returns #t if obj is an exact integer object within the fixnum range, #f otherwise.

[R6RS] These procedures returns bit size of fixnum, minimum and maximum value of the fixnum range, respectively.

[R6RS] These procedures return #t if their arguments are: equal, monotonically increasing, monotonically decreasing, monotonically nondecreasing, or monotonically nonincreasing, #f otherwise.

Function fxzero? fx
Function fxodd? fx
Function fxeven? fx

[R6RS] These numerical predicates test a fixnum for a particular property, returning #t or #f. The five properties tested by these procedures are: whether the number object is zero, greater than zero, less than zero, odd, or even.

[R6RS] These procedures return the maximum or minimum of their arguments.

Function fx+ fx1 fx2
Function fx* fx1 fx2

[R6RS] These procedures return the sum or product of their arguments, provided that sum or product is a fixnum. An exception with condition type &implementation-restriction is raised if that sum or product is not a fixnum.

[R6RS] With two arguments, this procedure returns the difference fx1- fx2, provided that difference is a fixnum.

With one argument, this procedure returns the additive inverse of its argument, provided that integer object is a fixnum.

An exception with condition type &implementation-restriction is raised if the mathematically correct result of this procedure is not a fixnum.

NOTE: R6RS says it raises &assertion if the result is not fixnum, however Sagittarius raises &implementation-restriction for consistency with fx+ and fx*.

[R6RS] Fx2 must be nonzero. These procedures implement number-theoretic integer division and return the results of the corresponding mathematical operations specified in (rnrs base (6)) section.

[R6RS] Returns the two fixnum results of the following computation:

(let* ((s (+ _fx1_ _fx2_ _fx3_))
       (s0 (mod0 s (expt 2 (fixnum-width))))
       (s1 (div0 s (expt 2 (fixnum-width)))))
  (values s0 s1))

[R6RS] Returns the two fixnum results of the following computation:

(let* ((d (- _fx1_ _fx2_ _fx3_))
       (d0 (mod0 d (expt 2 (fixnum-width))))
       (d1 (div0 d (expt 2 (fixnum-width)))))
  (values d0 d1))

[R6RS] Returns the two fixnum results of the following computation:

(let* ((s (+ (* _fx1_ _fx2_) _fx3_))
       (s0 (mod0 s (expt 2 (fixnum-width))))
       (s1 (div0 s (expt 2 (fixnum-width)))))
  (values s0 s1))
Function fxnot fx

[R6RS] Returns bitwise not of fixnum fx.

[R6RS] These procedures return the fixnum that is the bit-wise "and", "inclusive or", or "exclusive or" of the two's complement representations of their arguments. If they are passed only one argument, they return that argument. If they are passed no arguments, they return the fixnum (either - 1 or 0) that acts as identity for the operation.

[R6RS] Returns the fixnum that is the bit-wise "if" of the two's complement representations of its arguments, i.e. for each bit, if it is 1 in fx1, the corresponding bit in fx2 becomes the value of the corresponding bit in the result, and if it is 0, the corresponding bit in fx3 becomes the corresponding bit in the value of the result. This is the fixnum result of the following computation:

(fxior (fxand _fx1_ _fx2_)
       (fxand (fxnot _fx1_) _fx3_))

[R6RS] If fx is non-negative, this procedure returns the number of 1 bits in the two's complement representation of fx. Otherwise it returns the result of the following computation:

(fxnot (fxbit-count (fxnot _ei_)))

Function fxlength fx

[R6RS] Returns the number of bits needed to represent fx if it is positive, and the number of bits needed to represent (fxnot _fx_) if it is negative, which is the fixnum result of the following computation:

(do ((result 0 (+ result 1))
     (bits (if (fxnegative? _fx_)
               (fxnot _fx_)
               _fx_)
           (fxarithmetic-shift-right bits 1)))
    ((fxzero? bits)
     result))

[R6RS] Returns the index of the least significant 1 bit in the two's complement representation of fx. If fx is 0, then - 1 is returned.

[R6RS] Fx2 must be non-negative and less than (fixnum-width). The fxbit-set? procedure returns #t if the _fx2_th bit is 1 in the two's complement representation of fx1, and #f otherwise. This is the fixnum result of the following computation:

(not
  (fxzero?
    (fxand _fx1_           (fxarithmetic-shift-left 1 _fx2_))))

[R6RS] Fx2 must be non-negative and less than (fixnum-width). Fx3 must be 0 or 1. The fxcopy-bit procedure returns the result of replacing the _fx2_th bit of fx1 by fx3, which is the result of the following computation:

(let* ((mask (fxarithmetic-shift-left 1 _fx2_)))
  (fxif mask
        (fxarithmetic-shift-left _fx3_ _fx2_)
        _fx1_))

[R6RS] Fx2 and fx3 must be non-negative and less than (fixnum-width). Moreover, fx2 must be less than or equal to fx3. The fxbit-field procedure returns the number represented by the bits at the positions from fx2 (inclusive) to fx3 (exclusive), which is the fixnum result of the following computation:

(let* ((mask (fxnot
              (fxarithmetic-shift-left -1 _fx3_))))
  (fxarithmetic-shift-right (fxand _fx1_ mask)
                            _fx2_))

[R6RS] Fx2 and fx3 must be non-negative and less than (fixnum-width). Moreover, fx2 must be less than or equal to fx3. The fxcopy-bit-field procedure returns the result of replacing in fx1 the bits at positions from fx2 (inclusive) to fx3(exclusive) by the corresponding bits in fx4, which is the fixnum result of the following computation:

(let* ((to    _fx1_)
       (start _fx2_)
       (end   _fx3_)
       (from  _fx4_)
       (mask1 (fxarithmetic-shift-left -1 start))
       (mask2 (fxnot
               (fxarithmetic-shift-left -1 end)))
       (mask (fxand mask1 mask2)))
  (fxif mask
        (fxarithmetic-shift-left from start)
        to))

[R6RS] The absolute value of fx2 must be less than (fixnum-width). If

(floor (* _fx1_ (expt 2 _fx2_)))

is a fixnum, then that fixnum is returned. Otherwise an exception with condition type &implementation-restriction is raised.

[R6RS] Fx2 must be non-negative, and less than (fixnum-width). The fxarithmetic-shift-left procedure behaves the same as fxarithmetic-shift, and (fxarithmetic-shift-right _fx1_ _fx2_)behaves the same as (fxarithmetic-shift _fx1_ (fx- _fx2_)).

[R6RS] Fx2, fx3, and fx4 must be non-negative and less than (fixnum-width). Fx2 must be less than or equal to fx3. Fx4 must be less than the difference between fx3 and fx2. The fxrotate-bit-field procedure returns the result of cyclically permuting in fx1 the bits at positions from fx2 (inclusive) to fx3(exclusive) by fx4 bits towards the more significant bits, which is the result of the following computation:

(let* ((n     _fx1_)
       (start _fx2_)
       (end   _fx3_)
       (count _fx4_)
       (width (fx- end start)))
  (if (fxpositive? width)
      (let* ((count (fxmod count width))
             (field0
               (fxbit-field n start end))
             (field1
               (fxarithmetic-shift-left
                 field0 count))
             (field2
               (fxarithmetic-shift-right
                 field0 (fx- width count)))
             (field (fxior field1 field2)))
        (fxcopy-bit-field n start end field))
      n))

[R6RS] Fx2 and fx3 must be non-negative and less than (fixnum-width). Moreover, fx2 must be less than or equal to fx3. The fxreverse-bit-field procedure returns the fixnum obtained from fx1 by reversing the order of the bits at positions from fx2(inclusive) to fx3 (exclusive).

Flonums

This section describes the (rnrs arithmetic flonums (6))library.

This section uses fl, fl1, fl2, etc., as parameter names for arguments that must be flonums, and ifl as a name for arguments that must be integer-valued flonums, i.e., flonums for which the integer-valued?predicate returns true.

[R6RS] This library exports procedures for flonum operations.

Function flonum? obj

[R6RS] Returns #t if obj is a flonum, #f otherwise.

[R6RS] These procedures return #t if their arguments are (respectively): equal, monotonically increasing, monotonically decreasing, monotonically nondecreasing, or monotonically nonincreasing, #f otherwise.

Function flzero? fl
Function flodd? fl
Function fleven? fl
Function flnan? fl

[R6RS] These numerical predicates test a flonum for a particular property, returning #t or #f. The flinteger? procedure tests whether the number object is an integer, flzero? tests whether it is fl=? to zero, flpositive? tests whether it is greater than zero, flnegative?tests whether it is less than zero, flodd? tests whether it is odd, fleven? tests whether it is even, flfinite? tests whether it is not an infinity and not a NaN, flinfinite? tests whether it is an infinity, and flnan? tests whether it is a NaN.

[R6RS] These procedures return the maximum or minimum of their arguments. They always return a NaN when one or more of the arguments is a NaN.

Function fl+ fl1 ...
Function fl* fl1 ...

[R6RS] These procedures return the flonum sum or product of their flonum arguments. In general, they should return the flonum that best approximates the mathematical sum or product.

Function flabs fl

[R6RS] Returns the absolute value of fl.

[R6RS] These procedures implement number-theoretic integer division and return the results of the corresponding mathematical operations (see (rnrs base (6)) . For zero divisors, these procedures may return a NaN or some unspecified flonum.

[R6RS] These procedures return the numerator or denominator of fl as a flonum; the result is computed as if fl was represented as a fraction in lowest terms. The denominator is always positive. The denominator of 0.0 is defined to be 1.0.

Function flfloor fl
Function flround fl

[R6RS] These procedures return integral flonums for flonum arguments that are not infinities or NaNs. For such arguments, flfloor returns the largest integral flonum not larger than fl. The flceiling procedure returns the smallest integral flonum not smaller than fl. The fltruncateprocedure returns the integral flonum closest to fl whose absolute value is not larger than the absolute value of fl. The flround procedure returns the closest integral flonum to fl, rounding to even when _fl_represents a number halfway between two integers.

Although infinities and NaNs are not integer objects, these procedures return an infinity when given an infinity as an argument, and a NaN when given a NaN.

Function flexp fl
Function flsin fl
Function flcos fl
Function fltan fl
Function flasin fl
Function flacos fl

[R6RS] These procedures compute the usual transcendental functions. The flexpprocedure computes the base-e exponential of fl. The fllog procedure with a single argument computes the natural logarithm of fl1 (not the base ten logarithm); (fllog _fl1_ _fl2_) computes the base-_fl2_logarithm of fl1. The flasin, flacos, and flatanprocedures compute arcsine, arccosine, and arctangent, respectively. (flatan _fl1_ _fl2_) computes the arc tangent of fl1/fl2.

Function flsqrt fl

[R6RS] Returns the principal square root of fl. For - 0.0, flsqrtreturns 0.0; for other negative arguments, the result unspecified flonum.

[R6RS] Either fl1 should be non-negative, or, if fl1 is negative, fl2 should be an integer object. The flexpt procedure returns _fl1_raised to the power fl2. If fl1 is negative and fl2 is not an integer object, the result is a NaN. If fl1 is zero, then the result is zero.

Condition Type &no-infinities
Condition Type &no-nans

[R6RS] These types describe that a program has executed an arithmetic operations that is specified to return an infinity or a NaN, respectively.

Here is the hierarchy of these conditions.

+ &implementation-restriction (see ["Conditions"](#rnrs.conditions.6))
    + &no-infinities
    + &no-nans

[R6RS] Returns a flonum that is numerically closest to fx.

Exact bitwise arithmetic

This section describes the (rnrs arithmetic bitwise (6))library. The exact bitwise arithmetic provides generic operations on exact integer objects. This section uses ei, ei1, ei2, etc., as parameter names that must be exact integer objects.

[R6RS] This library exports procedures for exact bitwise arithmetic operations.

[R6RS] Returns the exact integer object whose two's complement representation is the one's complement of the two's complement representation of ei.

[R6RS] These procedures return the exact integer object that is the bit-wise "and", "inclusive or", or "exclusive or" of the two's complement representations of their arguments. If they are passed only one argument, they return that argument. If they are passed no arguments, they return the integer object (either - 1 or 0) that acts as identity for the operation.

[R6RS] Returns the exact integer object that is the bit-wise "if" of the two's complement representations of its arguments, i.e. for each bit, if it is 1 in ei1, the corresponding bit in ei2 becomes the value of the corresponding bit in the result, and if it is 0, the corresponding bit in ei3 becomes the corresponding bit in the value of the result. This is the result of the following computation:

(bitwise-ior (bitwise-and _ei1_ _ei2_)
             (bitwise-and (bitwise-not _ei1_) _ei3_))

[R6RS] If ei is non-negative, this procedure returns the number of 1 bits in the two's complement representation of ei. Otherwise it returns the result of the following computation:

(bitwise-not (bitwise-bit-count (bitwise-not _ei_)))

[R6RS] Returns the number of bits needed to represent ei if it is positive, and the number of bits needed to represent (bitwise-not _ei_) if it is negative, which is the exact integer object that is the result of the following computation:

(do ((result 0 (+ result 1))
     (bits (if (negative? _ei_)
               (bitwise-not _ei_)
               _ei_)
           (bitwise-arithmetic-shift bits -1)))
    ((zero? bits)
     result))

[R6RS] Returns the index of the least significant 1 bit in the two's complement representation of ei. If ei is 0, then - 1 is returned.

[R6RS] Ei2 must be non-negative. The bitwise-bit-set?procedure returns #t if the _ei2_th bit is 1 in the two's complement representation of ei1, and #f otherwise. This is the result of the following computation:

(not (zero?
       (bitwise-and
         (bitwise-arithmetic-shift-left 1 _ei2_)
         _ei1_)))

[R6RS] Ei2 must be non-negative, and ei3 must be either 0 or 1. The bitwise-copy-bit procedure returns the result of replacing the _ei2_th bit of ei1 by the _ei2_th bit of ei3, which is the result of the following computation:

(let* ((mask (bitwise-arithmetic-shift-left 1 _ei2_)))
  (bitwise-if mask
            (bitwise-arithmetic-shift-left _ei3_ _ei2_)
            _ei1_))

[R6RS] Ei2 and ei3 must be non-negative, and ei2 must be less than or equal to ei3. The bitwise-bit-field procedure returns he number represented by the bits at the positions from ei2 (inclusive) to ei3 (exclusive), which is the result of the following computation:

(let ((mask
       (bitwise-not
        (bitwise-arithmetic-shift-left -1 _ei3_))))
  (bitwise-arithmetic-shift-right
    (bitwise-and _ei1_ mask)
    _ei2_))

[R6RS] Ei2 and ei3 must be non-negative, and ei2 must be less than or equal to ei3. The bitwise-copy-bit-field procedure returns the result of replacing in ei1 the bits at positions from var{ei2} (inclusive) to ei3 (exclusive) by the corresponding bits in ei4, which is the fixnum result of the following computation:

(let* ((to    _ei1_)
       (start _ei2_)
       (end   _ei3_)
       (from  _ei4_)
       (mask1
         (bitwise-arithmetic-shift-left -1 start))
       (mask2
         (bitwise-not
           (bitwise-arithmetic-shift-left -1 end)))
       (mask (bitwise-and mask1 mask2)))
  (bitwise-if mask
              (bitwise-arithmetic-shift-left from
                                             start)
              to))

[R6RS] Returns the result of the following computation:

(floor (* _ei1_ (expt 2 _ei2_)))

ei2 must be a fixnum. This is implementation restriction.

[R6RS] Ei2 must be non-negative. The bitwise-arithmetic-shift-left procedure returns the same result as bitwise-arithmetic-shift, and

(bitwise-arithmetic-shift-right _ei1_ _ei2_)

returns the same result as

(bitwise-arithmetic-shift _ei1_ (- _ei2_))

.

ei2 must be a fixnum. This is implementation restriction.

[R6RS] Ei2, ei3, ei4 must be non-negative, _ei2_must be less than or equal to ei3, and ei4 must be non-negative. The bitwise-rotate-bit-field procedure returns the result of cyclically permuting in ei1 the bits at positions from ei2 (inclusive) to ei3 (exclusive) by ei4 bits towards the more significant bits, which is the result of the following computation:

(let* ((n     _ei1_)
       (start _ei2_)
       (end   _ei3_)
       (count _ei4_)
       (width (- end start)))
  (if (positive? width)
      (let* ((count (mod count width))
             (field0
               (bitwise-bit-field n start end))
             (field1 (bitwise-arithmetic-shift-left
                       field0 count))
             (field2 (bitwise-arithmetic-shift-right
                       field0
                       (- width count)))
             (field (bitwise-ior field1 field2)))
        (bitwise-copy-bit-field n start end field))
      n))

ei4 must be a fixnum. This is implementation restriction.

[R6RS] Ei2 and ei3 must be non-negative, and ei2 must be less than or equal to ei3. The bitwise-reverse-bit-field procedure returns the result obtained from ei1 by reversing the order of the bits at positions from ei2 (inclusive) to ei3 (exclusive).