calc: Data Type Formats

 
 18.5.7.1 Data Type Formats
 ..........................
 
 Integers are stored in either of two ways, depending on their magnitude.
 Integers less than one million in absolute value are stored as standard
 Lisp integers.  This is the only storage format for Calc data objects
 which is not a Lisp list.
 
    Large integers are stored as lists of the form ‘(bigpos D0 D1 D2
 ...)’ for sufficiently large positive integers (where “sufficiently
 large” depends on the machine), or ‘(bigneg D0 D1 D2 ...)’ for negative
 integers.  Each D is a base-‘10^n’ “digit” (where again, ‘n’ depends on
 the machine), a Lisp integer from 0 to 99...9.  The least significant
 digit is D0; the last digit, DN, which is always nonzero, is the most
 significant digit.  For example, the integer -12345678 might be stored
 as ‘(bigneg 678 345 12)’.
 
    The distinction between small and large integers is entirely hidden
 from the user.  In ‘defmath’ definitions, the Lisp predicate ‘integerp’
 returns true for either kind of integer, and in general both big and
 small integers are accepted anywhere the word “integer” is used in this
 manual.  If the distinction must be made, native Lisp integers are
 called “fixnums” and large integers are called “bignums”.
 
    Fractions are stored as a list of the form, ‘(frac N D)’ where N is
 an integer (big or small) numerator, D is an integer denominator greater
 than one, and N and D are relatively prime.  Note that fractions where D
 is one are automatically converted to plain integers by all math
 routines; fractions where D is negative are normalized by negating the
 numerator and denominator.
 
    Floating-point numbers are stored in the form, ‘(float MANT EXP)’,
 where MANT (the “mantissa”) is an integer less than ‘10^P’ in absolute
 value (P represents the current precision), and EXP (the “exponent”) is
 a fixnum.  The value of the float is ‘MANT * 10^EXP’.  For example, the
 number -3.14 is stored as ‘(float -314 -2) = -314*10^-2’.  Other
 constraints are that the number 0.0 is always stored as ‘(float 0 0)’,
 and, except for the 0.0 case, the rightmost base-10 digit of MANT is
 always nonzero.  (If the rightmost digit is zero, the number is
 rearranged by dividing MANT by ten and incrementing EXP.)
 
    Rectangular complex numbers are stored in the form ‘(cplx RE IM)’,
 where RE and IM are each real numbers, either integers, fractions, or
 floats.  The value is ‘RE + IMi’.  The IM part is nonzero; complex
 numbers with zero imaginary components are converted to real numbers
 automatically.
 
    Polar complex numbers are stored in the form ‘(polar R THETA)’, where
 R is a positive real value and THETA is a real value or HMS form
 representing an angle.  This angle is usually normalized to lie in the
 interval ‘(-180 .. 180)’ degrees, or ‘(-pi .. pi)’ radians, according to
 the current angular mode.  If the angle is 0 the value is converted to a
 real number automatically.  (If the angle is 180 degrees, the value is
 usually also converted to a negative real number.)
 
    Hours-minutes-seconds forms are stored as ‘(hms H M S)’, where H is
 an integer or an integer-valued float (i.e., a float with ‘EXP >= 0’), M
 is an integer or integer-valued float in the range ‘[0 .. 60)’, and S is
 any real number in the range ‘[0 .. 60)’.
 
    Date forms are stored as ‘(date N)’, where N is a real number that
 counts days since midnight on the morning of January 1, 1 AD.  If N is
 an integer, this is a pure date form.  If N is a fraction or float, this
 is a date/time form.
 
    Modulo forms are stored as ‘(mod N M)’, where M is a positive real
 number or HMS form, and N is a real number or HMS form in the range ‘[0
 .. M)’.
 
    Error forms are stored as ‘(sdev X SIGMA)’, where X is the mean value
 and SIGMA is the standard deviation.  Each component is either a number,
 an HMS form, or a symbolic object (a variable or function call).  If
 SIGMA is zero, the value is converted to a plain real number.  If SIGMA
 is negative or complex, it is automatically normalized to be a positive
 real.
 
    Interval forms are stored as ‘(intv MASK LO HI)’, where MASK is one
 of the integers 0, 1, 2, or 3, and LO and HI are real numbers, HMS
 forms, or symbolic objects.  The MASK is a binary integer where 1
 represents the fact that the interval is closed on the high end, and 2
 represents the fact that it is closed on the low end.  (Thus 3
 represents a fully closed interval.)  The interval ‘(intv 3 X X)’ is
 converted to the plain number X; intervals ‘(intv MASK X X)’ for any
 other MASK represent empty intervals.  If HI is less than LO, the
 interval is converted to a standard empty interval by replacing HI with
 LO.
 
    Vectors are stored as ‘(vec V1 V2 ...)’, where V1 is the first
 element of the vector, V2 is the second, and so on.  An empty vector is
 stored as ‘(vec)’.  A matrix is simply a vector where all V’s are
 themselves vectors of equal lengths.  Note that Calc vectors are
 unrelated to the Emacs Lisp “vector” type, which is generally unused by
 Calc data structures.
 
    Variables are stored as ‘(var NAME SYM)’, where NAME is a Lisp symbol
 whose print name is used as the visible name of the variable, and SYM is
 a Lisp symbol in which the variable’s value is actually stored.  Thus,
 ‘(var pi var-pi)’ represents the special constant ‘pi’.  Almost always,
 the form is ‘(var V var-V)’.  If the variable name was entered with ‘#’
 signs (which are converted to hyphens internally), the form is ‘(var U
 V)’, where U is a symbol whose name contains ‘#’ characters, and V is a
 symbol that contains ‘-’ characters instead.  The value of a variable is
 the Calc object stored in its SYM symbol’s value cell.  If the symbol’s
 value cell is void or if it contains ‘nil’, the variable has no value.
 Special constants have the form ‘(special-const VALUE)’ stored in their
 value cell, where VALUE is a formula which is evaluated when the
 constant’s value is requested.  Variables which represent units are not
 stored in any special way; they are units only because their names
 appear in the units table.  If the value cell contains a string, it is
 parsed to get the variable’s value when the variable is used.
 
    A Lisp list with any other symbol as the first element is a function
 call.  The symbols ‘+’, ‘-’, ‘*’, ‘/’, ‘%’, ‘^’, and ‘|’ represent
 special binary operators; these lists are always of the form ‘(OP LHS
 RHS)’ where LHS is the sub-formula on the lefthand side and RHS is the
 sub-formula on the right.  The symbol ‘neg’ represents unary negation;
 this list is always of the form ‘(neg ARG)’.  Any other symbol FUNC
 represents a function that would be displayed in function-call notation;
 the symbol FUNC is in general always of the form ‘calcFunc-NAME’.  The
 function cell of the symbol FUNC should contain a Lisp function for
 evaluating a call to FUNC.  This function is passed the remaining
 elements of the list (themselves already evaluated) as arguments; such
 functions should return ‘nil’ or call ‘reject-arg’ to signify that they
 should be left in symbolic form, or they should return a Calc object
 which represents their value, or a list of such objects if they wish to
 return multiple values.  (The latter case is allowed only for functions
 which are the outer-level call in an expression whose value is about to
 be pushed on the stack; this feature is considered obsolete and is not
 used by any built-in Calc functions.)