.\" Copyright (c) 1980 Regents of the University of California.
.\" All rights reserved.  The Berkeley software License Agreement
.\" specifies the terms and conditions for redistribution.
.\"
.\"	@(#)ch3.n	6.2 (Berkeley) 5/14/86
.\"
." $Header: ch3.n,v 1.3 83/06/21 13:00:48 sklower Exp $
.Lc Arithmetic\ Functions 3
.pp
This chapter describes 
.Fr "'s"
functions for doing arithmetic.
Often the same function is known by many names.
For example,
.i add
is also
.i plus ,
and
.i sum .
This is caused by our desire to be compatible with other Lisps.
The 
.Fr
user should avoid using functions with names
such as \(pl and \(** unless
their arguments are fixnums.
The Lisp compiler takes advantage of these implicit declarations.
.pp
An attempt to divide or to generate a floating
point result outside of the range of
floating point numbers
will cause a floating exception signal
from the UNIX operating system.
The user can catch and process this interrupt if desired (see the 
description of the
.i signal
function).
.sh 2 Simple\ Arithmetic\ Functions \n(ch 1
.Lf add "['n_arg1 ...]"
.Lx plus "['n_arg1 ...]"
.Lx sum "['n_arg1 ...]"
.Lx \(pl "['x_arg1 ...]"
.Re
the sum of the arguments. If no arguments are given, 0 is returned.
.No
if the size of the partial sum exceeds the limit of a fixnum, the
partial sum will be converted to a bignum.
If any of the arguments are flonums, the partial sum will be 
converted to a flonum when that argument is processed and the 
result will thus be a flonum.
Currently, if in the process of doing the 
addition a bignum must be converted into
a flonum an error message will result.
.Lf add1 'n_arg
.Lx 1+ 'x_arg
.Re
its argument plus 1.
.Lf diff "['n_arg1 ... ]"
.Lx difference "['n_arg1 ... ]"
.Lx \(mi  "['x_arg1 ... ]"
.Re
the result of subtracting from n_arg1 all subsequent arguments. 
If no arguments are given, 0 is returned.
.No
See the description of add for details on data type conversions and
restrictions.
.Lf sub1 "'n_arg"
.Lx 1\(mi "'x_arg"
.Re
its argument minus 1.
.Lf minus "'n_arg"
.Re
zero minus n_arg.
.Lf product "['n_arg1 ... ]"
.Lx times "['n_arg1 ... ]"
.Lx \(** "['x_arg1 ... ]"
.Re
the product of all of its arguments.
It returns 1 if there are no arguments.
.No
See the description of the function \fIadd\fP for details and restrictions to the
automatic data type coercion.
.Lf quotient "['n_arg1 ...]"
.Lx / "['x_arg1 ...]"
.Re
the result of dividing the first argument by succeeding ones.
.No
If there are no arguments, 1 is returned.
See the description of the function \fIadd\fP for details and restrictions
of data type coercion.
A divide by zero will cause a floating exception interrupt -- see 
the description of the
.i signal 
function.
.Lf *quo "'i_x 'i_y"
.Re
the integer part of i_x / i_y.
.Lf Divide "'i_dividend 'i_divisor"
.Re
a list whose car is the quotient and whose cadr is the remainder of the
division of i_dividend by i_divisor.
.No
this is restricted to integer division.
.Lf Emuldiv "'x_fact1 'x_fact2 'x_addn 'x_divisor"
.Re
a list of the quotient and remainder of this operation: 
((x_fact1\ *\ x_fact2)\ +\ (sign\ extended)\ x_addn)\ /\ x_divisor.
.No
this is useful for creating a bignum arithmetic package in Lisp.
.sh 2 predicates
.Lf numberp "'g_arg"
.Lf numbp "'g_arg"
.Re
t iff g_arg is a number (fixnum, flonum or bignum).
.Lf fixp "'g_arg"
.Re
t iff g_arg is a fixnum or bignum.
.Lf floatp "'g_arg"
.Re
t iff g_arg is a flonum.
.Lf evenp "'x_arg"
.Re
t iff x_arg is even.
.Lf oddp "'x_arg"
.Re
t iff x_arg is odd.
.Lf zerop "'g_arg"
.Re
t iff g_arg is a number equal to 0.
.Lf onep "'g_arg"
.Re
t iff g_arg is a number equal to 1.
.Lf plusp "'n_arg"
.Re
t iff n_arg is greater than zero.
.Lf minusp "'g_arg"
.Re
t iff g_arg is a negative number.
.Lf greaterp "['n_arg1 ...]"
.Lx > "'fx_arg1 'fx_arg2"
.Lx >& "'x_arg1 'x_arg2"
.Re
t iff the arguments are in a strictly decreasing order.
.No
In functions
.i greaterp
and
.i >
the function 
.i difference 
is used to compare adjacent values. 
If any of the arguments are non-numbers, the error message will come 
from the 
.i difference 
function.
The arguments to 
.i >
must  be fixnums or both flonums.
The arguments to
.i >&
must both be fixnums.
.Lf lessp "['n_arg1 ...]"
.Lx < "'fx_arg1 'fx_arg2"
.Lx <& "'x_arg1 'x_arg2"
.Re
t iff the arguments are in a strictly increasing order.
.No
In functions
.i lessp
and
.i <
the function \fIdifference\fP is used to compare adjacent values. 
If any of the arguments are non numbers, the error message will come 
from the \fIdifference\fP function.
The arguments to 
.i < 
may be either fixnums or flonums but must be the same type.
The arguments to
.i <&
must be fixnums.
.Lf \(eq "'fx_arg1 'fx_arg2"
.Lf \(eq& "'x_arg1 'x_arg2"
.Re
t iff the arguments have the same value.
The arguments to \(eq must be the either both fixnums or both flonums.
The arguments to \(eq& must be fixnums.
.sh 2 Trignometric\ Functions 
.pp
Some of these funtcions are taken from the host math library, and
we take no further responsibility for their accuracy.
.Lf cos "'fx_angle"
.Re
the (flonum) cosine of fx_angle (which is assumed to be in radians).
.Lf sin "'fx_angle"
.Re
the sine of fx_angle (which is assumed to be in radians).
.Lf acos "'fx_arg"
.Re
the (flonum) arc cosine of fx_arg in the range 0 to \(*p.
.Lf asin "'fx_arg"
.Re
the (flonum) arc sine of fx_arg in the range \(mi\(*p/2 to \(*p/2.
.Lf atan "'fx_arg1 'fx_arg2"
.Re
the (flonum) arc tangent of fx_arg1/fx_arg2 in the range -\(*p to \(*p.
.sh 2 Bignum/Fixnum\ Manipulation
.Lf haipart "bx_number x_bits"
.Re
a fixnum (or bignum) which contains
the x_bits high bits of
\fI(abs\ bx_number)\fP if x_bits is positive, otherwise
it returns the \fI(abs\ x_bits)\fP low bits of \fI(abs\ bx_number)\fP.
.Lf haulong "bx_number"
.Re
the number of significant bits in bx_number.
.No
the result is equal to the least integer greater to or equal to the
base two logarithm of
one plus the absolute value of bx_number.
.Lf bignum-leftshift "bx_arg x_amount"
.Re
bx_arg shifted left by x_amount.  If
x_amount is negative, bx_arg will be shifted right by the magnitude of
x_amount.
.No
If bx_arg is shifted right, it will be rounded to the nearest even number.
.Lf sticky-bignum-leftshift "'bx_arg 'x_amount"
.Re
bx_arg shifted left by x_amount.  If
x_amount is negative, bx_arg will be shifted right by the magnitude of
x_amount and rounded.
.No
sticky rounding is done this way: after shifting,
the low order bit is changed to 1
if any 1's were shifted off to the right.
.sh 2 Bit\ Manipulation
.Lf boole "'x_key 'x_v1 'x_v2 ..."
.Re
the result of the bitwise boolean operation as described in the following
table.
.No
If there are more than 3 arguments, then evaluation proceeds left to
right with each partial result becoming the new value of x_v1.
That is, 
.br
\ \ \ \ \ \fI(boole\ 'key\ 'v1\ 'v2\ 'v3)\ \(==\ (boole\ 'key\ (boole\ 'key\ 'v1\ 'v2)\ 'v3)\fP.
.br
In the following table, \(** represents bitwise and, \(pl represents
bitwise or, \o'\(ci\(pl' represents bitwise xor and \(no represents
bitwise negation and is the highest precedence operator.
.ps 8
.(b
.TS
center box ;
c s s s s s s s s
c c c c c c c c c.
(boole 'key 'x 'y)

=
key	0	1	2	3	4	5	6	7
result	0	x \(** y	\(no x \(** y	y	x \(** \(no y	x	x \o'\(ci\(pl' y	x \(pl y

common
names		and			bitclear		xor	or	

_

key	8	9	10	11	12	13	14	15
result	\(no (x \(pl y)	\(no(x \o'\(ci\(pl' y)	\(no x	\(no x \(pl y	\(no y	x \(pl \(no y	\(no x \(pl \(no y	-1
common
names	nor	equiv		implies			nand
.TE
.)b
.ps 10
.pp
.Lf lsh "'x_val 'x_amt"
.Re
x_val shifted left by x_amt if x_amt is positive.
If x_amt is negative, then 
.i lsh
returns x_val shifted right by the magnitude if x_amt.
.No
This always returns a fixnum even for those numbers whose magnitude is
so large that they would normally be represented as a bignum,
i.e. shifter bits are lost.
For more general bit shifters, see
.i bignum-leftshift
and
.i sticky-bignum-leftshift.
.Lf rot "'x_val 'x_amt"
.Re
x_val rotated left by x_amt if x_amt is positive. 
If x_amt is negative, then x_val is rotated right by the magnitude of x_amt.
.sh 2 Other\ Functions
.pp
As noted above, some of the following functions are inherited from the
host math library, with all their virtues and vices.
.Lf abs 'n_arg
.Lx absval 'n_arg
.Re
the absolute value of n_arg.
.Lf exp "'fx_arg"
.Re
.i e
raised to the fx_arg power (flonum) .
.Lf expt "'n_base 'n_power"
.Re
n_base raised to the n_power power.
.No
if either of the arguments are flonums, the calculation will be done using
.i log
and 
.i exp .
.Lf fact "'x_arg"
.Re
x_arg factorial. (fixnum or bignum)
.Lf fix "'n_arg"
.Re
a fixnum as close as we can get to n_arg.
.No
\fIfix\fP will round down.
Currently, if n_arg is a flonum larger 
than the size of a fixnum, this will fail.
.Lf float "'n_arg"
.Re
a flonum as close as we can get to n_arg.
.No
if n_arg is a bignum larger than the maximum size of a flonum,
then a floating exception will occur.
.Lf log "'fx_arg"
.Re
the natural logarithm of fx_arg.
.Lf max "'n_arg1 ... "
.Re
the maximum value in the list of arguments.
.Lf min "'n_arg1 ... "
.Re
the minimum value in the list of arguments.
.Lf mod "'i_dividend 'i_divisor"
.Lx remainder "'i_dividend 'i_divisor"
.Re
the remainder when i_dividend is divided by i_divisor.
.No
The sign of the result will have the same sign as i_dividend.
.Lf *mod "'x_dividend 'x_divisor"
.Re
the balanced representation of x_dividend modulo x_divisor.
.No
the range of the balanced representation is abs(x_divisor)/2 to 
(abs(x_divisor)/2) \(mi x_divisor + 1.
.Lf random "['x_limit]"
.Re
a fixnum between 0 and x_limit \(mi 1 if x_limit is given.
If x_limit is not given, any fixnum, positive or negative, might be
returned.
.Lf sqrt "'fx_arg"
.Re
the square root of fx_arg.
