Commit 2bcba673 authored by Daniel Kochmański's avatar Daniel Kochmański

complex-float: implement hashing methods

- _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.
parent 86f10de4
......@@ -49,9 +49,8 @@ _hash_eql(cl_hashkey h, cl_object x)
return hash_string(h, (unsigned char*)&ecl_double_float(x), sizeof(ecl_double_float(x)));
#ifdef ECL_LONG_FLOAT
case t_longfloat: {
/* We coerce to double because long double has extra bits
* that give rise to different hash key and are not
* meaningful */
/* We coerce to double because long double has extra bits that
* give rise to different hash key and are not meaningful. */
struct { double mantissa; int exponent; int sign; } aux;
aux.mantissa = frexpl(ecl_long_float(x), &aux.exponent);
aux.sign = (ecl_long_float(x) < 0)? -1: 1;
......@@ -61,6 +60,26 @@ _hash_eql(cl_hashkey h, cl_object x)
case t_complex:
h = _hash_eql(h, x->gencomplex.real);
return _hash_eql(h, x->gencomplex.imag);
#ifdef ECL_COMPLEX_FLOAT
case t_csfloat: return hash_string(h, (unsigned char*)&ecl_csfloat(x), sizeof(ecl_csfloat(x)));
case t_cdfloat: return hash_string(h, (unsigned char*)&ecl_cdfloat(x), sizeof(ecl_cdfloat(x)));
case t_clfloat: {
/* We coerce to _Complex double because _Complex long double has
* extra bits that give rise to different hash key and are not
* meaningful. */
struct {
double mantissa1, mantissa2;
int exponent1, exponent2;
int sign1, sign2; } aux;
long double realpart = creall(ecl_clfloat(x));
long double imagpart = cimagl(ecl_clfloat(x));
aux.mantissa1 = frexpl(realpart, &aux.exponent1);
aux.mantissa2 = frexpl(imagpart, &aux.exponent2);
aux.sign1 = (realpart < 0)? -1: 1;
aux.sign2 = (imagpart < 0)? -1: 1;
return hash_string(h, (unsigned char*)&aux, sizeof(aux));
}
#endif
case t_character:
return hash_word(h, ECL_CHAR_CODE(x));
#ifdef ECL_SSE2
......@@ -119,6 +138,9 @@ _hash_equal(int depth, cl_hashkey h, cl_object x)
(h, (unsigned char*)array->vector.self.b8, 4*624);
}
#ifdef ECL_SIGNED_ZERO
/* According to 3.2.4.2.2 Definition of Similarity two numbers are
"similar" if they are of the same type and represent the same
mathematical value. -- jd 2019-05-06*/
case t_singlefloat: {
float f = ecl_single_float(x);
if (f == 0.0) f = 0.0;
......@@ -145,6 +167,38 @@ _hash_equal(int depth, cl_hashkey h, cl_object x)
h = _hash_equal(depth, h, x->gencomplex.real);
return _hash_equal(depth, h, x->gencomplex.imag);
}
# ifdef ECL_COMPLEX_FLOAT
case t_csfloat: {
_Complex float f = ecl_csfloat(x);
if (crealf(f) == 0.0) f = 0.0 + I * cimagf(f);
if (cimagf(f) == 0.0) f = crealf(f) + I * 0.0;
return hash_string(h, (unsigned char*)&(f), sizeof(f));
}
case t_cdfloat: {
_Complex double f = ecl_cdfloat(x);
if (creal(f) == 0.0) f = 0.0 + I * cimag(f);
if (cimag(f) == 0.0) f = creal(f) + I * 0.0;
return hash_string(h, (unsigned char*)&(f), sizeof(f));
}
case t_clfloat: {
/* We coerce to _Complex double because _Complex long double has
* extra bits that give rise to different hash key and are not
* meaningful. */
struct {
double mantissa1, mantissa2;
int exponent1, exponent2;
int sign1, sign2; } aux;
long double realpart = creall(ecl_clfloat(x));
long double imagpart = cimagl(ecl_clfloat(x));
aux.mantissa1 = frexpl(realpart, &aux.exponent1);
aux.mantissa2 = frexpl(imagpart, &aux.exponent2);
aux.sign1 = (realpart < 0)? -1: 1;
aux.sign2 = (imagpart < 0)? -1: 1;
if (aux.mantissa1 == 0.0) aux.mantissa1 = 0.0;
if (aux.mantissa2 == 0.0) aux.mantissa2 = 0.0;
return hash_string(h, (unsigned char*)&aux, sizeof(aux));
}
# endif
#endif
default:
return _hash_eql(h, x);
......@@ -203,6 +257,12 @@ _hash_equalp(int depth, cl_hashkey h, cl_object x)
case t_complex:
h = _hash_equalp(0, h, x->gencomplex.real);
return _hash_equalp(0, h, x->gencomplex.imag);
#ifdef ECL_COMPLEX_FLOAT
/* FIXME! We should be more precise here! */
case t_csfloat: return hash_word(h, (cl_index)ecl_csfloat(x));
case t_cdfloat: return hash_word(h, (cl_index)ecl_cdfloat(x));
case t_clfloat: return hash_word(h, (cl_index)ecl_clfloat(x));
#endif
case t_instance:
case t_hashtable:
/* FIXME! We should be more precise here! */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment