Function EXT:!
(
returns the
factorial of EXT:!
n
)n
, n
being a nonnegative INTEGER
.
Function EXT:EXQUO
. (
returns
the integer quotient EXT:EXQUO
x
y
)x/y
of two integers
x
,y
, and SIGNAL
s an ERROR
when the quotient is not
integer. (This is more efficient than /
.)
Function EXT:XGCD
. (
returns the values EXT:XGCD
x1
... xn
)l
, k1
, ..., kn
, where l
is the
greatest common divisor of the integers x1
, ..., xn
, and
k1
, ..., kn
are the integer coefficients such that
l
= (GCD
x1
...xn
) = (+ (*k1
x1
) ... (*kn
xn
))
Function EXT:MOD-EXPT
. (
is equivalent to EXT:MOD-EXPT
k
l
m
)(
except it is more efficient for very large arguments.MOD
(EXPT
k
l
) m
)
DECODE-FLOAT
FLOAT-RADIX
always returns 2.
(
coerces
FLOAT-DIGITS
number
digits
)number
(a REAL
) to a floating point number with at least
digits
mantissa digits. The following always evaluates to T
:
(>=
(FLOAT-DIGITS
(FLOAT-DIGITS
number
digits
))digits
)
Byte specifiers are objects of built-in type BYTE,
not INTEGER
s.
Function EXPT
. (
is not very precise if EXPT
base
exponent
)exponent
has a large
absolute value.
Function LOG
. (
LOG
number
base
)SIGNAL
s an ERROR
if
.base
= 1
Constant PI
. The value of PI
is a LONG-FLOAT
with the precision given
by (
. When this precision is changed, the value of EXT:LONG-FLOAT-DIGITS
)PI
is
automatically recomputed. Therefore PI
is not a constant variable.
Function UPGRADED-COMPLEX-PART-TYPE
. When the argument is not a recognizable subtype or REAL
,
UPGRADED-COMPLEX-PART-TYPE
SIGNAL
s an ERROR
, otherwise it
returns its argument (even though a COMPLEX
number in CLISP can
always have REALPART
and IMAGPART
of any type) because it allows
the most precise type inference.
Variable CUSTOM:*DEFAULT-FLOAT-FORMAT*
. When rational numbers are to be converted to floats (due to
FLOAT
, COERCE
, SQRT
or a transcendental function), the result
type is given by the variable CUSTOM:*DEFAULT-FLOAT-FORMAT*
.
See also *READ-DEFAULT-FLOAT-FORMAT*
.
Macro EXT:WITHOUT-FLOATING-POINT-UNDERFLOW
. The macro (
executes the
EXT:WITHOUT-FLOATING-POINT-UNDERFLOW
{form
}*)form
s, with errors of type FLOATING-POINT-UNDERFLOW
inhibited.
Floating point operations will silently return zero instead of
SIGNAL
ing an ERROR
of type FLOATING-POINT-UNDERFLOW
.
Condition FLOATING-POINT-INVALID-OPERATION
. This CONDITION
is never SIGNAL
ed by CLISP.
Condition FLOATING-POINT-INEXACT
. This CONDITION
is never SIGNAL
ed by CLISP.
Table 12.2. Fixnum limits
CPU type | 32-bit CPU | 64-bit CPU |
---|---|---|
MOST-POSITIVE-FIXNUM | 224-1 = 16777215 | 248-1 = 281474976710655 |
MOST-NEGATIVE-FIXNUM | -224 = -16777216 | -248 = -281474976710656 |
BIGNUM
s are limited in size. Their maximum size is
32*(216-2)=2097088
bits.
The largest representable BIGNUM
is therefore
22097088-1
.
Together with PI
, the other LONG-FLOAT
constants
are recomputed whenever (
is EXT:LONG-FLOAT-DIGITS
)SETF
ed.
They are not constant variables.
Since the exponent of a
LONG-FLOAT
is a signed 32-bits
integer, MOST-POSITIVE-LONG-FLOAT
is about
2231
,
which is much larger that the largest
representable BIGNUM
, which is less than
2221
.
This, obviously, means that ROUND
, TRUNCATE
, FLOOR
and CEILING
SIGNAL
s an ERROR
on large LONG-FLOAT
s.
Less obviously, this means that (
also fails.FORMAT
NIL
"~E
"
MOST-POSITIVE-LONG-FLOAT
)
When a mathematical function may return an exact (RATIONAL
) or
inexact (FLOAT
) result, it always returns the exact result.
There are four floating point types: SHORT-FLOAT
,
SINGLE-FLOAT
, DOUBLE-FLOAT
and LONG-FLOAT
:
type | sign | mantissa | exponent | comment |
---|---|---|---|---|
SHORT-FLOAT | 1 bit | 16+1 bits | 8 bits | immediate |
SINGLE-FLOAT | 1 bit | 23+1 bits | 8 bits | IEEE 754 |
DOUBLE-FLOAT | 1 bit | 52+1 bits | 11 bits | IEEE 754 |
LONG-FLOAT | 1 bit | >=64 bits | 32 bits | variable length |
The single and double float formats are those of the IEEE 754
“Standard for Binary Floating-Point Arithmetic”,
except that CLISP does not support features like
±0
, ±inf
,
NaN
, gradual underflow, etc.
Common Lisp does not make use of these features, so, to reduce portability
problems, CLISP by design returns the same floating point results on
all platforms (CLISP has a floating-point emulation built in for
platforms that do not support IEEE 754). Note that
NaN
in your program, your program is broken, so you will spend time
determining where the NaN
came from.
It is better to SIGNAL
an ERROR
in this case.LONG-FLOAT
s of
variable precision - it does not
need unnormalized floats.
This is why *FEATURES*
does not contain the
:IEEE-FLOATING-POINT
keyword.
Arbitrary Precision Floats. LONG-FLOAT
s have variable mantissa length, which is a
multiple of 16 (or 32, depending on the word size of the processor).
The default length used when LONG-FLOAT
s are READ
is given by the
place (
. It can be set by EXT:LONG-FLOAT-DIGITS
)(
,
where SETF
(EXT:LONG-FLOAT-DIGITS
) n
)n
is a positive INTEGER
. E.g., (
sets the default precision of SETF
(EXT:LONG-FLOAT-DIGITS
)
3322)LONG-FLOAT
s to about
1000 decimal digits.
The floating point contagion is controlled by the variable
CUSTOM:*FLOATING-POINT-CONTAGION-ANSI*
. When it is non-NIL
, contagion is done as per the
[ANSI CL standard]: SHORT-FLOAT
→ SINGLE-FLOAT
→
DOUBLE-FLOAT
→ LONG-FLOAT
.
1.5
is actually 1.5±0.05
.
Consider adding 1.5
and 1.75
.
[ANSI CL standard] requires that (+
1.5 1.75)
return 3.25, while traditional CLISP
would return 3.3.
The implied random variables are: 3.25±0.005
and 3.3±0.05
.
Note that the traditional CLISP way does
lie about the mean: the mean is 3.25
and
nothing else, while the standard way
could be lying about the deviation
(accuracy): if the implied accuracy of 1.5
(i.e., 0.05)
is its actual accuracy, then the accuracy of the result cannot be
smaller that that. Therefore, since Common Lisp has no way of knowing the
actual accuracy, [ANSI CL standard] (and all the other standard engineering
programming languages, like C, Fortran
etc) decided that keeping the accuracy correct is the business of the
programmer, while the language should preserve what it can - the precision.
E(x2) -
E(x)2
can be negative!)
The user should not mix floats of different precision (that's what
CUSTOM:*WARN-ON-FLOATING-POINT-CONTAGION*
is for), but one should not be penalized for this too
harshly.When CUSTOM:*FLOATING-POINT-CONTAGION-ANSI*
is NIL
, the traditional CLISP method is used,
namely the result of an arithmetic operation whose arguments are of
different float types is rounded to the float format of the shortest
(least precise) of the arguments: RATIONAL
→
LONG-FLOAT
→ DOUBLE-FLOAT
→ SINGLE-FLOAT
→ SHORT-FLOAT
(in contrast to
[sec_12-1-4-4]!)
{1.0 ± 1e-8} + {1.0 ± 1e-16} = {2.0 ±
1e-8}
. So, if we add 1.0s0
and
1.0d0
, we should get 2.0s0
.
(-
(+
1.7 PI
) PI
)
should not return 1.700000726342836417234L0,
it should return 1.7f0 (or
1.700001f0 if there were rounding errors).
SHORT-FLOAT
s,
a LONG-FLOAT
(like PI
) happens to be used, the long precision
should not propagate throughout all the intermediate values.
Otherwise, the long result would look precise, but its accuracy is
only that of a SHORT-FLOAT
; furthermore much computation time
would be lost by calculating with LONG-FLOAT
s when only
SHORT-FLOAT
s would be needed.If the variable CUSTOM:*WARN-ON-FLOATING-POINT-CONTAGION*
is non-NIL
, a WARNING
is emitted for
every coercion involving different floating-point types.
As explained above, float precision contagion is not a good idea.
You can avoid the contagion by doing all your computations with the
same floating-point type (and using FLOAT
to convert all constants,
e.g., PI
, to your preferred type).
This variable helps you eliminate all occurrences of float
precision contagion: set it to T
to have CLISP SIGNAL
a
WARNING
on float precision contagion; set it to ERROR
to have
CLISP SIGNAL
an ERROR
on float precision contagion, so that you
can look at the stack backtrace.
The contagion between floating point and rational numbers is controlled
by the variable CUSTOM:*FLOATING-POINT-RATIONAL-CONTAGION-ANSI*
. When it is non-NIL
, contagion is done as per
the [ANSI CL standard]: RATIONAL
→ FLOAT
.
When CUSTOM:*FLOATING-POINT-RATIONAL-CONTAGION-ANSI*
is NIL
, the traditional CLISP method is used,
namely if the result is mathematically an exact rational number, this
rational number is returned (in contrast to
[sec_12-1-4-1]!)
CUSTOM:*FLOATING-POINT-RATIONAL-CONTAGION-ANSI*
has an effect only in those few cases when the mathematical
result is exact although one of the arguments is a floating-point number,
such as (
, *
0 1.618)(
,
/
0 1.618)(
, ATAN
0 1.0)(
,
EXPT
2.0 0)(
.PHASE
2.718)
If the variable CUSTOM:*WARN-ON-FLOATING-POINT-RATIONAL-CONTAGION*
is non-NIL
, a WARNING
is emitted for
every avoidable coercion from a rational number to a floating-point number.
You can avoid such coercions by calling FLOAT
to convert the particular
rational numbers to your preferred floating-point type.
This variable helps you eliminate all occurrences of avoidable
coercions to a floating-point number when a rational number result
would be possible: set it to T
to have CLISP SIGNAL
a WARNING
in such situations; set it to ERROR
to have CLISP SIGNAL
an
ERROR
in such situations, so that you can look at the stack
backtrace.
CUSTOM:*PHASE-ANSI*
A similar variable, CUSTOM:*PHASE-ANSI*
, controls the return
value of PHASE
when the argument is an exact nonnegative REAL
.
Namely, if CUSTOM:*PHASE-ANSI*
is non-NIL
, it returns a floating-point zero;
if CUSTOM:*PHASE-ANSI*
is NIL
, it returns an exact zero. Example:
(
PHASE
2/3)
Complex numbers can have a real part and an imaginary part of
different types. For example, (
evaluates to
the number SQRT
-9.0)
,
which has a real part of exactly #C
(0 3.0)0
,
not only 0.0
(which would mean “approximately 0”).
The type specifier for this is (
, and COMPLEX
INTEGER
SINGLE-FLOAT
)(
in general.COMPLEX
type-of-real-part
type-of-imaginary-part
)
The type specifier (
is equivalent to COMPLEX
type
)(
.COMPLEX
type
type
)
Complex numbers can have a real part and an imaginary part of
different types. If the imaginary part is EQL
to 0
,
the number is automatically converted to a real number.
This has the advantage that
(
- instead of
evaluating to LET
((x (SQRT
-9.0))) (* x x))
,
with #C
(-9.0 0.0)x
=
-
evaluates to #C
(0.0 3.0)
=
#C
(-9.0 0)-9.0
,
with x
=
.#C
(0 3.0)
To ease reproducibility, the variable *RANDOM-STATE*
is
initialized to the same value on each invocation, so that
$
clisp-norc
-x
'(RANDOM
1s0)'
will always print the same number.
If you want a new random state on each invocation, you can arrange for that by using init function:
$
clisp-norc
-x
'(EXT:SAVEINITMEM
"foo" :init-function (LAMBDA
() (SETQ
*RANDOM-STATE*
(MAKE-RANDOM-STATE
T
))))'$
clisp-norc
-M
foo.mem-x
'(RANDOM
1s0)'
or by placing (
into your RC file.SETQ
*RANDOM-STATE*
(MAKE-RANDOM-STATE
T
))
These notes document CLISP version 2.49.93+ | Last modified: 2018-02-19 |