Пример #1
0
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;
}
Пример #2
0
/* we need special routines for int64 */
ScmInt64 Scm_BignumToSI64(const ScmBignum *b, int clamp, int *oor)
{
#if SCM_EMULATE_INT64
    ScmInt64 r = {0, 0};
    if (clamp == SCM_CLAMP_NONE && oor != NULL) *oor = FALSE;
    if (b->sign > 0) {
        if (b->size > 2 || b->values[1] > LONG_MAX) {
            if (!(clamp & SCM_CLAMP_HI)) goto err;
            SCM_SET_INT64_MAX(r);
        } else {
            r.lo = b->values[0];
            if (b->size == 2) r.hi = b->values[1];
        }
    } else if (b->sign < 0) {
        if (b->size > 2 || b->values[1] > (u_long)LONG_MAX + 1) {
            if (!(clamp&SCM_CLAMP_LO)) goto err;
            SCM_SET_INT64_MIN(r);
        } else {
            b = SCM_BIGNUM(Scm_BignumComplement(b));
            r.lo = b->values[0];
            if (b->size == 2) r.hi = b->values[1];
            else              r.hi = -1;
        }
    }
    return r;
#else  /*!SCM_EMULATE_INT64*/
    int64_t r = 0;
    if (clamp == SCM_CLAMP_NONE && oor != NULL) *oor = FALSE;
    if (b->sign > 0) {
        if (b->size == 1) {
            r = b->values[0];
        } else if (b->size > 2 || b->values[1] > LONG_MAX) {
            if (!(clamp & SCM_CLAMP_HI)) goto err;
            SCM_SET_INT64_MAX(r);
        } else {
            r = ((int64_t)b->values[1] << 32) + (uint64_t)b->values[0];
        }
    } else { /* b->sign < 0 */
        if (b->size == 1) {
            r = -(int64_t)b->values[0];
        } else if (b->size > 2 || (b->values[1] > LONG_MAX && b->values[0] > 0)) {
            if (!(clamp&SCM_CLAMP_LO)) goto err;
            SCM_SET_INT64_MIN(r);
        } else {
            r = -(int64_t)(((int64_t)b->values[1] << 32) + (uint64_t)b->values[0]);
        }
    }
    return r;
#endif /*!SCM_EMULATE_INT64*/
  err:
    if (clamp == SCM_CLAMP_NONE && oor != NULL) {
        *oor = TRUE;
    } else {
        Scm_Error("argument out of range: %S", SCM_OBJ(b));
    }
    return r;
}