{Begin Chapter Numbers and Arithmetic Functions}
{Title Numbers and Arithmetic Functions}
{Text

{Tag Numbers}
{Tag SmallIntegers}


{index *PRIMARY* Numbers}
{index *PRIMARY* Arithmetic}

Numerical atoms, or simply numbers, do not have value cells, function definition cells, property lists, or explicit print names.  There are four different types of numbers in Interlisp: small integers,{index *PRIMARY* Small integers} large integers,{index *PRIMARY* Large integers} bignums (arbitrary-size integers),{index *PRIMARY* Bignums}{index *PRIMARY* Arbitrary-size integers} and floating point numbers.{index Floating point numbers}  Small integers are those integers that can be directly stored within a pointer value (implementation-dependent).  Large integers and floating point numbers are full-word quantities that are stored by "boxing" the number (see below).  Bignums are "boxed" as a series of words.


{index *PRIMARY* Boxing numbers}
{index *PRIMARY* Unboxing numbers}
{Tag Boxing}

Large integers and floating point numbers can be any full word quantity.  In order to distinguish between those full word quantities that represent large integers or floating point numbers, and other Interlisp pointers, these numbers are "boxed":  When a large integer or floating point number is created (via an arithmetic operation or by {fn READ}), Interlisp gets a new word from "number storage" and puts the large integer or floating point number into that word.  Interlisp then passes around the pointer to that word, i.e., the "boxed number", rather than the actual quantity itself.  Then when a numeric function needs the actual numeric quantity, it performs the extra level of addressing to obtain the "value" of the number.  This latter process is called "unboxing".  Note that unboxing does not use any storage, but that each boxing operation uses one new word of number storage.  Thus, if a computation creates many large integers{index Large integers} or floating point numbers,{index Floating point numbers} i.e., does lots of boxes, it may cause a garbage collection of large integer space, or of floating point number space.


Note:  Different implementations of Interlisp may use different boxing strategies.  Thus, while lots of arithmetic operations {it may} lead to garbage collections, this is not necessarily always the case.

{note add something about how bignums are boxed???}


The following functions can be used to distinguish the different types of numbers:


{index *PRIMARY* SMALLP Fn}
{FnDef {FnName SMALLP} {FnArgs X}
{Text
Returns {arg X}, if {arg X} is a small integer;  {lisp NIL} otherwise.  Does {it not} generate an error if {arg X} is not a number.
}}


{index *PRIMARY* FIXP Fn}
{FnDef {FnName FIXP} {FnArgs X}
{Text
Returns {arg X}, if {arg X} is an integer; {lisp NIL} otherwise.  Note that {fn FIXP} is true for small integers, large integers, and bignums.  Does {it not} generate an error if {arg X} is not a number.
}}


{index *PRIMARY* FLOATP Fn}
{FnDef {FnName FLOATP} {FnArgs X}
{Text
Returns {arg X} if {arg X} is a floating point number;  {lisp NIL} otherwise.  Does {it not} give an error if {arg X} is not a number.
}}


{index *PRIMARY* NUMBERP Fn}
{FnDef {FnName NUMBERP} {FnArgs X}
{Text
Returns {arg X}, if {arg X} is a number of any type ({lisp FIXP} or {lisp FLOATP});  {lisp NIL} otherwise.  Does {it not} generate an error if {arg X} is not a number.

Note that if {lisp (NUMBERP {arg X})} is true, then either {lisp (FIXP {arg X})} or {lisp (FLOATP {arg X})} is true.
}}


Each small integer has a unique representation, so {fn EQ} may be used to check equality.  Note that {fn EQ} should not be used for large integers,{index Large integers} bignums, or floating point numbers,{index Floating point numbers} {index EQP FN}{fn EQP}, {fn IEQP}, or {index EQUAL FN}{fn EQUAL} must be used instead.

{FnDef {FnName EQP} {FnArgs X Y}
{Text
Returns {lisp T}, if {arg X} and {arg Y} are {fn EQ}, or equal numbers; {lisp NIL} otherwise.  Note that {fn EQ} may be used if {arg X} and {arg Y} are known to be {it small} integers.  {fn EQP} does not convert {arg X} and {arg Y} to integers, e.g., {lisp (EQP 2000 2000.3)  =>  NIL}, but it can be used to compare an integer and a floating point number, e.g., {lisp (EQP 2000 2000.0)  =>  T}.  {fn EQP} does {it not} generate an error if {arg X} or {arg Y} are not numbers.

Note:  {fn EQP} can also be used to compare stack pointers ({PageRef Tag EQPStackPointers}) and compiled code objects ({PageRef Tag EQPCompiledCode}).
}}


{index *PRIMARY* Floating point overflow}
{index *PRIMARY* Overflow of floating point numbers}
{index *PRIMARY* Division by zero}

The action taken on division by zero and floating point overflow is determined with the following function:

{FnDef {Name OVERFLOW} {Args FLG}
{Text
Sets a flag that determines the system response to arithmetic overflow (for floating point arithmetic) and division by zero; returns the previous setting.

For integer arithmetic:  If {arg FLG}={lisp T}, an error occurs on division by zero.  If {arg FLG}={lisp NIL} or {lisp 0}, integer division by zero returns zero.  Integer overflow cannot occur, because small integers are converted to bignums ({PageRef Term Bignums}).

For floating point arithmetic:  If {arg FLG}={lisp T}, an error occurs on floating overflow{index OVERFLOW Error} or floating division by zero.  If {arg FLG}={lisp NIL} or {lisp 0}, the largest (or smallest) floating point number is returned as the result of the overflowed computation or floating division by zero.

The default value for {fn OVERFLOW} is {lisp T}, meaning to cause an error on division by zero or floating overflow.
}}



{Begin SubSec Generic Arithmetic}
{Title Generic Arithmetic}
{Text

{index *PRIMARY* Generic arithmetic}

The functions in this section are "generic" arithmetic functions.  If any of the arguments are floating point numbers ({PageRef Term floating point numbers}), they act exactly like floating point functions, and float all arguments, and return a floating point number as their value.  Otherwise, they act like the integer functions ({PageRef Term integers}).  If given a non-numeric argument, they generate an error, {lisp NON-NUMERIC ARG}.{index NON-NUMERIC ARG Error}


{FnDef {FnName PLUS} {FnArgs X{SUB 1} X{SUB 2} {ellipsis} X{SUB N}}
{Type NOSPREAD}
{Text
{arg X{sub 1}} + {arg X{sub 2}} + {ellipsis} + {arg X{sub N}}.
}}



{FnDef {FnName MINUS} {FnArgs X}
{Text
- {arg X}
}}



{FnDef {FnName DIFFERENCE} {FnArgs X Y}
{Text
{arg X} - {arg Y}
}}



{FnDef {FnName TIMES} {FnArgs X{SUB 1} X{SUB 2} {ellipsis} X{SUB N}}
{Type NOSPREAD}
{Text
{arg X{sub 1}} * {arg X{sub 2}} * {ellipsis} * {arg X{sub N}}
}}



{FnDef {FnName QUOTIENT} {FnArgs X Y}
{Text
If {arg X} and {arg Y} are both integers, returns the integer division of {arg X} and {arg Y}.  Otherwise, converts both {arg X} and {arg Y} to floating point numbers, and does a floating point division.

The results of division by zero and floating point overflow is determined by the function {fn OVERFLOW} ({PageRef Fn OVERFLOW}).
}}



{FnDef {FnName REMAINDER} {FnArgs X Y}
{Text
If {arg X} and {arg Y} are both integers, returns
{lisp (IREMAINDER {arg X} {arg Y})}, otherwise {lisp (FREMAINDER {arg X} {arg Y})}.
}}



{FnDef {FnName GREATERP} {FnArgs X Y}
{Text
{lisp T}, if {arg X} > {arg Y}, {lisp NIL} otherwise.
}}



{FnDef {FnName LESSP} {FnArgs X Y}
{Text
{lisp T} if {arg X} < {arg Y}, {lisp NIL} otherwise.
}}



{FnDef {FnName GEQ} {FnArgs X Y}
{Text
{lisp T}, if {arg X} {GE} {arg Y}, {lisp NIL} otherwise.
}}



{FnDef {FnName LEQ} {FnArgs X Y}
{Text
{lisp T}, if {arg X} {LE} {arg Y}, {lisp NIL} otherwise.
}}


{FnDef {FnName ZEROP} {FnArgs X}
{Text
{lisp (EQP {arg X} 0)}.
}}


{FnDef {FnName MINUSP} {FnArgs X}
{Text
{lisp T}, if {arg X} is negative; {lisp NIL} otherwise.  Works for both integers and floating point numbers.
}}



{FnDef {FnName MIN} {FnArgs X{SUB 1} X{SUB 2} {ellipsis} X{SUB N}}
{Type NOSPREAD}
{Text
Returns the minimum of {arg X{sub 1}}, {arg X{sub 2}}, {ellipsis}, {arg X{sub N}}.  {lisp (MIN)} returns the value of {var MAX.INTEGER} ({PageRef Var MAX.INTEGER}).
}}



{FnDef {FnName MAX} {FnArgs X{SUB 1} X{SUB 2} {ellipsis} X{SUB N}}
{Type NOSPREAD}
{Text
Returns the maximum of {arg X{sub 1}}, {arg X{sub 2}}, {ellipsis}, {arg X{sub N}}.  {lisp (MAX)} returns the value of {var MIN.INTEGER} ({PageRef Var MIN.INTEGER}).
}}



{FnDef {FnName ABS} {FnArgs X}
{Text
{arg X} if {arg X} > 0, otherwise -{arg X}.  {fn ABS} uses {fn GREATERP} and {fn MINUS} (not {fn IGREATERP} and {fn IMINUS}).
}}



}{End SubSec Generic Arithmetic}




{Begin SubSec Integer Arithmetic}
{Title Integer Arithmetic}
{Text

{index *PRIMARY* Integers}

{index *PRIMARY* Integer input syntax}

The input syntax for an integer is an optional sign ({lisp +} or {lisp -}) followed by a sequence of decimal digits, and terminated by a delimiting character.  Integers entered with this syntax are interpreted as decimal integers.  Integers in other radices can be entered as follows:

{index | (Read Macro)}

{Begin Labeledlist Integers in other radices}

{Label {index *PRIMARY* Octal integers}{index *PRIMARY* Q (following a number)}{lisp 123Q}}
{Label {lisp |o123}}
{Text
If an integer is followed by the letter {lisp Q}, or proceeded by a vertical bar and the letter "o", the digits are interpreted an octal (base 8) integer.
}

{Label {lisp |b10101}}
{Text
If an integer is proceeded by a vertical bar and the letter "b", the digits are interpreted as a binary (base 2) integer.
}

{Label {lisp |x1A90}}
{Text
If an integer is proceeded by a vertical bar and the letter "x", the digits are interpreted as a hexadecimal (base 16) integer.  The upper-case letters {lisp A} though {lisp F} are used as the digits after {lisp 9}.
}

{Label {lisp |5r1243}}
{Text
If an integer is proceeded by a vertical bar, a positive decimal integer {arg BASE}, and the letter "r", the digits are interpreted as an integer in the base {arg BASE}.  For example, {lisp |8r123} = {lisp 123Q}, and {lisp |16r12A3} = {lisp |x12A3}.  When inputting a number in a radix above ten, the upper-case letters {lisp A} through {lisp Z} can be used as the digits after {lisp 9} (but there is no digit above {lisp Z}, so it is not possible to type all base-99 digits).
}

{End Labeledlist Integers in other radices}

Note that {lisp 77Q} and {lisp 63} both correspond to the same integers, and in fact are indistinguishable internally since no record is kept of the syntax used to create an integer.  The function {index RADIX Fn}{fn RADIX} ({PageRef Fn RADIX}), sets the radix used to print integers.

Integers are created by {fn PACK} and {fn MKATOM} when given a sequence of characters observing the above syntax, e.g. {lisp (PACK '(1 2 Q))  =>  10}.  Integers are also created as a result of arithmetic operations.

The range of integers of various types is implementation-dependent.  This information is accessable to the user through the following variables:

{VarDef {Name MIN.SMALLP} }
{VarDef {Name MAX.SMALLP}
{Text
The smallest/largest possible small integer.
}}


{VarDef {Name MIN.FIXP} }
{VarDef {Name MAX.FIXP}
{Text
The smallest/largest possible large integer.
}}


{VarDef {Name MIN.INTEGER} }
{VarDef {Name MAX.INTEGER}
{Text
The smallest/largest possible integers.  For some algorithms, it is useful to have an integer that is larger than any other integer.  Therefore, the values of {var MAX.INTEGER} and {var MIN.INTEGER} are two special bignums; the value of {var MAX.INTEGER} is {fn GREATERP} than any other integer, and the value of {var MIN.INTEGER} is {fn LESSP} than any other integer. Trying to do arithmetic using these special bignums, other than comparison, will cause an error.
}}



{index *PRIMARY* Integer arithmetic}

All of the functions described below work on integers.  Unless specified otherwise, if given a floating point number, they first convert the number to an integer by truncating the fractional bits, e.g., {lisp (IPLUS 2.3 3.8)}={lisp 5}; if given a non-numeric argument,
they generate an error, {lisp NON-NUMERIC ARG}.{index NON-NUMERIC ARG Error}

{note "convert the number to an integer" by rounding or trucating??}

{FnDef {FnName IPLUS} {FnArgs X{SUB 1} X{SUB 2} {ellipsis} X{SUB N}}
{Type NOSPREAD}
{Text
Returns the sum {arg X{sub 1}} + {arg X{sub 2}} + {ellipsis} + {arg X{sub N}}.  {lisp (IPLUS)}={lisp 0}.
}}


{FnDef {FnName IMINUS} {FnArgs X}
{Text
-{arg X}
}}


{FnDef {FnName IDIFFERENCE} {FnArgs X Y}
{Text
{arg X} - {arg Y}
}}


{FnDef {FnName ADD1} {FnArgs X}
{Text
{arg X} + 1
}}


{FnDef {FnName SUB1} {FnArgs X}
{Text
{arg X} - 1
}}



{FnDef {FnName ITIMES} {FnArgs X{SUB 1} X{SUB 2} {ellipsis} X{SUB N}}
{Type NOSPREAD}
{Text
Returns the product {arg X{sub 1}} * {arg X{sub 2}} * {ellipsis} * {arg X{sub N}}.  {lisp (ITIMES)}={lisp 1}.
}}


{FnDef {FnName IQUOTIENT} {FnArgs X Y}
{Text
{arg X} / {arg Y} truncated.  Examples:

{lispcode (IQUOTIENT 3 2)  =>  1}

{lispcode (IQUOTIENT -3 2)  =>  -1}

If {arg Y} is zero, the result is determined by the function {fn OVERFLOW} ({PageRef Fn OVERFLOW}).
}}


{note Interlisp-Vax also returns first arg for (IQUOTIENT X 0) and (IREMAINDER X 0)}


{FnDef {FnName IREMAINDER} {FnArgs X Y}
{Text
Returns the remainder when {arg X} is divided by {arg Y}.  Example:

{lispcode (IREMAINDER 3 2)  =>  1}
}}


{FnDef {FnName IMOD} {FnArgs X N}
{Text
Computes the integer modulus; this differs from {fn IREMAINDER} in that the result is always a non-negative integer in the range {lisp [0,{arg N})}.

{note Macroexpands into a LOGAND when y is a constant power of 2.  An error if either x or y is not a number.}
}}


{FnDef {FnName IGREATERP} {FnArgs X Y}
{Text
{lisp T}, if {arg X} > {arg Y}; {lisp NIL} otherwise.
}}


{FnDef {FnName ILESSP} {FnArgs X Y}
{Text
{lisp T}, if {arg X} < {arg Y}; {lisp NIL} otherwise.
}}



{FnDef {FnName IGEQ} {FnArgs X Y}
{Text
{lisp T}, if {arg X} {GE} {arg Y}; {lisp NIL} otherwise.
}}


{FnDef {FnName ILEQ} {FnArgs X Y}
{Text
{lisp T}, if {arg X} {LE} {arg Y}; {lisp NIL} otherwise.
}}

{FnDef {FnName IMIN} {FnArgs X{SUB 1} X{SUB 2} {ellipsis} X{SUB N}}
{Type NOSPREAD}
{Text
Returns the minimum of {arg X{sub 1}}, {arg X{sub 2}}, {ellipsis}, {arg X{sub N}}.  {lisp (IMIN)} returns the largest possible large integer, the value of {var MAX.INTEGER}.{index MAX.INTEGER Var}
}}


{FnDef {FnName IMAX} {FnArgs X{SUB 1} X{SUB 2} ... X{SUB N}}
{Type NOSPREAD}
{Text
Returns the maximum of {arg X{sub 1}}, {arg X{sub 2}}, {ellipsis}, {arg X{sub N}}.
{lisp (IMAX)} returns the smallest possible large integer, the value of {var MIN.INTEGER}.{index MIN.INTEGER Var}
}}


{FnDef {FnName IEQP} {FnArgs X Y}
{Text
Returns {lisp T} if {arg X} and {arg Y} are {fn EQ} or equal integers; {lisp NIL} otherwise.  Note that {fn EQ} may be used if {arg X} and {arg Y} are known to be {it small} integers.  {fn IEQP} converts {arg X} and {arg Y} to integers, e.g., {lisp (IEQP 2000 2000.3)  =>  T}.  Causes {lisp NON-NUMERIC ARG} error if either {arg X} or {arg Y} are not numbers.
}}


{FnDef {FnName FIX} {FnArgs N}
{Text
If {arg N} is an integer, returns {arg N}.  Otherwise, converts {arg N} to an integer by truncating fractional bits  For example, {lisp (FIX 2.3)  =>  2}, {lisp (FIX -1.7)  =>  -1}.

Note:  Since {lisp FIX} is also a programmer's assistant command ({PageRef PAcom FIX}), typing {lisp FIX} directly to Interlisp will not cause the function {fn FIX} to be called.
}}

{FnDef {FnName FIXR} {FnArgs N}
{Text
If {arg N} is an integer, returns {arg N}.  Otherwise, converts {arg N} to an integer by rounding.  For example, {lisp (FIXR 2.3)  =>  2}, {lisp (FIXR -1.7)  =>  -2}, {lisp (FIXR 3.5)  =>  4)}.
}}


{FnDef {FnName GCD} {FnArgs N1 N2}
{Text
Returns the greatest common divisor of {arg N1} and {arg N2}, e.g., {lisp (GCD 72 64)}={lisp 8}.
}}



}{End SubSec Integer Arithmetic}



{Begin SubSec Logical Arithmetic Functions}
{Title Logical Arithmetic Functions}
{Text

{index *PRIMARY* Logical arithmetic functions}

{FnDef {FnName LOGAND} {FnArgs X{SUB 1} X{SUB 2} {ellipsis} X{SUB N}}
{Type NOSPREAD}
{Text
Returns the logical AND of all its arguments, as an integer.  Example:

{lispcode (LOGAND 7 5 6)  =>  4}
}}


{FnDef {FnName LOGOR} {FnArgs X{SUB 1} X{SUB 2} {ellipsis} X{SUB N}}
{Type NOSPREAD}
{Text
Returns the logical OR of all its arguments, as an integer.  Example:

{lispcode (LOGOR 1 3 9)  =>  11}
}}


{FnDef {FnName LOGXOR} {FnArgs X{SUB 1} X{SUB 2} {ellipsis} X{SUB N}}
{Type NOSPREAD}
{Text
Returns the logical exclusive OR of its arguments, as an integer.  Example:

{lispcode (LOGXOR 11 5)  =>  14}

{lispcode (LOGXOR 11 5 9) = (LOGXOR 14 9)  =>  7}
}}



{FnDef {FnName LSH} {FnArgs X N}
{Text
(arithmetic) "Left Shift."  Returns {arg X} shifted left {arg N} places, with the sign bit unaffected.  {arg X} can be positive or negative.  If {arg N} is negative, {arg X} is shifted {it right} {arg -N} places.
}}


{FnDef {FnName RSH} {FnArgs X N}
{Text
(arithmetic) "Right Shift."  Returns {arg X} shifted right {arg N} places, with the sign bit unaffected, and copies of the sign bit shifted into the leftmost bit.  {arg X} can be positive or negative.  If {arg N} is negative, {arg X} is shifted {it left} {arg -N} places.

Warning:  Be careful if using {fn RSH} to simulate division; {fn RSH}ing a negative number is not generally equivalent to dividing by a power of two.
}}



{FnDef {FnName LLSH} {FnArgs X N} }

{FnDef {FnName LRSH} {FnArgs X N}
{Text
"Logical Left Shift" and "Logical Right Shift".  The difference between a logical and arithmetic right shift lies in the treatment of the sign bit.  Logical shifting treats it just like any other bit; arithmetic shifting will not change it, and will "propagate" rightward when actually shifting rightwards.  Note that shifting (arithmetic) a negative number "all the way" to the right yields -1, not 0.

Note:  {fn LLSH} and {fn LRSH} are currently implemented using mod-2↑32 arithmetic. Passing a bignum to either of these will cause an error.  {fn LRSH} of negative numbers will shift in 0s in the high bits.
}}


{FnDef {FnName INTEGERLENGTH} {FnArgs X}
{Text
Returns the number of bits needed to represent {arg X} (coerced to an integer).  This is equivalent to: 1+floor[log2[abs[{arg X}]]].  {lisp (INTEGERLENGTH 0)} = 0.
}}



{FnDef {FnName POWEROFTWOP} {FnArgs X}
{Text
Returns non-{lisp NIL} if {arg X} (coerced to an integer) is a power of two.
}}



{FnDef {FnName EVENP} {FnArgs X Y}
{Type NOSPREAD}
{Text
If {arg Y} is not given, equivalent to {lisp (ZEROP (IMOD {arg X} 2))}; otherwise equivalent to {lisp (ZEROP (IMOD {arg X} {arg Y}))}.

{note  [CommonLisp specifies an error on non-numeric data, thus defaulting the second argument is different than supplying a NIL for it]}
}}



{FnDef {FnName ODDP} {FnArgs N MODULUS}
{Type NOSPREAD}
{Text
Equivalent to {lisp (NOT (EVENP {arg N} {arg MODULUS}))}. {arg MODULUS} defaults to 2.
}}



{MacDef {Name LOGNOT} {Args N}
{Text
Logical negation of the bits in {arg N}.  Equivalent to {lisp (LOGXOR {arg N} -1)}
}}


{MacDef {Name BITTEST} {Args N MASK}
{Text
Returns {lisp T} if any of the bits in {arg MASK} are on in the number {arg N}.  Equivalent to {lisp (NOT (ZEROP (LOGAND {arg N} {arg MASK})))}
}}


{MacDef {Name BITCLEAR} {Args N MASK}
{Text
Turns off bits from {arg MASK} in {arg N}.  Equivalent to {lisp (LOGAND {arg N} (LOGNOT {arg MASK}))}
}}


{MacDef {Name BITSET} {Args N MASK}
{Text
Turns on the bits from {arg MASK} in {arg N}.  Equivalent to {lisp (LOGOR {arg N} {arg MASK})}
}}


{MacDef {Name MASK.1'S} {Args POSITION SIZE}
{Text
Returns a bit-mask with {arg SIZE} one-bits starting with the bit at {arg POSITION}.  Equivalent to {lisp (LLSH (SUB1 (EXPT 2 {arg SIZE})) {arg POSITION})}
}}


{MacDef {Name MASK.0'S} {Args POSITION SIZE}
{Text
Returns a bit-mask with all one bits, except for {arg SIZE} bits starting at {arg POSITION}.  Equivalent to {lisp (LOGNOT (MASK.1'S {arg POSITION} {arg SIZE}))}
}}


{FnDef {Name LOADBYTE} {Args N POS SIZE}
{Text
Extracts {arg SIZE} bits from {arg N}, starting at position {arg POS}.  Equivalent to {lisp (LOGAND (RSH {arg N} {arg POS}) (MASK.1'S 0 {arg SIZE}))}
}}


{FnDef {Name DEPOSITBYTE} {Args N POS SIZE VAL}
{Text
Insert {arg SIZE} bits of {arg VAL} at position {arg POS} into {arg N}, returning the result.  Equivalent to

{lispcode (LOGOR (BITCLEAR {arg N} (MASK.1'S {arg POS} {arg SIZE}))
       (LSH (LOGAND {arg VAL} (MASK.1'S 0 {arg SIZE}))
            {arg POS}))}
}}



{FnDef {Name ROT} {Args X N FIELDSIZE}
{Text
"Rotate bits in field". It performs a bitwise left-rotation of the integer {arg X}, by {arg N} places, within a field of {arg FIELDSIZE} bits wide.  Bits being shifted out of the position selected by {lisp (EXPT 2 (SUB1 {arg FIELDSIZE}))} will flow into the "units" position.
}}



The notions of position and size can be combined to make up a "byte specifier", which is constructed by the macro {mac BYTE} [note reversal of arguments as compare with above functions]:

{MacDef {Name BYTE} {Args SIZE POSITION}
{Text
Constructs and returns a "byte specifier" containing {arg SIZE} and {arg POSITION}.
}}

{note [currently, byte-specs are implemented as a typerecord; Common Lisp
leaves unspecified whether there are any range limitations on "size" or "pos"]}


{MacDef {Name BYTESIZE} {Args BYTESPEC}
{Text
Returns the {arg SIZE} componant of the "byte specifier" {arg BYTESPEC}.
}}


{MacDef {Name BYTEPOSITION} {Args BYTESPEC}
{Text
Returns the {arg POSITION} componant of the "byte specifier" {arg BYTESPEC}.
}}


{MacDef {Name LDB} {Args BYTESPEC VAL}
{Text
Equivalent to

{lispcode (LOADBYTE {arg VAL}
          (BYTEPOSITION {arg BYTESPEC})
          (BYTESIZE {arg BYTESPEC}))}
}}

{MacDef {Name DPB} {Args N BYTESPEC VAL}
{Text
Equivalent to

{lispcode (DEPOSITBYTE {arg VAL}
             (BYTEPOSITION {arg BYTESPEC}) 
             (BYTESIZE {arg BYTESPEC}) 
             {arg N})}
}}


}{End SubSec Logical Arithmetic Functions}




{Begin SubSec Floating Point Arithmetic}
{Title Floating Point Arithmetic}
{Text


{index *PRIMARY* Floating point numbers}

A floating point number is input as a signed integer, followed by a decimal point, followed by another sequence of digits called the fraction, followed by an exponent (represented by {lisp E}{index *PRIMARY* E (in a floating point number)} followed by a signed integer) and terminated by a delimiter.

Both signs are optional, and either the fraction following the decimal point, or the integer preceding the decimal point may be omitted.{index . (in a floating point number)}  One or the other of the decimal point or exponent may also be omitted, but at least one of them must be present to distinguish a floating point number from an integer.  For example, the following will be recognized as floating point numbers:

{lispcode
5.      5.00    5.01    .3
5E2     5.1E2   5E-3    -5.2E+6}


Floating point numbers are printed using the format control specified by the function {fn FLTFMT} ({PageRef Fn FLTFMT}).  {fn FLTFMT} is initialized to {lisp T}, or free format.  For example, the above floating point numbers would be printed free format as:

{lispcode
5.0     5.0     5.01    .3
500.0   510.0   .005    -5.2E6}


Floating point numbers are created by the read program when a "{lisp .}" or an {lisp E} appears in a number, e.g., {lisp 1000} is an integer, {lisp 1000.} a floating point number, as are {lisp 1E3} and {lisp 1.E3}.  Note that {lisp 1000D}, {lisp 1000F}, and {lisp 1E3D} are perfectly legal literal atoms.  Floating point numbers are also created by {fn PACK} and {fn MKATOM}, and as a result of arithmetic operations.



{fn PRINTNUM} ({PageRef Fn PRINTNUM}) permits greater controls on the printed appearance of floating point numbers, allowing such things as left-justification, suppression of trailing decimals, etc.




The floating point number range is stored in the following variables:

{VarDef {Name MIN.FLOAT}
{Text
The smallest possible floating point number.
}}

{VarDef {Name MAX.FLOAT}
{Text
The largest possible floating point number.
}}



{index *PRIMARY* Floating point arithmetic}

All of the functions described below work on floating point numbers.  Unless specified otherwise, if given an integer, they first convert the number to a floating point number, e.g., {lisp (FPLUS 1 2.3)  <=>  (FPLUS 1.0 2.3)  =>  3.3}; if given a non-numeric argument, they generate an error, {lisp NON-NUMERIC ARG.}{index NON-NUMERIC ARG Error}




{FnDef {FnName FPLUS} {FnArgs X{SUB 1} X{SUB 2} {ellipsis} X{SUB N}}
{Type NOSPREAD}
{Text
{arg X{sub 1}} + {arg X{sub 2}} + {ellipsis} + {arg X{sub N}}
}}



{FnDef {FnName FMINUS} {FnArgs X}
{Text
- {arg X}
}}



{FnDef {FnName FDIFFERENCE} {FnArgs X Y}
{Text
{arg X} - {arg Y}
}}



{FnDef {FnName FTIMES} {FnArgs X{SUB 1} X{SUB 2} {ellipsis} X{SUB N}}
{Type NOSPREAD}
{Text
{arg X{sub 1}} * {arg X{sub 2}} * {ellipsis} * {arg X{sub N}}
}}



{FnDef {FnName FQUOTIENT} {FnArgs X Y}
{Text
{arg X} / {arg Y}.

The results of division by zero and floating point overflow is determined by the function {fn OVERFLOW} ({PageRef Fn OVERFLOW}).
}}



{FnDef {FnName FREMAINDER} {FnArgs X Y}
{Text
Returns the remainder when {arg X} is divided by {arg Y}.  Equivalent to:

{lispcode (FDIFFERENCE {arg X} (FTIMES {arg Y} (FIX (FQUOTIENT {arg X} {arg Y}))))}

Example:

{lispcode (FREMAINDER 7.5 2.3)  =>  0.6}
}}



{FnDef {FnName FGREATERP} {FnArgs X Y}
{Text
{lisp T}, if {arg X} > {arg Y}, {lisp NIL} otherwise.
}}



{FnDef {FnName FLESSP} {FnArgs X Y}
{Text
{lisp T}, if {arg X} < {arg Y}, {lisp NIL} otherwise.
}}



{FnDef {FnName FEQP} {FnArgs X Y}
{Text
Returns {lisp T} if {arg N} and {arg M} are equal floating point numbers; {lisp NIL} otherwise.  {fn FEQP} converts {arg N} and {arg M} to floating point numbers.Causes {lisp NON-NUMERIC ARG} error if either {arg N} or {arg M} are not numbers.
}}



{FnDef {FnName FMIN} {FnArgs X{SUB 1} X{SUB 2} {ellipsis} X{SUB N}}
{Type NOSPREAD}
{Text
Returns the minimum of {arg X{sub 1}}, {arg X{sub 2}}, {ellipsis}, {arg X{sub N}}.
{lisp (FMIN)} returns the largest possible floating point number, the value of {var MAX.FLOAT}.{index MAX.FLOAT Var}
}}



{FnDef {FnName FMAX} {FnArgs X{SUB 1} X{SUB 2} ... X{SUB N}}
{Type NOSPREAD}
{Text
Returns the maximum of {arg X{sub 1}}, {arg X{sub 2}}, {ellipsis}, {arg X{sub N}}.
{lisp (FMAX)} returns the smallest possible floating point number, the value of {var MIN.FLOAT}.{index MIN.FLOAT Var}
}}




{FnDef {FnName FLOAT} {FnArgs X}
{Text
Converts {arg X} to a floating point number.  Example:

{lispcode (FLOAT 0)  =>  0.0}
}}



}{End SubSec Floating Point Arithmetic}




{Begin SubSec Other Arithmetic Functions}
{Title Other Arithmetic Functions}
{text


{FnDef {FnName EXPT} {FnArgs A N}
{Text
Returns {arg A}↑{arg N}.  If {arg A} is an integer and {arg N} is a positive integer, returns an integer, e.g, {lisp (EXPT 3 4)  =>  81}, otherwise returns a floating point number.  If {arg A} is negative and {arg N} fractional, an error is generated, {lisp ILLEGAL EXPONENTIATION}.{index ILLEGAL EXPONENTIATION Error}  If {arg N} is floating and either too large or too small, an error is generated, {index VALUE OUT OF RANGE EXPT Error}{lisp VALUE OUT OF RANGE EXPT}.
}}



{FnDef {FnName SQRT} {FnArgs N}
{Text
Returns the square root of {arg N} as a floating point number.  {arg N} may be fixed or floating point.  Generates an error if {arg N} is negative.{index SQRT OF NEGATIVE VALUE Error}
}}



{FnDef {FnName LOG} {FnArgs X}
{Text
Returns the natural logarithm of {arg X} as a floating point number.  {arg X} can be integer or floating point.
}}



{FnDef {FnName ANTILOG} {FnArgs X}
{Text
Returns the floating point number whose logarithm is {arg X}.  {arg X} can be integer or floating point.  Example:

{lispcode (ANTILOG 1)  =  e  =>  2.71828...}
}}



{FnDef {FnName SIN} {FnArgs X RADIANSFLG}
{Text
Returns the sine of {arg X} as a floating point number.  {arg X} is in degrees unless {arg RADIANSFLG}={lisp T}.
}}



{FnDef {FnName COS} {FnArgs X RADIANSFLG}
{Text
Similar to {fn SIN}.
}}



{FnDef {FnName TAN} {FnArgs X RADIANSFLG}
{Text
Similar to {fn SIN}.
}}



{FnDef {FnName ARCSIN} {FnArgs X RADIANSFLG}
{Text
{arg X} is a number between -1 and 1 (or an error is generated{index ARCSIN: ARG NOT IN RANGE Error}).  The value of {fn ARCSIN} is a floating point number, and is in degrees unless {arg RADIANSFLG}={lisp T}.  In other words, if {lisp (ARCSIN {arg X} {arg RADIANSFLG})}={arg Z} then {lisp (SIN {arg Z} {arg RADIANSFLG})}={arg X}.  The range of the value of {fn ARCSIN} is -90 to +90 for degrees, -{pi}/2 to {pi}/2 for radians.
}}



{FnDef {FnName ARCCOS} {FnArgs X RADIANSFLG}
{Text
Similar to {fn ARCSIN}.  Range is 0 to 180, 0 to {pi}.{index ARCCOS: ARG NOT IN RANGE Error}
}}



{FnDef {FnName ARCTAN} {FnArgs X RADIANSFLG}
{Text
Similar to {fn ARCSIN}.  Range is 0 to 180, 0 to {pi}.
}}



{FnDef {FnName ARCTAN2} {FnArgs Y X RADIANSFLG}
{Text
Computes {lisp (ARCTAN (FQUOTIENT {arg Y} {arg X}) {arg RADIANSFLG})}, and returns a corresponding value in the range -180 to 180 (or -{pi} to {pi}), i.e. the result is in the proper quadrant as determined by the signs of {arg X} and {arg Y}.
}}

{index *PRIMARY* Random numbers}

{FnDef {FnName RAND} {FnArgs LOWER UPPER}
{Text
Returns a pseudo-random number between {arg LOWER} and {arg UPPER} inclusive, i.e., {fn RAND} can be used to generate a sequence of random numbers.  If both limits are integers, the value of {fn RAND} is an integer, otherwise it is a floating point number.  The algorithm is completely deterministic, i.e., given the same initial state, {fn RAND} produces the same sequence of values.  The internal state of {fn RAND} is initialized using the function {fn RANDSET} described below.
}}



{FnDef {FnName RANDSET} {FnArgs X}
{Text
Returns the internal state of {fn RAND}.  If {arg X}={lisp NIL}, just returns the current state.  If {arg X}={lisp T}, {fn RAND} is initialized using the clocks, and {fn RANDSET} returns the new state.  Otherwise, {arg X} is interpreted as a previous internal state, i.e., a value of {fn RANDSET}, and is used to reset {fn RAND}.  For example,

{lispcode
← (SETQ OLDSTATE (RANDSET))
...
← (for X from 1 to 10 do (PRIN1 (RAND 1 10)))
2847592748NIL
← (RANDSET OLDSTATE)
...
← (for X from 1 to 10 do (PRIN1 (RAND 1 10)))
2847592748NIL}
}}



}{End SubSec Other Arithmetic Functions}



}{End Chapter Numbers and Arithmetic Functions}