.c .c .c
9. Numbers

Lisp Machine Lisp 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. In Lisp Machine Lisp, 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 Lisp Machine Lisp are:
fixnumFixnums are 24-bit 2's complement binary integers. These are the "preferred, most efficient" type of number.
bignumBignums are arbitrary-precision binary integers.
flonumFlonums 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-flonumSmall 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. Small flonums are useful because, like fixnums, they don't require any storage. Computing with small flonums is more efficient than with regular flonums.
Numbers are different from other objects in that they don't "have identity." To put it another way, eq does not work on them. Numbers do not behave "like objects." 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. The Lisp machine automatically converts between fixnums and bignums as necessary when computing with integers. That is, if the result of a computation with fixnums is too large to be represented as a fixnum, it will be represented as a bignum. If the result of a computation with bignums is small enough to be represented as a fixnum, it will be. The Lisp machine never automatically converts between flonums and small flonums, since this would lead either to inefficiency or to unexpected numerical inaccuracies. The user controls whether floating-point calculations are done in large or small precision by the type of the original input data. 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. This will signal an error. 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 a fixnum meets a bignum, the result is (usually) a bignum. When a fixnum or a bignum 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. Unlike Maclisp, Lisp Machine Lisp does not have number declarations in the compiler. Note that because fixnums and small flonums are "inums" (require no associated storage) they are as efficient as declared numbers in Maclisp. The different types of numbers are distinguished by their printed representations. A leading or embedded 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 be accidentally tricked into computing with the lesser precision. Fixnums and bignums have similar printed representations; the number is a bignum if it is too big to be a fixnum.

9.1 Numeric Predicates
zerop x
Returns t if x is zero. Otherwise it returns nil . If x is not a number, zerop causes an error.
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.
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.
oddp number
Returns t if number is odd, otherwise nil . If number is not a fixnum or a bignum, oddp causes an error.
evenp number
Returns t if number is even, otherwise nil . If number is not a fixnum or a bignum, evenp causes an error.
signp Special Form
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 test x) returns t if x is a number which satisfies the test , nil if it is not. test is not evaluated, but x is. test can be one of the following:
lx < 0
lex ≤ 0
ex = 0
nx ≠ 0
gex ≥ 0
gx > 0
Examples:
(signp le 12) => t
(signp n 0) => nil
(signp g 'foo) => nil
See also the data-type predicates fixp , floatp , bigp , small-floatp , and numberp (LINK:(fixp-fun)). 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.
= x y
Returns t if x and y are numerically equal.
greaterp 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
> x y
Returns t if x is strictly greater than y , and nil otherwise.
>= x y Macro
≥ x y Macro
Returns t if x is greater than or equal to y , and nil otherwise.
lessp 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
< x y
Returns t if x is strictly less than y , and nil otherwise.
<= x y Macro
≤ x y Macro
Returns t if x is less than or equal to y , and nil otherwise.
≠ x y Macro
Returns t if x is not equal to y , and nil otherwise.
9.2 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.
plus &rest args
+ &rest args
+$ &rest args
Returns the sum of its arguments. If there are no arguments, it returns 0, which is the identity for this operation.
difference arg &rest args
Returns its first argument minus all of the rest of its arguments.
- arg &rest args
-$ 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.
times &rest args
* &rest args
*$ &rest args
Returns the product of its arguments. If there are no arguments, it returns 1, which is the identity for this operation.
quotient arg &rest args
Returns the first argument divided by all of the rest of its arguments.
// arg &rest args
//$ 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) .
Examples:
(// 3 2) => 1       ;Fixnum division truncates. 
(// 3 2.0) => 1.5
(// 3 2.0s0) => 1.5s0
(// 4 2) => 2
(// 12. 2. 3.) => 2
add1 x
1+ x
1+$ x
(add1 x) is the same as (plus x 1) .
sub1 x
1- x
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.
remainder x y
\ x y
Returns the remainder of x divided by y . x and y may not be flonums nor small flonums.
gcd x y
\\ x y
Returns the greatest common divisor of x and y . x and y may not be flonums nor small flonums.
expt x y
^ x y
^$ x y
Returns x raised to the y 'th power. y must be a fixnum. [I guess this is incompatible with Maclisp.]
exp x
Returns e raised to the x 'th power, where e is the base of natural logarithms.
log x
Returns the natural logarithm of x .
sin x
Returns the sine of x in radians.
sind x
Returns the sine of x in degrees.
cos x
Returns the cosine of x in radians.
cosd x
Returns the cosine of x in degrees.
sqrt x
Returns the square root of x .
atan y x
Returns the arctangent of the angle y/x . It always returns a non-negative number between zero and π/2.
atan2 y x
Returns the arctangent of the angle y/x , except that it returns a number between -π/2 and π/2.
max &rest args
max returns the largest of its arguments.
Example:
(max 1 3 2) => 3
max requires at least one argument.
min &rest args
min returns the smallest of its arguments.
Example:
(min 1 3 2) => 1
min requires at least one argument.
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)))
minus x
Returns the negative of x .
Examples:
(minus 1) => -1
(minus -3) => 3
*dif x y
*plus x y
*quo x y
*times x y
These are the internal micro-coded arithmetic functions. There is no reason why anyone should need to refer to these explicitly, since the compiler knows how to generate the appropriate code for plus , + , etc. These names are only here for Maclisp compatibility.
The following functions are provided to allow specific conversions of data types to be forced, when desired.
fix x
Converts x from a flonum (or small-flonum) to an integer, by truncation. The result is a fixnum or a bignum as appropriate. If x is already a fixnum or a bignum, it is returned unchanged.
fixr x
Converts x from a flonum (or small-flonum) to an integer, by truncation.
float x
Converts x to a flonum. x may be a fixnum, a bignum, a small-flonum, or a flonum.
small-float x
Converts x to a small flonum. x may be a fixnum, a bignum, a small-flonum, or a flonum.
9.3 Random Functions
random &optional arg (array si:random-array )
(random) returns a random fixnum, positive or negative. If arg is present, a fixnum between 0 and arg -1 inclusive is returned. If array is present, the given array is used instead of the default one (see below). [The random algorithm should be described.]
si:random-create-array size offset seed &optional (area default-array-area )
Creates, initializes and returns a random-number-generator array. This is used for more advanced applications of the pseudo-random number generator, in which it is desirable to have several different controllable resettable sources of random numbers. For the exact meaning of the arguments, read the code. size is the size of the array, offset is an integer less than size , seed is a fixnum. This calls si:random-initialize on the random array before returning it.
si:random-initialize array
array must be a random-number-generator array, such as is created by si:random-create-array . It reinitializes the contents of the array from the seed (calling random changes the contents of the array and the pointers, but not the seed).
si:random-array Variable
The value of si:random-array is the default random-number-generator array. It is created if random is called and si:random-array is unbound. A random-number-generator array has a leader which is a structure with the following elements: 3
si:random-fill-pointer
The fill-pointer, the length of the array.
si:random-seedThe seed from which to initialize the contents.
si:random-pointer-1
The first pointer.
si:random-pointer-2
The second pointer.
9.4 Logical Operations on Numbers
Except for lsh and rot , these functions operate on either fixnums or 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. (Negative numbers used to be disallowed in some cases.)
logior &rest args
Returns the bit-wise logical inclusive or of its arguments. A minimum of one argument is required.
Example:
(logior 4002 67) => 4067
logxor &rest args
Returns the bit-wise logical exclusive or of its arguments. A minimum of one argument is required.
Example:
(logxor 2531 7777) => 5246
logand &rest args
Returns the bit-wise logical and of its arguments. A minimum of one argument is required.
Examples:
(logand 3456 707) => 406
(logand 3456 -100) => 3400
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. A minimum of two arguments is required.
Examples:
(boole 1 x y) = (logand x y)
(boole 6 x y) = (logxor x y)
logand , logior , and logxor are usually preferred over boole .
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 )))
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 )))
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.
Examples:
(lsh 4 1) => 10    ;(octal) 
(lsh 14 -2) => 3
(lsh -1 1) => -2
ash x y
Shifts x arithmetically left y bits, or right -y bits, depending on the sign of y . x may be a fixnum or a bignum. The sign of the result is always the same as the sign of x .
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.
Examples:
(rot 1 2) => 4
(rot 1 -2) => 20000000
(rot -1 7) => -1
(rot 15 24.) => 15
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; note that if x is negative its absolute value is used.
haulong x
This returns the number of significant bits in x . x may be a fixnum or a bignum. The result does not depend on the sign of x . The result is the least integer not less than the base-2 logarithm of |x|+1 .
Examples:
(haulong 0) => 0
(haulong 3) => 2
(haulong -7) => 3
9.5 Byte Manipulation Functions

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.

ldb ppss num
ppss specifies a byte of num , which is returned as a number, right-justified. 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.
Example:
(ldb 0306 4567) => 56
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
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.
Example:
(dpb 23 0306 4567) => 4237
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
%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. the whole fixnum.
%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.
9.6 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 Lisp Machine Lisp, 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.
%24-bit-plus x y
Returns the sum of x and y modulo 2^24. Both arguments should be fixnums.
%24-bit-difference x y
Returns the difference of x and y modulo 2^24. Both arguments should be fixnums.
%24-bit-times x y
Returns the product of x and y modulo 2^24. Both arguments should be fixnums.
9.7 Double-Precision Arithmetic
These peculiar functions are useful in programs that don't want to use bignums for one reason or another.
%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 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.)
%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.
%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.
%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 .