Using isnan and isfinite to check for floating point exceptions
doesn't work when we want floats to be able to have infinity or NaN as
values, thus this option was removed with commit
5f71f728a3. However, we can still use
fetestexcept to explicitly check if floating point exceptions occurred
even when we can't use the feenableexcept/SIGFPE signal delivery
mechanism.
Previously, we had something like this in the
ECL_MATHERR_TEST/ECL_MATHERR_CLEAR macros, but this was not used
consistently in our codebase (the ECL_MATHERR_TEST macro was missing
in many places). Instead of error-prone testing at every point of
computation, we call fetestexcept in DO_DETECT_FPE when creating a new
float/complex float. In order to avoid having to do this twice, the
DO_DETECT_FPE2 macro is introduced.
A minor disadvantage of this strategy is that floating point
exceptions may be signaled later than they occurred.
Previously: unconditionally use the size from ECL_OPT_C_STACK_SIZE if
it is larger than the OS provided value and if possible resize the
stack at runtime.
Now: Use ECL_OPT_C_STACK_SIZE if provided. Otherwise, use a) the OS
provided value if we can resize the stack at runtime (for Unix) or b)
the new build option ECL_DEFAULT_C_STACK_SIZE (1 MB) if we can set the
stack size at link time (for Windows).
This is more robust against changes in the abi support in libffi.
We also remove unused struct and enum type definitions (left over from
our own dynamic ffi implementation?).
ecl_cs_set_org and cs_set_size had several problems:
-the size of the stack was estimated to be 1/2 of the actual value,
which could lead to wrong stack overflow errors. In particular, we
cannot assume that the stack pointer will always start at the stack
origin and increase/decrease linearly (counterexamples could
include callbacks from other threads).
-despite its name, cs_set_size did not actually set the stack size
even on systems where this is possible at runtime.
-there were several magic numbers used.
We also use the *in-all-symbols-functions* variable only for
determining which functions are to be exported during the build of ECL
itself. Otherwise, instead of specifying manually, which Lisp
functions are exported and in the core, we use the information from
symbols_list.h (i.e. we let all_symbols.d initialize all core
functions).
Previously, we assumed that the fixed and variadic arguments of a
variadic function were passed to the function in the same way. The
arm64 calling convention used by iOS breaks this assumption by passing
fixed arguments in registers or on the stack, depending on the
position, while variadic arguments are always passed on the stack.
Solving this problem while still allowing function redefinition at
runtime requires introducing additional dispatch functions. These
dispatch functions take no fixed arguments and pass all their
arguments to the actual function. This dispatch is enabled by passing
-DECL_C_COMPATIBLE_VARIADIC_DISPATCH to the C compiler.
This problem was originally identified and a solution provided by
thewhimer@gmail.com. This commit based on his work with minor
improvements.
Symbols must be associated with functions following an uniform naming
scheme because si:mangle-name does not return pre-existing string.
See #534 for details. This is a temporary solution.
Previously, we assumed that all stack frames were lying at the top of
the lisp stack. This is not always true due to e.g.
multiple-value-prog1 pushing onto the lisp stack.
We allocate arguments on a heap when number of them exceeds
ECL_C_ARGUMENTS_LIMIT. Was:
if (narg < ECL_C_ARGUMENTS_LIMIT) ... else ..
should be
if (narg <= ECL_C_ARGUMENTS_LIMIT) ... else ..
It is a partial fix for #513 (solves a segfault).
The pipe from which we read the output of the C compiler could fill up
when a large number of warnings were printed leading to a deadlock
because we waited for the C compiler to finish before reading the
output.
External format decoders now operatore on characters buffers instead
of reading input byte by byte from the streams. This allows us to
provide efficient read_vector implementations.
Many parts of the source code were bent backward to support builds
without long floats which are always present given we depend expect
c99 compiler.
The corresponding C macros (ECL_LONG_FLOAT) and the *feature*
entry (:long-float) are marked as deprecated in the documentation.
- add ffi implementation for long-float
- add ffi implementation for (complex float) types
- add compiler optimizations and definitions for complex float
We do not add c?float common constants (long-float i.e has optimizer
for 0.0 and -0.0), because we don't know if they are common at all and
if we think about it each would have four entries counting signed
zeros).
Also add informative comment about global-entries.
cl_type_of: give better results for (type-of <complex>)
Instead of simply returning complex we return:
(complex real)
when code is built without complex float support, and otherwise
(complex rational)
(complex single-float)
(complex double-float)
(complex long-float)
New functions:
- ecl_to_csfloat
- ecl_to_cdfloat
- ecl_to_clfloat
What has changed:
- new types si:complex-float, si:complex-single-float,
si:complex-double-float and si:complex-long-float
- new builtin classes long-float (for completness) and
si:complex-float
- new internal function si:complex-float and si:complex-float-p for
constructing complex floats (both arguments must be of the same
float type) and a type predicate
- printer for new types (right now it conses, see below)
- a new feature :complex-float
- a new type is recognized as a type disjoint of complex and real
- cleanup: +built-in-type-list+: remove some redundancy
For instance instread of saying
(real (or integer single-float double-float ratio))
We say
(real (or integer float ratio))
etc.
Flaws which will be fixed in upcoming commits:
- complex-float hierarchy is independent of the complex hierarchy
- ecl_make_complex_float could be replaced by _ecl_make_complex_*float
- write_complex_float allocates new objects for printing
- write_complex_float does print unreadable object
- math dispatchers doesn't recognize the object
Testing things out:
> (si:complex-float 0.0d0 0.0d0)
; #<CF(0.0d0 0.0d0)>
> (si:complex-float 0.0d0 0.0s0) ; signals type error
> (+ (si:complex-float 0.0d0 0.0d0) 1) ; signals type error
lisp runtime: make si_complex-float a subtype of a number.
Complex is a macro specified in complex.h for c99 to simplify using
_Complex type. This file also contains functions to work on complex
floats. To avoid conflicts we rename internal name complex to
gencomplex and update all references to it.
We do not check for c99-mandated functions for long float (we only
check for the type). We also check for complex numbers in a separate
function and define ECL_COMPLEX_FLOAT when found.