At least one library (adt) redefines structures with slot names being
uninterned symbols. That means that we lose slot offset if we
reference it by name what leads to load errors if
make-load-form-saving-slots was called. We fix that by handling
structure-object's separately.
allocate-instance is another oddball in the spec when taken with
structure-classes (and it is used in make-load-form-saving-slots). If
there are *some* slots saved then rest must be initialized so object
could be used - we put there NIL without checking for a type. SBCL
tries to find a constructor for a structure (custom protocol) or
errors while CCL initializes slots to NIL. We follow the latter.
As explained in the comment: structure may be a result of code
generation which will likely use gensym. In this case name eql casues
compilation/load problems. I.e adt library dos that.
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.
- extract functions for handling different kind of results
- add specialised code for floats and complex floats in integer case
- improve comments a little
- fix the regression where (expt -1.0 2) results in complex result
For functions without returned value we did return cl_object value0
which was not initialized. That could lead to segmentation faults if
we have used result of calling a function defined as such location.
SFFI definition like this:
(ffi:def-function ("my_test_function3" sffi-test-3)
((x :float) (y :double))
:returning :void)
was previously compiled to
/* function definition for SFFI-TEST-3 */
/* optimize speed 3, debug 0, space 0, safety 2 */
static cl_object L6sffi_test_3(cl_object v1x, cl_object v2y)
{
cl_object env0 = ECL_NIL;
const cl_env_ptr cl_env_copy = ecl_process_env();
cl_object value0;
ecl_cs_check(cl_env_copy,value0);
{
TTL:
my_test_function3(ecl_to_float(v1x),ecl_to_double(v2y));
cl_env_copy->nvalues = 0;
return value0;
}
}
and now it is compiled to
/* function definition for SFFI-TEST-3 */
/* optimize speed 3, debug 0, space 0, safety 2 */
static cl_object L6sffi_test_3(cl_object v1x, cl_object v2y)
{
cl_object env0 = ECL_NIL;
const cl_env_ptr cl_env_copy = ecl_process_env();
cl_object value0;
ecl_cs_check(cl_env_copy,value0);
{
TTL:
my_test_function3(ecl_to_float(v1x),ecl_to_double(v2y));
value0 = ECL_NIL;
cl_env_copy->nvalues = 0;
return value0;
}
}
void functions are treated the same as when *destionation* is 'RETURN
in cmpmulti.lsp.
libffi is incapable of properly handling complex float argument types
yet. Commit disables complex types and adds a comment explaining
what's going on.
SFFI types which doesn't have counterpart in DFFI conversion table are
NULL and function ecl_type_to_libffi_type will signal a condition when
they are used.
Most of things is covered in ANSI-TESTS anway, these are just smoke
tests for some functionality and taking into account internal
implementation details.
numlib is similar to math operation definitions in core but these
functions are implemented in C.
- refactor functions for code clarity
- add definitions for complex float
- 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.
During printing we cons new floats for imag and real part. We could
opencode that but that would add a lot of code for a little gain. If
this proves to be a real bottleneck we will refactor float printing.
- _Complex long double is first cast to _Complex double (just like
long double) to avoid hashing non-meaningful bits
- We adhere to the "similarity" principle, that is sxhash -0.0 is the
same as sxhash 0.0.
equalp is delegated to ecl_number_equalp. we do not treat signed zero,
infinity nor nan.
float_eql is not the same as ==, because we have signed zeros and nan
values which should be compared memory-wise.
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.
When the number of digits was not specified, we were sometimes
outputting a number that was exactly halfway between the exact value
and the next higher float. When reading that number in again, one
would get a different value due to rounding issues. Therefore, we now
always output enough digits, so that the number can be reconstructed
unambigously. Fixes#500.
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.