calc: Computational Lisp Functions

 
 18.5.7.5 Computational Functions
 ................................
 
 The functions described here do the actual computational work of the
 Calculator.  In addition to these, note that any function described in
 the main body of this manual may be called from Lisp; for example, if
 the documentation refers to the ‘calc-sqrt’ [‘sqrt’] command, this means
 ‘calc-sqrt’ is an interactive stack-based square-root command and ‘sqrt’
 (which ‘defmath’ expands to ‘calcFunc-sqrt’) is the actual Lisp function
 for taking square roots.
 
    The functions ‘math-add’, ‘math-sub’, ‘math-mul’, ‘math-div’,
 ‘math-mod’, and ‘math-neg’ are not included in this list, since
 ‘defmath’ allows you to write native Lisp ‘+’, ‘-’, ‘*’, ‘/’, ‘%’, and
 unary ‘-’, respectively, instead.
 
  -- Function: normalize val
      (Full form: ‘math-normalize’.)  Reduce the value VAL to standard
      form.  For example, if VAL is a fixnum, it will be converted to a
      bignum if it is too large, and if VAL is a bignum it will be
      normalized by clipping off trailing (i.e., most-significant) zero
      digits and converting to a fixnum if it is small.  All the various
      data types are similarly converted to their standard forms.
      Variables are left alone, but function calls are actually evaluated
      in formulas.  For example, normalizing ‘(+ 2 (calcFunc-abs -4))’
      will return 6.
 
      If a function call fails, because the function is void or has the
      wrong number of parameters, or because it returns ‘nil’ or calls
      ‘reject-arg’ or ‘inexact-result’, ‘normalize’ returns the formula
      still in symbolic form.
 
      If the current simplification mode is “none” or “numeric arguments
      only,” ‘normalize’ will act appropriately.  However, the more
      powerful simplification modes (like Algebraic Simplification) are
      not handled by ‘normalize’.  They are handled by ‘calc-normalize’,
      which calls ‘normalize’ and possibly some other routines, such as
      ‘simplify’ or ‘simplify-units’.  Programs generally will never call
      ‘calc-normalize’ except when popping or pushing values on the
      stack.
 
  -- Function: evaluate-expr expr
      Replace all variables in EXPR that have values with their values,
      then use ‘normalize’ to simplify the result.  This is what happens
      when you press the ‘=’ key interactively.
 
  -- Macro: with-extra-prec n body
      Evaluate the Lisp forms in BODY with precision increased by N
      digits.  This is a macro which expands to
 
           (math-normalize
             (let ((calc-internal-prec (+ calc-internal-prec N)))
               BODY))
 
      The surrounding call to ‘math-normalize’ causes a floating-point
      result to be rounded down to the original precision afterwards.
      This is important because some arithmetic operations assume a
      number’s mantissa contains no more digits than the current
      precision allows.
 
  -- Function: make-frac n d
      Build a fraction ‘N:D’.  This is equivalent to calling ‘(normalize
      (list 'frac N D))’, but more efficient.
 
  -- Function: make-float mant exp
      Build a floating-point value out of MANT and EXP, both of which are
      arbitrary integers.  This function will return a properly
      normalized float value, or signal an overflow or underflow if EXP
      is out of range.
 
  -- Function: make-sdev x sigma
      Build an error form out of X and the absolute value of SIGMA.  If
      SIGMA is zero, the result is the number X directly.  If SIGMA is
      negative or complex, its absolute value is used.  If X or SIGMA is
      not a valid type of object for use in error forms, this calls
      ‘reject-arg’.
 
  -- Function: make-intv mask lo hi
      Build an interval form out of MASK (which is assumed to be an
      integer from 0 to 3), and the limits LO and HI.  If LO is greater
      than HI, an empty interval form is returned.  This calls
      ‘reject-arg’ if LO or HI is unsuitable.
 
  -- Function: sort-intv mask lo hi
      Build an interval form, similar to ‘make-intv’, except that if LO
      is less than HI they are simply exchanged, and the bits of MASK are
      swapped accordingly.
 
  -- Function: make-mod n m
      Build a modulo form out of N and the modulus M.  Since modulo forms
      do not allow formulas as their components, if N or M is not a real
      number or HMS form the result will be a formula which is a call to
      ‘makemod’, the algebraic version of this function.
 
  -- Function: float x
      Convert X to floating-point form.  Integers and fractions are
      converted to numerically equivalent floats; components of complex
      numbers, vectors, HMS forms, date forms, error forms, intervals,
      and modulo forms are recursively floated.  If the argument is a
      variable or formula, this calls ‘reject-arg’.
 
  -- Function: compare x y
      Compare the numbers X and Y, and return -1 if ‘(lessp X Y)’, 1 if
      ‘(lessp Y X)’, 0 if ‘(math-equal X Y)’, or 2 if the order is
      undefined or cannot be determined.
 
  -- Function: numdigs n
      Return the number of digits of integer N, effectively
      ‘ceil(log10(N))’, but much more efficient.  Zero is considered to
      have zero digits.
 
  -- Function: scale-int x n
      Shift integer X left N decimal digits, or right -N digits with
      truncation toward zero.
 
  -- Function: scale-rounding x n
      Like ‘scale-int’, except that a right shift rounds to the nearest
      integer rather than truncating.
 
  -- Function: fixnum n
      Return the integer N as a fixnum, i.e., a native Lisp integer.  If
      N is outside the permissible range for Lisp integers (usually 24
      binary bits) the result is undefined.
 
  -- Function: sqr x
      Compute the square of X; short for ‘(* X X)’.
 
  -- Function: quotient x y
      Divide integer X by integer Y; return an integer quotient and
      discard the remainder.  If X or Y is negative, the direction of
      rounding is undefined.
 
  -- Function: idiv x y
      Perform an integer division; if X and Y are both nonnegative
      integers, this uses the ‘quotient’ function, otherwise it computes
      ‘floor(X/Y)’.  Thus the result is well-defined but slower than for
      ‘quotient’.
 
  -- Function: imod x y
      Divide integer X by integer Y; return the integer remainder and
      discard the quotient.  Like ‘quotient’, this works only for integer
      arguments and is not well-defined for negative arguments.  For a
      more well-defined result, use ‘(% X Y)’.
 
  -- Function: idivmod x y
      Divide integer X by integer Y; return a cons cell whose ‘car’ is
      ‘(quotient X Y)’ and whose ‘cdr’ is ‘(imod X Y)’.
 
  -- Function: pow x y
      Compute X to the power Y.  In ‘defmath’ code, this can also be
      written ‘(^ X Y)’ or ‘(expt X Y)’.
 
  -- Function: abs-approx x
      Compute a fast approximation to the absolute value of X.  For
      example, for a rectangular complex number the result is the sum of
      the absolute values of the components.
 
  -- Function: pi
      The function ‘(pi)’ computes ‘pi’ to the current precision.  Other
      related constant-generating functions are ‘two-pi’, ‘pi-over-2’,
      ‘pi-over-4’, ‘pi-over-180’, ‘sqrt-two-pi’, ‘e’, ‘sqrt-e’, ‘ln-2’,
      ‘ln-10’, ‘phi’ and ‘gamma-const’.  Each function returns a
      floating-point value in the current precision, and each uses
      caching so that all calls after the first are essentially free.
 
  -- Macro: math-defcache FUNC INITIAL FORM
      This macro, usually used as a top-level call like ‘defun’ or
      ‘defvar’, defines a new cached constant analogous to ‘pi’, etc.  It
      defines a function ‘func’ which returns the requested value; if
      INITIAL is non-‘nil’ it must be a ‘(float ...)’ form which serves
      as an initial value for the cache.  If FUNC is called when the
      cache is empty or does not have enough digits to satisfy the
      current precision, the Lisp expression FORM is evaluated with the
      current precision increased by four, and the result minus its two
      least significant digits is stored in the cache.  For example,
      calling ‘(pi)’ with a precision of 30 computes ‘pi’ to 34 digits,
      rounds it down to 32 digits for future use, then rounds it again to
      30 digits for use in the present request.
 
  -- Function: full-circle symb
      If the current angular mode is Degrees or HMS, this function
      returns the integer 360.  In Radians mode, this function returns
      either the corresponding value in radians to the current precision,
      or the formula ‘2*pi’, depending on the Symbolic mode.  There are
      also similar function ‘half-circle’ and ‘quarter-circle’.
 
  -- Function: power-of-2 n
      Compute two to the integer power N, as a (potentially very large)
      integer.  Powers of two are cached, so only the first call for a
      particular N is expensive.
 
  -- Function: integer-log2 n
      Compute the base-2 logarithm of N, which must be an integer which
      is a power of two.  If N is not a power of two, this function will
      return ‘nil’.
 
  -- Function: div-mod a b m
      Divide A by B, modulo M.  This returns ‘nil’ if there is no
      solution, or if any of the arguments are not integers.
 
  -- Function: pow-mod a b m
      Compute A to the power B, modulo M.  If A, B, and M are integers,
      this uses an especially efficient algorithm.  Otherwise, it simply
      computes ‘(% (^ a b) m)’.
 
  -- Function: isqrt n
      Compute the integer square root of N.  This is the square root of N
      rounded down toward zero, i.e., ‘floor(sqrt(N))’.  If N is itself
      an integer, the computation is especially efficient.
 
  -- Function: to-hms a ang
      Convert the argument A into an HMS form.  If ANG is specified, it
      is the angular mode in which to interpret A, either ‘deg’ or ‘rad’.
      Otherwise, the current angular mode is used.  If A is already an
      HMS form it is returned as-is.
 
  -- Function: from-hms a ang
      Convert the HMS form A into a real number.  If ANG is specified, it
      is the angular mode in which to express the result, otherwise the
      current angular mode is used.  If A is already a real number, it is
      returned as-is.
 
  -- Function: to-radians a
      Convert the number or HMS form A to radians from the current
      angular mode.
 
  -- Function: from-radians a
      Convert the number A from radians to the current angular mode.  If
      A is a formula, this returns the formula ‘deg(A)’.
 
  -- Function: to-radians-2 a
      Like ‘to-radians’, except that in Symbolic mode a degrees to
      radians conversion yields a formula like ‘A*pi/180’.
 
  -- Function: from-radians-2 a
      Like ‘from-radians’, except that in Symbolic mode a radians to
      degrees conversion yields a formula like ‘A*180/pi’.
 
  -- Function: random-digit
      Produce a random base-1000 digit in the range 0 to 999.
 
  -- Function: random-digits n
      Produce a random N-digit integer; this will be an integer in the
      interval ‘[0, 10^N)’.
 
  -- Function: random-float
      Produce a random float in the interval ‘[0, 1)’.
 
  -- Function: prime-test n iters
      Determine whether the integer N is prime.  Return a list which has
      one of these forms: ‘(nil F)’ means the number is non-prime because
      it was found to be divisible by F; ‘(nil)’ means it was found to be
      non-prime by table look-up (so no factors are known); ‘(nil
      unknown)’ means it is definitely non-prime but no factors are known
      because N was large enough that Fermat’s probabilistic test had to
      be used; ‘(t)’ means the number is definitely prime; and ‘(maybe I
      P)’ means that Fermat’s test, after I iterations, is P percent sure
      that the number is prime.  The ITERS parameter is the number of
      Fermat iterations to use, in the case that this is necessary.  If
      ‘prime-test’ returns “maybe,” you can call it again with the same N
      to get a greater certainty; ‘prime-test’ remembers where it left
      off.
 
  -- Function: to-simple-fraction f
      If F is a floating-point number which can be represented exactly as
      a small rational number, return that number, else return F.  For
      example, 0.75 would be converted to 3:4.  This function is very
      fast.
 
  -- Function: to-fraction f tol
      Find a rational approximation to floating-point number F to within
      a specified tolerance TOL; this corresponds to the algebraic
      function ‘frac’, and can be rather slow.
 
  -- Function: quarter-integer n
      If N is an integer or integer-valued float, this function returns
      zero.  If N is a half-integer (i.e., an integer plus 1:2 or 0.5),
      it returns 2.  If N is a quarter-integer, it returns 1 or 3.  If N
      is anything else, this function returns ‘nil’.