예제 #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);
}
예제 #2
0
/*
 *  call-seq:
 *     OCI8::Math.atan2(y, x) -> oranumber
 *
 *  Computes the arc tangent given <i>y</i> and <i>x</i>. Returns
 *  -PI..PI.
 */
static VALUE omath_atan2(VALUE self, VALUE Ycoordinate, VALUE Xcoordinate)
{
    OCIError *errhp = oci8_errhp;
    OCINumber nY;
    OCINumber nX;
    OCINumber rv;
    boolean is_zero;
    sword sign;

    set_oci_number_from_num(&nX, Xcoordinate, 1, errhp);
    set_oci_number_from_num(&nY, Ycoordinate, 1, errhp);
    /* check zero */
    chkerr(OCINumberIsZero(errhp, &nX, &is_zero));
    if (is_zero) {
        chkerr(OCINumberSign(errhp, &nY, &sign));
        switch (sign) {
        case 0:
            return INT2FIX(0); /* atan2(0, 0) => 0 or ERROR? */
        case 1:
            return oci8_make_ocinumber(&const_PI2, errhp); /* atan2(positive, 0) => PI/2 */
        case -1:
            return oci8_make_ocinumber(&const_mPI2, errhp); /* atan2(negative, 0) => -PI/2 */
        }
    }
    /* atan2 */
    chkerr(OCINumberArcTan2(errhp, &nY, &nX, &rv));
    return oci8_make_ocinumber(&rv, errhp);
}
예제 #3
0
static VALUE onum_coerce(VALUE self, VALUE other)
{
    signed long sl;
    OCINumber n;

    switch(rboci8_type(other)) {
    case T_FIXNUM:
        sl = NUM2LONG(other);
        chkerr(OCINumberFromInt(oci8_errhp, &sl, sizeof(sl), OCI_NUMBER_SIGNED, &n));
        return rb_assoc_new(oci8_make_ocinumber(&n, oci8_errhp), self);
    case T_BIGNUM:
        /* change via string. */
        other = rb_big2str(other, 10);
        set_oci_number_from_str(&n, other, Qnil, Qnil, oci8_errhp);
        return rb_assoc_new(oci8_make_ocinumber(&n, oci8_errhp), self);
    case T_FLOAT:
        return rb_assoc_new(other, onum_to_f(self));
    case RBOCI8_T_RATIONAL:
        return rb_assoc_new(other, onum_to_r(self));
    case RBOCI8_T_BIGDECIMAL:
        return rb_assoc_new(other, onum_to_d(self));
    }
    rb_raise(rb_eTypeError, "Can't coerce %s to %s",
             rb_class2name(CLASS_OF(other)), rb_class2name(cOCINumber));
}
예제 #4
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);
}
예제 #5
0
/*
 *  call-seq:
 *     OCI8::Math.log(numeric)    -> oranumber
 *     OCI8::Math.log(numeric, base_num)  -> oranumber
 *
 *  Returns the natural logarithm of <i>numeric</i> for one argument.
 *  Returns the base <i>base_num</i> logarithm of <i>numeric</i> for two arguments.
 */
static VALUE omath_log(int argc, VALUE *argv, VALUE obj)
{
    OCIError *errhp = oci8_errhp;
    VALUE num, base;
    OCINumber n;
    OCINumber b;
    OCINumber r;
    sword sign;

    rb_scan_args(argc, argv, "11", &num, &base);
    set_oci_number_from_num(&n, num, 1, errhp);
    chkerr(OCINumberSign(errhp, &n, &sign));
    if (sign <= 0)
        rb_raise(rb_eRangeError, "nonpositive value for log");
    if (NIL_P(base)) {
        chkerr(OCINumberLn(errhp, &n, &r));
    } else {
        set_oci_number_from_num(&b, base, 1, errhp);
        chkerr(OCINumberSign(errhp, &b, &sign));
        if (sign <= 0)
            rb_raise(rb_eRangeError, "nonpositive value for the base of log");
        chkerr(OCINumberCmp(errhp, &b, &const_p1, &sign));
        if (sign == 0)
            rb_raise(rb_eRangeError, "base 1 for log");
        chkerr(OCINumberLog(errhp, &b, &n, &r));
    }
    return oci8_make_ocinumber(&r, errhp);
}
예제 #6
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);
}
예제 #7
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);
}
예제 #8
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);
}
예제 #9
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);
}
예제 #10
0
/*
 *  call-seq:
 *     OCI8::Math.tanh()    -> oranumber
 *
 *  Computes the hyperbolic tangent of <i>x</i> (expressed in
 *  radians).
 */
static VALUE omath_tanh(VALUE obj, VALUE num)
{
    OCIError *errhp = oci8_errhp;
    OCINumber n;
    OCINumber r;

    oci_lc(OCINumberHypTan(errhp, TO_OCINUM(&n, num, errhp), &r));
    return oci8_make_ocinumber(&r, errhp);
}
예제 #11
0
/*
 *  call-seq:
 *     OCI8::Math.tan(x)    -> oranumber
 *
 *  Returns the tangent of <i>x</i> (expressed in radians).
 */
static VALUE omath_tan(VALUE obj, VALUE radian)
{
    OCIError *errhp = oci8_errhp;
    OCINumber r;
    OCINumber rv;

    chkerr(OCINumberTan(errhp, TO_OCINUM(&r, radian, errhp), &rv));
    return oci8_make_ocinumber(&rv, errhp);
}
예제 #12
0
/*
 *  call-seq:
 *     OCI8::Math.cos(x) -> oranumber
 *
 *  Computes the cosine of <i>x</i> (expressed in radians). Returns
 *  -1..1.
 */
static VALUE omath_cos(VALUE obj, VALUE radian)
{
    OCIError *errhp = oci8_errhp;
    OCINumber r;
    OCINumber rv;

    oci_lc(OCINumberCos(errhp, TO_OCINUM(&r, radian, errhp), &rv));
    return oci8_make_ocinumber(&rv, errhp);
}
예제 #13
0
/*
 *  call-seq:
 *     OCI8::Math.exp(x)    -> oranumber
 *
 *  Returns e**x.
 */
static VALUE omath_exp(VALUE obj, VALUE num)
{
    OCIError *errhp = oci8_errhp;
    OCINumber n;
    OCINumber r;

    chkerr(OCINumberExp(errhp, TO_OCINUM(&n, num, errhp), &r));
    return oci8_make_ocinumber(&r, errhp);
}
예제 #14
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);
}
예제 #15
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);
    }
}
예제 #16
0
/*
 *  call-seq:
 *     OCI8::Math.log10(numeric)    -> oranumber
 *
 *  Returns the base 10 logarithm of <i>numeric</i>.
 */
static VALUE omath_log10(VALUE obj, VALUE num)
{
    OCIError *errhp = oci8_errhp;
    OCINumber n;
    OCINumber r;
    sword sign;

    set_oci_number_from_num(&n, num, 1, errhp);
    chkerr(OCINumberSign(errhp, &n, &sign));
    if (sign <= 0)
        rb_raise(rb_eRangeError, "nonpositive value for log10");
    chkerr(OCINumberLog(errhp, &const_p10, &n, &r));
    return oci8_make_ocinumber(&r, errhp);
}
예제 #17
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);
}
예제 #18
0
/*
 *  call-seq:
 *    OraNumber._load(string)   -> oranumber
 *
 *  Unmarshal a dumped <code>OraNumber</code> object.
 */
static VALUE
onum_s_load(VALUE klass, VALUE str)
{
    unsigned char *c;
    size_t size;
    OCINumber num;

    Check_Type(str, T_STRING);
    c = RSTRING_ORATEXT(str);
    size = RSTRING_LEN(str);
    if (size == 0 || size != c[0] + 1u || size > sizeof(num)) {
        rb_raise(rb_eTypeError, "marshaled OCI::Number format differ");
    }
    memset(&num, 0, sizeof(num));
    memcpy(&num, c, size);
    return oci8_make_ocinumber(&num, oci8_errhp);
}
예제 #19
0
/*
 *  call-seq:
 *     OCI8::Math.sqrt(numeric)    -> oranumber
 *
 *  Returns the non-negative square root of <i>numeric</i>.
 */
static VALUE omath_sqrt(VALUE obj, VALUE num)
{
    OCIError *errhp = oci8_errhp;
    OCINumber n;
    OCINumber r;
    sword sign;

    set_oci_number_from_num(&n, num, 1, errhp);
    /* check whether num is negative */
    chkerr(OCINumberSign(errhp, &n, &sign));
    if (sign < 0) {
        errno = EDOM;
        rb_sys_fail("sqrt");
    }
    chkerr(OCINumberSqrt(errhp, &n, &r));
    return oci8_make_ocinumber(&r, errhp);
}
예제 #20
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);
}
예제 #21
0
/*
 *  call-seq:
 *     OCI8::Math.asin(x)    -> oranumber
 *
 *  Computes the arc sine of <i>x</i>. Returns 0..PI.
 */
static VALUE omath_asin(VALUE obj, VALUE num)
{
    OCIError *errhp = oci8_errhp;
    OCINumber n;
    OCINumber r;
    sword sign;

    set_oci_number_from_num(&n, num, 1, errhp);
    /* check upper bound */
    chkerr(OCINumberCmp(errhp, &n, &const_p1, &sign));
    if (sign > 0)
        rb_raise(rb_eRangeError, "out of range for asin");
    /* check lower bound */
    chkerr(OCINumberCmp(errhp, &n, &const_m1, &sign));
    if (sign < 0)
        rb_raise(rb_eRangeError, "out of range for asin");
    /* asin */
    chkerr(OCINumberArcSin(errhp, &n, &r));
    return oci8_make_ocinumber(&r, errhp);
}
예제 #22
0
/*
 * bind_ocinumber
 */
static VALUE bind_ocinumber_get(oci8_bind_t *obind, void *data, void *null_struct)
{
    return oci8_make_ocinumber((OCINumber*)data, oci8_errhp);
}
예제 #23
0
void
Init_oci_number(VALUE cOCI8, OCIError *errhp)
{
    VALUE mMath;
    OCINumber num1, num2;
    VALUE obj_PI;
    signed long sl;

    id_power = rb_intern("**");
    id_cmp = rb_intern("<=>");
    id_finite_p = rb_intern("finite?");
    id_split = rb_intern("split");
    id_numerator = rb_intern("numerator");
    id_denominator = rb_intern("denominator");
    id_Rational = rb_intern("Rational");
    id_BigDecimal = rb_intern("BigDecimal");

    cOCINumber = rb_define_class("OraNumber", rb_cNumeric);
    mMath = rb_define_module_under(cOCI8, "Math");

    /* constants for internal use. */
    /* set const_p1 */
    sl = 1;
    OCINumberFromInt(errhp, &sl, sizeof(sl), OCI_NUMBER_SIGNED, &const_p1);
    /* set const_p10 */
    sl = 10;
    OCINumberFromInt(errhp, &sl, sizeof(sl), OCI_NUMBER_SIGNED, &const_p10);
    /* set const_m1 */
    sl = -1;
    OCINumberFromInt(errhp, &sl, sizeof(sl), OCI_NUMBER_SIGNED, &const_m1);
    /* set const_PI2 */
    sl = 2;
    OCINumberSetPi(errhp, &num1);
    OCINumberFromInt(errhp, &sl, sizeof(sl), OCI_NUMBER_SIGNED, &num2);
    OCINumberDiv(errhp, &num1 /* PI */, &num2 /* 2 */, &const_PI2);
    /* set const_mPI2 */
    OCINumberNeg(errhp, &const_PI2 /* PI/2 */, &const_mPI2);

    /* PI */
    OCINumberSetPi(errhp, &num1);
    obj_PI = oci8_make_ocinumber(&num1, errhp);

    /* The ratio of the circumference of a circle to its diameter. */
    rb_define_const(mMath, "PI", obj_PI);

    /*
     * module functions of OCI::Math.
     */
    rb_define_module_function(mMath, "atan2", omath_atan2, 2);

    rb_define_module_function(mMath, "cos", omath_cos, 1);
    rb_define_module_function(mMath, "sin", omath_sin, 1);
    rb_define_module_function(mMath, "tan", omath_tan, 1);

    rb_define_module_function(mMath, "acos", omath_acos, 1);
    rb_define_module_function(mMath, "asin", omath_asin, 1);
    rb_define_module_function(mMath, "atan", omath_atan, 1);

    rb_define_module_function(mMath, "cosh", omath_cosh, 1);
    rb_define_module_function(mMath, "sinh", omath_sinh, 1);
    rb_define_module_function(mMath, "tanh", omath_tanh, 1);

    rb_define_module_function(mMath, "exp", omath_exp, 1);
    rb_define_module_function(mMath, "log", omath_log, -1);
    rb_define_module_function(mMath, "log10", omath_log10, 1);
    rb_define_module_function(mMath, "sqrt", omath_sqrt, 1);

    rb_define_alloc_func(cOCINumber, onum_s_alloc);

    /* methods of OCI::Number */
    rb_define_method(rb_cObject, "OraNumber", onum_f_new, -1);
    rb_define_method_nodoc(cOCINumber, "initialize", onum_initialize, -1);
    rb_define_method_nodoc(cOCINumber, "initialize_copy", onum_initialize_copy, 1);
    rb_define_method_nodoc(cOCINumber, "coerce", onum_coerce, 1);

    rb_include_module(cOCINumber, rb_mComparable);

    rb_define_method(cOCINumber, "-@", onum_neg, 0);
    rb_define_method(cOCINumber, "+", onum_add, 1);
    rb_define_method(cOCINumber, "-", onum_sub, 1);
    rb_define_method(cOCINumber, "*", onum_mul, 1);
    rb_define_method(cOCINumber, "/", onum_div, 1);
    rb_define_method(cOCINumber, "%", onum_mod, 1);
    rb_define_method(cOCINumber, "**", onum_power, 1);
    rb_define_method(cOCINumber, "<=>", onum_cmp, 1);

    rb_define_method(cOCINumber, "floor", onum_floor, 0);
    rb_define_method(cOCINumber, "ceil", onum_ceil, 0);
    rb_define_method(cOCINumber, "round", onum_round, -1);
    rb_define_method(cOCINumber, "truncate", onum_trunc, -1);
    rb_define_method(cOCINumber, "round_prec", onum_round_prec, 1);

    rb_define_method(cOCINumber, "to_s", onum_to_s, 0);
    rb_define_method(cOCINumber, "to_char", onum_to_char, -1);
    rb_define_method(cOCINumber, "to_i", onum_to_i, 0);
    rb_define_method(cOCINumber, "to_f", onum_to_f, 0);
    rb_define_method(cOCINumber, "to_r", onum_to_r, 0);
    rb_define_method(cOCINumber, "to_d", onum_to_d, 0);
    rb_define_method(cOCINumber, "has_decimal_part?", onum_has_decimal_part_p, 0);
    rb_define_method_nodoc(cOCINumber, "to_onum", onum_to_onum, 0);

    rb_define_method(cOCINumber, "zero?", onum_zero_p, 0);
    rb_define_method(cOCINumber, "abs", onum_abs, 0);
    rb_define_method(cOCINumber, "shift", onum_shift, 1);
    rb_define_method(cOCINumber, "dump", onum_dump, 0);

    rb_define_method_nodoc(cOCINumber, "hash", onum_hash, 0);
    rb_define_method_nodoc(cOCINumber, "inspect", onum_inspect, 0);

    /* methods for marshaling */
    rb_define_method(cOCINumber, "_dump", onum__dump, -1);
    rb_define_singleton_method(cOCINumber, "_load", onum_s_load, 1);

    oci8_define_bind_class("OraNumber", &bind_ocinumber_vtable);
    oci8_define_bind_class("Integer", &bind_integer_vtable);
    oci8_define_bind_class("Float", &bind_float_vtable);
}