/*
 * call-seq:
 *   fix * numeric   =>  numeric_result
 *
 * Performs multiplication: the class of the resulting object depends on
 * the class of <code>numeric</code> and on the magnitude of the
 * result.
 */

static VALUE
fix_mul(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
#ifdef __HP_cc
/* avoids an optimization bug of HP aC++/ANSI C B3910B A.06.05 [Jul 25 2005] */
        volatile
#endif
        SIGNED_VALUE a, b;
#if SIZEOF_VALUE * 2 <= SIZEOF_LONG_LONG
        LONG_LONG d;
#else
        SIGNED_VALUE c;
        VALUE r;
#endif

        a = FIX2LONG(x);
        b = FIX2LONG(y);

#if SIZEOF_VALUE * 2 <= SIZEOF_LONG_LONG
        d = (LONG_LONG)a * b;
        if (FIXABLE(d)) return LONG2FIX(d);
        return rb_ll2inum(d);
#else
        if (FIT_SQRT_LONG(a) && FIT_SQRT_LONG(b))
            return LONG2FIX(a*b);
        c = a * b;
        r = LONG2FIX(c);

        if (a == 0) return x;
        if (FIX2LONG(r) != c || c/a != b) {
            r = rb_big_mul(rb_int2big(a), rb_int2big(b));
        }
        return r;
#endif
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        return rb_big_mul(y, x);
      case T_FLOAT:
        return DOUBLE2NUM((double)FIX2LONG(x) * RFLOAT_VALUE(y));
      default:
        return rb_num_coerce_bin(x, y, '*');
    }
}