REDUCE

3.1 Numbers and Arithmetic Functions

Most of the arithmetic functions in PSL expect numbers as arguments. In all cases an error occurs if the parameter to an arithmetic function is not a number:

⋆⋆⋆⋆⋆  Non-numeric argument in arithmetic

Exceptions to the rule are noted.

The underlying machine arithmetic requires parameters to be either all integers or all floats. If a function receives mixed types of arguments, integers are converted to floats before arithmetic operations are performed. The range of numbers which can be represented by an integer is different than that represented by a float. Because of this difference, a conversion is not always possible; an unsuccessful attempt to convert may cause an error to be signalled.

The mathlib package contains some useful mathematical functions.

3.1.1 Big Integers

Loading the ZBIG 1 1ZIB version of big integers, the optimal version for the particular architecture module redefines the basic arithmetic operations, including the logical operations, to permit arbitrary precision (or ”bignum”) integer operations.

3.1.2 Conversion Between Integers and Floats

The conversions mentioned above can be done explicitly by the following functions. Other functions which alter types can be found in Section 2.3.

(fix U:number): integer expr
Returns the integer which corresponds to the truncated value of U. The result of conversion must retain all significant portions of U. If U is an integer it is returned unchanged.
    1 lisp> (fix 2.1)  
    2  
    2 lisp> (fix -2.1)  
    -2

(float U:number): float expr
The float corresponding to the value of the argument U is returned. Some of the least significant digits of an integer may be lost due to the implementation of float. If U a float then it will be returned unchanged. If U is too large to represent in float an error occurs.
    ⋆⋆⋆⋆⋆ Argument to FLOAT is too large

3.1.3 Arithmetic Operators

This section describes arithmetic functions in the library module numeric-ops. The names of these functions are based upon mathematical notation.

There is a switch called fast-integers whose value has an effect on the compilation of forms which contain applications of the functions described here. The documentation assumes that the switch fast-integers is nil. When this switch is non-nil the compiler will generate code which is very efficient. However, it is assumed that arguments and results will be integers in the inum range. If this assumption is violated then at best your code will not generate correct results, you may actually damage the PSL system.

Common LISP operators

(= X:number Y:number): boolean expr
Numeric Equal. True if the two arguments are numbers of the same type and same value. Unlike the Common LISP operator, no type coercion is done, no error is signalled if one or both arguments are non-numeric, and only two arguments are permitted. Instead, it is merely incorrect to supply a non-numeric argument.

(/= X:number Y:number): boolean expr
Numeric Not Equal. Nil if X and Y are numbers of equal type and value; t if X and Y are numbers of unequal type or value. It is incorrect to supply a non-numeric argument.

(< X:number Y:number): boolean expr
Numeric Less Than. True if X is less than Y, regardless of type. An error is signalled if either argument is not numeric.

(> X:number Y:number): boolean expr
Numeric Greater Than. True if X is greater than Y, regardless of type. An error is signalled if either argument is not numeric.

(<= X:number Y:number): boolean expr
Numeric Less Than or Equal. True if X is less than or equal to Y, regardless of numeric type. An error is signalled if either argument is not numeric.

(>= X:number Y:number): boolean expr
Numeric Greater Than or Equal. True if X is greater than or equal to Y, regardless of numeric type. An error is signalled if either argument is not numeric.

(+ [N:number]): number macro
Numeric Addition. The value returned is the sum of all the arguments. The arguments may be of any numeric type. An error is signalled if any argument is not numeric. If supplied no arguments, the value is 0.

(– N:number [N:number]): number macro
Numeric Minus or Subtraction. If given one argument, returns the negative of that argument. If given more than one argument, returns the result of successively subtracting succeeding arguments from the first argument. Signals an error if no arguments are supplied or if any argument is non-numeric.

(* [N:number]): number macro
Numeric Multiplication. The value returned is the product of all the arguments. The arguments may be of any numeric type. An error is signalled if any argument is not numeric. If supplied no arguments, the value is 1.

(/ N:number [N:number]): number macro
Numeric Reciprocal or Division. If given one argument, returns the reciprocal of that argument. If given more than one argument, returns the result of successively dividing succeeding arguments from the first argument. Signals an error if no arguments are supplied or if any argument is non-numeric.
Additional Operators

(~= X:number Y:number): number expr
Numeric Not Equal. Same as /=.

(// X:integer Y:integer): integer expr
Integer Remainder. Same as remainder.

(~ X:integer): integer expr
Integer Bitwise Logical Not. Same as lnot.

(& X:integer Y:integer): integer expr
Integer Bitwise Logical And. Same as land.

(| X:integer Y:integer): integer expr
Integer Bitwise Logical Or. Same as lor.

(X:integer Y:integer): integer expr
Integer Bitwise Logical Xor. Same as lxor.

(<< X:integer Y:integer): integer expr
Integer Bitwise Logical Left Shift. Same as lshift.

(>> X:integer Y:integer): integer expr
Integer Bitwise Logical Right Shift. Same as (lshift X (minus Y)).

3.1.4 Arithmetic Functions

The functions described below handle arithmetic operations. Please note the remarks at the beginning of this Chapter regarding the mixing of argument types.

(abs U:number): number expr
Returns the absolute value of its argument.

(add1 U:number): number expr
Returns the value of U plus 1; the returned value is of the same type as U (integer or float).

(decr U:form [Xi:number]): number macro
This function is defined in the useful module. With only one argument, this is equivalent to
    (setf u (sub1 u))

With multiple arguments, it is equivalent to

    (setf u (difference u (plus x1 ... xn)))

    1 lisp> (setq y '(1 5 7))  
    (1 5 7)  
    2 lisp> (decr (car y))  
    0  
    3 lisp> y  
    (0 5 7)  
    4 lisp> (decr (cadr y) 3 4)  
    -2  
    5 lisp> y  
    (0 -2 7)

(difference U:number V:number): number expr
The value of U - V is returned.

(divide U:number V:number): pair expr
The pair (quotient . remainder) is returned, as if the quotient part was computed by the quotient function and the remainder by the remainder function. An error occurs if division by zero is attempted:
    ⋆⋆⋆⋆⋆ Attempt to divide by 0 in Divide

(expt U:number V:integer): number expr
Returns U raised to the V power. A float U to an integer power V does not have V changed to a float before exponentiation.

(incr U:form [Xi:number]): number macro
Part of the useful package. With only one argument, this is equivalent to
    (setf u (add1 u))

With multiple arguments it is equivalent to

    (setf u (plus u x1 ... xn))

(minus U:number): number expr
Returns -U.

(plus [U:number]): number macro
Forms the sum of all its arguments. Plus may be called with only one argument. In this case it returns its argument. If plus is called with no arguments, it returns zero.

(plus2 U:number V:number): number expr
Returns the sum of U and V.

(quotient U:number V:number): number expr
The quotient of U divided by V is returned. Division of two positive or two negative integers is conventional. If both U and V are integers and exactly one of them is negative, the value returned is truncated toward 0. If either argument is a float, a float is returned which is exact within the implemented precision of floats. An error occurs if division by zero is attempted:
    ⋆⋆⋆⋆⋆ Attempt to divide by 0 in QUOTIENT

(recip U:number): float expr
Recip converts U to a float if necessary, and then finds the inverse using the function quotient.

(remainder U:integer V:integer): integer expr
(- U (* V (fix (/ U (float V)))))
    (remainder 13 4)    =  1  
    (remainder -13 4)   = -1  
    (remainder 13 -4)   =  1  
    (remainder -13 -4)  = -1

(sub1 U:number): number expr
Returns the value of U minus 1. If U is a float, the value returned is U minus 1.0.

(times [U:number]): number macro
Returns the product of all its arguments. Times may be called with only one argument. In this case it returns the value of its argument. If times is called with no arguments, it returns 1.

(times2 U:number V:number): number expr
Returns the product of U and V.

3.1.5 Functions for Numeric Comparison

The following functions compare the values of their arguments. Functions which test for equality and inequality are documented in Section 2.2.1.

(geq U:any V:any): boolean expr
Equivalent to (= U V).

(greaterp U:number V:number): boolean expr
Equivalent to ( U V).

(leq U:number V:number): boolean expr
Equivalent to (= U V).

(lessp U:number V:number): boolean expr
Equivalent to ( U V).

(max [U:number]): number macro
Returns the largest of the values in U (numeric maximum). If two or more values are the same, the first is returned.

(max2 U:number V:number): number expr
Returns the larger of U and V. If U and V are of the same value, U is returned (U and V might be of different types).

(min [U:number]): number macro
Returns the smallest (numeric minimum), of the values in U. If two or more values are the same, the first of these is returned.

(min2 U:number V:number): number expr
Returns the smaller of its arguments. If U and V are the same value, U is returned (U and V might be of different types).

(minusp U:any): boolean expr
Returns t if U is a number and less than 0. The return value is nil if U is not a number, or if U is a positive number.

(onep U:any): boolean expr
Returns t if U is a number and has the value 1 or 1.0. Returns nil otherwise.

(zerop U:any): boolean expr
Returns t if U is a number and has the value 0 or 0.0. Returns nil otherwise.

3.1.6 Bit Operations

The functions described in this section operate on the binary representation of the integers given as arguments. The returned value is an integer.

(land U:integer V:integer): integer expr
Bitwise or logical and. Each bit of the result is independently determined from the corresponding bits of the operands.

(lor U:integer V:integer): integer expr
Bitwise or logical or. Each bit of the result is independently determined from corresponding bits of the operands. This is an inclusive or, the value of (lor 1 1) is 1.

(lnot U:integer): integer expr
Logical not. Defined as (- -U 1) so that it works for bignums as if they were 2’s complement.

(lxor U:integer V:integer): integer expr
Bitwise or logical exclusive or, the value of (lxor 1 1) is 0. Each bit of the result is independently determined from the corresponding bits of the operands.

(lshift N:integer K:integer): integer expr
Shifts N to the left by K bits. The effect is similar to multiplying by 2 to the K power. Negative values are acceptable for K, and cause a right shift (in the usual manner). Lshift is a logical shift, so right shifts do not resemble division by a power of 2.

3.1.7 Various Mathematical Functions

The optionally loadable mathlib module defines several commonly used mathematical functions. Some effort has been made to be compatible with Common Lisp. When reading the examples, note that the precision of the results depend on the machine being used.

(ceiling X:number): integer expr
Returns the smallest integer greater than or equal to X. For example:
    1 lisp> (ceiling 2.1)  
    3  
    2 lisp> (ceiling -2.1)  
    -2

(floor X:number): integer expr
Returns the largest integer less than or equal to X. (Note that this differs from the fix function.)
    1 lisp> (floor 2.1)  
    2  
    2 lisp> (floor -2.1)  
    -3  
    3 lisp> (fix -2.1)  
    -2

(round X:number): integer expr
Returns the nearest integer to X. If the fractional part of X is 0.5 then the smaller integer is returned.
    (de round (x)  
      (if (fixp x) x (floor (plus x 0.5))))

    1 lisp> (round 2.5)  
    3  
    2 lisp> (round -2.5)  
    -2

(transfersign S:number VAL:number): number expr
Transfers the sign of S to VAL.
    (de transfersign (s val)  
      (if (>= s 0) (abs val) (minus (abs val))))

(mod M:integer N:integer): integer expr
(- U (* V (floor (/ U (float V)))))
    (mod 13 4)    =  1  
    (mod -13 4)   =  3  
    (mod 13 -4)   = -3  
    (mod -13 -4)  = -1

(degreestoradians X:number): number expr
Returns an angle in radians given an angle in degrees.
    1 lisp> (degreestoradians 180)  
    3.1415926

(radianstodegrees X:number): number expr
Returns an angle in degrees given an angle in radians.
    1 lisp> (radianstodegrees 3.1415926)  
    180.0

(radianstodms X:number): list expr
Given an angle X in radians, returns a list of three integers, which represent the degrees, minutes, and seconds.
    1 lisp> (radianstodms 1.0)  
    (57 17 45)

(dmstoradians Degs:number Mins:number Secs:number): number expr
Returns an angle in radians, given three arguments representing an angle in degrees minutes and seconds.
    1 lisp> (dmstoradians 57 17 45)  
    1.0000009  
    2 lisp> (dmstoradians 180 0 0)  
    3.1415926

(degreestodms X:number): list expr
Given an angle X in degrees, returns a list of three integers giving the angle in (Degrees Minutes Seconds).

(dmstodegrees Degs:number Mins:number Secs:number): number expr
Returns an angle in degrees, given three arguments representing an angle in degrees minutes and seconds.

(sin X:number): number expr
Returns the sine of X, an angle in radians.

(sind X:number): number expr
Returns the sine of X, an angle in degrees.

(cos X:number): number expr
Returns the cosine of X, an angle in radians.

(cosd X:number): number expr
Returns the cosine of X, an angle in degrees.

(tan X:number): number expr
Returns the tangent of X, an angle in radians.

(tand X:number): number expr
Returns the tangent of X, an angle in degrees.

(cot X:number): number expr
Returns the cotangent of X, an angle in radians.

(cotd X:number): number expr
Returns the cotangent of X, an angle in degrees.

(sec X:number): number expr
Returns the secant of X, an angle in radians.

(secd X:number): number expr
Returns the secant of X, an angle in degrees.

(csc X:number): number expr
Returns the cosecant of X, an angle in radians.

(cscd X:number): number expr
Returns the cosecant of X, an angle in degrees.

(asin X:number): number expr
Returns the arc sine, as an angle in radians, of X.
    (eqn (sin (asin X)) X)

(asind X:number): number expr
Returns the arc sine, as an angle in degrees, of X.

(acos X:number): number expr
Returns the arc cosine, as an angle in radians, of X.
    (eqn (cos (acos X)) X)

(acosd X:number): number expr
Returns the arc cosine, as an angle in degrees, of X.

(atan X:number): number expr
Returns the arc tangent, as an angle in radians, of X.
    (eqn (tan (atan X)) X)

(atand X:number): number expr
Returns the arc tangent, as an angle in degrees, of X.

(atan2 Y:number X:number): number expr
Returns an angle in radians corresponding to the angle between the X axis and the vector [X Y]. Note that Y is the first argument.
    1 lisp> (atan2 0 -1)  
    3.1415927

(atan2d Y:number X:number): number expr
Returns an angle in degrees corresponding to the angle between the X axis and the vector [X Y].
    1 lisp> (atan2d -1 1)  
    315.0

(acot X:number): number expr
Returns the arc cotangent, as an angle in radians, of X.
    (eqn (cot (acot X)) X)

(acotd X:number): number expr
Returns the arc cotangent, as an angle in degrees, of X.

(asec X:number): number expr
Returns the arc secant, as an angle in radians, of X.
    (eqn (sec (asec X)) X)

(asecd X:number): number expr
Returns the arc secant, as an angle in degrees, of X.

(acsc X:number): number expr
Returns the arc cosecant, as an angle in radians, of X.
    (eqn (csc (acsc X)) X)

(acscd X:number): number expr
Returns the arc cosecant, as an angle in degrees, of X.

(sqrt X:number): number expr
Returns the square root of X.

(exp X:number): number expr
Returns the exponential of X.

(log X:number): number expr
Returns the natural (base e) logarithm of X. note that (log (log (exp X)) is equal to X.

(log2 X:number): number expr
Returns the base two logarithm of X.

(log10 X:number): number expr
Returns the base ten logarithm of X.

(random N:integer): integer expr
Returns a pseudo-random number uniformly selected from the range 0 ... (sub1 N).

The random number generator uses a linear congruential method.

randomseed = Initially: set from time global
   
To get a reproducible sequence of random numbers you should assign one (or some other small number) to the fluid variable randomseed.

(factorial N:integer): integer expr
The factorial function is defined as follows
      1. The factorial of 0 is 1.

      2. The factorial of N is N times the factorial of N-1.

    (de factorial (n)  
      (if (zerop n) 1 (⋆ n (factorial (sub1 n)))))