[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7. "Numbers"

.setq number section-page .setq number-chapter chapter-number Zetalisp includes several types of numbers, with different characteristics. Most numeric functions will accept any type of numbers as arguments and do the right thing. That is to say, they are generic. In Maclisp, there are generic numeric functions (like plus) and there are specific numeric functions (like +) which only operate on a certain type, and are much more efficient. In Zetalisp, this distinction does not exist; both function names exist for compatibility but they are identical. The microprogrammed structure of the machine makes it possible to have only the generic functions without loss of efficiency.

The types of numbers in Zetalisp are:

fixnum
Fixnums are 24-bit 2's complement binary integers. These are the "preferred, most efficient" type of number.
bignum
Bignums are arbitrary-precision binary integers.
flonum
Flonums are floating-point numbers. They have a mantissa of 32 bits and an exponent of 11 bits, providing a precision of about 9 digits and a range of about 10^300. Stable rounding is employed.
small-flonum
Small flonums are another form of floating-point number, with a mantissa of 18 bits and an exponent of 7 bits, providing a precision of about 5 digits and a range of about 10^19. Stable rounding is employed. Small flonums are useful because, like fixnums, and unlike flonums, they don't require any storage. Computing with small flonums is more efficient than with regular flonums because the operations are faster and consing overhead is eliminated.

Generally, Lisp objects have a unique identity; each exists, independent of any other, and you can use the eq predicate to determine whether two references are to the same object or not. Numbers are the exception to this rule; they don't work this way. The following function may return either t or nil. Its behavior is considered undefined, but as this manual is written it returns t when interpreted but nil when compiled.
 
(defun foo ()
   (let ((x (float 5)))
     (eq x (car (cons x nil)))))
This is very strange from the point of view of Lisp's usual object semantics, but the implementation works this way, in order to gain efficiency, and on the grounds that identity testing of numbers is not really an interesting thing to do. So, the rule is that the result of applying eq to numbers is undefined, and may return either t or nil at will. If you want to compare the values of two numbers, use = (see (=-fun)).

Fixnums and small flonums are exceptions to this rule; some system code knows that eq works on fixnums used to represent characters or small integers, and uses memq or assq on them. eq works as well as = as an equality test for fixnums. Small flonums that are = tend to be eq also, but it is unwise to depend on this.

The distinction between fixnums and bignums is largely transparent to the user. The user simply computes with integers, and the system represents some as fixnums and the rest (less efficiently) as bignums. The system automatically converts back and forth between fixnums and bignums based solely on the size of the integer. There are a few "low level" functions which only work on fixnums; this fact is noted in their documentation. Also when using eq on numbers the user needs to be aware of the fixnum/bignum distinction.

Integer computations cannot "overflow", except for division by zero, since bignums can be of arbitrary size. Floating-point computations can get exponent overflow or underflow, if the result is too large or small to be represented. Exponent overflow always signals an error. Exponent underflow normally signals an error, and assumes 0.0 as the answer if the user says to proceed from the error. However, if the value of the variable zunderflow is non-nil, the error is skipped and computation proceeds with 0.0 in place of the result that was too small.

When an arithmetic function of more than one argument is given arguments of different numeric types, uniform coercion rules are followed to convert the arguments to a common type, which is also the type of the result (for functions which return a number). When an integer meets a small flonum or a flonum, the result is a small flonum or a flonum (respectively). When a small flonum meets a regular flonum, the result is a regular flonum.

Thus if the constants in a numerical algorithm are written as small flonums (assuming this provides adequate precision), and if the input is a small flonum, the computation will be done in small-flonum mode and the result will a small flonum, while if the input is a large flonum the computations will be done in full precision and the result will be a flonum.

Zetalisp never automatically converts between flonums and small flonums, in the way it automatically converts between fixnums and bignums, since this would lead either to inefficiency or to unexpected numerical inaccuracies. (When a small flonum meets a flonum, the result is a flonum, but if you use only one type, all the results will be of the same type too.) This means that a small-flonum computation can get an exponent overflow error even when the result could have been represented as a large flonum.

Floating-point numbers retain only a certain number of bits of precision; therefore, the results of computations are only approximate. Large flonums have 31 bits and small flonums have 17 bits, not counting the sign. The method of approximation is "stable rounding". The result of an arithmetic operation will be the flonum which is closest to the exact value. If the exact result falls precisely halfway between two flonums, the result will be rounded down if the least-significant bit is 0, or up if the least-significant bit is 1. This choice is arbitrary but insures that no systematic bias is introduced.

.setq division-rule page Integer addition, subtraction, and multiplication always produce an exact result. Integer division, on the other hand, returns an integer rather than the exact rational-number result. The quotient is truncated towards zero rather than rounded. The exact rule is that if A is divided by B, yielding a quotient of C and a remainder of D, then A = B * C + D exactly. D is either zero or the same sign as A. Thus the absolute value of C is less than or equal to the true quotient of the absolute values of A and B. This is compatible with Maclisp and most computer hardware. However, it has the serious problem that it does not obey the rule that if A divided by B yields a quotient of C and a remainder of D, then dividing A + k * B by B will yield a quotient of C + k and a remainder of D for all integer k. The lack of this property sometimes makes regular integer division hard to use. New functions that implement a different kind of division, that obeys this rule, will be implemented in the future.

Unlike Maclisp, Zetalisp does not have number declarations in the compiler. Note that because fixnums and small flonums require no associated storage they are as efficient as declared numbers in Maclisp. Bignums and (large) flonums are less efficient, however bignum and flonum intermediate results are garbage collected in a special way that avoids the overhead of the full garbage collector.

The different types of numbers can be distinguished by their printed representations. A leading or embedded (but not trailing) decimal point, and/or an exponent separated by "e", indicates a flonum. If a number has an exponent separated by "s", it is a small flonum. Small flonums require a special indicator so that naive users will not accidentally compute with the lesser precision. Fixnums and bignums have similar printed representations since there is no numerical value that has a choice of whether to be a fixnum or a bignum; an integer is a bignum if and only if its magnitude too big for a fixnum. See the examples on (flonum-examples), in the description of what the reader understands.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.1 "Numeric Predicates"

Function: zerop x
Returns t if x is zero. Otherwise it returns nil. If x is not a number, zerop causes an error. For flonums, this only returns t for exactly 0.0 or 0.0s0; there is no "fuzz".

Function: plusp x
Returns t if its argument is a positive number, strictly greater than zero. Otherwise it returns nil. If x is not a number, plusp causes an error.

Function: minusp x
Returns t if its argument is a negative number, strictly less than zero. Otherwise it returns nil. If x is not a number, minusp causes an error.

Function: oddp number
Returns t if number is odd, otherwise nil. If number is not a fixnum or a bignum, oddp causes an error.

Function: evenp number
Returns t if number is even, otherwise nil. If number is not a fixnum or a bignum, evenp causes an error.

Special Form: signp test x
signp is used to test the sign of a number. It is present only for Maclisp compatibility, and is not recommended for use in new programs. signp returns t if x is a number which satisfies the test, nil if it is not a number or does not meet the test. test is not evaluated, but x is. test can be one of the following:

l
x < 0
le
x  0
e
x = 0
n
x  0
ge
x  0
g
x > 0

 
Examples:
(signp ge 12) => t
(signp le 12) => nil
(signp n 0) => nil
(signp g 'foo) => nil

See also the data-type predicates fixp, floatp, bigp, small-floatp, and numberp ((fixp-fun)).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.2 Numeric Comparisons

All of these functions require that their arguments be numbers, and signal an error if given a non-number. They work on all types of numbers, automatically performing any required coercions (as opposed to Maclisp in which generally only the spelled-out names work for all kinds of numbers).

Function: = x y
Returns t if x and y are numerically equal. An integer can be = to a flonum.

Function: greaterp x y &rest more-args
Function: > x y &rest more-args
greaterp compares its arguments from left to right. If any argument is not greater than the next, greaterp returns nil. But if the arguments are monotonically strictly decreasing, the result is t.
 
Examples:
(greaterp 4 3) => t
(greaterp 4 3 2 1 0) => t
(greaterp 4 3 1 2 0) => nil

Function: >= x y &rest more-args
Function:  x y &rest more-args
 compares its arguments from left to right. If any argument is less than the next,  returns nil. But if the arguments are monotonically decreasing or equal, the result is t.

Function: lessp x y &rest more-args
Function: < x y &rest more-args
lessp compares its arguments from left to right. If any argument is not less than the next, lessp returns nil. But if the arguments are monotonically strictly increasing, the result is t.
 
Examples:
(lessp 3 4) => t
(lessp 1 1) => nil
(lessp 0 1 2 3 4) => t
(lessp 0 1 3 2 4) => nil

Function: <= x y &rest more-args
Function:  x y &rest more-args
 compares its arguments from left to right. If any argument is greater than the next,  returns nil. But if the arguments are monotonically increasing or equal, the result is t.

Function:  x y
Returns t if x is not numerically equal to y, and nil otherwise.

Function: max &rest args
max returns the largest of its arguments.
 
Example:
(max 1 3 2) => 3
max requires at least one argument.

Function: min &rest args
min returns the smallest of its arguments.
 
Example:
(min 1 3 2) => 1
min requires at least one argument.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.3 "Arithmetic"

All of these functions require that their arguments be numbers, and signal an error if given a non-number. They work on all types of numbers, automatically performing any required coercions (as opposed to Maclisp, in which generally only the spelled-out versions work for all kinds of numbers, and the "$" versions are needed for flonums).

Function: plus &rest args
Function: + &rest args
Function: +$ &rest args
Returns the sum of its arguments. If there are no arguments, it returns 0, which is the identity for this operation.

Function: difference arg &rest args
Returns its first argument minus all of the rest of its arguments.

Function: minus x
Returns the negative of x.
 
Examples:
(minus 1) => -1
(minus -3.0) => 3.0

Function: - arg &rest args
Function: -$ arg &rest args
With only one argument, - is the same as minus; it returns the negative of its argument. With more than one argument, - is the same as difference; it returns its first argument minus all of the rest of its arguments.

Function: abs x
Returns |x|, the absolute value of the number x. abs could have been defined by:
 
(defun abs (x)
    (cond ((minusp x) (minus x))
	  (t x)))

Function: times &rest args
Function: * &rest args
Function: *$ &rest args
Returns the product of its arguments. If there are no arguments, it returns 1, which is the identity for this operation.

Function: quotient arg &rest args
Returns the first argument divided by all of the rest of its arguments.

Function: // arg &rest args
Function: //$ arg &rest args
The name of this function is written // rather than / because / is the quoting character in Lisp syntax and must be doubled. With more than one argument, // is the same as quotient; it returns the first argument divided by all of the rest of its arguments. With only one argument, (// x) is the same as (// 1 x). The exact rules for the meaning of the quotient and remainder of two integers are given on (division-rule); this explains why the rules used for integer division are not correct for all applications.
 
Examples:
(// 3 2) => 1       ;Fixnum division truncates.
(// 3 -2) => -1
(// -3 2) => -1
(// -3 -2) => 1
(// 3 2.0) => 1.5
(// 3 2.0s0) => 1.5s0
(// 4 2) => 2
(// 12. 2. 3.) => 2
(// 4.0) => .25

Function: remainder x y
Function: \ x y
Returns the remainder of x divided by y. x and y must be integers (fixnums or bignums). The exact rules for the meaning of the quotient and remainder of two integers are given on (division-rule).
 
(\ 3 2) => 1
(\ -3 2) => -1
(\ 3 -2) => 1
(\ -3 -2) => -1

Function: add1 x
Function: 1+ x
Function: 1+$ x
(add1 x) is the same as (plus x 1).

Function: sub1 x
Function: 1- x
Function: 1-$ x
(sub1 x) is the same as (difference x 1). Note that the short name may be confusing: (1- x) does not mean 1-x; rather, it means x-1.

Function: gcd x y &rest args
Function: \\ x y &rest args
Returns the greatest common divisor of all its arguments. The arguments must be integers (fixnums or bignums).

Function: expt x y
Function: ^ x y
Function: ^$ x y
Returns x raised to the y'th power. The result is an integer if both arguments are integers (even if y is negative!) and floating-point if either x or y or both is floating-point. If the exponent is an integer a repeated-squaring algorithm is used, while if the exponent is floating the result is (exp (* y (log x))).

Function: sqrt x
Returns the square root of x.

Function: isqrt x
Integer square-root. x must be an integer; the result is the greatest integer less than or equal to the exact square root of x.

Function: *dif x y
Function: *plus x y
Function: *quo x y
Function: *times x y
These are the internal micro-coded arithmetic functions. There is no reason why anyone should need to write code with these explicitly, since the compiler knows how to generate the appropriate code for plus, +, etc. These names are only here for Maclisp compatibility.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.4 Transcendental Functions

These functions are only for floating-point arguments; if given an integer they will convert it to a flonum. If given a small-flonum, they will return a small-flonum [currently this is not true of most of them, but it will be fixed in the future].

Function: exp x
Returns e raised to the x'th power, where e is the base of natural logarithms.

Function: log x
Returns the natural logarithm of x.

Function: sin x
Returns the sine of x, where x is expressed in radians.

Function: sind x
Returns the sine of x, where x is expressed in degrees.

Function: cos x
Returns the cosine of x, where x is expressed in radians.

Function: cosd x
Returns the cosine of x, where x is expressed in degrees.

Function: atan y x
Returns the angle, in radians, whose tangent is y/x. atan always returns a non-negative number between zero and 2.

Function: atan2 y x
Returns the angle, in radians, whose tangent is y/x. atan2 always returns a number between - and .


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.5 Numeric Type Conversions

These functions are provided to allow specific conversions of data types to be forced, when desired.

Function: fix x
Converts x from a flonum (or small-flonum) to an integer, truncating towards negative infinity. The result is a fixnum or a bignum as appropriate. If x is already a fixnum or a bignum, it is returned unchanged.

Function: fixr x
Converts x from a flonum (or small-flonum) to an integer, rounding to the nearest integer. If x is exactly halfway between two integers, this rounds up (towards positive infinity). fixr could have been defined by:
 
(defun fixr (x)
  (if (fixp x) x (fix (+ x 0.5))))

Function: float x
Converts any kind of number to a flonum.

Function: small-float x
Converts any kind of number to a small flonum.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.6 "Logical Operations on Numbers"

Except for lsh and rot, these functions operate on both fixnums and bignums. lsh and rot have an inherent word-length limitation and hence only operate on 24-bit fixnums. Negative numbers are operated on in their 2's-complement representation.

Function: logior &rest args
Returns the bit-wise logical inclusive or of its arguments. At least one argument is required.
 
Example:
(logior 4002 67) => 4067

Function: logxor &rest args
Returns the bit-wise logical exclusive or of its arguments. At least one argument is required.
 
Example:
(logxor 2531 7777) => 5246

Function: logand &rest args
Returns the bit-wise logical and of its arguments. At least one argument is required.
 
Examples:
(logand 3456 707) => 406
(logand 3456 -100) => 3400

Function: lognot number
Returns the logical complement of number. This is the same as logxor'ing number with -1.
 
Example:
(lognot 3456) => -3457

Function: boole fn &rest args
boole is the generalization of logand, logior, and logxor. fn should be a fixnum between 0 and 17 octal inclusive; it controls the function which is computed. If the binary representation of fn is abcd (a is the most significant bit, d the least) then the truth table for the Boolean operation is as follows: .sp
 
       y
   | 0  1
---------
  0| a  c
x  |
  1| b  d

If boole has more than three arguments, it is associated left to right; thus,
 
(boole fn x y z) = (boole fn (boole fn x y) z)
With two arguments, the result of boole is simply its second argument. At least two arguments are required.

 
Examples:
(boole 1 x y) = (logand x y)
(boole 6 x y) = (logxor x y)
(boole 2 x y) = (logand (lognot x) y)

logand, logior, and logxor are usually preferred over the equivalent forms of boole, to avoid putting magic numbers in the program.

Function: bit-test x y
bit-test is a predicate which returns t if any of the bits designated by the 1's in x are 1's in y. bit-test is implemented as a macro which expands as follows:
 
(bit-test x y) ==> (not (zerop (logand x y)))

Function: lsh x y
Returns x shifted left y bits if y is positive or zero, or x shifted right |y| bits if y is negative. Zero bits are shifted in (at either end) to fill unused positions. x and y must be fixnums. (In some applications you may find ash useful for shifting bignums; see below.)
 
Examples:
(lsh 4 1) => 10    ;(octal)
(lsh 14 -2) => 3
(lsh -1 1) => -2

Function: ash x y
Shifts x arithmetically left y bits if y is positive, or right -y bits if y is negative. Unused positions are filled by zeroes from the right, and by copies of the sign bit from the left. Thus, unlike lsh, the sign of the result is always the same as the sign of x. If x is a fixnum or a bignum, this is a shifting operation. If x is a flonum, this does scaling (multiplication by a power of two), rather than actually shifting any bits.

Function: rot x y
Returns x rotated left y bits if y is positive or zero, or x rotated right |y| bits if y is negative. The rotation considers x as a 24-bit number (unlike Maclisp, which considers x to be a 36-bit number in both the pdp-10 and Multics implementations). x and y must be fixnums. (There is no function for rotating bignums.)
 
Examples:
(rot 1 2) => 4
(rot 1 -2) => 20000000
(rot -1 7) => -1
(rot 15 24.) => 15

Function: haulong x
This returns the number of significant bits in |x|. x may be a fixnum or a bignum. Its sign is ignored. The result is the least integer strictly greater than the base-2 logarithm of |x|.
 
Examples:
(haulong 0) => 0
(haulong 3) => 2
(haulong -7) => 3

Function: haipart x n
Returns the high n bits of the binary representation of |x|, or the low -n bits if n is negative. x may be a fixnum or a bignum; its sign is ignored. haipart could have been defined by:
 
(defun haipart (x n)
  (setq x (abs x))
  (if (minusp n)
      (logand x (1- (ash 1 (- n))))
      (ash x (min (- n (haulong x))
		  0))))


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.7 "Byte Manipulation Functions"

.setq byte-manipulation-functions section-page Several functions are provided for dealing with an arbitrary-width field of contiguous bits appearing anywhere in an integer (a fixnum or a bignum). Such a contiguous set of bits is called a byte. Note that we are not using the term byte to mean eight bits, but rather any number of bits within a number. These functions use numbers called byte specifiers to designate a specific byte position within any word. Byte specifiers are fixnums whose two lowest octal digits represent the size of the byte, and whose higher (usually two, but sometimes more) octal digits represent the position of the byte within a number, counting from the right in bits. A position of zero means that the byte is at the right end of the number. For example, the byte-specifier 0010 (i.e. 10 octal) refers to the lowest eight bits of a word, and the byte-specifier 1010 refers to the next eight bits. These byte-specifiers will be stylized below as ppss. The maximum value of the ss digits is 27 (octal), since a byte must fit in a fixnum although bytes can be loaded from and deposited into bignums. (Bytes are always positive numbers.) The format of byte-specifiers is taken from the pdp-10 byte instructions.

Function: ldb ppss num
ppss specifies a byte of num to be extracted. The ss bits of the byte starting at bit pp are the lowest ss bits in the returned value, and the rest of the bits in the returned value are zero. The name of the function, ldb, means "load byte". num may be a fixnum or a bignum. The returned value is always a fixnum.
 
Example:
(ldb 0306 4567) => 56

Function: load-byte num position size
This is like ldb except that instead of using a byte specifier, the position and size are passed as separate arguments. The argument order is not analogous to that of ldb so that load-byte can be compatible with Maclisp.

Function: ldb-test ppss y
ldb-test is a predicate which returns t if any of the bits designated by the byte specifier ppss are 1's in y. That is, it returns t if the designated field is non-zero. ldb-test is implemented as a macro which expands as follows:
 
(ldb-test ppss y) ==> (not (zerop (ldb ppss y)))

Function: mask-field ppss num
This is similar to ldb; however, the specified byte of num is returned as a number in position pp of the returned word, instead of position 0 as with ldb. num must be a fixnum.
 
Example:
(mask-field 0306 4567) => 560

Function: dpb byte ppss num
Returns a number which is the same as num except in the bits specified by ppss. The low ss bits of byte are placed in those bits. byte is interpreted as being right-justified, as if it were the result of ldb. num may be a fixnum or a bignum. The name means "deposit byte".
 
Example:
(dpb 23 0306 4567) => 4237

Function: deposit-byte num position size byte
This is like dpb except that instead of using a byte specifier, the position and size are passed as separate arguments. The argument order is not analogous to that of dpb so that deposit-byte can be compatible with Maclisp.

Function: deposit-field byte ppss num
This is like dpb, except that byte is not taken to be left-justified; the ppss bits of byte are used for the ppss bits of the result, with the rest of the bits taken from num. num must be a fixnum.
 
Example:
(deposit-field 230 0306 4567) => 4237

The behavior of the following two functions depends on the size of fixnums, and so functions using them may not work the same way on future implementations of Zetalisp. Their names start with "%" because they are more like machine-level subprimitives than the previous functions.

Function: %logldb ppss fixnum
%logldb is like ldb except that it only loads out of fixnums and allows a byte size of 30 (octal), i.e. all 24. bits of the fixnum including the sign bit.

Function: %logdpb byte ppss fixnum
%logdpb is like dpb except that it only deposits into fixnums. Using this to change the sign-bit will leave the result as a fixnum, while dpb would produce a bignum result for arithmetic correctness. %logdpb is good for manipulating fixnum bit-masks such as are used in some internal system tables and data-structures.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.8 "Random Numbers"

The functions in this section provide a pseudo-random number generator facility. The basic function you use is random, which returns a new pseudo-random number each time it is called. Between calls, its state is saved in a data object called a random-array. Usually there is only one random-array; however, if you want to create a reproducible series of pseudo-random numbers, and be able to reset the state to control when the series starts over, then you need some of the other functions here.

Function: random &optional arg random-array
(random) returns a random fixnum, positive or negative. If arg is present, a fixnum between 0 and arg minus 1 inclusive is returned. If random-array is present, the given array is used instead of the default one (see below). Otherwise, the default random-array is used (and is created if it doesn't already exist). The algorithm is executed inside a without-interrupts (see (without-interrupts-fun)) so two processes can use the same random-array without colliding.

A random-array consists of an array of numbers, and two pointers into the array. The pointers circulate around the array; each time a random number is requested, both pointers are advanced by one, wrapping around at the end of the array. Thus, the distance forward from the first pointer to the second pointer, allowing for wraparound, stays the same. Let the length of the array be length and the distance between the pointers be offset. To generate a new random number, each pointer is set to its old value plus one, modulo length. Then the two elements of the array addressed by the pointers are added together; the sum is stored back into the array at the location where the second pointer points, and is returned as the random number after being normalized into the right range.

This algorithm produces well-distributed random numbers if length and offset are chosen carefully, so that the polynomial x^length+x^offset+1 is irreducible over the mod-2 integers. The system uses 71. and 35.

The contents of the array of numbers should be initialized to anything moderately random, to make the algorithm work. The contents get initialized by a simple random number generator, based on a number called the seed. The initial value of the seed is set when the random-array is created, and it can be changed. To have several different controllable resettable sources of random numbers, you can create your own random-arrays. If you don't care about reproducibility of sequences, just use random without the random-array argument.

Function: si:random-create-array length offset seed &optional (area nil)
Creates, initializes, and returns a random-array. length is the length of the array. offset is the distance between the pointers and should be an integer less than length. seed is the initial value of the seed, and should be a fixnum. This calls si:random-initialize on the random array before returning it.

Function: si:random-initialize array &optional new-seed
array must be a random-array, such as is created by si:random-create-array. If new-seed is provided, it should be a fixnum, and the seed is set to it. si:random-initialize reinitializes the contents of the array from the seed (calling random changes the contents of the array and the pointers, but not the seed).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.9 "24-Bit Numbers"

Sometimes it is desirable to have a form of arithmetic which has no overflow checking (which would produce bignums), and truncates results to the word size of the machine. In Zetalisp, this is provided by the following set of functions. Their answers are only correct modulo 2^24. These functions should not be used for "efficiency"; they are probably less efficient than the functions which do check for overflow. They are intended for algorithms which require this sort of arithmetic, such as hash functions and pseudo-random number generation.

Function: %24-bit-plus x y
Returns the sum of x and y modulo 2^24. Both arguments must be fixnums.

Function: %24-bit-difference x y
Returns the difference of x and y modulo 2^24. Both arguments must be fixnums.

Function: %24-bit-times x y
Returns the product of x and y modulo 2^24. Both arguments must be fixnums.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.10 "Double-Precision Arithmetic"

These peculiar functions are useful in programs that don't want to use bignums for one reason or another. They should usually be avoided, as they are difficult to use and understand, and they depend on special numbers of bits and on the use of two's-complement notation.

Function: %multiply-fractions num1 num2
Returns bits 24 through 46 (the most significant half) of the product of num1 and num2. If you call this and %24-bit-times on the same arguments num1 and num2, regarding them as integers, you can combine the results into a double-precision product. If num1 and num2 are regarded as two's-complement fractions, -1  num < 1, %multiply-fractions returns 1/2 of their correct product as a fraction. (The name of this function isn't too great.)

Function: %divide-double dividend[24:46] dividend[0:23] divisor
Divides the double-precision number given by the first two arguments by the third argument, and returns the single-precision quotient. Causes an error if division by zero or if the quotient won't fit in single precision.

Function: %remainder-double dividend[24:46] dividend[0:23] divisor
Divides the double-precision number given by the first two arguments by the third argument, and returns the remainder. Causes an error if division by zero.

Function: %float-double high24 low24
high24 and low24, which must be fixnums, are concatenated to produce a 48-bit unsigned positive integer. A flonum containing the same value is constructed and returned. Note that only the 31 most-significant bits are retained (after removal of leading zeroes.) This function is mainly for the benefit of read.


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Brad Parker on June, 13 2006 using texi2html