ruby-oci8-master 2.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ChangeLog +2321 -0
- data/Makefile +88 -0
- data/NEWS +303 -0
- data/README +76 -0
- data/VERSION +1 -0
- data/dist-files +83 -0
- data/doc/api.en.html +527 -0
- data/doc/api.en.rd +554 -0
- data/doc/api.ja.html +525 -0
- data/doc/api.ja.rd +557 -0
- data/doc/manual.css +35 -0
- data/ext/oci8/.document +18 -0
- data/ext/oci8/MANIFEST +18 -0
- data/ext/oci8/apiwrap.c.tmpl +182 -0
- data/ext/oci8/apiwrap.h.tmpl +61 -0
- data/ext/oci8/apiwrap.rb +91 -0
- data/ext/oci8/apiwrap.yml +1455 -0
- data/ext/oci8/attr.c +105 -0
- data/ext/oci8/bind.c +366 -0
- data/ext/oci8/connection_pool.c +199 -0
- data/ext/oci8/encoding.c +289 -0
- data/ext/oci8/env.c +178 -0
- data/ext/oci8/error.c +378 -0
- data/ext/oci8/extconf.rb +179 -0
- data/ext/oci8/lob.c +805 -0
- data/ext/oci8/metadata.c +232 -0
- data/ext/oci8/object.c +727 -0
- data/ext/oci8/oci8.c +1156 -0
- data/ext/oci8/oci8.h +574 -0
- data/ext/oci8/oci8lib.c +527 -0
- data/ext/oci8/ocidatetime.c +484 -0
- data/ext/oci8/ocihandle.c +751 -0
- data/ext/oci8/ocinumber.c +1612 -0
- data/ext/oci8/oraconf.rb +1119 -0
- data/ext/oci8/oradate.c +611 -0
- data/ext/oci8/oranumber_util.c +352 -0
- data/ext/oci8/oranumber_util.h +24 -0
- data/ext/oci8/post-config.rb +5 -0
- data/ext/oci8/stmt.c +673 -0
- data/ext/oci8/thread_util.c +85 -0
- data/ext/oci8/thread_util.h +30 -0
- data/ext/oci8/win32.c +137 -0
- data/lib/.document +1 -0
- data/lib/dbd/OCI8.rb +591 -0
- data/lib/oci8.rb.in +94 -0
- data/lib/oci8/.document +8 -0
- data/lib/oci8/bindtype.rb +349 -0
- data/lib/oci8/compat.rb +113 -0
- data/lib/oci8/connection_pool.rb +99 -0
- data/lib/oci8/datetime.rb +611 -0
- data/lib/oci8/encoding-init.rb +74 -0
- data/lib/oci8/encoding.yml +537 -0
- data/lib/oci8/metadata.rb +2132 -0
- data/lib/oci8/object.rb +581 -0
- data/lib/oci8/oci8.rb +721 -0
- data/lib/oci8/ocihandle.rb +425 -0
- data/lib/oci8/oracle_version.rb +144 -0
- data/lib/oci8/properties.rb +73 -0
- data/metaconfig +142 -0
- data/pre-distclean.rb +7 -0
- data/ruby-oci8.gemspec +63 -0
- data/setup.rb +1331 -0
- data/test/README +4 -0
- data/test/config.rb +122 -0
- data/test/test_all.rb +51 -0
- data/test/test_appinfo.rb +63 -0
- data/test/test_array_dml.rb +333 -0
- data/test/test_bind_raw.rb +46 -0
- data/test/test_bind_time.rb +178 -0
- data/test/test_break.rb +96 -0
- data/test/test_clob.rb +82 -0
- data/test/test_connstr.rb +81 -0
- data/test/test_datetime.rb +582 -0
- data/test/test_dbi.rb +366 -0
- data/test/test_dbi_clob.rb +53 -0
- data/test/test_encoding.rb +100 -0
- data/test/test_error.rb +88 -0
- data/test/test_metadata.rb +1399 -0
- data/test/test_oci8.rb +434 -0
- data/test/test_oracle_version.rb +70 -0
- data/test/test_oradate.rb +256 -0
- data/test/test_oranumber.rb +746 -0
- data/test/test_rowid.rb +33 -0
- metadata +137 -0
@@ -0,0 +1,1612 @@
|
|
1
|
+
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
|
2
|
+
/*
|
3
|
+
* ocinumber.c
|
4
|
+
*
|
5
|
+
* Copyright (C) 2005-2011 KUBO Takehiro <kubo@jiubao.org>
|
6
|
+
*
|
7
|
+
*/
|
8
|
+
#include "oci8.h"
|
9
|
+
#include <orl.h>
|
10
|
+
#include <errno.h>
|
11
|
+
#include <math.h>
|
12
|
+
#include "oranumber_util.h"
|
13
|
+
|
14
|
+
#ifndef RB_NUM_COERCE_FUNCS_NEED_OPID
|
15
|
+
/* ruby 1.8 */
|
16
|
+
#define rb_num_coerce_cmp(x, y, id) rb_num_coerce_cmp((x), (y))
|
17
|
+
#define rb_num_coerce_bin(x, y, id) rb_num_coerce_bin((x), (y))
|
18
|
+
#endif
|
19
|
+
|
20
|
+
int oci8_float_conversion_type_is_ruby = 1;
|
21
|
+
|
22
|
+
#ifndef INFINITY
|
23
|
+
#define INFINITY (1.0/+0.0)
|
24
|
+
#endif
|
25
|
+
|
26
|
+
static ID id_power; /* rb_intern("**") */
|
27
|
+
static ID id_cmp; /* rb_intern("<=>") */
|
28
|
+
static ID id_finite_p;
|
29
|
+
static ID id_split;
|
30
|
+
static ID id_numerator;
|
31
|
+
static ID id_denominator;
|
32
|
+
static ID id_Rational;
|
33
|
+
static ID id_BigDecimal;
|
34
|
+
|
35
|
+
#ifndef T_RATIONAL
|
36
|
+
static VALUE cRational;
|
37
|
+
#endif
|
38
|
+
static VALUE cBigDecimal;
|
39
|
+
|
40
|
+
static VALUE cOCINumber;
|
41
|
+
static OCINumber const_p1; /* +1 */
|
42
|
+
static OCINumber const_p10; /* +10 */
|
43
|
+
static OCINumber const_m1; /* -1 */
|
44
|
+
static OCINumber const_PI2; /* +PI/2 */
|
45
|
+
static OCINumber const_mPI2; /* -PI/2 */
|
46
|
+
|
47
|
+
#define _NUMBER(val) ((OCINumber *)DATA_PTR(val)) /* dangerous macro */
|
48
|
+
|
49
|
+
#ifndef T_MASK
|
50
|
+
#define T_MASK 0x100 /* TODO: rboci8_type() should be changed to be more portable. */
|
51
|
+
#endif
|
52
|
+
#define RBOCI8_T_ORANUMBER (T_MASK + 1)
|
53
|
+
#define RBOCI8_T_BIGDECIMAL (T_MASK + 2)
|
54
|
+
#ifdef T_RATIONAL
|
55
|
+
#define RBOCI8_T_RATIONAL T_RATIONAL
|
56
|
+
#else
|
57
|
+
#define RBOCI8_T_RATIONAL (T_MASK + 3)
|
58
|
+
#endif
|
59
|
+
|
60
|
+
static int rboci8_type(VALUE obj)
|
61
|
+
{
|
62
|
+
int type = TYPE(obj);
|
63
|
+
VALUE klass;
|
64
|
+
|
65
|
+
switch (type) {
|
66
|
+
#ifndef T_RATIONAL
|
67
|
+
case T_OBJECT:
|
68
|
+
klass = CLASS_OF(obj);
|
69
|
+
if (cRational != 0) {
|
70
|
+
if (klass == cRational) {
|
71
|
+
return RBOCI8_T_RATIONAL;
|
72
|
+
}
|
73
|
+
} else {
|
74
|
+
if (strcmp(rb_class2name(klass), "Rational") == 0) {
|
75
|
+
cRational = rb_const_get(rb_cObject, id_Rational);
|
76
|
+
return RBOCI8_T_RATIONAL;
|
77
|
+
}
|
78
|
+
}
|
79
|
+
break;
|
80
|
+
#endif
|
81
|
+
case T_DATA:
|
82
|
+
klass = CLASS_OF(obj);
|
83
|
+
if (klass == cOCINumber) {
|
84
|
+
return RBOCI8_T_ORANUMBER;
|
85
|
+
}
|
86
|
+
if (cBigDecimal != 0) {
|
87
|
+
if (klass == cBigDecimal) {
|
88
|
+
return RBOCI8_T_BIGDECIMAL;
|
89
|
+
}
|
90
|
+
} else {
|
91
|
+
if (strcmp(rb_class2name(klass), "BigDecimal") == 0) {
|
92
|
+
cBigDecimal = rb_const_get(rb_cObject, id_BigDecimal);
|
93
|
+
return RBOCI8_T_BIGDECIMAL;
|
94
|
+
}
|
95
|
+
}
|
96
|
+
}
|
97
|
+
return type;
|
98
|
+
}
|
99
|
+
|
100
|
+
static VALUE onum_to_f(VALUE self);
|
101
|
+
static VALUE onum_to_r(VALUE self);
|
102
|
+
static VALUE onum_to_d(VALUE self);
|
103
|
+
static VALUE onum_to_d_real(OCINumber *num, OCIError *errhp);
|
104
|
+
|
105
|
+
static VALUE onum_s_alloc(VALUE klass)
|
106
|
+
{
|
107
|
+
VALUE obj;
|
108
|
+
OCINumber *d;
|
109
|
+
|
110
|
+
obj = Data_Make_Struct(klass, OCINumber, NULL, xfree, d);
|
111
|
+
OCINumberSetZero(oci8_errhp, d);
|
112
|
+
return obj;
|
113
|
+
}
|
114
|
+
|
115
|
+
/* construct an ruby object(OCI::Number) from C structure (OCINumber). */
|
116
|
+
VALUE oci8_make_ocinumber(OCINumber *s, OCIError *errhp)
|
117
|
+
{
|
118
|
+
VALUE obj;
|
119
|
+
OCINumber *d;
|
120
|
+
|
121
|
+
obj = Data_Make_Struct(cOCINumber, OCINumber, NULL, xfree, d);
|
122
|
+
chkerr(OCINumberAssign(errhp, s, d));
|
123
|
+
return obj;
|
124
|
+
}
|
125
|
+
|
126
|
+
VALUE oci8_make_integer(OCINumber *s, OCIError *errhp)
|
127
|
+
{
|
128
|
+
signed long sl;
|
129
|
+
char buf[512];
|
130
|
+
sword rv;
|
131
|
+
|
132
|
+
if (OCINumberToInt(errhp, s, sizeof(sl), OCI_NUMBER_SIGNED, &sl) == OCI_SUCCESS) {
|
133
|
+
return LONG2NUM(sl);
|
134
|
+
}
|
135
|
+
/* convert to Integer via String */
|
136
|
+
rv = oranumber_to_str(s, buf, sizeof(buf));
|
137
|
+
if (rv > 0) {
|
138
|
+
return rb_cstr2inum(buf, 10);
|
139
|
+
}
|
140
|
+
oranumber_dump(s, buf);
|
141
|
+
rb_raise(eOCIException, "Invalid internal number format: %s", buf);
|
142
|
+
}
|
143
|
+
|
144
|
+
VALUE oci8_make_float(OCINumber *s, OCIError *errhp)
|
145
|
+
{
|
146
|
+
return rb_float_new(oci8_onum_to_dbl(s, errhp));
|
147
|
+
}
|
148
|
+
|
149
|
+
/* fill C structure (OCINumber) from a string. */
|
150
|
+
static void set_oci_number_from_str(OCINumber *result, VALUE str, VALUE fmt, VALUE nls_params, OCIError *errhp)
|
151
|
+
{
|
152
|
+
oratext *fmt_ptr;
|
153
|
+
oratext *nls_params_ptr;
|
154
|
+
ub4 fmt_len;
|
155
|
+
ub4 nls_params_len;
|
156
|
+
|
157
|
+
StringValue(str);
|
158
|
+
/* set from string. */
|
159
|
+
if (NIL_P(fmt)) {
|
160
|
+
int rv = oranumber_from_str(result, RSTRING_PTR(str), RSTRING_LEN(str));
|
161
|
+
if (rv == ORANUMBER_SUCCESS) {
|
162
|
+
return; /* success */
|
163
|
+
} else {
|
164
|
+
const char *default_msg = NULL;
|
165
|
+
switch (rv) {
|
166
|
+
case ORANUMBER_INVALID_NUMBER:
|
167
|
+
default_msg = "invalid number";
|
168
|
+
break;
|
169
|
+
case ORANUMBER_NUMERIC_OVERFLOW:
|
170
|
+
default_msg = "numeric overflow";
|
171
|
+
break;
|
172
|
+
}
|
173
|
+
oci8_raise_by_msgno(rv, default_msg);
|
174
|
+
}
|
175
|
+
}
|
176
|
+
StringValue(fmt);
|
177
|
+
fmt_ptr = RSTRING_ORATEXT(fmt);
|
178
|
+
fmt_len = RSTRING_LEN(fmt);
|
179
|
+
if (NIL_P(nls_params)) {
|
180
|
+
nls_params_ptr = NULL;
|
181
|
+
nls_params_len = 0;
|
182
|
+
} else {
|
183
|
+
StringValue(nls_params);
|
184
|
+
nls_params_ptr = RSTRING_ORATEXT(nls_params);
|
185
|
+
nls_params_len = RSTRING_LEN(nls_params);
|
186
|
+
}
|
187
|
+
chkerr(OCINumberFromText(errhp,
|
188
|
+
RSTRING_ORATEXT(str), RSTRING_LEN(str),
|
189
|
+
fmt_ptr, fmt_len, nls_params_ptr, nls_params_len,
|
190
|
+
result));
|
191
|
+
}
|
192
|
+
|
193
|
+
/* fill C structure (OCINumber) from a numeric object. */
|
194
|
+
/* 1 - success, 0 - error */
|
195
|
+
static int set_oci_number_from_num(OCINumber *result, VALUE num, int force, OCIError *errhp)
|
196
|
+
{
|
197
|
+
signed long sl;
|
198
|
+
|
199
|
+
if (!RTEST(rb_obj_is_kind_of(num, rb_cNumeric)))
|
200
|
+
rb_raise(rb_eTypeError, "expect Numeric but %s", rb_class2name(CLASS_OF(num)));
|
201
|
+
if (rb_respond_to(num, id_finite_p) && !RTEST(rb_funcall(num, id_finite_p, 0))) {
|
202
|
+
rb_raise(rb_eTypeError, "cannot accept number which isn't finite.");
|
203
|
+
}
|
204
|
+
switch (rb_type(num)) {
|
205
|
+
case T_FIXNUM:
|
206
|
+
/* set from long. */
|
207
|
+
sl = NUM2LONG(num);
|
208
|
+
chkerr(OCINumberFromInt(errhp, &sl, sizeof(sl), OCI_NUMBER_SIGNED, result));
|
209
|
+
return 1;
|
210
|
+
case T_FLOAT:
|
211
|
+
/* set from double. */
|
212
|
+
oci8_dbl_to_onum(result, NUM2DBL(num), errhp);
|
213
|
+
return 1;
|
214
|
+
case T_BIGNUM:
|
215
|
+
/* change via string. */
|
216
|
+
num = rb_big2str(num, 10);
|
217
|
+
set_oci_number_from_str(result, num, Qnil, Qnil, errhp);
|
218
|
+
return 1;
|
219
|
+
}
|
220
|
+
if (RTEST(rb_obj_is_instance_of(num, cOCINumber))) {
|
221
|
+
/* OCI::Number */
|
222
|
+
chkerr(OCINumberAssign(errhp, DATA_PTR(num), result));
|
223
|
+
return 1;
|
224
|
+
}
|
225
|
+
if (rb_respond_to(num, id_split)) {
|
226
|
+
/* BigDecimal */
|
227
|
+
VALUE split = rb_funcall(num, id_split, 0);
|
228
|
+
|
229
|
+
if (TYPE(split) == T_ARRAY && RARRAY_LEN(split) == 4) {
|
230
|
+
/*
|
231
|
+
* sign, significant_digits, base, exponent = num.split
|
232
|
+
* onum = sign * "0.#{significant_digits}".to_f * (base ** exponent)
|
233
|
+
*/
|
234
|
+
VALUE *ary = RARRAY_PTR(split);
|
235
|
+
int sign;
|
236
|
+
OCINumber digits;
|
237
|
+
int exponent;
|
238
|
+
int digits_len;
|
239
|
+
OCINumber work;
|
240
|
+
|
241
|
+
/* check sign */
|
242
|
+
if (TYPE(ary[0]) != T_FIXNUM) {
|
243
|
+
goto is_not_big_decimal;
|
244
|
+
}
|
245
|
+
sign = FIX2INT(ary[0]);
|
246
|
+
/* check digits */
|
247
|
+
StringValue(ary[1]);
|
248
|
+
digits_len = RSTRING_LEN(ary[1]);
|
249
|
+
set_oci_number_from_str(&digits, ary[1], Qnil, Qnil, errhp);
|
250
|
+
/* check base */
|
251
|
+
if (TYPE(ary[2]) != T_FIXNUM || FIX2LONG(ary[2]) != 10) {
|
252
|
+
goto is_not_big_decimal;
|
253
|
+
}
|
254
|
+
/* check exponent */
|
255
|
+
if (TYPE(ary[3]) != T_FIXNUM) {
|
256
|
+
goto is_not_big_decimal;
|
257
|
+
}
|
258
|
+
exponent = FIX2INT(ary[3]);
|
259
|
+
|
260
|
+
chkerr(OCINumberShift(errhp, &digits, exponent - digits_len, &work));
|
261
|
+
if (sign >= 0) {
|
262
|
+
chkerr(OCINumberAssign(errhp, &work, result));
|
263
|
+
} else {
|
264
|
+
chkerr(OCINumberNeg(errhp, &work, result));
|
265
|
+
}
|
266
|
+
return 1;
|
267
|
+
}
|
268
|
+
}
|
269
|
+
is_not_big_decimal:
|
270
|
+
if (rb_respond_to(num, id_numerator) && rb_respond_to(num, id_denominator)) {
|
271
|
+
/* Rational */
|
272
|
+
OCINumber numerator;
|
273
|
+
OCINumber denominator;
|
274
|
+
|
275
|
+
if (set_oci_number_from_num(&numerator, rb_funcall(num, id_numerator, 0), 0, errhp) &&
|
276
|
+
set_oci_number_from_num(&denominator, rb_funcall(num, id_denominator, 0), 0, errhp)) {
|
277
|
+
chkerr(OCINumberDiv(errhp, &numerator, &denominator, result));
|
278
|
+
return 1;
|
279
|
+
}
|
280
|
+
}
|
281
|
+
if (force) {
|
282
|
+
/* change via string as a last resort. */
|
283
|
+
/* TODO: if error, raise TypeError instead of OCI::Error */
|
284
|
+
set_oci_number_from_str(result, num, Qnil, Qnil, errhp);
|
285
|
+
return 1;
|
286
|
+
}
|
287
|
+
return 0;
|
288
|
+
}
|
289
|
+
|
290
|
+
OCINumber *oci8_set_ocinumber(OCINumber *result, VALUE self, OCIError *errhp)
|
291
|
+
{
|
292
|
+
set_oci_number_from_num(result, self, 1, errhp);
|
293
|
+
return result;
|
294
|
+
}
|
295
|
+
#define TO_OCINUM oci8_set_ocinumber
|
296
|
+
|
297
|
+
OCINumber *oci8_set_integer(OCINumber *result, VALUE self, OCIError *errhp)
|
298
|
+
{
|
299
|
+
OCINumber work;
|
300
|
+
|
301
|
+
set_oci_number_from_num(&work, self, 1, errhp);
|
302
|
+
chkerr(OCINumberTrunc(errhp, &work, 0, result));
|
303
|
+
return result;
|
304
|
+
}
|
305
|
+
|
306
|
+
double oci8_onum_to_dbl(OCINumber *s, OCIError *errhp)
|
307
|
+
{
|
308
|
+
if (oci8_float_conversion_type_is_ruby) {
|
309
|
+
char buf[256];
|
310
|
+
sword rv;
|
311
|
+
|
312
|
+
rv = oranumber_to_str(s, buf, sizeof(buf));
|
313
|
+
if (rv <= 0) {
|
314
|
+
char buf[ORANUMBER_DUMP_BUF_SIZ];
|
315
|
+
|
316
|
+
oranumber_dump(s, buf);
|
317
|
+
rb_raise(eOCIException, "Invalid internal number format: %s", buf);
|
318
|
+
}
|
319
|
+
if (strcmp(buf, "~") == 0) {
|
320
|
+
return INFINITY;
|
321
|
+
} else if (strcmp(buf, "-~") == 0) {
|
322
|
+
return -INFINITY;
|
323
|
+
}
|
324
|
+
return rb_cstr_to_dbl(buf, Qtrue);
|
325
|
+
} else {
|
326
|
+
double dbl;
|
327
|
+
|
328
|
+
chkerr(OCINumberToReal(errhp, s, sizeof(double), &dbl));
|
329
|
+
return dbl;
|
330
|
+
}
|
331
|
+
}
|
332
|
+
|
333
|
+
OCINumber *oci8_dbl_to_onum(OCINumber *result, double dbl, OCIError *errhp)
|
334
|
+
{
|
335
|
+
switch (fpclassify(dbl)) {
|
336
|
+
case FP_NAN:
|
337
|
+
rb_raise(rb_eFloatDomainError, "NaN");
|
338
|
+
/* never reach here */
|
339
|
+
break;
|
340
|
+
case FP_INFINITE:
|
341
|
+
if (dbl > 0.0) {
|
342
|
+
oranumber_from_str(result, "~", 1);
|
343
|
+
} else {
|
344
|
+
oranumber_from_str(result, "-~", 2);
|
345
|
+
}
|
346
|
+
return result;
|
347
|
+
}
|
348
|
+
|
349
|
+
if (oci8_float_conversion_type_is_ruby) {
|
350
|
+
VALUE str;
|
351
|
+
sword rv;
|
352
|
+
|
353
|
+
str = rb_obj_as_string(rb_float_new(dbl));
|
354
|
+
rv = oranumber_from_str(result, RSTRING_PTR(str), RSTRING_LEN(str));
|
355
|
+
if (rv != 0) {
|
356
|
+
oci8_raise_by_msgno(rv, NULL);
|
357
|
+
}
|
358
|
+
} else {
|
359
|
+
chkerr(OCINumberFromReal(errhp, &dbl, sizeof(dbl), result));
|
360
|
+
}
|
361
|
+
return result;
|
362
|
+
}
|
363
|
+
|
364
|
+
/*
|
365
|
+
* call-seq:
|
366
|
+
* OCI8::Math.atan2(y, x) -> oranumber
|
367
|
+
*
|
368
|
+
* Computes the arc tangent given <i>y</i> and <i>x</i>. Returns
|
369
|
+
* -PI..PI.
|
370
|
+
*/
|
371
|
+
static VALUE omath_atan2(VALUE self, VALUE Ycoordinate, VALUE Xcoordinate)
|
372
|
+
{
|
373
|
+
OCIError *errhp = oci8_errhp;
|
374
|
+
OCINumber nY;
|
375
|
+
OCINumber nX;
|
376
|
+
OCINumber rv;
|
377
|
+
boolean is_zero;
|
378
|
+
sword sign;
|
379
|
+
|
380
|
+
set_oci_number_from_num(&nX, Xcoordinate, 1, errhp);
|
381
|
+
set_oci_number_from_num(&nY, Ycoordinate, 1, errhp);
|
382
|
+
/* check zero */
|
383
|
+
chkerr(OCINumberIsZero(errhp, &nX, &is_zero));
|
384
|
+
if (is_zero) {
|
385
|
+
chkerr(OCINumberSign(errhp, &nY, &sign));
|
386
|
+
switch (sign) {
|
387
|
+
case 0:
|
388
|
+
return INT2FIX(0); /* atan2(0, 0) => 0 or ERROR? */
|
389
|
+
case 1:
|
390
|
+
return oci8_make_ocinumber(&const_PI2, errhp); /* atan2(positive, 0) => PI/2 */
|
391
|
+
case -1:
|
392
|
+
return oci8_make_ocinumber(&const_mPI2, errhp); /* atan2(negative, 0) => -PI/2 */
|
393
|
+
}
|
394
|
+
}
|
395
|
+
/* atan2 */
|
396
|
+
chkerr(OCINumberArcTan2(errhp, &nY, &nX, &rv));
|
397
|
+
return oci8_make_ocinumber(&rv, errhp);
|
398
|
+
}
|
399
|
+
|
400
|
+
/*
|
401
|
+
* call-seq:
|
402
|
+
* OCI8::Math.cos(x) -> oranumber
|
403
|
+
*
|
404
|
+
* Computes the cosine of <i>x</i> (expressed in radians). Returns
|
405
|
+
* -1..1.
|
406
|
+
*/
|
407
|
+
static VALUE omath_cos(VALUE obj, VALUE radian)
|
408
|
+
{
|
409
|
+
OCIError *errhp = oci8_errhp;
|
410
|
+
OCINumber r;
|
411
|
+
OCINumber rv;
|
412
|
+
|
413
|
+
chkerr(OCINumberCos(errhp, TO_OCINUM(&r, radian, errhp), &rv));
|
414
|
+
return oci8_make_ocinumber(&rv, errhp);
|
415
|
+
}
|
416
|
+
|
417
|
+
/*
|
418
|
+
* call-seq:
|
419
|
+
* OCI8::Math.sin(x) -> oranumber
|
420
|
+
*
|
421
|
+
* Computes the sine of <i>x</i> (expressed in radians). Returns
|
422
|
+
* -1..1.
|
423
|
+
*/
|
424
|
+
static VALUE omath_sin(VALUE obj, VALUE radian)
|
425
|
+
{
|
426
|
+
OCIError *errhp = oci8_errhp;
|
427
|
+
OCINumber r;
|
428
|
+
OCINumber rv;
|
429
|
+
|
430
|
+
chkerr(OCINumberSin(errhp, TO_OCINUM(&r, radian, errhp), &rv));
|
431
|
+
return oci8_make_ocinumber(&rv, errhp);
|
432
|
+
}
|
433
|
+
|
434
|
+
/*
|
435
|
+
* call-seq:
|
436
|
+
* OCI8::Math.tan(x) -> oranumber
|
437
|
+
*
|
438
|
+
* Returns the tangent of <i>x</i> (expressed in radians).
|
439
|
+
*/
|
440
|
+
static VALUE omath_tan(VALUE obj, VALUE radian)
|
441
|
+
{
|
442
|
+
OCIError *errhp = oci8_errhp;
|
443
|
+
OCINumber r;
|
444
|
+
OCINumber rv;
|
445
|
+
|
446
|
+
chkerr(OCINumberTan(errhp, TO_OCINUM(&r, radian, errhp), &rv));
|
447
|
+
return oci8_make_ocinumber(&rv, errhp);
|
448
|
+
}
|
449
|
+
|
450
|
+
/*
|
451
|
+
* call-seq:
|
452
|
+
* OCI8::Math.acos(x) -> oranumber
|
453
|
+
*
|
454
|
+
* Computes the arc cosine of <i>x</i>. Returns 0..PI.
|
455
|
+
*/
|
456
|
+
static VALUE omath_acos(VALUE obj, VALUE num)
|
457
|
+
{
|
458
|
+
OCIError *errhp = oci8_errhp;
|
459
|
+
OCINumber n;
|
460
|
+
OCINumber r;
|
461
|
+
sword sign;
|
462
|
+
|
463
|
+
set_oci_number_from_num(&n, num, 1, errhp);
|
464
|
+
/* check upper bound */
|
465
|
+
chkerr(OCINumberCmp(errhp, &n, &const_p1, &sign));
|
466
|
+
if (sign > 0)
|
467
|
+
rb_raise(rb_eRangeError, "out of range for acos");
|
468
|
+
/* check lower bound */
|
469
|
+
chkerr(OCINumberCmp(errhp, &n, &const_m1, &sign));
|
470
|
+
if (sign < 0)
|
471
|
+
rb_raise(rb_eRangeError, "out of range for acos");
|
472
|
+
/* acos */
|
473
|
+
chkerr(OCINumberArcCos(errhp, &n, &r));
|
474
|
+
return oci8_make_ocinumber(&r, errhp);
|
475
|
+
}
|
476
|
+
|
477
|
+
/*
|
478
|
+
* call-seq:
|
479
|
+
* OCI8::Math.asin(x) -> oranumber
|
480
|
+
*
|
481
|
+
* Computes the arc sine of <i>x</i>. Returns 0..PI.
|
482
|
+
*/
|
483
|
+
static VALUE omath_asin(VALUE obj, VALUE num)
|
484
|
+
{
|
485
|
+
OCIError *errhp = oci8_errhp;
|
486
|
+
OCINumber n;
|
487
|
+
OCINumber r;
|
488
|
+
sword sign;
|
489
|
+
|
490
|
+
set_oci_number_from_num(&n, num, 1, errhp);
|
491
|
+
/* check upper bound */
|
492
|
+
chkerr(OCINumberCmp(errhp, &n, &const_p1, &sign));
|
493
|
+
if (sign > 0)
|
494
|
+
rb_raise(rb_eRangeError, "out of range for asin");
|
495
|
+
/* check lower bound */
|
496
|
+
chkerr(OCINumberCmp(errhp, &n, &const_m1, &sign));
|
497
|
+
if (sign < 0)
|
498
|
+
rb_raise(rb_eRangeError, "out of range for asin");
|
499
|
+
/* asin */
|
500
|
+
chkerr(OCINumberArcSin(errhp, &n, &r));
|
501
|
+
return oci8_make_ocinumber(&r, errhp);
|
502
|
+
}
|
503
|
+
|
504
|
+
/*
|
505
|
+
* call-seq:
|
506
|
+
* OCI8::Math.atan(x) -> oranumber
|
507
|
+
*
|
508
|
+
* Computes the arc tangent of <i>x</i>. Returns -{PI/2} .. {PI/2}.
|
509
|
+
*/
|
510
|
+
static VALUE omath_atan(VALUE obj, VALUE num)
|
511
|
+
{
|
512
|
+
OCIError *errhp = oci8_errhp;
|
513
|
+
OCINumber n;
|
514
|
+
OCINumber r;
|
515
|
+
|
516
|
+
chkerr(OCINumberArcTan(errhp, TO_OCINUM(&n, num, errhp), &r));
|
517
|
+
return oci8_make_ocinumber(&r, errhp);
|
518
|
+
}
|
519
|
+
|
520
|
+
/*
|
521
|
+
* call-seq:
|
522
|
+
* OCI8::Math.cosh(x) -> oranumber
|
523
|
+
*
|
524
|
+
* Computes the hyperbolic cosine of <i>x</i> (expressed in radians).
|
525
|
+
*/
|
526
|
+
static VALUE omath_cosh(VALUE obj, VALUE num)
|
527
|
+
{
|
528
|
+
OCIError *errhp = oci8_errhp;
|
529
|
+
OCINumber n;
|
530
|
+
OCINumber r;
|
531
|
+
|
532
|
+
chkerr(OCINumberHypCos(errhp, TO_OCINUM(&n, num, errhp), &r));
|
533
|
+
return oci8_make_ocinumber(&r, errhp);
|
534
|
+
}
|
535
|
+
|
536
|
+
/*
|
537
|
+
* call-seq:
|
538
|
+
* OCI8::Math.sinh(x) -> oranumber
|
539
|
+
*
|
540
|
+
* Computes the hyperbolic sine of <i>x</i> (expressed in
|
541
|
+
* radians).
|
542
|
+
*/
|
543
|
+
static VALUE omath_sinh(VALUE obj, VALUE num)
|
544
|
+
{
|
545
|
+
OCIError *errhp = oci8_errhp;
|
546
|
+
OCINumber n;
|
547
|
+
OCINumber r;
|
548
|
+
|
549
|
+
chkerr(OCINumberHypSin(errhp, TO_OCINUM(&n, num, errhp), &r));
|
550
|
+
return oci8_make_ocinumber(&r, errhp);
|
551
|
+
}
|
552
|
+
|
553
|
+
/*
|
554
|
+
* call-seq:
|
555
|
+
* OCI8::Math.tanh() -> oranumber
|
556
|
+
*
|
557
|
+
* Computes the hyperbolic tangent of <i>x</i> (expressed in
|
558
|
+
* radians).
|
559
|
+
*/
|
560
|
+
static VALUE omath_tanh(VALUE obj, VALUE num)
|
561
|
+
{
|
562
|
+
OCIError *errhp = oci8_errhp;
|
563
|
+
OCINumber n;
|
564
|
+
OCINumber r;
|
565
|
+
|
566
|
+
chkerr(OCINumberHypTan(errhp, TO_OCINUM(&n, num, errhp), &r));
|
567
|
+
return oci8_make_ocinumber(&r, errhp);
|
568
|
+
}
|
569
|
+
|
570
|
+
/*
|
571
|
+
* call-seq:
|
572
|
+
* OCI8::Math.exp(x) -> oranumber
|
573
|
+
*
|
574
|
+
* Returns e**x.
|
575
|
+
*/
|
576
|
+
static VALUE omath_exp(VALUE obj, VALUE num)
|
577
|
+
{
|
578
|
+
OCIError *errhp = oci8_errhp;
|
579
|
+
OCINumber n;
|
580
|
+
OCINumber r;
|
581
|
+
|
582
|
+
chkerr(OCINumberExp(errhp, TO_OCINUM(&n, num, errhp), &r));
|
583
|
+
return oci8_make_ocinumber(&r, errhp);
|
584
|
+
}
|
585
|
+
|
586
|
+
/*
|
587
|
+
* call-seq:
|
588
|
+
* OCI8::Math.log(numeric) -> oranumber
|
589
|
+
* OCI8::Math.log(numeric, base_num) -> oranumber
|
590
|
+
*
|
591
|
+
* Returns the natural logarithm of <i>numeric</i> for one argument.
|
592
|
+
* Returns the base <i>base_num</i> logarithm of <i>numeric</i> for two arguments.
|
593
|
+
*/
|
594
|
+
static VALUE omath_log(int argc, VALUE *argv, VALUE obj)
|
595
|
+
{
|
596
|
+
OCIError *errhp = oci8_errhp;
|
597
|
+
VALUE num, base;
|
598
|
+
OCINumber n;
|
599
|
+
OCINumber b;
|
600
|
+
OCINumber r;
|
601
|
+
sword sign;
|
602
|
+
|
603
|
+
rb_scan_args(argc, argv, "11", &num, &base);
|
604
|
+
set_oci_number_from_num(&n, num, 1, errhp);
|
605
|
+
chkerr(OCINumberSign(errhp, &n, &sign));
|
606
|
+
if (sign <= 0)
|
607
|
+
rb_raise(rb_eRangeError, "nonpositive value for log");
|
608
|
+
if (NIL_P(base)) {
|
609
|
+
chkerr(OCINumberLn(errhp, &n, &r));
|
610
|
+
} else {
|
611
|
+
set_oci_number_from_num(&b, base, 1, errhp);
|
612
|
+
chkerr(OCINumberSign(errhp, &b, &sign));
|
613
|
+
if (sign <= 0)
|
614
|
+
rb_raise(rb_eRangeError, "nonpositive value for the base of log");
|
615
|
+
chkerr(OCINumberCmp(errhp, &b, &const_p1, &sign));
|
616
|
+
if (sign == 0)
|
617
|
+
rb_raise(rb_eRangeError, "base 1 for log");
|
618
|
+
chkerr(OCINumberLog(errhp, &b, &n, &r));
|
619
|
+
}
|
620
|
+
return oci8_make_ocinumber(&r, errhp);
|
621
|
+
}
|
622
|
+
|
623
|
+
/*
|
624
|
+
* call-seq:
|
625
|
+
* OCI8::Math.log10(numeric) -> oranumber
|
626
|
+
*
|
627
|
+
* Returns the base 10 logarithm of <i>numeric</i>.
|
628
|
+
*/
|
629
|
+
static VALUE omath_log10(VALUE obj, VALUE num)
|
630
|
+
{
|
631
|
+
OCIError *errhp = oci8_errhp;
|
632
|
+
OCINumber n;
|
633
|
+
OCINumber r;
|
634
|
+
sword sign;
|
635
|
+
|
636
|
+
set_oci_number_from_num(&n, num, 1, errhp);
|
637
|
+
chkerr(OCINumberSign(errhp, &n, &sign));
|
638
|
+
if (sign <= 0)
|
639
|
+
rb_raise(rb_eRangeError, "nonpositive value for log10");
|
640
|
+
chkerr(OCINumberLog(errhp, &const_p10, &n, &r));
|
641
|
+
return oci8_make_ocinumber(&r, errhp);
|
642
|
+
}
|
643
|
+
|
644
|
+
/*
|
645
|
+
* call-seq:
|
646
|
+
* OCI8::Math.sqrt(numeric) -> oranumber
|
647
|
+
*
|
648
|
+
* Returns the non-negative square root of <i>numeric</i>.
|
649
|
+
*/
|
650
|
+
static VALUE omath_sqrt(VALUE obj, VALUE num)
|
651
|
+
{
|
652
|
+
OCIError *errhp = oci8_errhp;
|
653
|
+
OCINumber n;
|
654
|
+
OCINumber r;
|
655
|
+
sword sign;
|
656
|
+
|
657
|
+
set_oci_number_from_num(&n, num, 1, errhp);
|
658
|
+
/* check whether num is negative */
|
659
|
+
chkerr(OCINumberSign(errhp, &n, &sign));
|
660
|
+
if (sign < 0) {
|
661
|
+
errno = EDOM;
|
662
|
+
rb_sys_fail("sqrt");
|
663
|
+
}
|
664
|
+
chkerr(OCINumberSqrt(errhp, &n, &r));
|
665
|
+
return oci8_make_ocinumber(&r, errhp);
|
666
|
+
}
|
667
|
+
|
668
|
+
|
669
|
+
/*
|
670
|
+
* call-seq:
|
671
|
+
* OraNumber(obj) -> oranumber
|
672
|
+
*
|
673
|
+
* Returns a new <code>OraNumber</code>.
|
674
|
+
*/
|
675
|
+
static VALUE onum_f_new(int argc, VALUE *argv, VALUE self)
|
676
|
+
{
|
677
|
+
VALUE obj = rb_obj_alloc(cOCINumber);
|
678
|
+
rb_obj_call_init(obj, argc, argv);
|
679
|
+
return obj;
|
680
|
+
}
|
681
|
+
|
682
|
+
static VALUE onum_initialize(int argc, VALUE *argv, VALUE self)
|
683
|
+
{
|
684
|
+
OCIError *errhp = oci8_errhp;
|
685
|
+
VALUE val;
|
686
|
+
VALUE fmt;
|
687
|
+
VALUE nls_params;
|
688
|
+
|
689
|
+
if (rb_scan_args(argc, argv, "03", &val /* 0 */, &fmt /* nil */, &nls_params /* nil */) == 0) {
|
690
|
+
OCINumberSetZero(errhp, _NUMBER(self));
|
691
|
+
} else if (RTEST(rb_obj_is_kind_of(val, rb_cNumeric))) {
|
692
|
+
set_oci_number_from_num(_NUMBER(self), val, 1, errhp);
|
693
|
+
} else {
|
694
|
+
set_oci_number_from_str(_NUMBER(self), val, fmt, nls_params, errhp);
|
695
|
+
}
|
696
|
+
return Qnil;
|
697
|
+
}
|
698
|
+
|
699
|
+
static VALUE onum_initialize_copy(VALUE lhs, VALUE rhs)
|
700
|
+
{
|
701
|
+
if (!RTEST(rb_obj_is_instance_of(rhs, CLASS_OF(lhs)))) {
|
702
|
+
rb_raise(rb_eTypeError, "invalid type: expected %s but %s",
|
703
|
+
rb_class2name(CLASS_OF(lhs)), rb_class2name(CLASS_OF(rhs)));
|
704
|
+
}
|
705
|
+
chkerr(OCINumberAssign(oci8_errhp, _NUMBER(rhs), _NUMBER(lhs)));
|
706
|
+
return lhs;
|
707
|
+
}
|
708
|
+
|
709
|
+
static VALUE onum_coerce(VALUE self, VALUE other)
|
710
|
+
{
|
711
|
+
signed long sl;
|
712
|
+
OCINumber n;
|
713
|
+
|
714
|
+
switch(rboci8_type(other)) {
|
715
|
+
case T_FIXNUM:
|
716
|
+
sl = NUM2LONG(other);
|
717
|
+
chkerr(OCINumberFromInt(oci8_errhp, &sl, sizeof(sl), OCI_NUMBER_SIGNED, &n));
|
718
|
+
return rb_assoc_new(oci8_make_ocinumber(&n, oci8_errhp), self);
|
719
|
+
case T_BIGNUM:
|
720
|
+
/* change via string. */
|
721
|
+
other = rb_big2str(other, 10);
|
722
|
+
set_oci_number_from_str(&n, other, Qnil, Qnil, oci8_errhp);
|
723
|
+
return rb_assoc_new(oci8_make_ocinumber(&n, oci8_errhp), self);
|
724
|
+
case T_FLOAT:
|
725
|
+
return rb_assoc_new(other, onum_to_f(self));
|
726
|
+
case RBOCI8_T_RATIONAL:
|
727
|
+
return rb_assoc_new(other, onum_to_r(self));
|
728
|
+
case RBOCI8_T_BIGDECIMAL:
|
729
|
+
return rb_assoc_new(other, onum_to_d(self));
|
730
|
+
}
|
731
|
+
rb_raise(rb_eTypeError, "Can't coerce %s to %s",
|
732
|
+
rb_class2name(CLASS_OF(other)), rb_class2name(cOCINumber));
|
733
|
+
}
|
734
|
+
|
735
|
+
/*
|
736
|
+
* call-seq:
|
737
|
+
* -onum -> oranumber
|
738
|
+
*
|
739
|
+
* Returns a negated <code>OraNumber</code>.
|
740
|
+
*/
|
741
|
+
static VALUE onum_neg(VALUE self)
|
742
|
+
{
|
743
|
+
OCIError *errhp = oci8_errhp;
|
744
|
+
OCINumber r;
|
745
|
+
|
746
|
+
chkerr(OCINumberNeg(errhp, _NUMBER(self), &r));
|
747
|
+
return oci8_make_ocinumber(&r, errhp);
|
748
|
+
}
|
749
|
+
|
750
|
+
|
751
|
+
/*
|
752
|
+
* call-seq:
|
753
|
+
* onum + other -> number
|
754
|
+
*
|
755
|
+
* Returns the sum of <i>onum</i> and <i>other</i>.
|
756
|
+
*/
|
757
|
+
static VALUE onum_add(VALUE lhs, VALUE rhs)
|
758
|
+
{
|
759
|
+
OCIError *errhp = oci8_errhp;
|
760
|
+
OCINumber n;
|
761
|
+
OCINumber r;
|
762
|
+
|
763
|
+
switch (rboci8_type(rhs)) {
|
764
|
+
case T_FIXNUM:
|
765
|
+
case T_BIGNUM:
|
766
|
+
if (set_oci_number_from_num(&n, rhs, 0, errhp)) {
|
767
|
+
chkerr(OCINumberAdd(errhp, _NUMBER(lhs), &n, &r));
|
768
|
+
return oci8_make_ocinumber(&r, errhp);
|
769
|
+
}
|
770
|
+
break;
|
771
|
+
case RBOCI8_T_ORANUMBER:
|
772
|
+
chkerr(OCINumberAdd(errhp, _NUMBER(lhs), _NUMBER(rhs), &r));
|
773
|
+
return oci8_make_ocinumber(&r, errhp);
|
774
|
+
case T_FLOAT:
|
775
|
+
return rb_funcall(onum_to_f(lhs), oci8_id_add_op, 1, rhs);
|
776
|
+
case RBOCI8_T_RATIONAL:
|
777
|
+
return rb_funcall(onum_to_r(lhs), oci8_id_add_op, 1, rhs);
|
778
|
+
case RBOCI8_T_BIGDECIMAL:
|
779
|
+
return rb_funcall(onum_to_d(lhs), oci8_id_add_op, 1, rhs);
|
780
|
+
}
|
781
|
+
return rb_num_coerce_bin(lhs, rhs, oci8_id_add_op);
|
782
|
+
}
|
783
|
+
|
784
|
+
/*
|
785
|
+
* call-seq:
|
786
|
+
* onum - integer -> oranumber
|
787
|
+
* onum - numeric -> numeric
|
788
|
+
*
|
789
|
+
* Returns the difference of <i>onum</i> and <i>other</i>.
|
790
|
+
*/
|
791
|
+
static VALUE onum_sub(VALUE lhs, VALUE rhs)
|
792
|
+
{
|
793
|
+
OCIError *errhp = oci8_errhp;
|
794
|
+
OCINumber n;
|
795
|
+
OCINumber r;
|
796
|
+
|
797
|
+
switch (rboci8_type(rhs)) {
|
798
|
+
case T_FIXNUM:
|
799
|
+
case T_BIGNUM:
|
800
|
+
if (set_oci_number_from_num(&n, rhs, 0, errhp)) {
|
801
|
+
chkerr(OCINumberSub(errhp, _NUMBER(lhs), &n, &r));
|
802
|
+
return oci8_make_ocinumber(&r, errhp);
|
803
|
+
}
|
804
|
+
break;
|
805
|
+
case RBOCI8_T_ORANUMBER:
|
806
|
+
chkerr(OCINumberSub(errhp, _NUMBER(lhs), _NUMBER(rhs), &r));
|
807
|
+
return oci8_make_ocinumber(&r, errhp);
|
808
|
+
case T_FLOAT:
|
809
|
+
return rb_funcall(onum_to_f(lhs), oci8_id_sub_op, 1, rhs);
|
810
|
+
case RBOCI8_T_RATIONAL:
|
811
|
+
return rb_funcall(onum_to_r(lhs), oci8_id_sub_op, 1, rhs);
|
812
|
+
case RBOCI8_T_BIGDECIMAL:
|
813
|
+
return rb_funcall(onum_to_d(lhs), oci8_id_sub_op, 1, rhs);
|
814
|
+
}
|
815
|
+
return rb_num_coerce_bin(lhs, rhs, oci8_id_sub_op);
|
816
|
+
}
|
817
|
+
|
818
|
+
/*
|
819
|
+
* call-seq:
|
820
|
+
* onum * other -> number
|
821
|
+
*
|
822
|
+
* Returns the product of <i>onum</i> and <i>other</i>.
|
823
|
+
*/
|
824
|
+
static VALUE onum_mul(VALUE lhs, VALUE rhs)
|
825
|
+
{
|
826
|
+
OCIError *errhp = oci8_errhp;
|
827
|
+
OCINumber n;
|
828
|
+
OCINumber r;
|
829
|
+
|
830
|
+
switch (rboci8_type(rhs)) {
|
831
|
+
case T_FIXNUM:
|
832
|
+
case T_BIGNUM:
|
833
|
+
if (set_oci_number_from_num(&n, rhs, 0, errhp)) {
|
834
|
+
chkerr(OCINumberMul(errhp, _NUMBER(lhs), &n, &r));
|
835
|
+
return oci8_make_ocinumber(&r, errhp);
|
836
|
+
}
|
837
|
+
break;
|
838
|
+
case RBOCI8_T_ORANUMBER:
|
839
|
+
chkerr(OCINumberMul(errhp, _NUMBER(lhs), _NUMBER(rhs), &r));
|
840
|
+
return oci8_make_ocinumber(&r, errhp);
|
841
|
+
case T_FLOAT:
|
842
|
+
return rb_funcall(onum_to_f(lhs), oci8_id_mul_op, 1, rhs);
|
843
|
+
case RBOCI8_T_RATIONAL:
|
844
|
+
return rb_funcall(onum_to_r(lhs), oci8_id_mul_op, 1, rhs);
|
845
|
+
case RBOCI8_T_BIGDECIMAL:
|
846
|
+
return rb_funcall(onum_to_d(lhs), oci8_id_mul_op, 1, rhs);
|
847
|
+
}
|
848
|
+
return rb_num_coerce_bin(lhs, rhs, oci8_id_mul_op);
|
849
|
+
}
|
850
|
+
|
851
|
+
/*
|
852
|
+
* call-seq:
|
853
|
+
* onum / integer -> oranumber
|
854
|
+
* onum / numeric -> numeric
|
855
|
+
*
|
856
|
+
* Returns the result of dividing <i>onum</i> by <i>other</i>.
|
857
|
+
*/
|
858
|
+
static VALUE onum_div(VALUE lhs, VALUE rhs)
|
859
|
+
{
|
860
|
+
OCIError *errhp = oci8_errhp;
|
861
|
+
OCINumber n;
|
862
|
+
OCINumber r;
|
863
|
+
boolean is_zero;
|
864
|
+
|
865
|
+
switch (rboci8_type(rhs)) {
|
866
|
+
case T_FIXNUM:
|
867
|
+
if (rhs == INT2FIX(0)) {
|
868
|
+
rb_num_zerodiv();
|
869
|
+
}
|
870
|
+
case T_BIGNUM:
|
871
|
+
if (set_oci_number_from_num(&n, rhs, 0, errhp)) {
|
872
|
+
chkerr(OCINumberDiv(errhp, _NUMBER(lhs), &n, &r));
|
873
|
+
return oci8_make_ocinumber(&r, errhp);
|
874
|
+
}
|
875
|
+
break;
|
876
|
+
case RBOCI8_T_ORANUMBER:
|
877
|
+
chkerr(OCINumberIsZero(errhp, _NUMBER(rhs), &is_zero));
|
878
|
+
if (is_zero) {
|
879
|
+
rb_num_zerodiv();
|
880
|
+
}
|
881
|
+
chkerr(OCINumberDiv(errhp, _NUMBER(lhs), _NUMBER(rhs), &r));
|
882
|
+
return oci8_make_ocinumber(&r, errhp);
|
883
|
+
case T_FLOAT:
|
884
|
+
return rb_funcall(onum_to_f(lhs), oci8_id_div_op, 1, rhs);
|
885
|
+
case RBOCI8_T_RATIONAL:
|
886
|
+
return rb_funcall(onum_to_r(lhs), oci8_id_div_op, 1, rhs);
|
887
|
+
case RBOCI8_T_BIGDECIMAL:
|
888
|
+
return rb_funcall(onum_to_d(lhs), oci8_id_div_op, 1, rhs);
|
889
|
+
}
|
890
|
+
return rb_num_coerce_bin(lhs, rhs, oci8_id_div_op);
|
891
|
+
}
|
892
|
+
|
893
|
+
/*
|
894
|
+
* call-seq:
|
895
|
+
* onum % other -> oranumber
|
896
|
+
*
|
897
|
+
* Returns the modulo after division of <i>onum</i> by <i>other</i>.
|
898
|
+
*/
|
899
|
+
static VALUE onum_mod(VALUE lhs, VALUE rhs)
|
900
|
+
{
|
901
|
+
OCIError *errhp = oci8_errhp;
|
902
|
+
OCINumber n;
|
903
|
+
OCINumber r;
|
904
|
+
boolean is_zero;
|
905
|
+
|
906
|
+
/* change to OCINumber */
|
907
|
+
if (!set_oci_number_from_num(&n, rhs, 0, errhp))
|
908
|
+
return rb_num_coerce_bin(lhs, rhs, '%');
|
909
|
+
/* check whether argument is not zero. */
|
910
|
+
chkerr(OCINumberIsZero(errhp, &n, &is_zero));
|
911
|
+
if (is_zero)
|
912
|
+
rb_num_zerodiv();
|
913
|
+
/* modulo */
|
914
|
+
chkerr(OCINumberMod(errhp, _NUMBER(lhs), &n, &r));
|
915
|
+
return oci8_make_ocinumber(&r, errhp);
|
916
|
+
}
|
917
|
+
|
918
|
+
/*
|
919
|
+
* call-seq:
|
920
|
+
* onum ** other -> oranumber
|
921
|
+
*
|
922
|
+
* Raises <i>onum</i> the <i>other</i> power.
|
923
|
+
*/
|
924
|
+
static VALUE onum_power(VALUE lhs, VALUE rhs)
|
925
|
+
{
|
926
|
+
OCIError *errhp = oci8_errhp;
|
927
|
+
OCINumber n;
|
928
|
+
OCINumber r;
|
929
|
+
|
930
|
+
if (FIXNUM_P(rhs)) {
|
931
|
+
chkerr(OCINumberIntPower(errhp, _NUMBER(lhs), FIX2INT(rhs), &r));
|
932
|
+
} else {
|
933
|
+
/* change to OCINumber */
|
934
|
+
if (!set_oci_number_from_num(&n, rhs, 0, errhp))
|
935
|
+
return rb_num_coerce_bin(lhs, rhs, id_power);
|
936
|
+
chkerr(OCINumberPower(errhp, _NUMBER(lhs), &n, &r));
|
937
|
+
}
|
938
|
+
return oci8_make_ocinumber(&r, errhp);
|
939
|
+
}
|
940
|
+
|
941
|
+
/*
|
942
|
+
* call-seq:
|
943
|
+
* onum <=> other -> -1, 0, +1
|
944
|
+
*
|
945
|
+
* Returns -1, 0, or +1 depending on whether <i>onum</i> is less than,
|
946
|
+
* equal to, or greater than <i>other</i>. This is the basis for the
|
947
|
+
* tests in <code>Comparable</code>.
|
948
|
+
*/
|
949
|
+
static VALUE onum_cmp(VALUE lhs, VALUE rhs)
|
950
|
+
{
|
951
|
+
OCIError *errhp = oci8_errhp;
|
952
|
+
OCINumber n;
|
953
|
+
sword r;
|
954
|
+
|
955
|
+
/* change to OCINumber */
|
956
|
+
if (!set_oci_number_from_num(&n, rhs, 0, errhp))
|
957
|
+
return rb_num_coerce_cmp(lhs, rhs, id_cmp);
|
958
|
+
/* compare */
|
959
|
+
chkerr(OCINumberCmp(errhp, _NUMBER(lhs), &n, &r));
|
960
|
+
if (r > 0) {
|
961
|
+
return INT2FIX(1);
|
962
|
+
} else if (r == 0) {
|
963
|
+
return INT2FIX(0);
|
964
|
+
} else {
|
965
|
+
return INT2FIX(-1);
|
966
|
+
}
|
967
|
+
}
|
968
|
+
|
969
|
+
/*
|
970
|
+
* call-seq:
|
971
|
+
* onum.floor -> integer
|
972
|
+
*
|
973
|
+
* Returns the largest <code>Integer</code> less than or equal to <i>onum</i>.
|
974
|
+
*/
|
975
|
+
static VALUE onum_floor(VALUE self)
|
976
|
+
{
|
977
|
+
OCIError *errhp = oci8_errhp;
|
978
|
+
OCINumber r;
|
979
|
+
|
980
|
+
chkerr(OCINumberFloor(errhp, _NUMBER(self), &r));
|
981
|
+
return oci8_make_integer(&r, errhp);
|
982
|
+
}
|
983
|
+
|
984
|
+
/*
|
985
|
+
* call-seq:
|
986
|
+
* onum.ceil -> integer
|
987
|
+
*
|
988
|
+
* Returns the smallest <code>Integer</code> greater than or equal to
|
989
|
+
* <i>onum</i>.
|
990
|
+
*/
|
991
|
+
static VALUE onum_ceil(VALUE self)
|
992
|
+
{
|
993
|
+
OCIError *errhp = oci8_errhp;
|
994
|
+
OCINumber r;
|
995
|
+
|
996
|
+
chkerr(OCINumberCeil(errhp, _NUMBER(self), &r));
|
997
|
+
return oci8_make_integer(&r, errhp);
|
998
|
+
}
|
999
|
+
|
1000
|
+
/*
|
1001
|
+
* call-seq:
|
1002
|
+
* onum.round -> integer
|
1003
|
+
* onum.round(decplace) -> oranumber
|
1004
|
+
*
|
1005
|
+
* Rounds <i>onum</i> to the nearest <code>Integer</code> when no argument.
|
1006
|
+
* Rounds <i>onum</i> to a specified decimal place <i>decplace</i> when one argument.
|
1007
|
+
*
|
1008
|
+
* OraNumber.new(1.234).round(1) #=> 1.2
|
1009
|
+
* OraNumber.new(1.234).round(2) #=> 1.23
|
1010
|
+
* OraNumber.new(1.234).round(3) #=> 1.234
|
1011
|
+
*/
|
1012
|
+
static VALUE onum_round(int argc, VALUE *argv, VALUE self)
|
1013
|
+
{
|
1014
|
+
OCIError *errhp = oci8_errhp;
|
1015
|
+
VALUE decplace;
|
1016
|
+
OCINumber r;
|
1017
|
+
|
1018
|
+
rb_scan_args(argc, argv, "01", &decplace /* 0 */);
|
1019
|
+
chkerr(OCINumberRound(errhp, _NUMBER(self), NIL_P(decplace) ? 0 : NUM2INT(decplace), &r));
|
1020
|
+
if (argc == 0) {
|
1021
|
+
return oci8_make_integer(&r, errhp);
|
1022
|
+
} else {
|
1023
|
+
return oci8_make_ocinumber(&r, errhp);
|
1024
|
+
}
|
1025
|
+
}
|
1026
|
+
|
1027
|
+
/*
|
1028
|
+
* call-seq:
|
1029
|
+
* onum.truncate -> integer
|
1030
|
+
* onum.truncate(decplace) -> oranumber
|
1031
|
+
*
|
1032
|
+
* Truncates <i>onum</i> to the <code>Integer</code> when no argument.
|
1033
|
+
* Truncates <i>onum</i> to a specified decimal place <i>decplace</i> when one argument.
|
1034
|
+
*/
|
1035
|
+
static VALUE onum_trunc(int argc, VALUE *argv, VALUE self)
|
1036
|
+
{
|
1037
|
+
OCIError *errhp = oci8_errhp;
|
1038
|
+
VALUE decplace;
|
1039
|
+
OCINumber r;
|
1040
|
+
|
1041
|
+
rb_scan_args(argc, argv, "01", &decplace /* 0 */);
|
1042
|
+
chkerr(OCINumberTrunc(errhp, _NUMBER(self), NIL_P(decplace) ? 0 : NUM2INT(decplace), &r));
|
1043
|
+
return oci8_make_ocinumber(&r, errhp);
|
1044
|
+
}
|
1045
|
+
|
1046
|
+
/*
|
1047
|
+
* call-seq:
|
1048
|
+
* onum.round_prec(digits) -> oranumber
|
1049
|
+
*
|
1050
|
+
* Rounds <i>onum</i> to a specified number of decimal digits.
|
1051
|
+
* This method is available on Oracle 8.1 client or upper.
|
1052
|
+
*
|
1053
|
+
* OraNumber.new(1.234).round_prec(2) #=> 1.2
|
1054
|
+
* OraNumber.new(12.34).round_prec(2) #=> 12
|
1055
|
+
* OraNumber.new(123.4).round_prec(2) #=> 120
|
1056
|
+
*/
|
1057
|
+
static VALUE onum_round_prec(VALUE self, VALUE ndigs)
|
1058
|
+
{
|
1059
|
+
OCIError *errhp = oci8_errhp;
|
1060
|
+
OCINumber r;
|
1061
|
+
|
1062
|
+
chkerr(OCINumberPrec(errhp, _NUMBER(self), NUM2INT(ndigs), &r));
|
1063
|
+
return oci8_make_ocinumber(&r, errhp);
|
1064
|
+
}
|
1065
|
+
|
1066
|
+
/*
|
1067
|
+
* call-seq:
|
1068
|
+
* onum.to_char(fmt = nil, nls_params = nil) -> string
|
1069
|
+
*
|
1070
|
+
* Returns a string containing a representation of self.
|
1071
|
+
* <i>fmt</i> and <i>nls_params</i> are same meanings with
|
1072
|
+
* <code>TO_CHAR</code> of Oracle function.
|
1073
|
+
*/
|
1074
|
+
static VALUE onum_to_char(int argc, VALUE *argv, VALUE self)
|
1075
|
+
{
|
1076
|
+
OCIError *errhp = oci8_errhp;
|
1077
|
+
VALUE fmt;
|
1078
|
+
VALUE nls_params;
|
1079
|
+
char buf[512];
|
1080
|
+
ub4 buf_size = sizeof(buf);
|
1081
|
+
oratext *fmt_ptr;
|
1082
|
+
oratext *nls_params_ptr;
|
1083
|
+
ub4 fmt_len;
|
1084
|
+
ub4 nls_params_len;
|
1085
|
+
sword rv;
|
1086
|
+
|
1087
|
+
rb_scan_args(argc, argv, "02", &fmt /* nil */, &nls_params /* nil */);
|
1088
|
+
if (NIL_P(fmt)) {
|
1089
|
+
rv = oranumber_to_str(_NUMBER(self), buf, sizeof(buf));
|
1090
|
+
if (rv > 0) {
|
1091
|
+
return rb_usascii_str_new(buf, rv);
|
1092
|
+
}
|
1093
|
+
oranumber_dump(_NUMBER(self), buf);
|
1094
|
+
rb_raise(eOCIException, "Invalid internal number format: %s", buf);
|
1095
|
+
}
|
1096
|
+
StringValue(fmt);
|
1097
|
+
fmt_ptr = RSTRING_ORATEXT(fmt);
|
1098
|
+
fmt_len = RSTRING_LEN(fmt);
|
1099
|
+
if (NIL_P(nls_params)) {
|
1100
|
+
nls_params_ptr = NULL;
|
1101
|
+
nls_params_len = 0;
|
1102
|
+
} else {
|
1103
|
+
StringValue(nls_params);
|
1104
|
+
nls_params_ptr = RSTRING_ORATEXT(nls_params);
|
1105
|
+
nls_params_len = RSTRING_LEN(nls_params);
|
1106
|
+
}
|
1107
|
+
rv = OCINumberToText(errhp, _NUMBER(self),
|
1108
|
+
fmt_ptr, fmt_len, nls_params_ptr, nls_params_len,
|
1109
|
+
&buf_size, TO_ORATEXT(buf));
|
1110
|
+
if (rv == OCI_ERROR) {
|
1111
|
+
sb4 errcode;
|
1112
|
+
OCIErrorGet(errhp, 1, NULL, &errcode, NULL, 0, OCI_HTYPE_ERROR);
|
1113
|
+
if (errcode == 22065) {
|
1114
|
+
/* OCI-22065: number to text translation for the given format causes overflow */
|
1115
|
+
if (NIL_P(fmt)) /* implicit conversion */
|
1116
|
+
return rb_usascii_str_new_cstr("overflow");
|
1117
|
+
}
|
1118
|
+
chkerr(rv);
|
1119
|
+
}
|
1120
|
+
return rb_usascii_str_new(buf, buf_size);
|
1121
|
+
}
|
1122
|
+
|
1123
|
+
/*
|
1124
|
+
* call-seq:
|
1125
|
+
* onum.to_s -> string
|
1126
|
+
*
|
1127
|
+
* Returns a string containing a representation of self.
|
1128
|
+
*/
|
1129
|
+
static VALUE onum_to_s(VALUE self)
|
1130
|
+
{
|
1131
|
+
return onum_to_char(0, NULL, self);
|
1132
|
+
}
|
1133
|
+
|
1134
|
+
/*
|
1135
|
+
* call-seq:
|
1136
|
+
* onum.to_i -> integer
|
1137
|
+
*
|
1138
|
+
* Returns <i>onum</i> truncated to an <code>Integer</code>.
|
1139
|
+
*/
|
1140
|
+
static VALUE onum_to_i(VALUE self)
|
1141
|
+
{
|
1142
|
+
OCIError *errhp = oci8_errhp;
|
1143
|
+
OCINumber num;
|
1144
|
+
|
1145
|
+
chkerr(OCINumberTrunc(errhp, _NUMBER(self), 0, &num));
|
1146
|
+
return oci8_make_integer(&num, errhp);
|
1147
|
+
}
|
1148
|
+
|
1149
|
+
/*
|
1150
|
+
* call-seq:
|
1151
|
+
* onum.to_f -> float
|
1152
|
+
*
|
1153
|
+
* Return the value as a <code>Float</code>.
|
1154
|
+
*
|
1155
|
+
*/
|
1156
|
+
static VALUE onum_to_f(VALUE self)
|
1157
|
+
{
|
1158
|
+
return rb_float_new(oci8_onum_to_dbl(_NUMBER(self), oci8_errhp));
|
1159
|
+
}
|
1160
|
+
|
1161
|
+
/*
|
1162
|
+
* call-seq:
|
1163
|
+
* onum.to_r -> rational
|
1164
|
+
*
|
1165
|
+
* Return the value as a <code>Rational</code>.
|
1166
|
+
*
|
1167
|
+
*/
|
1168
|
+
static VALUE onum_to_r(VALUE self)
|
1169
|
+
{
|
1170
|
+
VALUE x, y;
|
1171
|
+
int nshift = 0;
|
1172
|
+
OCINumber onum[2];
|
1173
|
+
int current = 0;
|
1174
|
+
boolean is_int;
|
1175
|
+
|
1176
|
+
chkerr(OCINumberAssign(oci8_errhp, _NUMBER(self), &onum[0]));
|
1177
|
+
|
1178
|
+
for (;;) {
|
1179
|
+
chkerr(OCINumberIsInt(oci8_errhp, &onum[current], &is_int));
|
1180
|
+
if (is_int) {
|
1181
|
+
break;
|
1182
|
+
}
|
1183
|
+
nshift++;
|
1184
|
+
chkerr(OCINumberShift(oci8_errhp, &onum[current], 1, &onum[1 - current]));
|
1185
|
+
current = 1 - current;
|
1186
|
+
}
|
1187
|
+
x = oci8_make_integer(&onum[current], oci8_errhp);
|
1188
|
+
if (nshift == 0) {
|
1189
|
+
y = INT2FIX(1);
|
1190
|
+
} else {
|
1191
|
+
y = rb_funcall(INT2FIX(10), rb_intern("**"), 1, INT2FIX(nshift));
|
1192
|
+
}
|
1193
|
+
#ifdef T_RATIONAL
|
1194
|
+
return rb_Rational(x, y);
|
1195
|
+
#else
|
1196
|
+
if (!cRational) {
|
1197
|
+
rb_require("rational");
|
1198
|
+
cRational = rb_const_get(rb_cObject, id_Rational);
|
1199
|
+
}
|
1200
|
+
return rb_funcall(rb_cObject, id_Rational, 2, x, y);
|
1201
|
+
#endif
|
1202
|
+
}
|
1203
|
+
|
1204
|
+
/*
|
1205
|
+
* call-seq:
|
1206
|
+
* onum.to_d -> bigdecimal
|
1207
|
+
*
|
1208
|
+
* Return the value as a <code>BigDecimal</code>.
|
1209
|
+
*
|
1210
|
+
*/
|
1211
|
+
static VALUE onum_to_d(VALUE self)
|
1212
|
+
{
|
1213
|
+
return onum_to_d_real(_NUMBER(self), oci8_errhp);
|
1214
|
+
}
|
1215
|
+
|
1216
|
+
/* Converts to BigDecimal via number in scientific notation */
|
1217
|
+
static VALUE onum_to_d_real(OCINumber *num, OCIError *errhp)
|
1218
|
+
{
|
1219
|
+
char buf[64];
|
1220
|
+
ub4 buf_size = sizeof(buf);
|
1221
|
+
const char *fmt = "FM9.99999999999999999999999999999999999999EEEE";
|
1222
|
+
|
1223
|
+
if (!cBigDecimal) {
|
1224
|
+
rb_require("bigdecimal");
|
1225
|
+
cBigDecimal = rb_const_get(rb_cObject, id_BigDecimal);
|
1226
|
+
}
|
1227
|
+
chkerr(OCINumberToText(errhp, num, (const oratext *)fmt, strlen(fmt),
|
1228
|
+
NULL, 0, &buf_size, TO_ORATEXT(buf)));
|
1229
|
+
return rb_funcall(rb_cObject, id_BigDecimal, 1, rb_usascii_str_new(buf, buf_size));
|
1230
|
+
}
|
1231
|
+
|
1232
|
+
/*
|
1233
|
+
* call-seq:
|
1234
|
+
* onum.has_decimal_part? -> true or false
|
1235
|
+
*
|
1236
|
+
* Returns +true+ if <i>self</i> has a decimal part.
|
1237
|
+
*
|
1238
|
+
* OraNumber(10).has_decimal_part? # => false
|
1239
|
+
* OraNumber(10.1).has_decimal_part? # => true
|
1240
|
+
*/
|
1241
|
+
static VALUE onum_has_decimal_part_p(VALUE self)
|
1242
|
+
{
|
1243
|
+
OCIError *errhp = oci8_errhp;
|
1244
|
+
boolean result;
|
1245
|
+
|
1246
|
+
chkerr(OCINumberIsInt(errhp, _NUMBER(self), &result));
|
1247
|
+
return result ? Qfalse : Qtrue;
|
1248
|
+
}
|
1249
|
+
|
1250
|
+
/*
|
1251
|
+
* call-seq:
|
1252
|
+
* onum.to_onum -> oranumber
|
1253
|
+
*
|
1254
|
+
* Returns self.
|
1255
|
+
*
|
1256
|
+
*/
|
1257
|
+
static VALUE onum_to_onum(VALUE self)
|
1258
|
+
{
|
1259
|
+
return self;
|
1260
|
+
}
|
1261
|
+
|
1262
|
+
/*
|
1263
|
+
* call-seq:
|
1264
|
+
* onum.zero? -> true or false
|
1265
|
+
*
|
1266
|
+
* Returns <code>true</code> if <i>onum</i> is zero.
|
1267
|
+
*
|
1268
|
+
*/
|
1269
|
+
static VALUE onum_zero_p(VALUE self)
|
1270
|
+
{
|
1271
|
+
OCIError *errhp = oci8_errhp;
|
1272
|
+
boolean result;
|
1273
|
+
|
1274
|
+
chkerr(OCINumberIsZero(errhp, _NUMBER(self), &result));
|
1275
|
+
return result ? Qtrue : Qfalse;
|
1276
|
+
}
|
1277
|
+
|
1278
|
+
/*
|
1279
|
+
* call-seq:
|
1280
|
+
* onum.abs -> oranumber
|
1281
|
+
*
|
1282
|
+
* Returns the absolute value of <i>onum</i>.
|
1283
|
+
*
|
1284
|
+
*/
|
1285
|
+
static VALUE onum_abs(VALUE self)
|
1286
|
+
{
|
1287
|
+
OCIError *errhp = oci8_errhp;
|
1288
|
+
OCINumber result;
|
1289
|
+
|
1290
|
+
chkerr(OCINumberAbs(errhp, _NUMBER(self), &result));
|
1291
|
+
return oci8_make_ocinumber(&result, errhp);
|
1292
|
+
}
|
1293
|
+
|
1294
|
+
/*
|
1295
|
+
* call-seq:
|
1296
|
+
* onum.shift(fixnum) -> oranumber
|
1297
|
+
*
|
1298
|
+
* Returns <i>onum</i> * 10**<i>fixnum</i>
|
1299
|
+
* This method is available on Oracle 8.1 client or upper.
|
1300
|
+
*/
|
1301
|
+
static VALUE onum_shift(VALUE self, VALUE exp)
|
1302
|
+
{
|
1303
|
+
OCIError *errhp = oci8_errhp;
|
1304
|
+
OCINumber result;
|
1305
|
+
|
1306
|
+
chkerr(OCINumberShift(errhp, _NUMBER(self), NUM2INT(exp), &result));
|
1307
|
+
return oci8_make_ocinumber(&result, errhp);
|
1308
|
+
}
|
1309
|
+
|
1310
|
+
/*
|
1311
|
+
* call-seq:
|
1312
|
+
* onum.dump -> string
|
1313
|
+
*
|
1314
|
+
* Returns internal representation whose format is same with
|
1315
|
+
* the return value of Oracle SQL function DUMP().
|
1316
|
+
*
|
1317
|
+
* OraNumber.new(100).dump #=> "Typ=2 Len=2: 194,2"
|
1318
|
+
* OraNumber.new(123).dump #=> "Typ=2 Len=3: 194,2,24"
|
1319
|
+
* OraNumber.new(0.1).dump #=> "Typ=2 Len=2: 192,11"
|
1320
|
+
*/
|
1321
|
+
static VALUE onum_dump(VALUE self)
|
1322
|
+
{
|
1323
|
+
char buf[ORANUMBER_DUMP_BUF_SIZ];
|
1324
|
+
int rv = oranumber_dump(_NUMBER(self), buf);
|
1325
|
+
return rb_usascii_str_new(buf, rv);
|
1326
|
+
}
|
1327
|
+
|
1328
|
+
static VALUE onum_hash(VALUE self)
|
1329
|
+
{
|
1330
|
+
char *c = DATA_PTR(self);
|
1331
|
+
int size = c[0] + 1;
|
1332
|
+
long i, hash;
|
1333
|
+
|
1334
|
+
/* assert(size <= 22); ?*/
|
1335
|
+
if (size > 22)
|
1336
|
+
size = 22;
|
1337
|
+
|
1338
|
+
for (hash = 0, i = 1; i< size; i++) {
|
1339
|
+
hash += c[i] * 971;
|
1340
|
+
}
|
1341
|
+
if (hash < 0) hash = -hash;
|
1342
|
+
return INT2FIX(hash);
|
1343
|
+
}
|
1344
|
+
|
1345
|
+
static VALUE onum_inspect(VALUE self)
|
1346
|
+
{
|
1347
|
+
const char *name = rb_class2name(CLASS_OF(self));
|
1348
|
+
volatile VALUE s = onum_to_s(self);
|
1349
|
+
size_t len = strlen(name) + RSTRING_LEN(s) + 5;
|
1350
|
+
char *str = ALLOCA_N(char, len);
|
1351
|
+
|
1352
|
+
snprintf(str, len, "#<%s:%s>", name, RSTRING_PTR(s));
|
1353
|
+
str[len - 1] = '\0';
|
1354
|
+
return rb_usascii_str_new_cstr(str);
|
1355
|
+
}
|
1356
|
+
|
1357
|
+
/*
|
1358
|
+
* call-seq:
|
1359
|
+
* onum._dump -> string
|
1360
|
+
*
|
1361
|
+
* Dump <i>onum</i> for marshaling.
|
1362
|
+
*/
|
1363
|
+
static VALUE onum__dump(int argc, VALUE *argv, VALUE self)
|
1364
|
+
{
|
1365
|
+
char *c = DATA_PTR(self);
|
1366
|
+
int size = c[0] + 1;
|
1367
|
+
VALUE dummy;
|
1368
|
+
|
1369
|
+
rb_scan_args(argc, argv, "01", &dummy);
|
1370
|
+
return rb_str_new(c, size);
|
1371
|
+
}
|
1372
|
+
|
1373
|
+
/*
|
1374
|
+
* call-seq:
|
1375
|
+
* OraNumber._load(string) -> oranumber
|
1376
|
+
*
|
1377
|
+
* Unmarshal a dumped <code>OraNumber</code> object.
|
1378
|
+
*/
|
1379
|
+
static VALUE
|
1380
|
+
onum_s_load(VALUE klass, VALUE str)
|
1381
|
+
{
|
1382
|
+
unsigned char *c;
|
1383
|
+
int size;
|
1384
|
+
OCINumber num;
|
1385
|
+
|
1386
|
+
Check_Type(str, T_STRING);
|
1387
|
+
c = RSTRING_ORATEXT(str);
|
1388
|
+
size = RSTRING_LEN(str);
|
1389
|
+
if (size == 0 || size != c[0] + 1 || size > sizeof(num)) {
|
1390
|
+
rb_raise(rb_eTypeError, "marshaled OCI::Number format differ");
|
1391
|
+
}
|
1392
|
+
memset(&num, 0, sizeof(num));
|
1393
|
+
memcpy(&num, c, size);
|
1394
|
+
return oci8_make_ocinumber(&num, oci8_errhp);
|
1395
|
+
}
|
1396
|
+
|
1397
|
+
/*
|
1398
|
+
* bind_ocinumber
|
1399
|
+
*/
|
1400
|
+
static VALUE bind_ocinumber_get(oci8_bind_t *obind, void *data, void *null_struct)
|
1401
|
+
{
|
1402
|
+
return oci8_make_ocinumber((OCINumber*)data, oci8_errhp);
|
1403
|
+
}
|
1404
|
+
|
1405
|
+
static VALUE bind_integer_get(oci8_bind_t *obind, void *data, void *null_struct)
|
1406
|
+
{
|
1407
|
+
return oci8_make_integer((OCINumber*)data, oci8_errhp);
|
1408
|
+
}
|
1409
|
+
|
1410
|
+
static VALUE bind_float_get(oci8_bind_t *obind, void *data, void *null_struct)
|
1411
|
+
{
|
1412
|
+
return oci8_make_float((OCINumber*)data, oci8_errhp);
|
1413
|
+
}
|
1414
|
+
|
1415
|
+
static void bind_ocinumber_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
|
1416
|
+
{
|
1417
|
+
set_oci_number_from_num((OCINumber*)data, val, 1, oci8_errhp);
|
1418
|
+
}
|
1419
|
+
|
1420
|
+
static void bind_integer_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
|
1421
|
+
{
|
1422
|
+
OCIError *errhp = oci8_errhp;
|
1423
|
+
OCINumber num;
|
1424
|
+
|
1425
|
+
set_oci_number_from_num(&num, val, 1, errhp);
|
1426
|
+
chker2(OCINumberTrunc(errhp, &num, 0, (OCINumber*)data),
|
1427
|
+
&obind->base);
|
1428
|
+
}
|
1429
|
+
|
1430
|
+
static void bind_ocinumber_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
|
1431
|
+
{
|
1432
|
+
obind->value_sz = sizeof(OCINumber);
|
1433
|
+
obind->alloc_sz = sizeof(OCINumber);
|
1434
|
+
}
|
1435
|
+
|
1436
|
+
static void bind_ocinumber_init_elem(oci8_bind_t *obind, VALUE svc)
|
1437
|
+
{
|
1438
|
+
OCIError *errhp = oci8_errhp;
|
1439
|
+
ub4 idx = 0;
|
1440
|
+
|
1441
|
+
do {
|
1442
|
+
OCINumberSetZero(errhp, (OCINumber*)obind->valuep + idx);
|
1443
|
+
} while (++idx < obind->maxar_sz);
|
1444
|
+
}
|
1445
|
+
|
1446
|
+
static const oci8_bind_vtable_t bind_ocinumber_vtable = {
|
1447
|
+
{
|
1448
|
+
NULL,
|
1449
|
+
oci8_bind_free,
|
1450
|
+
sizeof(oci8_bind_t)
|
1451
|
+
},
|
1452
|
+
bind_ocinumber_get,
|
1453
|
+
bind_ocinumber_set,
|
1454
|
+
bind_ocinumber_init,
|
1455
|
+
bind_ocinumber_init_elem,
|
1456
|
+
NULL,
|
1457
|
+
SQLT_VNU,
|
1458
|
+
};
|
1459
|
+
|
1460
|
+
static const oci8_bind_vtable_t bind_integer_vtable = {
|
1461
|
+
{
|
1462
|
+
NULL,
|
1463
|
+
oci8_bind_free,
|
1464
|
+
sizeof(oci8_bind_t)
|
1465
|
+
},
|
1466
|
+
bind_integer_get,
|
1467
|
+
bind_integer_set,
|
1468
|
+
bind_ocinumber_init,
|
1469
|
+
bind_ocinumber_init_elem,
|
1470
|
+
NULL,
|
1471
|
+
SQLT_VNU,
|
1472
|
+
};
|
1473
|
+
|
1474
|
+
static const oci8_bind_vtable_t bind_float_vtable = {
|
1475
|
+
{
|
1476
|
+
NULL,
|
1477
|
+
oci8_bind_free,
|
1478
|
+
sizeof(oci8_bind_t)
|
1479
|
+
},
|
1480
|
+
bind_float_get,
|
1481
|
+
bind_ocinumber_set,
|
1482
|
+
bind_ocinumber_init,
|
1483
|
+
bind_ocinumber_init_elem,
|
1484
|
+
NULL,
|
1485
|
+
SQLT_VNU,
|
1486
|
+
};
|
1487
|
+
|
1488
|
+
void
|
1489
|
+
Init_oci_number(VALUE cOCI8, OCIError *errhp)
|
1490
|
+
{
|
1491
|
+
VALUE mMath;
|
1492
|
+
OCINumber num1, num2;
|
1493
|
+
VALUE obj_PI;
|
1494
|
+
signed long sl;
|
1495
|
+
|
1496
|
+
id_power = rb_intern("**");
|
1497
|
+
id_cmp = rb_intern("<=>");
|
1498
|
+
id_finite_p = rb_intern("finite?");
|
1499
|
+
id_split = rb_intern("split");
|
1500
|
+
id_numerator = rb_intern("numerator");
|
1501
|
+
id_denominator = rb_intern("denominator");
|
1502
|
+
id_Rational = rb_intern("Rational");
|
1503
|
+
id_BigDecimal = rb_intern("BigDecimal");
|
1504
|
+
|
1505
|
+
cOCINumber = rb_define_class("OraNumber", rb_cNumeric);
|
1506
|
+
mMath = rb_define_module_under(cOCI8, "Math");
|
1507
|
+
|
1508
|
+
/* constants for internal use. */
|
1509
|
+
/* set const_p1 */
|
1510
|
+
sl = 1;
|
1511
|
+
OCINumberFromInt(errhp, &sl, sizeof(sl), OCI_NUMBER_SIGNED, &const_p1);
|
1512
|
+
/* set const_p10 */
|
1513
|
+
sl = 10;
|
1514
|
+
OCINumberFromInt(errhp, &sl, sizeof(sl), OCI_NUMBER_SIGNED, &const_p10);
|
1515
|
+
/* set const_m1 */
|
1516
|
+
sl = -1;
|
1517
|
+
OCINumberFromInt(errhp, &sl, sizeof(sl), OCI_NUMBER_SIGNED, &const_m1);
|
1518
|
+
/* set const_PI2 */
|
1519
|
+
sl = 2;
|
1520
|
+
OCINumberSetPi(errhp, &num1);
|
1521
|
+
OCINumberFromInt(errhp, &sl, sizeof(sl), OCI_NUMBER_SIGNED, &num2);
|
1522
|
+
OCINumberDiv(errhp, &num1 /* PI */, &num2 /* 2 */, &const_PI2);
|
1523
|
+
/* set const_mPI2 */
|
1524
|
+
OCINumberNeg(errhp, &const_PI2 /* PI/2 */, &const_mPI2);
|
1525
|
+
|
1526
|
+
/* PI */
|
1527
|
+
OCINumberSetPi(errhp, &num1);
|
1528
|
+
obj_PI = oci8_make_ocinumber(&num1, errhp);
|
1529
|
+
|
1530
|
+
/* The ratio of the circumference of a circle to its diameter. */
|
1531
|
+
rb_define_const(mMath, "PI", obj_PI);
|
1532
|
+
|
1533
|
+
/*
|
1534
|
+
* module functions of OCI::Math.
|
1535
|
+
*/
|
1536
|
+
rb_define_module_function(mMath, "atan2", omath_atan2, 2);
|
1537
|
+
|
1538
|
+
rb_define_module_function(mMath, "cos", omath_cos, 1);
|
1539
|
+
rb_define_module_function(mMath, "sin", omath_sin, 1);
|
1540
|
+
rb_define_module_function(mMath, "tan", omath_tan, 1);
|
1541
|
+
|
1542
|
+
rb_define_module_function(mMath, "acos", omath_acos, 1);
|
1543
|
+
rb_define_module_function(mMath, "asin", omath_asin, 1);
|
1544
|
+
rb_define_module_function(mMath, "atan", omath_atan, 1);
|
1545
|
+
|
1546
|
+
rb_define_module_function(mMath, "cosh", omath_cosh, 1);
|
1547
|
+
rb_define_module_function(mMath, "sinh", omath_sinh, 1);
|
1548
|
+
rb_define_module_function(mMath, "tanh", omath_tanh, 1);
|
1549
|
+
|
1550
|
+
rb_define_module_function(mMath, "exp", omath_exp, 1);
|
1551
|
+
rb_define_module_function(mMath, "log", omath_log, -1);
|
1552
|
+
rb_define_module_function(mMath, "log10", omath_log10, 1);
|
1553
|
+
rb_define_module_function(mMath, "sqrt", omath_sqrt, 1);
|
1554
|
+
|
1555
|
+
rb_define_alloc_func(cOCINumber, onum_s_alloc);
|
1556
|
+
|
1557
|
+
/* methods of OCI::Number */
|
1558
|
+
rb_define_method(rb_cObject, "OraNumber", onum_f_new, -1);
|
1559
|
+
rb_define_method_nodoc(cOCINumber, "initialize", onum_initialize, -1);
|
1560
|
+
rb_define_method_nodoc(cOCINumber, "initialize_copy", onum_initialize_copy, 1);
|
1561
|
+
rb_define_method_nodoc(cOCINumber, "coerce", onum_coerce, 1);
|
1562
|
+
|
1563
|
+
rb_include_module(cOCINumber, rb_mComparable);
|
1564
|
+
|
1565
|
+
rb_define_method(cOCINumber, "-@", onum_neg, 0);
|
1566
|
+
rb_define_method(cOCINumber, "+", onum_add, 1);
|
1567
|
+
rb_define_method(cOCINumber, "-", onum_sub, 1);
|
1568
|
+
rb_define_method(cOCINumber, "*", onum_mul, 1);
|
1569
|
+
rb_define_method(cOCINumber, "/", onum_div, 1);
|
1570
|
+
rb_define_method(cOCINumber, "%", onum_mod, 1);
|
1571
|
+
rb_define_method(cOCINumber, "**", onum_power, 1);
|
1572
|
+
rb_define_method(cOCINumber, "<=>", onum_cmp, 1);
|
1573
|
+
|
1574
|
+
rb_define_method(cOCINumber, "floor", onum_floor, 0);
|
1575
|
+
rb_define_method(cOCINumber, "ceil", onum_ceil, 0);
|
1576
|
+
rb_define_method(cOCINumber, "round", onum_round, -1);
|
1577
|
+
rb_define_method(cOCINumber, "truncate", onum_trunc, -1);
|
1578
|
+
rb_define_method(cOCINumber, "round_prec", onum_round_prec, 1);
|
1579
|
+
|
1580
|
+
rb_define_method(cOCINumber, "to_s", onum_to_s, 0);
|
1581
|
+
rb_define_method(cOCINumber, "to_char", onum_to_char, -1);
|
1582
|
+
rb_define_method(cOCINumber, "to_i", onum_to_i, 0);
|
1583
|
+
rb_define_method(cOCINumber, "to_f", onum_to_f, 0);
|
1584
|
+
rb_define_method(cOCINumber, "to_r", onum_to_r, 0);
|
1585
|
+
rb_define_method(cOCINumber, "to_d", onum_to_d, 0);
|
1586
|
+
rb_define_method(cOCINumber, "has_decimal_part?", onum_has_decimal_part_p, 0);
|
1587
|
+
rb_define_method_nodoc(cOCINumber, "to_onum", onum_to_onum, 0);
|
1588
|
+
|
1589
|
+
rb_define_method(cOCINumber, "zero?", onum_zero_p, 0);
|
1590
|
+
rb_define_method(cOCINumber, "abs", onum_abs, 0);
|
1591
|
+
rb_define_method(cOCINumber, "shift", onum_shift, 1);
|
1592
|
+
rb_define_method(cOCINumber, "dump", onum_dump, 0);
|
1593
|
+
|
1594
|
+
rb_define_method_nodoc(cOCINumber, "hash", onum_hash, 0);
|
1595
|
+
rb_define_method_nodoc(cOCINumber, "inspect", onum_inspect, 0);
|
1596
|
+
|
1597
|
+
/* methods for marshaling */
|
1598
|
+
rb_define_method(cOCINumber, "_dump", onum__dump, -1);
|
1599
|
+
rb_define_singleton_method(cOCINumber, "_load", onum_s_load, 1);
|
1600
|
+
|
1601
|
+
oci8_define_bind_class("OraNumber", &bind_ocinumber_vtable);
|
1602
|
+
oci8_define_bind_class("Integer", &bind_integer_vtable);
|
1603
|
+
oci8_define_bind_class("Float", &bind_float_vtable);
|
1604
|
+
}
|
1605
|
+
|
1606
|
+
OCINumber *oci8_get_ocinumber(VALUE num)
|
1607
|
+
{
|
1608
|
+
if (!rb_obj_is_kind_of(num, cOCINumber)) {
|
1609
|
+
rb_raise(rb_eTypeError, "invalid argument %s (expect a subclass of %s)", rb_class2name(CLASS_OF(num)), rb_class2name(cOCINumber));
|
1610
|
+
}
|
1611
|
+
return _NUMBER(num);
|
1612
|
+
}
|