Esempio n. 1
0
int fs_decimal_divide(const fs_decimal *n, const fs_decimal *d, fs_decimal *q)
{
    fs_decimal norm;
    int shift = 0;

    /* catch divide by zero error */
    if (fs_decimal_is_zero(d)) {
        return 1;
    }

    /* use Newton-Raphson series approximation to calculate 1/d */
    fs_decimal_normalise(d, &norm, &shift);

    fs_decimal x;
    if (norm.digit[FS_D_OVER_DIGITS + FS_D_INT_DIGITS] >= 5) {
        /* for 0.5 < norm < 1.0 we can use x = 2.914 - 2d as starting pt */
        fs_decimal twod;
        fs_decimal_multiply(&d2_val, &norm, &twod);
        fs_decimal_subtract(&d2_914_val, &twod, &x);
    } else {
        /* otherwise, don't know where to start, use 1.0 */
        x = d1_val;
    }

    fs_decimal last = zero_val;

    /* if it hasn't converged after 30 iterations it usually doesn't */
    for (int i=0; i<30; i++) {
#if 0
        printf("step %2d = ", i);
        fs_decimal_print(&x, stdout);
        printf("\n");
#endif
        /* calculate x = x(2-dx) */
        fs_decimal dx, tmp;
        fs_decimal_multiply(&norm, &x, &dx);
        fs_decimal_subtract(&d2_val, &dx, &tmp);
        fs_decimal_multiply(&tmp, &x, &x);
        if (fs_decimal_equal(&x, &last)) break;
        last = x;
    }
    /* round up to nearest representable number */
    fs_decimal_add(&x, &unit_val, &x);

#if 0
    printf("step  N = ");
    fs_decimal_print(&x, stdout);
    printf("\n");
#endif

    /* shift the aproximate reciprocal back to correct power */
    decimal_shift(&x, &x, shift);

    /* q = n * 1/d */
    fs_decimal_multiply(n, &x, q);
    q->flags ^= (d->flags & FS_D_NEGATIVE);

    return 0;
}
Esempio n. 2
0
fs_value fn_numeric_multiply(fs_query *q, fs_value a, fs_value b)
{
    a = fs_value_promote(q, a, b);
    b = fs_value_promote(q, b, a);

    if (a.attr == b.attr && a.attr != FS_RID_NULL && a.attr != fs_c.empty) {
	fs_value v = fs_value_blank();
	v.attr = a.attr;
	if (a.attr == fs_c.xsd_double || a.attr == fs_c.xsd_float) {
	    v.fp = a.fp * b.fp;
	    v.valid = fs_valid_bit(FS_V_FP);

	    return v;
	} else if (a.attr == fs_c.xsd_decimal) {
            fs_decimal_multiply(&a.de, &b.de, &v.de);
	    v.valid = fs_valid_bit(FS_V_DE);

	    return v;
	} else if (a.attr == fs_c.xsd_integer) {
	    v.in = a.in * b.in;
	    v.valid = fs_valid_bit(FS_V_IN);

	    return v;
	}
    }

    return fs_value_error(FS_ERROR_INVALID_TYPE, "non-numeric arguments to fn:numeric-multiply");
}