Beispiel #1
0
/*
 *  call-seq:
 *    onum * other   -> number
 *
 *  Returns the product of <i>onum</i> and <i>other</i>.
 */
static VALUE onum_mul(VALUE lhs, VALUE rhs)
{
    OCIError *errhp = oci8_errhp;
    OCINumber n;
    OCINumber r;

    switch (rboci8_type(rhs)) {
    case T_FIXNUM:
    case T_BIGNUM:
        if (set_oci_number_from_num(&n, rhs, 0, errhp)) {
            chkerr(OCINumberMul(errhp, _NUMBER(lhs), &n, &r));
            return oci8_make_ocinumber(&r, errhp);
        }
        break;
    case RBOCI8_T_ORANUMBER:
        chkerr(OCINumberMul(errhp, _NUMBER(lhs), _NUMBER(rhs), &r));
        return oci8_make_ocinumber(&r, errhp);
    case T_FLOAT:
        return rb_funcall(onum_to_f(lhs), oci8_id_mul_op, 1, rhs);
    case RBOCI8_T_RATIONAL:
        return rb_funcall(onum_to_r(lhs), oci8_id_mul_op, 1, rhs);
    case RBOCI8_T_BIGDECIMAL:
        return rb_funcall(onum_to_d(lhs), oci8_id_mul_op, 1, rhs);
    }
    return rb_num_coerce_bin(lhs, rhs, oci8_id_mul_op);
}
Beispiel #2
0
/*
 *  call-seq:
 *    onum / integer   -> oranumber
 *    onum / numeric   -> numeric
 *
 *  Returns the result of dividing <i>onum</i> by <i>other</i>.
 */
static VALUE onum_div(VALUE lhs, VALUE rhs)
{
    OCIError *errhp = oci8_errhp;
    OCINumber n;
    OCINumber r;
    boolean is_zero;

    switch (rboci8_type(rhs)) {
    case T_FIXNUM:
        if (rhs == INT2FIX(0)) {
            rb_num_zerodiv();
        }
    case T_BIGNUM:
        if (set_oci_number_from_num(&n, rhs, 0, errhp)) {
            chkerr(OCINumberDiv(errhp, _NUMBER(lhs), &n, &r));
            return oci8_make_ocinumber(&r, errhp);
        }
        break;
    case RBOCI8_T_ORANUMBER:
        chkerr(OCINumberIsZero(errhp, _NUMBER(rhs), &is_zero));
        if (is_zero) {
            rb_num_zerodiv();
        }
        chkerr(OCINumberDiv(errhp, _NUMBER(lhs), _NUMBER(rhs), &r));
        return oci8_make_ocinumber(&r, errhp);
    case T_FLOAT:
        return rb_funcall(onum_to_f(lhs), oci8_id_div_op, 1, rhs);
    case RBOCI8_T_RATIONAL:
        return rb_funcall(onum_to_r(lhs), oci8_id_div_op, 1, rhs);
    case RBOCI8_T_BIGDECIMAL:
        return rb_funcall(onum_to_d(lhs), oci8_id_div_op, 1, rhs);
    }
    return rb_num_coerce_bin(lhs, rhs, oci8_id_div_op);
}
Beispiel #3
0
static VALUE onum_initialize_copy(VALUE lhs, VALUE rhs)
{
    if (!RTEST(rb_obj_is_instance_of(rhs, CLASS_OF(lhs)))) {
        rb_raise(rb_eTypeError, "invalid type: expected %s but %s",
                 rb_class2name(CLASS_OF(lhs)), rb_class2name(CLASS_OF(rhs)));
    }
    chkerr(OCINumberAssign(oci8_errhp, _NUMBER(rhs), _NUMBER(lhs)));
    return lhs;
}
Beispiel #4
0
/*
 *  call-seq:
 *     onum.to_char(fmt = nil, nls_params = nil)  -> string
 *
 *  Returns a string containing a representation of self.
 *  <i>fmt</i> and <i>nls_params</i> are same meanings with
 *  <code>TO_CHAR</code> of Oracle function.
 */
static VALUE onum_to_char(int argc, VALUE *argv, VALUE self)
{
    OCIError *errhp = oci8_errhp;
    VALUE fmt;
    VALUE nls_params;
    char buf[512];
    ub4 buf_size = sizeof(buf);
    oratext *fmt_ptr;
    oratext *nls_params_ptr;
    ub4 fmt_len;
    ub4 nls_params_len;
    sword rv;

    rb_scan_args(argc, argv, "02", &fmt /* nil */, &nls_params /* nil */);
    if (NIL_P(fmt)) {
        rv = oranumber_to_str(_NUMBER(self), buf, sizeof(buf));
        if (rv > 0) {
            return rb_usascii_str_new(buf, rv);
        }
        oranumber_dump(_NUMBER(self), buf);
        rb_raise(eOCIException, "Invalid internal number format: %s", buf);
    }
    StringValue(fmt);
    fmt_ptr = RSTRING_ORATEXT(fmt);
    fmt_len = RSTRING_LEN(fmt);
    if (NIL_P(nls_params)) {
        nls_params_ptr = NULL;
        nls_params_len = 0;
    } else {
        StringValue(nls_params);
        nls_params_ptr = RSTRING_ORATEXT(nls_params);
        nls_params_len = RSTRING_LEN(nls_params);
    }
    rv = OCINumberToText(errhp, _NUMBER(self),
                         fmt_ptr, fmt_len, nls_params_ptr, nls_params_len,
                         &buf_size, TO_ORATEXT(buf));
    if (rv == OCI_ERROR) {
        sb4 errcode;
        OCIErrorGet(errhp, 1, NULL, &errcode, NULL, 0, OCI_HTYPE_ERROR);
        if (errcode == 22065) {
            /* OCI-22065: number to text translation for the given format causes overflow */
            if (NIL_P(fmt)) /* implicit conversion */
                return rb_usascii_str_new_cstr("overflow");
        }
        chkerr(rv);
    }
    return rb_usascii_str_new(buf, buf_size);
}
Beispiel #5
0
static VALUE onum_initialize(int argc, VALUE *argv, VALUE self)
{
    OCIError *errhp = oci8_errhp;
    VALUE val;
    VALUE fmt;
    VALUE nls_params;

    if (rb_scan_args(argc, argv, "03", &val /* 0 */, &fmt /* nil */, &nls_params /* nil */) == 0) {
        OCINumberSetZero(errhp, _NUMBER(self));
    } else if (RTEST(rb_obj_is_kind_of(val, rb_cNumeric))) {
        set_oci_number_from_num(_NUMBER(self), val, 1, errhp);
    } else {
        set_oci_number_from_str(_NUMBER(self), val, fmt, nls_params, errhp);
    }
    return Qnil;
}
Beispiel #6
0
/*
 *  call-seq:
 *     onum.to_r -> rational
 *
 *  Return the value as a <code>Rational</code>.
 *
 */
static VALUE onum_to_r(VALUE self)
{
    VALUE x, y;
    int nshift = 0;
    OCINumber onum[2];
    int current = 0;
    boolean is_int;

    chkerr(OCINumberAssign(oci8_errhp, _NUMBER(self), &onum[0]));

    for (;;) {
        chkerr(OCINumberIsInt(oci8_errhp, &onum[current], &is_int));
        if (is_int) {
            break;
        }
        nshift++;
        chkerr(OCINumberShift(oci8_errhp, &onum[current], 1, &onum[1 - current]));
        current = 1 - current;
    }
    x = oci8_make_integer(&onum[current], oci8_errhp);
    if (nshift == 0) {
        y = INT2FIX(1);
    } else {
        y = rb_funcall(INT2FIX(10), rb_intern("**"), 1, INT2FIX(nshift));
    }
#ifdef T_RATIONAL
    return rb_Rational(x, y);
#else
    if (!cRational) {
        rb_require("rational");
        cRational = rb_const_get(rb_cObject, id_Rational);
    }
    return rb_funcall(rb_cObject, id_Rational, 2, x, y);
#endif
}
Beispiel #7
0
/*
 *  call-seq:
 *    onum ** other   -> oranumber
 *
 *  Raises <i>onum</i> the <i>other</i> power.
 */
static VALUE onum_power(VALUE lhs, VALUE rhs)
{
    OCIError *errhp = oci8_errhp;
    OCINumber n;
    OCINumber r;

    if (FIXNUM_P(rhs)) {
        chkerr(OCINumberIntPower(errhp, _NUMBER(lhs), FIX2INT(rhs), &r));
    } else {
        /* change to OCINumber */
        if (!set_oci_number_from_num(&n, rhs, 0, errhp))
            return rb_num_coerce_bin(lhs, rhs, id_power);
        chkerr(OCINumberPower(errhp, _NUMBER(lhs), &n, &r));
    }
    return oci8_make_ocinumber(&r, errhp);
}
Beispiel #8
0
OCINumber *oci8_get_ocinumber(VALUE num)
{
    if (!rb_obj_is_kind_of(num, cOCINumber)) {
        rb_raise(rb_eTypeError, "invalid argument %s (expect a subclass of %s)", rb_class2name(CLASS_OF(num)), rb_class2name(cOCINumber));
    }
    return _NUMBER(num);
}
Beispiel #9
0
/*
 *  call-seq:
 *     onum.shift(fixnum)    -> oranumber
 *
 *  Returns <i>onum</i> * 10**<i>fixnum</i>
 *  This method is available on Oracle 8.1 client or upper.
 */
static VALUE onum_shift(VALUE self, VALUE exp)
{
    OCIError *errhp = oci8_errhp;
    OCINumber result;

    chkerr(OCINumberShift(errhp, _NUMBER(self), NUM2INT(exp), &result));
    return oci8_make_ocinumber(&result, errhp);
}
Beispiel #10
0
/*
 *  call-seq:
 *     onum.floor   -> integer
 *
 *  Returns the largest <code>Integer</code> less than or equal to <i>onum</i>.
 */
static VALUE onum_floor(VALUE self)
{
    OCIError *errhp = oci8_errhp;
    OCINumber r;

    oci_lc(OCINumberFloor(errhp, _NUMBER(self), &r));
    return oci8_make_integer(&r, errhp);
}
Beispiel #11
0
/*
 *  call-seq:
 *     onum.zero?    -> true or false
 *
 *  Returns <code>true</code> if <i>onum</i> is zero.
 *
 */
static VALUE onum_zero_p(VALUE self)
{
    OCIError *errhp = oci8_errhp;
    boolean result;

    chkerr(OCINumberIsZero(errhp, _NUMBER(self), &result));
    return result ? Qtrue : Qfalse;
}
Beispiel #12
0
/*
 *  call-seq:
 *     onum.has_decimal_part? -> true or false
 *
 *  Returns +true+ if <i>self</i> has a decimal part.
 *
 *    OraNumber(10).has_decimal_part?   # => false
 *    OraNumber(10.1).has_decimal_part? # => true
 */
static VALUE onum_has_decimal_part_p(VALUE self)
{
    OCIError *errhp = oci8_errhp;
    boolean result;

    chkerr(OCINumberIsInt(errhp, _NUMBER(self), &result));
    return result ? Qfalse : Qtrue;
}
Beispiel #13
0
/*
 *  call-seq:
 *     onum.to_i       -> integer
 *
 *  Returns <i>onum</i> truncated to an <code>Integer</code>.
 */
static VALUE onum_to_i(VALUE self)
{
    OCIError *errhp = oci8_errhp;
    OCINumber num;

    chkerr(OCINumberTrunc(errhp, _NUMBER(self), 0, &num));
    return oci8_make_integer(&num, errhp);
}
Beispiel #14
0
/*
 *  call-seq:
 *     onum.round_prec(digits) -> oranumber
 *
 *  Rounds <i>onum</i> to a specified number of decimal digits.
 *  This method is available on Oracle 8.1 client or upper.
 *
 *   OraNumber.new(1.234).round_prec(2)  #=> 1.2
 *   OraNumber.new(12.34).round_prec(2)  #=> 12
 *   OraNumber.new(123.4).round_prec(2)  #=> 120
 */
static VALUE onum_round_prec(VALUE self, VALUE ndigs)
{
    OCIError *errhp = oci8_errhp;
    OCINumber r;

    chkerr(OCINumberPrec(errhp, _NUMBER(self), NUM2INT(ndigs), &r));
    return oci8_make_ocinumber(&r, errhp);
}
Beispiel #15
0
/*
 *  call-seq:
 *     onum.abs -> oranumber
 *
 *  Returns the absolute value of <i>onum</i>.
 *
 */
static VALUE onum_abs(VALUE self)
{
    OCIError *errhp = oci8_errhp;
    OCINumber result;

    chkerr(OCINumberAbs(errhp, _NUMBER(self), &result));
    return oci8_make_ocinumber(&result, errhp);
}
Beispiel #16
0
/*
 *  call-seq:
 *     onum.ceil    -> integer
 *
 *  Returns the smallest <code>Integer</code> greater than or equal to
 *  <i>onum</i>.
 */
static VALUE onum_ceil(VALUE self)
{
    OCIError *errhp = oci8_errhp;
    OCINumber r;

    chkerr(OCINumberCeil(errhp, _NUMBER(self), &r));
    return oci8_make_integer(&r, errhp);
}
Beispiel #17
0
/*
 *  call-seq:
 *     -onum   -> oranumber
 *
 *  Returns a negated <code>OraNumber</code>.
 */
static VALUE onum_neg(VALUE self)
{
    OCIError *errhp = oci8_errhp;
    OCINumber r;

    chkerr(OCINumberNeg(errhp, _NUMBER(self), &r));
    return oci8_make_ocinumber(&r, errhp);
}
Beispiel #18
0
/*
 *  call-seq:
 *     onum.to_f -> float
 *
 *  Return the value as a <code>Float</code>.
 *
 */
static VALUE onum_to_f(VALUE self)
{
    OCIError *errhp = oci8_errhp;
    double dbl;

    oci_lc(OCINumberToReal(errhp, _NUMBER(self), sizeof(dbl), &dbl));
    return rb_float_new(dbl);
}
Beispiel #19
0
/*
 *  call-seq:
 *     onum.truncate     -> integer
 *     onum.truncate(decplace) -> oranumber
 *
 *  Truncates <i>onum</i> to the <code>Integer</code> when no argument.
 *  Truncates <i>onum</i> to a specified decimal place <i>decplace</i> when one argument.
 */
static VALUE onum_trunc(int argc, VALUE *argv, VALUE self)
{
    OCIError *errhp = oci8_errhp;
    VALUE decplace;
    OCINumber r;

    rb_scan_args(argc, argv, "01", &decplace /* 0 */);
    chkerr(OCINumberTrunc(errhp, _NUMBER(self), NIL_P(decplace) ? 0 : NUM2INT(decplace), &r));
    return oci8_make_ocinumber(&r, errhp);
}
Beispiel #20
0
/*
 *  call-seq:
 *     onum.round      -> integer
 *     onum.round(decplace) -> oranumber
 *
 *  Rounds <i>onum</i> to the nearest <code>Integer</code> when no argument.
 *  Rounds <i>onum</i> to a specified decimal place <i>decplace</i> when one argument.
 *
 *   OraNumber.new(1.234).round(1)  #=> 1.2
 *   OraNumber.new(1.234).round(2)  #=> 1.23
 *   OraNumber.new(1.234).round(3)  #=> 1.234
 */
static VALUE onum_round(int argc, VALUE *argv, VALUE self)
{
    OCIError *errhp = oci8_errhp;
    VALUE decplace;
    OCINumber r;

    rb_scan_args(argc, argv, "01", &decplace /* 0 */);
    chkerr(OCINumberRound(errhp, _NUMBER(self), NIL_P(decplace) ? 0 : NUM2INT(decplace), &r));
    if (argc == 0) {
        return oci8_make_integer(&r, errhp);
    } else {
        return oci8_make_ocinumber(&r, errhp);
    }
}
Beispiel #21
0
/*
 *  call-seq:
 *    onum % other   -> oranumber
 *
 *  Returns the modulo after division of <i>onum</i> by <i>other</i>.
 */
static VALUE onum_mod(VALUE lhs, VALUE rhs)
{
    OCIError *errhp = oci8_errhp;
    OCINumber n;
    OCINumber r;
    boolean is_zero;

    /* change to OCINumber */
    if (!set_oci_number_from_num(&n, rhs, 0, errhp))
        return rb_num_coerce_bin(lhs, rhs, '%');
    /* check whether argument is not zero. */
    chkerr(OCINumberIsZero(errhp, &n, &is_zero));
    if (is_zero)
        rb_num_zerodiv();
    /* modulo */
    chkerr(OCINumberMod(errhp, _NUMBER(lhs), &n, &r));
    return oci8_make_ocinumber(&r, errhp);
}
Beispiel #22
0
/*
 *  call-seq:
 *    onum <=> other   -> -1, 0, +1
 *
 *  Returns -1, 0, or +1 depending on whether <i>onum</i> is less than,
 *  equal to, or greater than <i>other</i>. This is the basis for the
 *  tests in <code>Comparable</code>.
 */
static VALUE onum_cmp(VALUE lhs, VALUE rhs)
{
    OCIError *errhp = oci8_errhp;
    OCINumber n;
    sword r;

    /* change to OCINumber */
    if (!set_oci_number_from_num(&n, rhs, 0, errhp))
        return rb_num_coerce_cmp(lhs, rhs, id_cmp);
    /* compare */
    chkerr(OCINumberCmp(errhp, _NUMBER(lhs), &n, &r));
    if (r > 0) {
        return INT2FIX(1);
    } else if (r == 0) {
        return INT2FIX(0);
    } else {
        return INT2FIX(-1);
    }
}
Beispiel #23
0
/*
 *  call-seq:
 *     onum.to_f -> float
 *
 *  Return the value as a <code>Float</code>.
 *
 */
static VALUE onum_to_f(VALUE self)
{
    return rb_float_new(oci8_onum_to_dbl(_NUMBER(self), oci8_errhp));
}
Beispiel #24
0
/*
 *  call-seq:
 *     onum.to_d -> bigdecimal
 *
 *  Return the value as a <code>BigDecimal</code>.
 *
 */
static VALUE onum_to_d(VALUE self)
{
    return onum_to_d_real(_NUMBER(self), oci8_errhp);
}
Beispiel #25
0
/*
 *  call-seq:
 *     onum.dump    -> string
 *
 *  Returns internal representation whose format is same with
 *  the return value of Oracle SQL function DUMP().
 *
 *   OraNumber.new(100).dump  #=> "Typ=2 Len=2: 194,2"
 *   OraNumber.new(123).dump  #=> "Typ=2 Len=3: 194,2,24"
 *   OraNumber.new(0.1).dump  #=> "Typ=2 Len=2: 192,11"
 */
static VALUE onum_dump(VALUE self)
{
    char buf[ORANUMBER_DUMP_BUF_SIZ];
    int rv = oranumber_dump(_NUMBER(self), buf);
    return rb_usascii_str_new(buf, rv);
}