int Scm_EqvP(ScmObj x, ScmObj y) { /* For our implementation, only numbers need different treatment than SCM_EQ. We first check flonums, or we'd have to FLONUM_ENSURE_MEM before we pass them to Scm_NumEq. */ if (SCM_NUMBERP(x)) { if (SCM_NUMBERP(y)) { /* Since flonums are the only "inexact real" type in Gauche, we can safely reject the cases where either one is flonum and another is not. */ if (SCM_FLONUMP(x)) { if (SCM_FLONUMP(y)) { return (SCM_FLONUM_VALUE(x) == SCM_FLONUM_VALUE(y)); } else { return FALSE; } } else if (SCM_FLONUMP(y)) { return FALSE; } /* More generic case. */ if ((SCM_EXACTP(x) && SCM_EXACTP(y)) || (SCM_INEXACTP(x) && SCM_INEXACTP(y))) { return Scm_NumEq(x, y); } } return FALSE; } return SCM_EQ(x, y); }
u_long Scm_EqvHash(ScmObj obj) { u_long hashval; if (SCM_NUMBERP(obj)) { if (SCM_INTP(obj)) { SMALL_INT_HASH(hashval, SCM_INT_VALUE(obj)); } else if (SCM_BIGNUMP(obj)) { u_int i; u_long u = 0; for (i=0; i<SCM_BIGNUM_SIZE(obj); i++) { u += SCM_BIGNUM(obj)->values[i]; } SMALL_INT_HASH(hashval, u); } else if (SCM_FLONUMP(obj)) { /* TODO: I'm not sure this is a good hash. */ hashval = (u_long)(SCM_FLONUM_VALUE(obj)*2654435761UL); } else if (SCM_RATNUMP(obj)) { /* Ratnum must be normalized, so we can simply combine hashvals of numerator and denominator. */ u_long h1 = Scm_EqvHash(SCM_RATNUM_NUMER(obj)); u_long h2 = Scm_EqvHash(SCM_RATNUM_DENOM(obj)); hashval = COMBINE(h1, h2); } else { /* TODO: I'm not sure this is a good hash. */ hashval = (u_long)((SCM_COMPNUM_REAL(obj)+SCM_COMPNUM_IMAG(obj))*2654435761UL); } } else { ADDRESS_HASH(hashval, obj); } return hashval&HASHMASK; }