ruby-staci 2.2.9

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.
Files changed (115) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +14 -0
  3. data/COPYING +30 -0
  4. data/COPYING_old +64 -0
  5. data/ChangeLog +3826 -0
  6. data/Makefile +92 -0
  7. data/NEWS +1194 -0
  8. data/README.md +66 -0
  9. data/dist-files +113 -0
  10. data/docs/bind-array-to-in_cond.md +38 -0
  11. data/docs/conflicts-local-connections-and-processes.md +98 -0
  12. data/docs/hanging-after-inactivity.md +63 -0
  13. data/docs/install-binary-package.md +44 -0
  14. data/docs/install-full-client.md +111 -0
  15. data/docs/install-instant-client.md +194 -0
  16. data/docs/install-on-osx.md +133 -0
  17. data/docs/ldap-auth-and-function-interposition.md +123 -0
  18. data/docs/number-type-mapping.md +79 -0
  19. data/docs/osx-install-dev-tools.png +0 -0
  20. data/docs/platform-specific-issues.md +164 -0
  21. data/docs/report-installation-issue.md +50 -0
  22. data/docs/timeout-parameters.md +94 -0
  23. data/ext/oci8/.document +18 -0
  24. data/ext/oci8/MANIFEST +18 -0
  25. data/ext/oci8/apiwrap.c.tmpl +178 -0
  26. data/ext/oci8/apiwrap.h.tmpl +61 -0
  27. data/ext/oci8/apiwrap.rb +96 -0
  28. data/ext/oci8/apiwrap.yml +1322 -0
  29. data/ext/oci8/attr.c +57 -0
  30. data/ext/oci8/bind.c +838 -0
  31. data/ext/oci8/connection_pool.c +216 -0
  32. data/ext/oci8/encoding.c +196 -0
  33. data/ext/oci8/env.c +139 -0
  34. data/ext/oci8/error.c +385 -0
  35. data/ext/oci8/extconf.rb +219 -0
  36. data/ext/oci8/hook_funcs.c +407 -0
  37. data/ext/oci8/lob.c +1278 -0
  38. data/ext/oci8/metadata.c +279 -0
  39. data/ext/oci8/object.c +919 -0
  40. data/ext/oci8/oci8.c +1058 -0
  41. data/ext/oci8/oci8.h +556 -0
  42. data/ext/oci8/oci8lib.c +704 -0
  43. data/ext/oci8/ocidatetime.c +506 -0
  44. data/ext/oci8/ocihandle.c +852 -0
  45. data/ext/oci8/ocinumber.c +1922 -0
  46. data/ext/oci8/oraconf.rb +1145 -0
  47. data/ext/oci8/oradate.c +670 -0
  48. data/ext/oci8/oranumber_util.c +352 -0
  49. data/ext/oci8/oranumber_util.h +24 -0
  50. data/ext/oci8/plthook.h +66 -0
  51. data/ext/oci8/plthook_elf.c +702 -0
  52. data/ext/oci8/plthook_osx.c +505 -0
  53. data/ext/oci8/plthook_win32.c +391 -0
  54. data/ext/oci8/post-config.rb +5 -0
  55. data/ext/oci8/stmt.c +448 -0
  56. data/ext/oci8/thread_util.c +81 -0
  57. data/ext/oci8/thread_util.h +18 -0
  58. data/ext/oci8/util.c +71 -0
  59. data/ext/oci8/win32.c +117 -0
  60. data/lib/.document +1 -0
  61. data/lib/dbd/STACI.rb +591 -0
  62. data/lib/oci8/.document +8 -0
  63. data/lib/oci8/bindtype.rb +333 -0
  64. data/lib/oci8/check_load_error.rb +146 -0
  65. data/lib/oci8/compat.rb +117 -0
  66. data/lib/oci8/connection_pool.rb +179 -0
  67. data/lib/oci8/cursor.rb +605 -0
  68. data/lib/oci8/datetime.rb +605 -0
  69. data/lib/oci8/encoding-init.rb +45 -0
  70. data/lib/oci8/encoding.yml +537 -0
  71. data/lib/oci8/metadata.rb +2148 -0
  72. data/lib/oci8/object.rb +641 -0
  73. data/lib/oci8/oci8.rb +756 -0
  74. data/lib/oci8/ocihandle.rb +591 -0
  75. data/lib/oci8/oracle_version.rb +153 -0
  76. data/lib/oci8/properties.rb +196 -0
  77. data/lib/oci8/version.rb +3 -0
  78. data/lib/ruby-staci.rb +1 -0
  79. data/lib/staci.rb +190 -0
  80. data/metaconfig +142 -0
  81. data/pre-distclean.rb +7 -0
  82. data/ruby-aci.gemspec +83 -0
  83. data/setup.rb +1342 -0
  84. data/test/README.md +37 -0
  85. data/test/config.rb +201 -0
  86. data/test/setup_test_object.sql +199 -0
  87. data/test/setup_test_package.sql +59 -0
  88. data/test/test_all.rb +56 -0
  89. data/test/test_appinfo.rb +62 -0
  90. data/test/test_array_dml.rb +333 -0
  91. data/test/test_bind_array.rb +70 -0
  92. data/test/test_bind_boolean.rb +99 -0
  93. data/test/test_bind_integer.rb +47 -0
  94. data/test/test_bind_raw.rb +45 -0
  95. data/test/test_bind_string.rb +105 -0
  96. data/test/test_bind_time.rb +177 -0
  97. data/test/test_break.rb +124 -0
  98. data/test/test_clob.rb +86 -0
  99. data/test/test_connection_pool.rb +124 -0
  100. data/test/test_connstr.rb +220 -0
  101. data/test/test_datetime.rb +585 -0
  102. data/test/test_dbi.rb +365 -0
  103. data/test/test_dbi_clob.rb +53 -0
  104. data/test/test_encoding.rb +103 -0
  105. data/test/test_error.rb +87 -0
  106. data/test/test_metadata.rb +2674 -0
  107. data/test/test_object.rb +546 -0
  108. data/test/test_oci8.rb +624 -0
  109. data/test/test_oracle_version.rb +68 -0
  110. data/test/test_oradate.rb +255 -0
  111. data/test/test_oranumber.rb +786 -0
  112. data/test/test_package_type.rb +981 -0
  113. data/test/test_properties.rb +17 -0
  114. data/test/test_rowid.rb +32 -0
  115. metadata +158 -0
@@ -0,0 +1,1922 @@
1
+ /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * ocinumber.c
4
+ *
5
+ * Copyright (C) 2005-2015 Kubo Takehiro <kubo@jiubao.org>
6
+ *
7
+ */
8
+ #include "oci8.h"
9
+
10
+ #include <errno.h>
11
+ #include <math.h>
12
+ #include "oranumber_util.h"
13
+
14
+ int oci8_float_conversion_type_is_ruby = 1;
15
+
16
+ #ifndef INFINITY
17
+ #define INFINITY (1.0/+0.0)
18
+ #endif
19
+
20
+ static ID id_power; /* rb_intern("**") */
21
+ static ID id_cmp; /* rb_intern("<=>") */
22
+ static ID id_finite_p;
23
+ static ID id_split;
24
+ static ID id_numerator;
25
+ static ID id_denominator;
26
+ static ID id_BigDecimal;
27
+
28
+ static VALUE cBigDecimal;
29
+
30
+ static VALUE cOCINumber;
31
+ static ACINumber const_p1; /* +1 */
32
+ static ACINumber const_p10; /* +10 */
33
+ static ACINumber const_m1; /* -1 */
34
+ static ACINumber const_PI2; /* +PI/2 */
35
+ static ACINumber const_mPI2; /* -PI/2 */
36
+
37
+ /* Dangerous macro! Don't use this if you are unsure that the val is an ACINumber. */
38
+ #define _NUMBER(val) ((ACINumber *)RTYPEDDATA_DATA(val))
39
+
40
+ #ifndef T_MASK
41
+ #define T_MASK 0x100 /* TODO: rboci8_type() should be changed to be more portable. */
42
+ #endif
43
+ #define RBOCI8_T_ORANUMBER (T_MASK + 1)
44
+ #define RBOCI8_T_BIGDECIMAL (T_MASK + 2)
45
+
46
+ static int rboci8_type(VALUE obj)
47
+ {
48
+ int type = TYPE(obj);
49
+ VALUE klass;
50
+
51
+ switch (type) {
52
+ case T_DATA:
53
+ klass = CLASS_OF(obj);
54
+ if (klass == cOCINumber) {
55
+ return RBOCI8_T_ORANUMBER;
56
+ }
57
+ if (cBigDecimal != 0) {
58
+ if (klass == cBigDecimal) {
59
+ return RBOCI8_T_BIGDECIMAL;
60
+ }
61
+ } else {
62
+ if (strcmp(rb_class2name(klass), "BigDecimal") == 0) {
63
+ cBigDecimal = rb_const_get(rb_cObject, id_BigDecimal);
64
+ return RBOCI8_T_BIGDECIMAL;
65
+ }
66
+ }
67
+ }
68
+ return type;
69
+ }
70
+
71
+ static VALUE onum_to_f(VALUE self);
72
+ static VALUE onum_to_r(VALUE self);
73
+ static VALUE onum_to_d(VALUE self);
74
+ static VALUE onum_to_d_real(ACINumber *num, ACIError *errhp);
75
+
76
+ static size_t onum_memsize(const void *ptr)
77
+ {
78
+ return sizeof(ACINumber);
79
+ }
80
+
81
+ static const rb_data_type_t onum_data_type = {
82
+ "OraNumber",
83
+ {NULL, RUBY_DEFAULT_FREE, onum_memsize,},
84
+ #ifdef RUBY_TYPED_FREE_IMMEDIATELY
85
+ NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
86
+ #endif
87
+ #ifdef RUBY_TYPED_WB_PROTECTED
88
+ | RUBY_TYPED_WB_PROTECTED
89
+ #endif
90
+ };
91
+
92
+ static VALUE onum_s_alloc(VALUE klass)
93
+ {
94
+ VALUE obj;
95
+ ACINumber *d;
96
+
97
+ obj = TypedData_Make_Struct(klass, ACINumber, &onum_data_type, d);
98
+ ACINumberSetZero(oci8_errhp, d);
99
+ return obj;
100
+ }
101
+
102
+ /*
103
+ * ACINumber (C datatype) -> OraNumber (ruby object)
104
+ */
105
+ VALUE oci8_make_ocinumber(ACINumber *s, ACIError *errhp)
106
+ {
107
+ VALUE obj;
108
+ ACINumber *d;
109
+
110
+ obj = TypedData_Make_Struct(cOCINumber, ACINumber, &onum_data_type, d);
111
+ chkerr(ACINumberAssign(errhp, s, d));
112
+ return obj;
113
+ }
114
+
115
+ /*
116
+ * ACINumber (C datatype) -> Integer (ruby object)
117
+ */
118
+ VALUE oci8_make_integer(ACINumber *s, ACIError *errhp)
119
+ {
120
+ signed long sl;
121
+ char buf[512];
122
+ sword rv;
123
+
124
+ if (ACINumberToInt(errhp, s, sizeof(sl), ACI_NUMBER_SIGNED, &sl) == ACI_SUCCESS) {
125
+ return LONG2NUM(sl);
126
+ }
127
+ /* convert to Integer via String */
128
+ rv = oranumber_to_str(s, buf, sizeof(buf));
129
+ if (rv > 0) {
130
+ return rb_cstr2inum(buf, 10);
131
+ }
132
+ oranumber_dump(s, buf);
133
+ rb_raise(eOCIException, "Invalid internal number format: %s", buf);
134
+ }
135
+
136
+ /*
137
+ * OCINumber (C datatype) -> Float (ruby object)
138
+ */
139
+ VALUE oci8_make_float(ACINumber *s, ACIError *errhp)
140
+ {
141
+ return rb_float_new(oci8_onum_to_dbl(s, errhp));
142
+ }
143
+
144
+ /*
145
+ * String (ruby object) -> ACINumber (C datatype)
146
+ */
147
+ static void set_oci_number_from_str(ACINumber *result, VALUE str, VALUE fmt, VALUE nls_params, ACIError *errhp)
148
+ {
149
+ oratext *fmt_ptr;
150
+ oratext *nls_params_ptr;
151
+ ub4 fmt_len;
152
+ ub4 nls_params_len;
153
+
154
+ StringValue(str);
155
+ /* set from string. */
156
+ if (NIL_P(fmt)) {
157
+ int rv = oranumber_from_str(result, RSTRING_PTR(str), RSTRING_LEN(str));
158
+ if (rv == ORANUMBER_SUCCESS) {
159
+ return; /* success */
160
+ } else {
161
+ const char *default_msg = NULL;
162
+ switch (rv) {
163
+ case ORANUMBER_INVALID_NUMBER:
164
+ default_msg = "invalid number";
165
+ break;
166
+ case ORANUMBER_NUMERIC_OVERFLOW:
167
+ default_msg = "numeric overflow";
168
+ break;
169
+ }
170
+ oci8_raise_by_msgno(rv, default_msg);
171
+ }
172
+ }
173
+ StringValue(fmt);
174
+ fmt_ptr = RSTRING_ORATEXT(fmt);
175
+ fmt_len = RSTRING_LEN(fmt);
176
+ if (NIL_P(nls_params)) {
177
+ nls_params_ptr = NULL;
178
+ nls_params_len = 0;
179
+ } else {
180
+ StringValue(nls_params);
181
+ nls_params_ptr = RSTRING_ORATEXT(nls_params);
182
+ nls_params_len = RSTRING_LEN(nls_params);
183
+ }
184
+ chkerr(ACINumberFromText(errhp,
185
+ RSTRING_ORATEXT(str), RSTRING_LEN(str),
186
+ fmt_ptr, fmt_len, nls_params_ptr, nls_params_len,
187
+ result));
188
+ }
189
+
190
+ /*
191
+ * Numeric (ruby object) -> ACINumber (C datatype)
192
+ *
193
+ * @return 1 on success. Otherwise, 0.
194
+ */
195
+ static int set_oci_number_from_num(ACINumber *result, VALUE num, int force, ACIError *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(ACINumberFromInt(errhp, &sl, sizeof(sl), ACI_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
+ default:
220
+ break;
221
+ }
222
+ if (RTEST(rb_obj_is_instance_of(num, cOCINumber))) {
223
+ /* OCI::Number */
224
+ chkerr(ACINumberAssign(errhp, _NUMBER(num), result));
225
+ return 1;
226
+ }
227
+ if (rb_respond_to(num, id_split)) {
228
+ /* BigDecimal */
229
+ volatile VALUE split = rb_funcall(num, id_split, 0);
230
+
231
+ if (TYPE(split) == T_ARRAY && RARRAY_LEN(split) == 4) {
232
+ /*
233
+ * sign, significant_digits, base, exponent = num.split
234
+ * onum = sign * "0.#{significant_digits}".to_f * (base ** exponent)
235
+ */
236
+ const VALUE *ary = RARRAY_CONST_PTR(split);
237
+ int sign;
238
+ ACINumber digits;
239
+ int exponent;
240
+ int digits_len;
241
+ ACINumber work;
242
+
243
+ /* check sign */
244
+ if (TYPE(ary[0]) != T_FIXNUM) {
245
+ goto is_not_big_decimal;
246
+ }
247
+ sign = FIX2INT(ary[0]);
248
+ /* check digits */
249
+ if (TYPE(ary[1]) != T_STRING) {
250
+ goto is_not_big_decimal;
251
+ }
252
+ digits_len = RSTRING_LEN(ary[1]);
253
+ set_oci_number_from_str(&digits, ary[1], Qnil, Qnil, errhp);
254
+ /* check base */
255
+ if (TYPE(ary[2]) != T_FIXNUM || FIX2LONG(ary[2]) != 10) {
256
+ goto is_not_big_decimal;
257
+ }
258
+ /* check exponent */
259
+ if (TYPE(ary[3]) != T_FIXNUM) {
260
+ goto is_not_big_decimal;
261
+ }
262
+ exponent = FIX2INT(ary[3]);
263
+
264
+ chkerr(ACINumberShift(errhp, &digits, exponent - digits_len, &work));
265
+ if (sign >= 0) {
266
+ chkerr(ACINumberAssign(errhp, &work, result));
267
+ } else {
268
+ chkerr(ACINumberNeg(errhp, &work, result));
269
+ }
270
+ return 1;
271
+ }
272
+ }
273
+ is_not_big_decimal:
274
+ if (rb_respond_to(num, id_numerator) && rb_respond_to(num, id_denominator)) {
275
+ /* Rational */
276
+ ACINumber numerator;
277
+ ACINumber denominator;
278
+
279
+ if (set_oci_number_from_num(&numerator, rb_funcall(num, id_numerator, 0), 0, errhp) &&
280
+ set_oci_number_from_num(&denominator, rb_funcall(num, id_denominator, 0), 0, errhp)) {
281
+ chkerr(ACINumberDiv(errhp, &numerator, &denominator, result));
282
+ return 1;
283
+ }
284
+ }
285
+ if (force) {
286
+ /* change via string as a last resort. */
287
+ /* TODO: if error, raise TypeError instead of ACI::Error */
288
+ set_oci_number_from_str(result, num, Qnil, Qnil, errhp);
289
+ return 1;
290
+ }
291
+ return 0;
292
+ }
293
+
294
+ /*
295
+ * Numeric (ruby object) -> ACINumber (C datatype)
296
+ */
297
+ ACINumber *oci8_set_ocinumber(ACINumber *result, VALUE self, ACIError *errhp)
298
+ {
299
+ set_oci_number_from_num(result, self, 1, errhp);
300
+ return result;
301
+ }
302
+ #define TO_OCINUM oci8_set_ocinumber
303
+
304
+ /*
305
+ * Numeric (ruby object) -> ACINumber (C datatype) as an integer
306
+ */
307
+ ACINumber *oci8_set_integer(ACINumber *result, VALUE self, ACIError *errhp)
308
+ {
309
+ ACINumber work;
310
+
311
+ set_oci_number_from_num(&work, self, 1, errhp);
312
+ chkerr(ACINumberTrunc(errhp, &work, 0, result));
313
+ return result;
314
+ }
315
+
316
+ /*
317
+ * ACINumber (C datatype) -> double (C datatype)
318
+ */
319
+ double oci8_onum_to_dbl(ACINumber *s, ACIError *errhp)
320
+ {
321
+ if (oci8_float_conversion_type_is_ruby) {
322
+ char buf[256];
323
+ sword rv;
324
+
325
+ rv = oranumber_to_str(s, buf, sizeof(buf));
326
+ if (rv <= 0) {
327
+ char buf[ORANUMBER_DUMP_BUF_SIZ];
328
+
329
+ oranumber_dump(s, buf);
330
+ rb_raise(eOCIException, "Invalid internal number format: %s", buf);
331
+ }
332
+ if (strcmp(buf, "~") == 0) {
333
+ return INFINITY;
334
+ } else if (strcmp(buf, "-~") == 0) {
335
+ return -INFINITY;
336
+ }
337
+ return rb_cstr_to_dbl(buf, Qtrue);
338
+ } else {
339
+ double dbl;
340
+
341
+ chkerr(ACINumberToReal(errhp, s, sizeof(double), &dbl));
342
+ return dbl;
343
+ }
344
+ }
345
+
346
+ /*
347
+ * double (C datatype) -> ACINumber (C datatype)
348
+ */
349
+ ACINumber *oci8_dbl_to_onum(ACINumber *result, double dbl, ACIError *errhp)
350
+ {
351
+ if (isnan(dbl)) {
352
+ rb_raise(rb_eFloatDomainError, "NaN");
353
+ /* never reach here */
354
+ } else if (isinf(dbl)) {
355
+ if (dbl > 0.0) {
356
+ oranumber_from_str(result, "~", 1);
357
+ } else {
358
+ oranumber_from_str(result, "-~", 2);
359
+ }
360
+ return result;
361
+ }
362
+
363
+ if (oci8_float_conversion_type_is_ruby) {
364
+ VALUE str;
365
+ sword rv;
366
+
367
+ str = rb_obj_as_string(rb_float_new(dbl));
368
+ rv = oranumber_from_str(result, RSTRING_PTR(str), RSTRING_LEN(str));
369
+ if (rv != 0) {
370
+ oci8_raise_by_msgno(rv, NULL);
371
+ }
372
+ } else {
373
+ chkerr(ACINumberFromReal(errhp, &dbl, sizeof(dbl), result));
374
+ }
375
+ return result;
376
+ }
377
+
378
+ /*
379
+ * Document-module: STACI::Math
380
+ *
381
+ * The <code>STACI::Math</code> module contains module functions for basic
382
+ * trigonometric and transcendental functions. Their accuracy is
383
+ * same with {OraNumber}.
384
+ */
385
+
386
+ /*
387
+ * @overload atan2(y, x)
388
+ *
389
+ * Computes the principal value of the arc tangent of <i>y/x</i>,
390
+ * using the signs of both arguments to determine the quadrant of the
391
+ * return value.
392
+ *
393
+ * @param [Numeric] y
394
+ * @param [Numeric] x
395
+ * @return [OraNumber] Computed value in the range [-{PI}, {PI}]
396
+ */
397
+ static VALUE omath_atan2(VALUE self, VALUE Ycoordinate, VALUE Xcoordinate)
398
+ {
399
+ ACIError *errhp = oci8_errhp;
400
+ ACINumber nY;
401
+ ACINumber nX;
402
+ ACINumber rv;
403
+ boolean is_zero;
404
+ sword sign;
405
+
406
+ set_oci_number_from_num(&nX, Xcoordinate, 1, errhp);
407
+ set_oci_number_from_num(&nY, Ycoordinate, 1, errhp);
408
+ /* check zero */
409
+ chkerr(ACINumberIsZero(errhp, &nX, &is_zero));
410
+ if (is_zero) {
411
+ chkerr(ACINumberSign(errhp, &nY, &sign));
412
+ switch (sign) {
413
+ case 0:
414
+ return INT2FIX(0); /* atan2(0, 0) => 0 or ERROR? */
415
+ case 1:
416
+ return oci8_make_ocinumber(&const_PI2, errhp); /* atan2(positive, 0) => PI/2 */
417
+ case -1:
418
+ return oci8_make_ocinumber(&const_mPI2, errhp); /* atan2(negative, 0) => -PI/2 */
419
+ }
420
+ }
421
+ /* atan2 */
422
+ chkerr(ACINumberArcTan2(errhp, &nY, &nX, &rv));
423
+ return oci8_make_ocinumber(&rv, errhp);
424
+ }
425
+
426
+ /*
427
+ * @overload cos(x)
428
+ *
429
+ * Computes the cosine of <i>x</i>, measured in radians.
430
+ *
431
+ * @param [Numeric] x
432
+ * @return [OraNumber] Computed value in the range [-1, 1]
433
+ */
434
+ static VALUE omath_cos(VALUE obj, VALUE radian)
435
+ {
436
+ ACIError *errhp = oci8_errhp;
437
+ ACINumber r;
438
+ ACINumber rv;
439
+
440
+ chkerr(ACINumberCos(errhp, TO_OCINUM(&r, radian, errhp), &rv));
441
+ return oci8_make_ocinumber(&rv, errhp);
442
+ }
443
+
444
+ /*
445
+ * @overload sin(x)
446
+ *
447
+ * Computes the sine of <i>x</i>, measured in radians.
448
+ *
449
+ * @param [Numeric] x
450
+ * @return [OraNumber] Computed value in the range [-1, 1]
451
+ */
452
+ static VALUE omath_sin(VALUE obj, VALUE radian)
453
+ {
454
+ ACIError *errhp = oci8_errhp;
455
+ ACINumber r;
456
+ ACINumber rv;
457
+
458
+ chkerr(ACINumberSin(errhp, TO_OCINUM(&r, radian, errhp), &rv));
459
+ return oci8_make_ocinumber(&rv, errhp);
460
+ }
461
+
462
+ /*
463
+ * @overload tan(x)
464
+ *
465
+ * Computes the tangent of <i>x</i>, measured in radians.
466
+ *
467
+ * @param [Numeric] x
468
+ * @return [OraNumber]
469
+ */
470
+ static VALUE omath_tan(VALUE obj, VALUE radian)
471
+ {
472
+ ACIError *errhp = oci8_errhp;
473
+ ACINumber r;
474
+ ACINumber rv;
475
+
476
+ chkerr(ACINumberTan(errhp, TO_OCINUM(&r, radian, errhp), &rv));
477
+ return oci8_make_ocinumber(&rv, errhp);
478
+ }
479
+
480
+ /*
481
+ * @overload acos(x)
482
+ *
483
+ * Computes the principal value of the arc cosine of <i>x</i>.
484
+ *
485
+ * @param [Numeric] x
486
+ * @return [OraNumber] Computed value in the range [0, {PI}]
487
+ */
488
+ static VALUE omath_acos(VALUE obj, VALUE num)
489
+ {
490
+ ACIError *errhp = oci8_errhp;
491
+ ACINumber n;
492
+ ACINumber r;
493
+ sword sign;
494
+
495
+ set_oci_number_from_num(&n, num, 1, errhp);
496
+ /* check upper bound */
497
+ chkerr(ACINumberCmp(errhp, &n, &const_p1, &sign));
498
+ if (sign > 0)
499
+ rb_raise(rb_eRangeError, "out of range for acos");
500
+ /* check lower bound */
501
+ chkerr(ACINumberCmp(errhp, &n, &const_m1, &sign));
502
+ if (sign < 0)
503
+ rb_raise(rb_eRangeError, "out of range for acos");
504
+ /* acos */
505
+ chkerr(ACINumberArcCos(errhp, &n, &r));
506
+ return oci8_make_ocinumber(&r, errhp);
507
+ }
508
+
509
+ /*
510
+ * @overload asin(x)
511
+ *
512
+ * Computes the principal value of the arc sine of <i>x</i>.
513
+ *
514
+ * @param [Numeric] x
515
+ * @return [OraNumber] Computed value in the range [-{PI}/2, {PI}]/2]
516
+ */
517
+ static VALUE omath_asin(VALUE obj, VALUE num)
518
+ {
519
+ ACIError *errhp = oci8_errhp;
520
+ ACINumber n;
521
+ ACINumber r;
522
+ sword sign;
523
+
524
+ set_oci_number_from_num(&n, num, 1, errhp);
525
+ /* check upper bound */
526
+ chkerr(ACINumberCmp(errhp, &n, &const_p1, &sign));
527
+ if (sign > 0)
528
+ rb_raise(rb_eRangeError, "out of range for asin");
529
+ /* check lower bound */
530
+ chkerr(ACINumberCmp(errhp, &n, &const_m1, &sign));
531
+ if (sign < 0)
532
+ rb_raise(rb_eRangeError, "out of range for asin");
533
+ /* asin */
534
+ chkerr(ACINumberArcSin(errhp, &n, &r));
535
+ return oci8_make_ocinumber(&r, errhp);
536
+ }
537
+
538
+ /*
539
+ * @overload atan(x)
540
+ *
541
+ * Computes the principal value of the arc tangent of their argument <i>x</i>.
542
+ *
543
+ * @param [Numeric] x
544
+ * @return [OraNumber] Computed value in the range [-{PI}/2, {PI}/2]
545
+ */
546
+ static VALUE omath_atan(VALUE obj, VALUE num)
547
+ {
548
+ ACIError *errhp = oci8_errhp;
549
+ ACINumber n;
550
+ ACINumber r;
551
+
552
+ chkerr(ACINumberArcTan(errhp, TO_OCINUM(&n, num, errhp), &r));
553
+ return oci8_make_ocinumber(&r, errhp);
554
+ }
555
+
556
+ /*
557
+ * @overload cosh(x)
558
+ *
559
+ * Computes the hyperbolic cosine of <i>x</i>.
560
+ *
561
+ * @param [Numeric] x
562
+ * @return [OraNumber]
563
+ */
564
+ static VALUE omath_cosh(VALUE obj, VALUE num)
565
+ {
566
+ ACIError *errhp = oci8_errhp;
567
+ ACINumber n;
568
+ ACINumber r;
569
+
570
+ chkerr(ACINumberHypCos(errhp, TO_OCINUM(&n, num, errhp), &r));
571
+ return oci8_make_ocinumber(&r, errhp);
572
+ }
573
+
574
+ /*
575
+ * @overload sinh(x)
576
+ *
577
+ * Computes the hyperbolic sine of <i>x</i>.
578
+ *
579
+ * @param [Numeric] x
580
+ * @return [OraNumber]
581
+ */
582
+ static VALUE omath_sinh(VALUE obj, VALUE num)
583
+ {
584
+ ACIError *errhp = oci8_errhp;
585
+ ACINumber n;
586
+ ACINumber r;
587
+
588
+ chkerr(ACINumberHypSin(errhp, TO_OCINUM(&n, num, errhp), &r));
589
+ return oci8_make_ocinumber(&r, errhp);
590
+ }
591
+
592
+ /*
593
+ * @overload tanh(x)
594
+ *
595
+ * Computes the hyperbolic tangent of <i>x</i>.
596
+ *
597
+ * @param [Numeric] x
598
+ * @return [OraNumber]
599
+ */
600
+ static VALUE omath_tanh(VALUE obj, VALUE num)
601
+ {
602
+ ACIError *errhp = oci8_errhp;
603
+ ACINumber n;
604
+ ACINumber r;
605
+
606
+ chkerr(ACINumberHypTan(errhp, TO_OCINUM(&n, num, errhp), &r));
607
+ return oci8_make_ocinumber(&r, errhp);
608
+ }
609
+
610
+ /*
611
+ * @overload exp(x)
612
+ *
613
+ * Computes the base- <i>e</i> exponential of <i>x</i>.
614
+ *
615
+ * @param [Numeric] x
616
+ * @return [OraNumber]
617
+ */
618
+ static VALUE omath_exp(VALUE obj, VALUE num)
619
+ {
620
+ ACIError *errhp = oci8_errhp;
621
+ ACINumber n;
622
+ ACINumber r;
623
+
624
+ chkerr(ACINumberExp(errhp, TO_OCINUM(&n, num, errhp), &r));
625
+ return oci8_make_ocinumber(&r, errhp);
626
+ }
627
+
628
+ /*
629
+ * @overload log(x)
630
+ *
631
+ * Computes the natural logarithm of <i>x</i>.
632
+ *
633
+ * @param [Numeric] x
634
+ * @return [OraNumber]
635
+ *
636
+ * @overload log(x, y)
637
+ *
638
+ * Computes the base <i>y</I> logarithm of <i>x</i>.
639
+ *
640
+ * @param [Numeric] x
641
+ * @param [Numeric] y
642
+ * @return [OraNumber]
643
+ */
644
+ static VALUE omath_log(int argc, VALUE *argv, VALUE obj)
645
+ {
646
+ ACIError *errhp = oci8_errhp;
647
+ VALUE num, base;
648
+ ACINumber n;
649
+ ACINumber b;
650
+ ACINumber r;
651
+ sword sign;
652
+
653
+ rb_scan_args(argc, argv, "11", &num, &base);
654
+ set_oci_number_from_num(&n, num, 1, errhp);
655
+ chkerr(ACINumberSign(errhp, &n, &sign));
656
+ if (sign <= 0)
657
+ rb_raise(rb_eRangeError, "nonpositive value for log");
658
+ if (NIL_P(base)) {
659
+ chkerr(ACINumberLn(errhp, &n, &r));
660
+ } else {
661
+ set_oci_number_from_num(&b, base, 1, errhp);
662
+ chkerr(ACINumberSign(errhp, &b, &sign));
663
+ if (sign <= 0)
664
+ rb_raise(rb_eRangeError, "nonpositive value for the base of log");
665
+ chkerr(ACINumberCmp(errhp, &b, &const_p1, &sign));
666
+ if (sign == 0)
667
+ rb_raise(rb_eRangeError, "base 1 for log");
668
+ chkerr(ACINumberLog(errhp, &b, &n, &r));
669
+ }
670
+ return oci8_make_ocinumber(&r, errhp);
671
+ }
672
+
673
+ /*
674
+ * @overload log10(x)
675
+ *
676
+ * Computes the base 10 logarithm of <i>x</i>.
677
+ *
678
+ * @param [Numeric] x
679
+ * @return [OraNumber]
680
+ */
681
+ static VALUE omath_log10(VALUE obj, VALUE num)
682
+ {
683
+ ACIError *errhp = oci8_errhp;
684
+ ACINumber n;
685
+ ACINumber r;
686
+ sword sign;
687
+
688
+ set_oci_number_from_num(&n, num, 1, errhp);
689
+ chkerr(ACINumberSign(errhp, &n, &sign));
690
+ if (sign <= 0)
691
+ rb_raise(rb_eRangeError, "nonpositive value for log10");
692
+ chkerr(ACINumberLog(errhp, &const_p10, &n, &r));
693
+ return oci8_make_ocinumber(&r, errhp);
694
+ }
695
+
696
+ /*
697
+ * @overload sqrt(x)
698
+ *
699
+ * Computes the square root of <i>x</i>.
700
+ *
701
+ * @param [Numeric] x
702
+ * @return [OraNumber]
703
+ */
704
+ static VALUE omath_sqrt(VALUE obj, VALUE num)
705
+ {
706
+ ACIError *errhp = oci8_errhp;
707
+ ACINumber n;
708
+ ACINumber r;
709
+ sword sign;
710
+
711
+ set_oci_number_from_num(&n, num, 1, errhp);
712
+ /* check whether num is negative */
713
+ chkerr(ACINumberSign(errhp, &n, &sign));
714
+ if (sign < 0) {
715
+ errno = EDOM;
716
+ rb_sys_fail("sqrt");
717
+ }
718
+ chkerr(ACINumberSqrt(errhp, &n, &r));
719
+ return oci8_make_ocinumber(&r, errhp);
720
+ }
721
+
722
+ /*
723
+ * Document-class: OraNumber
724
+ *
725
+ * OraNumber is a ruby representation of
726
+ * {http://docs.oracle.com/database/121/SQLRF/sql_elements001.htm#SQLRF30020 Oracle NUMBER data type}.
727
+ * without precision and scale designators.
728
+ */
729
+
730
+ /*
731
+ * @overload OraNumber(expr = nil, fmt = nil, nlsparam = nil)
732
+ *
733
+ * Converts <i>expr</i> to a value of OraNumber. The <i>expr</i> can be a Numeric value
734
+ * or a String value. If it is a String value, optional <i>fmt</i> and <i>nlsparam</i>.
735
+ * is used as {http://docs.oracle.com/database/121/SQLRF/functions226.htm Oracle SQL function TO_NUMBER}
736
+ * does.
737
+ *
738
+ * @example
739
+ * # Numeric expr
740
+ * OraNumber(123456.789) # -> 123456.789
741
+ * # String expr
742
+ * OraNumber('123456.789') # -> 123456.789
743
+ * # String expr with fmt
744
+ * OraNumber('123,456.789', '999,999,999.999') # -> 123456.789
745
+ * # String expr with fmt and nlsparam
746
+ * OraNumber('123.456,789', '999G999G999D999', "NLS_NUMERIC_CHARACTERS = ',.'") # -> 123456.789
747
+ *
748
+ * @param [String, Numeric] expr
749
+ * @param [String] fmt
750
+ * @param [String] nlsparam
751
+ * @return [OraNumber]
752
+ *
753
+ * @since 2.0.3
754
+ */
755
+ static VALUE onum_f_new(int argc, VALUE *argv, VALUE self)
756
+ {
757
+ VALUE obj = rb_obj_alloc(cOCINumber);
758
+ rb_obj_call_init(obj, argc, argv);
759
+ return obj;
760
+ }
761
+
762
+ /*
763
+ * @overload initialize(expr = nil, fmt = nil, nlsparam = nil)
764
+ *
765
+ * Creates a value of OraNumber from <i>expr</i>. The <i>expr</i> can be a Numeric value
766
+ * or a String value. If it is a String value, optional <i>fmt</i> and <i>nlsparam</i>
767
+ * is used as {http://docs.oracle.com/database/121/SQLRF/functions226.htm Oracle SQL function TO_NUMBER}
768
+ * does.
769
+ *
770
+ * @example
771
+ * # Numeric expr
772
+ * OraNumber.new(123456.789) # -> 123456.789
773
+ * # String expr
774
+ * OraNumber.new('123456.789') # => #<OraNumber:123456.789>
775
+ * # String expr with fmt
776
+ * OraNumber.new('123,456.789', '999,999,999.999') # => #<OraNumber:123456.789>
777
+ * # String expr with fmt and nlsparam
778
+ * OraNumber.new('123.456,789', '999G999G999D999', "NLS_NUMERIC_CHARACTERS = ',.'") # => #<OraNumber:123456.789>
779
+ *
780
+ * @param [String, Numeric] expr
781
+ * @param [String] fmt
782
+ * @param [String] nlsparam
783
+ */
784
+ static VALUE onum_initialize(int argc, VALUE *argv, VALUE self)
785
+ {
786
+ ACIError *errhp = oci8_errhp;
787
+ VALUE val;
788
+ VALUE fmt;
789
+ VALUE nls_params;
790
+
791
+ if (rb_scan_args(argc, argv, "03", &val /* 0 */, &fmt /* nil */, &nls_params /* nil */) == 0) {
792
+ ACINumberSetZero(errhp, _NUMBER(self));
793
+ } else if (RTEST(rb_obj_is_kind_of(val, rb_cNumeric))) {
794
+ set_oci_number_from_num(_NUMBER(self), val, 1, errhp);
795
+ } else {
796
+ set_oci_number_from_str(_NUMBER(self), val, fmt, nls_params, errhp);
797
+ }
798
+ return Qnil;
799
+ }
800
+
801
+ /*
802
+ * @overload initialize_copy(obj)
803
+ *
804
+ * Replaces <i>self</i> with <i>obj</i>. <code>Object#clone</code> and <code>Object#dup</code>
805
+ * call this method to copy data unknown by the ruby interpreter.
806
+ *
807
+ * @param [OraNumber] obj
808
+ *
809
+ * @private
810
+ */
811
+ static VALUE onum_initialize_copy(VALUE lhs, VALUE rhs)
812
+ {
813
+ if (!RTEST(rb_obj_is_instance_of(rhs, CLASS_OF(lhs)))) {
814
+ rb_raise(rb_eTypeError, "invalid type: expected %s but %s",
815
+ rb_class2name(CLASS_OF(lhs)), rb_class2name(CLASS_OF(rhs)));
816
+ }
817
+ chkerr(ACINumberAssign(oci8_errhp, _NUMBER(rhs), _NUMBER(lhs)));
818
+ return lhs;
819
+ }
820
+
821
+ /*
822
+ * @private
823
+ */
824
+ static VALUE onum_coerce(VALUE self, VALUE other)
825
+ {
826
+ signed long sl;
827
+ ACINumber n;
828
+
829
+ switch(rboci8_type(other)) {
830
+ case T_FIXNUM:
831
+ sl = NUM2LONG(other);
832
+ chkerr(ACINumberFromInt(oci8_errhp, &sl, sizeof(sl), ACI_NUMBER_SIGNED, &n));
833
+ return rb_assoc_new(oci8_make_ocinumber(&n, oci8_errhp), self);
834
+ case T_BIGNUM:
835
+ /* change via string. */
836
+ other = rb_big2str(other, 10);
837
+ set_oci_number_from_str(&n, other, Qnil, Qnil, oci8_errhp);
838
+ return rb_assoc_new(oci8_make_ocinumber(&n, oci8_errhp), self);
839
+ case T_FLOAT:
840
+ return rb_assoc_new(other, onum_to_f(self));
841
+ case T_RATIONAL:
842
+ return rb_assoc_new(other, onum_to_r(self));
843
+ case RBOCI8_T_BIGDECIMAL:
844
+ return rb_assoc_new(other, onum_to_d(self));
845
+ }
846
+ rb_raise(rb_eTypeError, "Can't coerce %s to %s",
847
+ rb_class2name(CLASS_OF(other)), rb_class2name(cOCINumber));
848
+ }
849
+
850
+ /*
851
+ * Returns a negated value of <i>self</i>
852
+ *
853
+ * @example
854
+ * -OraNumber(2) # => #<OraNumber:-2>
855
+ *
856
+ * @return [OraNumber]
857
+ */
858
+ static VALUE onum_neg(VALUE self)
859
+ {
860
+ ACIError *errhp = oci8_errhp;
861
+ ACINumber r;
862
+
863
+ chkerr(ACINumberNeg(errhp, _NUMBER(self), &r));
864
+ return oci8_make_ocinumber(&r, errhp);
865
+ }
866
+
867
+ /*
868
+ * @overload +(other)
869
+ *
870
+ * Returns the sum of <i>self</i> and <i>other</i>.
871
+ * When <i>other</i>'s class is Integer, it returns an OraNumber value.
872
+ * Otherwise, it returns a value same with <i>other</i>'s class.
873
+ *
874
+ * @example
875
+ * OraNumber(2) + 3 # => #<OraNumber:5>
876
+ * OraNumber(2) + 1.5 # => 3.5 (Float)
877
+ *
878
+ * @param [Numeric] other
879
+ * @return [Numeric]
880
+ */
881
+ static VALUE onum_add(VALUE lhs, VALUE rhs)
882
+ {
883
+ ACIError *errhp = oci8_errhp;
884
+ ACINumber n;
885
+ ACINumber r;
886
+
887
+ switch (rboci8_type(rhs)) {
888
+ case T_FIXNUM:
889
+ case T_BIGNUM:
890
+ if (set_oci_number_from_num(&n, rhs, 0, errhp)) {
891
+ chkerr(ACINumberAdd(errhp, _NUMBER(lhs), &n, &r));
892
+ return oci8_make_ocinumber(&r, errhp);
893
+ }
894
+ break;
895
+ case RBOCI8_T_ORANUMBER:
896
+ chkerr(ACINumberAdd(errhp, _NUMBER(lhs), _NUMBER(rhs), &r));
897
+ return oci8_make_ocinumber(&r, errhp);
898
+ case T_FLOAT:
899
+ return rb_funcall(onum_to_f(lhs), oci8_id_add_op, 1, rhs);
900
+ case T_RATIONAL:
901
+ return rb_funcall(onum_to_r(lhs), oci8_id_add_op, 1, rhs);
902
+ case RBOCI8_T_BIGDECIMAL:
903
+ return rb_funcall(onum_to_d(lhs), oci8_id_add_op, 1, rhs);
904
+ }
905
+ return rb_num_coerce_bin(lhs, rhs, oci8_id_add_op);
906
+ }
907
+
908
+ /*
909
+ * @overload -(other)
910
+ *
911
+ * Returns the difference of <i>self</i> and <i>other</i>.
912
+ * When <i>other</i>'s class is Integer, it returns an OraNumber value.
913
+ * Otherwise, it returns a value same with <i>other</i>'s class.
914
+ *
915
+ * @example
916
+ * OraNumber(2) - 3 # => #<OraNumber:-1>
917
+ * OraNumber(2) - 1.5 # => 0.5 (Float)
918
+ *
919
+ * @param [Numeric] other
920
+ * @return [Numeric]
921
+ */
922
+ static VALUE onum_sub(VALUE lhs, VALUE rhs)
923
+ {
924
+ ACIError *errhp = oci8_errhp;
925
+ ACINumber n;
926
+ ACINumber r;
927
+
928
+ switch (rboci8_type(rhs)) {
929
+ case T_FIXNUM:
930
+ case T_BIGNUM:
931
+ if (set_oci_number_from_num(&n, rhs, 0, errhp)) {
932
+ chkerr(ACINumberSub(errhp, _NUMBER(lhs), &n, &r));
933
+ return oci8_make_ocinumber(&r, errhp);
934
+ }
935
+ break;
936
+ case RBOCI8_T_ORANUMBER:
937
+ chkerr(ACINumberSub(errhp, _NUMBER(lhs), _NUMBER(rhs), &r));
938
+ return oci8_make_ocinumber(&r, errhp);
939
+ case T_FLOAT:
940
+ return rb_funcall(onum_to_f(lhs), oci8_id_sub_op, 1, rhs);
941
+ case T_RATIONAL:
942
+ return rb_funcall(onum_to_r(lhs), oci8_id_sub_op, 1, rhs);
943
+ case RBOCI8_T_BIGDECIMAL:
944
+ return rb_funcall(onum_to_d(lhs), oci8_id_sub_op, 1, rhs);
945
+ }
946
+ return rb_num_coerce_bin(lhs, rhs, oci8_id_sub_op);
947
+ }
948
+
949
+ /*
950
+ * @overload *(other)
951
+ *
952
+ * Returns the product of <i>self</i> and <i>other</i>.
953
+ * When <i>other</i>'s class is Integer, it returns an OraNumber value.
954
+ * Otherwise, it returns a value same with <i>other</i>'s class.
955
+ *
956
+ * @example
957
+ * OraNumber(2) * 3 # => #<OraNumber:6>
958
+ * OraNumber(2) * 1.5 # => 3.0 (Float)
959
+ *
960
+ * @param [Numeric] other
961
+ * @return [Numeric]
962
+ */
963
+ static VALUE onum_mul(VALUE lhs, VALUE rhs)
964
+ {
965
+ ACIError *errhp = oci8_errhp;
966
+ ACINumber n;
967
+ ACINumber r;
968
+
969
+ switch (rboci8_type(rhs)) {
970
+ case T_FIXNUM:
971
+ case T_BIGNUM:
972
+ if (set_oci_number_from_num(&n, rhs, 0, errhp)) {
973
+ chkerr(ACINumberMul(errhp, _NUMBER(lhs), &n, &r));
974
+ return oci8_make_ocinumber(&r, errhp);
975
+ }
976
+ break;
977
+ case RBOCI8_T_ORANUMBER:
978
+ chkerr(ACINumberMul(errhp, _NUMBER(lhs), _NUMBER(rhs), &r));
979
+ return oci8_make_ocinumber(&r, errhp);
980
+ case T_FLOAT:
981
+ return rb_funcall(onum_to_f(lhs), oci8_id_mul_op, 1, rhs);
982
+ case T_RATIONAL:
983
+ return rb_funcall(onum_to_r(lhs), oci8_id_mul_op, 1, rhs);
984
+ case RBOCI8_T_BIGDECIMAL:
985
+ return rb_funcall(onum_to_d(lhs), oci8_id_mul_op, 1, rhs);
986
+ }
987
+ return rb_num_coerce_bin(lhs, rhs, oci8_id_mul_op);
988
+ }
989
+
990
+ /*
991
+ * @overload /(other)
992
+ *
993
+ * Returns the result of dividing <i>self</i> by <i>other</i>.
994
+ * When <i>other</i>'s class is Integer, it returns an OraNumber value.
995
+ * Otherwise, it returns a value same with <i>other</i>'s class.
996
+ *
997
+ * @example
998
+ * OraNumber(2) / 3 # => #<OraNumber:0.6666666666666666666666666666666666666667>
999
+ * OraNumber(2) / 1.5 # => 1.3333333333333333 (Float)
1000
+ *
1001
+ * @param [Numeric] other
1002
+ * @return [Numeric]
1003
+ */
1004
+ static VALUE onum_div(VALUE lhs, VALUE rhs)
1005
+ {
1006
+ ACIError *errhp = oci8_errhp;
1007
+ ACINumber n;
1008
+ ACINumber r;
1009
+ boolean is_zero;
1010
+
1011
+ switch (rboci8_type(rhs)) {
1012
+ case T_FIXNUM:
1013
+ if (rhs == INT2FIX(0)) {
1014
+ rb_num_zerodiv();
1015
+ }
1016
+ case T_BIGNUM:
1017
+ if (set_oci_number_from_num(&n, rhs, 0, errhp)) {
1018
+ chkerr(ACINumberDiv(errhp, _NUMBER(lhs), &n, &r));
1019
+ return oci8_make_ocinumber(&r, errhp);
1020
+ }
1021
+ break;
1022
+ case RBOCI8_T_ORANUMBER:
1023
+ chkerr(ACINumberIsZero(errhp, _NUMBER(rhs), &is_zero));
1024
+ if (is_zero) {
1025
+ rb_num_zerodiv();
1026
+ }
1027
+ chkerr(ACINumberDiv(errhp, _NUMBER(lhs), _NUMBER(rhs), &r));
1028
+ return oci8_make_ocinumber(&r, errhp);
1029
+ case T_FLOAT:
1030
+ return rb_funcall(onum_to_f(lhs), oci8_id_div_op, 1, rhs);
1031
+ case T_RATIONAL:
1032
+ return rb_funcall(onum_to_r(lhs), oci8_id_div_op, 1, rhs);
1033
+ case RBOCI8_T_BIGDECIMAL:
1034
+ return rb_funcall(onum_to_d(lhs), oci8_id_div_op, 1, rhs);
1035
+ }
1036
+ return rb_num_coerce_bin(lhs, rhs, oci8_id_div_op);
1037
+ }
1038
+
1039
+ /*
1040
+ * @overload %(other)
1041
+ *
1042
+ * Returns the modulo after division of <i>self</i> by <i>other</i>.
1043
+ *
1044
+ * @example
1045
+ * OraNumber(13) % 5 # => #<OraNumber:3>
1046
+ *
1047
+ * @param [Numeric] other
1048
+ * @return [OraNumber]
1049
+ *
1050
+ * @raise [ZeroDivisionError] when <i>other</i> is zero.
1051
+ */
1052
+ static VALUE onum_mod(VALUE lhs, VALUE rhs)
1053
+ {
1054
+ ACIError *errhp = oci8_errhp;
1055
+ ACINumber n;
1056
+ ACINumber r;
1057
+ boolean is_zero;
1058
+
1059
+ /* change to ACINumber */
1060
+ if (!set_oci_number_from_num(&n, rhs, 0, errhp))
1061
+ return rb_num_coerce_bin(lhs, rhs, '%');
1062
+ /* check whether argument is not zero. */
1063
+ chkerr(ACINumberIsZero(errhp, &n, &is_zero));
1064
+ if (is_zero)
1065
+ rb_num_zerodiv();
1066
+ /* modulo */
1067
+ chkerr(ACINumberMod(errhp, _NUMBER(lhs), &n, &r));
1068
+ return oci8_make_ocinumber(&r, errhp);
1069
+ }
1070
+
1071
+ /*
1072
+ * @overload **(other)
1073
+ *
1074
+ * Raises <i>self</i> to the power of <i>other</i>.
1075
+ *
1076
+ * @example
1077
+ * OraNumber(2) ** 2 # => #<OraNumber:4>
1078
+ * OraNumber(2) ** 2.5 # => #<OraNumber:5.65685424949238019520675489683879231435>
1079
+ *
1080
+ * @param [Numeric] other
1081
+ * @return [OraNumber]
1082
+ */
1083
+ static VALUE onum_power(VALUE lhs, VALUE rhs)
1084
+ {
1085
+ ACIError *errhp = oci8_errhp;
1086
+ ACINumber n;
1087
+ ACINumber r;
1088
+
1089
+ if (FIXNUM_P(rhs)) {
1090
+ chkerr(ACINumberIntPower(errhp, _NUMBER(lhs), FIX2INT(rhs), &r));
1091
+ } else {
1092
+ /* change to ACINumber */
1093
+ if (!set_oci_number_from_num(&n, rhs, 0, errhp))
1094
+ return rb_num_coerce_bin(lhs, rhs, id_power);
1095
+ chkerr(ACINumberPower(errhp, _NUMBER(lhs), &n, &r));
1096
+ }
1097
+ return oci8_make_ocinumber(&r, errhp);
1098
+ }
1099
+
1100
+ /*
1101
+ * @overload <=>(other)
1102
+ *
1103
+ * Returns -1, 0, or +1 depending on whether <i>self</i> is less than,
1104
+ * equal to, or greater than <i>other</i>. This is the basis for the
1105
+ * tests in <code>Comparable</code>.
1106
+ *
1107
+ * @example
1108
+ * OraNumber(5) <=> 3 # => 1
1109
+ * OraNumber(4) <=> 4 # => 0
1110
+ * OraNumber(2) <=> 2.5 # => 1
1111
+ *
1112
+ * @param [Numeric] other
1113
+ * @return [-1, 0 or +1]
1114
+ */
1115
+ static VALUE onum_cmp(VALUE lhs, VALUE rhs)
1116
+ {
1117
+ ACIError *errhp = oci8_errhp;
1118
+ ACINumber n;
1119
+ sword r;
1120
+
1121
+ /* change to ACINumber */
1122
+ if (!set_oci_number_from_num(&n, rhs, 0, errhp))
1123
+ return rb_num_coerce_cmp(lhs, rhs, id_cmp);
1124
+ /* compare */
1125
+ chkerr(ACINumberCmp(errhp, _NUMBER(lhs), &n, &r));
1126
+ if (r > 0) {
1127
+ return INT2FIX(1);
1128
+ } else if (r == 0) {
1129
+ return INT2FIX(0);
1130
+ } else {
1131
+ return INT2FIX(-1);
1132
+ }
1133
+ }
1134
+
1135
+ /*
1136
+ * @overload floor
1137
+ *
1138
+ * Returns the largest <code>Integer</code> less than or equal to <i>self</i>.
1139
+ *
1140
+ * @example
1141
+ * OraNumber(11.1).floor # => 11
1142
+ * OraNumber(25.8).floor # => 25
1143
+ * OraNumber(-25.8).floor # => -26
1144
+ *
1145
+ * @return [Integer]
1146
+ */
1147
+ static VALUE onum_floor(VALUE self)
1148
+ {
1149
+ ACIError *errhp = oci8_errhp;
1150
+ ACINumber r;
1151
+
1152
+ chkerr(ACINumberFloor(errhp, _NUMBER(self), &r));
1153
+ return oci8_make_integer(&r, errhp);
1154
+ }
1155
+
1156
+ /*
1157
+ * @overload ceil
1158
+ *
1159
+ * Returns the smallest <code>Integer</code> greater than or equal to <i>self</i>.
1160
+ *
1161
+ * @example
1162
+ * OraNumber(11.1).ceil # => 12
1163
+ * OraNumber(25.8).ceil # => 26
1164
+ * OraNumber(-25.8).ceil # => -25
1165
+ *
1166
+ * @return [Integer]
1167
+ */
1168
+ static VALUE onum_ceil(VALUE self)
1169
+ {
1170
+ ACIError *errhp = oci8_errhp;
1171
+ ACINumber r;
1172
+
1173
+ chkerr(ACINumberCeil(errhp, _NUMBER(self), &r));
1174
+ return oci8_make_integer(&r, errhp);
1175
+ }
1176
+
1177
+ /*
1178
+ * @overload round
1179
+ *
1180
+ * Rounds <i>self</i> to the nearest <code>Integer</code>.
1181
+ *
1182
+ * @example
1183
+ * OraNumber(1.49).round # => 1
1184
+ * OraNumber(1.5).round # => 2
1185
+ * OraNumber(-1.49).round # => -1
1186
+ * OraNumber(-1.5).round # => -2
1187
+ *
1188
+ * @return [Integer]
1189
+ *
1190
+ * @overload round(decplace)
1191
+ *
1192
+ * Rounds <i>onum</i> to a specified decimal place <i>decplace</i>.
1193
+ *
1194
+ * @example
1195
+ * OraNumber(123.456).round(2) # => #<OraNumber:123.46>
1196
+ * OraNumber(123.456).round(1) # => #<OraNumber:123.5>
1197
+ * OraNumber(123.456).round(0) # => #<OraNumber:123>
1198
+ * OraNumber(123.456).round(-1) # => #<OraNumber:120>
1199
+ *
1200
+ * @param [Integer] decplace
1201
+ * @return [OraNumber]
1202
+ */
1203
+ static VALUE onum_round(int argc, VALUE *argv, VALUE self)
1204
+ {
1205
+ ACIError *errhp = oci8_errhp;
1206
+ VALUE decplace;
1207
+ ACINumber r;
1208
+
1209
+ rb_scan_args(argc, argv, "01", &decplace /* 0 */);
1210
+ chkerr(ACINumberRound(errhp, _NUMBER(self), NIL_P(decplace) ? 0 : NUM2INT(decplace), &r));
1211
+ if (argc == 0) {
1212
+ return oci8_make_integer(&r, errhp);
1213
+ } else {
1214
+ return oci8_make_ocinumber(&r, errhp);
1215
+ }
1216
+ }
1217
+
1218
+ /*
1219
+ * @overload truncate(decplace = 0)
1220
+ *
1221
+ * Truncates <i>self</i> to a specified decimal place <i>decplace</i>.
1222
+ *
1223
+ * @example
1224
+ * OraNumber(123.456).truncate # => #<OraNumber:123>
1225
+ * OraNumber(123.456).truncate(1) # => #<OraNumber:123.4>
1226
+ * OraNumber(123.456).truncate(2) # => #<OraNumber:123.45>
1227
+ * OraNumber(123.456).truncate(-1) # => #<OraNumber:120>
1228
+ *
1229
+ * OraNumber(-123.456).truncate # => #<OraNumber:-123>
1230
+ * OraNumber(-123.456).truncate(1) # => #<OraNumber:-123.4>
1231
+ * OraNumber(-123.456).truncate(2) # => #<OraNumber:-123.45>
1232
+ * OraNumber(-123.456).truncate(-1) # => #<OraNumber:-120>
1233
+ *
1234
+ * @param [Integer] decplace
1235
+ * @return [OraNumber]
1236
+ * @todo returns <i>Integer</i> when <i>decplace</i> is not specified.
1237
+ */
1238
+ static VALUE onum_trunc(int argc, VALUE *argv, VALUE self)
1239
+ {
1240
+ ACIError *errhp = oci8_errhp;
1241
+ VALUE decplace;
1242
+ ACINumber r;
1243
+
1244
+ rb_scan_args(argc, argv, "01", &decplace /* 0 */);
1245
+ chkerr(ACINumberTrunc(errhp, _NUMBER(self), NIL_P(decplace) ? 0 : NUM2INT(decplace), &r));
1246
+ return oci8_make_ocinumber(&r, errhp);
1247
+ }
1248
+
1249
+ /*
1250
+ * @overload round_prec(digits)
1251
+ *
1252
+ * Rounds <i>self</i> to a specified number of decimal digits.
1253
+ * This method is available on Oracle 8.1 client or upper.
1254
+ *
1255
+ * @example
1256
+ * OraNumber(1.234).round_prec(2) # => #<OraNumber:1.2>
1257
+ * OraNumber(12.34).round_prec(2) # => #<OraNumber:12>
1258
+ * OraNumber(123.4).round_prec(2) # => #<OraNumber:120>
1259
+ *
1260
+ * @param [Integer] digits
1261
+ * @return [OraNumber]
1262
+ */
1263
+ static VALUE onum_round_prec(VALUE self, VALUE ndigs)
1264
+ {
1265
+ ACIError *errhp = oci8_errhp;
1266
+ ACINumber r;
1267
+
1268
+ // chkerr(ACINumberPrec(errhp, _NUMBER(self), NUM2INT(ndigs), &r));
1269
+ return oci8_make_ocinumber(&r, errhp);
1270
+ }
1271
+
1272
+ /*
1273
+ * @overload onum.to_char(fmt = nil, nlsparam = nil)
1274
+ *
1275
+ * Returns a string containing a representation of self.
1276
+ * <i>fmt</i> and <i>nlsparam</i> are used as
1277
+ * {http://docs.oracle.com/database/121/SQLRF/functions216.htm Oracle SQL function TO_CHAR(number)}
1278
+ * does.
1279
+ *
1280
+ * @example
1281
+ * OraNumber(123456.789).to_char('FM999,999,999.999') # => "123,456.789"
1282
+ * OraNumber(123456.789).to_char('FM999G999G999D999', "NLS_NUMERIC_CHARACTERS = ',.'") # => "123.456,789"
1283
+ *
1284
+ * @param [String] fmt
1285
+ * @param [String] nlsparam
1286
+ * @return [String]
1287
+ */
1288
+ static VALUE onum_to_char(int argc, VALUE *argv, VALUE self)
1289
+ {
1290
+ ACIError *errhp = oci8_errhp;
1291
+ VALUE fmt;
1292
+ VALUE nls_params;
1293
+ char buf[512];
1294
+ ub4 buf_size = sizeof(buf);
1295
+ oratext *fmt_ptr;
1296
+ oratext *nls_params_ptr;
1297
+ ub4 fmt_len;
1298
+ ub4 nls_params_len;
1299
+ sword rv;
1300
+
1301
+ rb_scan_args(argc, argv, "02", &fmt /* nil */, &nls_params /* nil */);
1302
+ if (NIL_P(fmt)) {
1303
+ rv = oranumber_to_str(_NUMBER(self), buf, sizeof(buf));
1304
+ if (rv > 0) {
1305
+ return rb_usascii_str_new(buf, rv);
1306
+ }
1307
+ oranumber_dump(_NUMBER(self), buf);
1308
+ rb_raise(eOCIException, "Invalid internal number format: %s", buf);
1309
+ }
1310
+ StringValue(fmt);
1311
+ fmt_ptr = RSTRING_ORATEXT(fmt);
1312
+ fmt_len = RSTRING_LEN(fmt);
1313
+ if (NIL_P(nls_params)) {
1314
+ nls_params_ptr = NULL;
1315
+ nls_params_len = 0;
1316
+ } else {
1317
+ StringValue(nls_params);
1318
+ nls_params_ptr = RSTRING_ORATEXT(nls_params);
1319
+ nls_params_len = RSTRING_LEN(nls_params);
1320
+ }
1321
+ rv = ACINumberToText(errhp, _NUMBER(self),
1322
+ fmt_ptr, fmt_len, nls_params_ptr, nls_params_len,
1323
+ &buf_size, TO_ORATEXT(buf));
1324
+ if (rv == ACI_ERROR) {
1325
+ sb4 errcode;
1326
+ ACIErrorGet(errhp, 1, NULL, &errcode, NULL, 0, ACI_HTYPE_ERROR);
1327
+ if (errcode == 22065) {
1328
+ /* ACI-22065: number to text translation for the given format causes overflow */
1329
+ if (NIL_P(fmt)) /* implicit conversion */
1330
+ return rb_usascii_str_new_cstr("overflow");
1331
+ }
1332
+ chkerr(rv);
1333
+ }
1334
+ return rb_usascii_str_new(buf, buf_size);
1335
+ }
1336
+
1337
+ /*
1338
+ * @overload to_s
1339
+ *
1340
+ * Returns a string containing a representation of self.
1341
+ *
1342
+ * @return [String]
1343
+ *
1344
+ * @see #to_char
1345
+ */
1346
+ static VALUE onum_to_s(VALUE self)
1347
+ {
1348
+ return onum_to_char(0, NULL, self);
1349
+ }
1350
+
1351
+ /*
1352
+ * @overload to_i
1353
+ *
1354
+ * Returns <i>self</i> truncated to an <code>Integer</code>.
1355
+ *
1356
+ * @return [Integer]
1357
+ */
1358
+ static VALUE onum_to_i(VALUE self)
1359
+ {
1360
+ ACIError *errhp = oci8_errhp;
1361
+ ACINumber num;
1362
+
1363
+ chkerr(ACINumberTrunc(errhp, _NUMBER(self), 0, &num));
1364
+ return oci8_make_integer(&num, errhp);
1365
+ }
1366
+
1367
+ /*
1368
+ * Converts <i>self</i> to <code>Float</code>.
1369
+ *
1370
+ * When {ACI8.properties ACI8.properties [:float_conversion_type\]}
1371
+ * is <code>:ruby</code>, <i>self</I> is converted by <code>self.to_s.to_f</code>.
1372
+ * When it is <code>:oracle</code>, <i>self</I> is converted by the Oracle
1373
+ * ACI function ACINumberToReal().
1374
+ *
1375
+ * @return [Float]
1376
+ */
1377
+ static VALUE onum_to_f(VALUE self)
1378
+ {
1379
+ return rb_float_new(oci8_onum_to_dbl(_NUMBER(self), oci8_errhp));
1380
+ }
1381
+
1382
+ /*
1383
+ * @overload to_r
1384
+ *
1385
+ * Returns <i>self</i> as a <code>Rational</code>.
1386
+ *
1387
+ * @return [Rational]
1388
+ */
1389
+ static VALUE onum_to_r(VALUE self)
1390
+ {
1391
+ VALUE x, y;
1392
+ int nshift = 0;
1393
+ ACINumber onum[2];
1394
+ int current = 0;
1395
+ boolean is_int;
1396
+
1397
+ chkerr(ACINumberAssign(oci8_errhp, _NUMBER(self), &onum[0]));
1398
+
1399
+ for (;;) {
1400
+ chkerr(ACINumberIsInt(oci8_errhp, &onum[current], &is_int));
1401
+ if (is_int) {
1402
+ break;
1403
+ }
1404
+ nshift++;
1405
+ chkerr(ACINumberShift(oci8_errhp, &onum[current], 1, &onum[1 - current]));
1406
+ current = 1 - current;
1407
+ }
1408
+ x = oci8_make_integer(&onum[current], oci8_errhp);
1409
+ if (nshift == 0) {
1410
+ y = INT2FIX(1);
1411
+ } else {
1412
+ y = rb_funcall(INT2FIX(10), rb_intern("**"), 1, INT2FIX(nshift));
1413
+ }
1414
+ return rb_Rational(x, y);
1415
+ }
1416
+
1417
+ /*
1418
+ * @overload to_d
1419
+ *
1420
+ * Returns <i>self</i> as a <code>BigDecimal</code>.
1421
+ *
1422
+ * @return [BigDecimal]
1423
+ */
1424
+ static VALUE onum_to_d(VALUE self)
1425
+ {
1426
+ return onum_to_d_real(_NUMBER(self), oci8_errhp);
1427
+ }
1428
+
1429
+ /* Converts to BigDecimal via number in scientific notation */
1430
+ static VALUE onum_to_d_real(ACINumber *num, ACIError *errhp)
1431
+ {
1432
+ char buf[64];
1433
+ ub4 buf_size = sizeof(buf);
1434
+ const char *fmt = "FM9.09999999999999999999999999999999999999EEEE";
1435
+
1436
+ if (!cBigDecimal) {
1437
+ rb_require("bigdecimal");
1438
+ cBigDecimal = rb_const_get(rb_cObject, id_BigDecimal);
1439
+ }
1440
+ chkerr(ACINumberToText(errhp, num, (const oratext *)fmt, strlen(fmt),
1441
+ NULL, 0, &buf_size, TO_ORATEXT(buf)));
1442
+ return rb_funcall(rb_cObject, id_BigDecimal, 1, rb_usascii_str_new(buf, buf_size));
1443
+ }
1444
+
1445
+ /*
1446
+ * @overload has_fractional_part?
1447
+ *
1448
+ * Returns <code>true</code> if <i>self</i> has a fractional part.
1449
+ *
1450
+ * @example
1451
+ * OraNumber(10).has_fractional_part? # => false
1452
+ * OraNumber(10.1).has_fractional_part? # => true
1453
+ *
1454
+ * @since 2.2.5
1455
+ */
1456
+ static VALUE onum_has_fractional_part_p(VALUE self)
1457
+ {
1458
+ ACIError *errhp = oci8_errhp;
1459
+ boolean result;
1460
+
1461
+ chkerr(ACINumberIsInt(errhp, _NUMBER(self), &result));
1462
+ return result ? Qfalse : Qtrue;
1463
+ }
1464
+
1465
+ /*
1466
+ * @overload to_onum
1467
+ *
1468
+ * Returns self.
1469
+ *
1470
+ * @return [OraNumber]
1471
+ */
1472
+ static VALUE onum_to_onum(VALUE self)
1473
+ {
1474
+ return self;
1475
+ }
1476
+
1477
+ /*
1478
+ * @overload zero?
1479
+ *
1480
+ * Returns <code>true</code> if <i>self</i> is zero.
1481
+ *
1482
+ */
1483
+ static VALUE onum_zero_p(VALUE self)
1484
+ {
1485
+ ACIError *errhp = oci8_errhp;
1486
+ boolean result;
1487
+
1488
+ chkerr(ACINumberIsZero(errhp, _NUMBER(self), &result));
1489
+ return result ? Qtrue : Qfalse;
1490
+ }
1491
+
1492
+ /*
1493
+ * @overload abs
1494
+ *
1495
+ * Returns the absolute value of <i>self</i>.
1496
+ *
1497
+ * @return [OraNumber]
1498
+ */
1499
+ static VALUE onum_abs(VALUE self)
1500
+ {
1501
+ ACIError *errhp = oci8_errhp;
1502
+ ACINumber result;
1503
+
1504
+ chkerr(ACINumberAbs(errhp, _NUMBER(self), &result));
1505
+ return oci8_make_ocinumber(&result, errhp);
1506
+ }
1507
+
1508
+ /*
1509
+ * @overload shift(ndigits)
1510
+ *
1511
+ * Returns <i>self</i> shifted by <i>ndigits</i>
1512
+ * This method is available on Oracle 8.1 client or upper.
1513
+ *
1514
+ * @example
1515
+ * OraNumber(123).shift(3) # => #<OraNumber:123000>
1516
+ * OraNumber(123).shift(-3) # => #<OraNumber:0.123>
1517
+ *
1518
+ * @param [Integer] ndigits
1519
+ * @return [OraNumber]
1520
+ */
1521
+ static VALUE onum_shift(VALUE self, VALUE exp)
1522
+ {
1523
+ ACIError *errhp = oci8_errhp;
1524
+ ACINumber result;
1525
+
1526
+ chkerr(ACINumberShift(errhp, _NUMBER(self), NUM2INT(exp), &result));
1527
+ return oci8_make_ocinumber(&result, errhp);
1528
+ }
1529
+
1530
+ /*
1531
+ * @overload dump
1532
+ *
1533
+ * Returns internal representation whose format is same with the return value of
1534
+ * {http://docs.oracle.com/database/121/SQLRF/functions062.htm Oracle SQL function DUMP}.
1535
+ *
1536
+ * @example
1537
+ * OraNumber.new(100).dump #=> "Typ=2 Len=2: 194,2"
1538
+ * OraNumber.new(123).dump #=> "Typ=2 Len=3: 194,2,24"
1539
+ * OraNumber.new(0.1).dump #=> "Typ=2 Len=2: 192,11"
1540
+ *
1541
+ * @return [String]
1542
+ * @since 2.0.4
1543
+ */
1544
+ static VALUE onum_dump(VALUE self)
1545
+ {
1546
+ char buf[ORANUMBER_DUMP_BUF_SIZ];
1547
+ int rv = oranumber_dump(_NUMBER(self), buf);
1548
+ return rb_usascii_str_new(buf, rv);
1549
+ }
1550
+
1551
+ /*
1552
+ * @private
1553
+ */
1554
+ static VALUE onum_hash(VALUE self)
1555
+ {
1556
+ char *c = RTYPEDDATA_DATA(self);
1557
+ int size = c[0] + 1;
1558
+ long i, hash;
1559
+
1560
+ /* assert(size <= 22); ?*/
1561
+ if (size > 22)
1562
+ size = 22;
1563
+
1564
+ for (hash = 0, i = 1; i< size; i++) {
1565
+ hash += c[i] * 971;
1566
+ }
1567
+ if (hash < 0) hash = -hash;
1568
+ return INT2FIX(hash);
1569
+ }
1570
+
1571
+ /*
1572
+ * @private
1573
+ */
1574
+ static VALUE onum_inspect(VALUE self)
1575
+ {
1576
+ const char *name = rb_class2name(CLASS_OF(self));
1577
+ volatile VALUE s = onum_to_s(self);
1578
+ size_t len = strlen(name) + RSTRING_LEN(s) + 5;
1579
+ char *str = ALLOCA_N(char, len);
1580
+
1581
+ snprintf(str, len, "#<%s:%s>", name, RSTRING_PTR(s));
1582
+ str[len - 1] = '\0';
1583
+ return rb_usascii_str_new_cstr(str);
1584
+ }
1585
+
1586
+ /*
1587
+ * @overload _dump
1588
+ *
1589
+ * Serializes <i>self</i>.
1590
+ * This method is called by Marshal.dump().
1591
+ *
1592
+ * @return [String] a byte stream
1593
+ * @see OraNumber._load
1594
+ */
1595
+ static VALUE onum__dump(int argc, VALUE *argv, VALUE self)
1596
+ {
1597
+ char *c = RTYPEDDATA_DATA(self);
1598
+ int size = c[0] + 1;
1599
+ VALUE dummy;
1600
+
1601
+ rb_scan_args(argc, argv, "01", &dummy);
1602
+ return rb_str_new(c, size);
1603
+ }
1604
+
1605
+ /*
1606
+ * @overload _load(bytes)
1607
+ *
1608
+ * Restores a byte stream serialized by {OraNumber#_dump}.
1609
+ * This method is called by Marshal.load() to deserialize a byte stream
1610
+ * created by Marshal.dump().
1611
+ *
1612
+ * @param [String] bytes a byte stream
1613
+ * @return [OraNumber] a deserialized object
1614
+ */
1615
+ static VALUE
1616
+ onum_s_load(VALUE klass, VALUE str)
1617
+ {
1618
+ unsigned char *c;
1619
+ size_t size;
1620
+ ACINumber num;
1621
+
1622
+ Check_Type(str, T_STRING);
1623
+ c = RSTRING_ORATEXT(str);
1624
+ size = RSTRING_LEN(str);
1625
+ if (size == 0 || size != c[0] + 1u || size > sizeof(num)) {
1626
+ rb_raise(rb_eTypeError, "marshaled ACI::Number format differ");
1627
+ }
1628
+ memset(&num, 0, sizeof(num));
1629
+ memcpy(&num, c, size);
1630
+ return oci8_make_ocinumber(&num, oci8_errhp);
1631
+ }
1632
+
1633
+ /*
1634
+ * Document-class: ACI8::BindType::OraNumber
1635
+ */
1636
+
1637
+ /*
1638
+ * Document-class: STACI::BindType::Integer
1639
+ */
1640
+
1641
+ /*
1642
+ * Document-class: STACI::BindType::Float
1643
+ */
1644
+
1645
+ static VALUE bind_ocinumber_get(oci8_bind_t *obind, void *data, void *null_struct)
1646
+ {
1647
+ return oci8_make_ocinumber((ACINumber*)data, oci8_errhp);
1648
+ }
1649
+
1650
+ static VALUE bind_integer_get(oci8_bind_t *obind, void *data, void *null_struct)
1651
+ {
1652
+ return oci8_make_integer((ACINumber*)data, oci8_errhp);
1653
+ }
1654
+
1655
+ static VALUE bind_float_get(oci8_bind_t *obind, void *data, void *null_struct)
1656
+ {
1657
+ return oci8_make_float((ACINumber*)data, oci8_errhp);
1658
+ }
1659
+
1660
+ static void bind_ocinumber_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
1661
+ {
1662
+ set_oci_number_from_num((ACINumber*)data, val, 1, oci8_errhp);
1663
+ }
1664
+
1665
+ static void bind_integer_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
1666
+ {
1667
+ ACIError *errhp = oci8_errhp;
1668
+ ACINumber num;
1669
+
1670
+ set_oci_number_from_num(&num, val, 1, errhp);
1671
+ chker2(ACINumberTrunc(errhp, &num, 0, (ACINumber*)data),
1672
+ &obind->base);
1673
+ }
1674
+
1675
+ static void bind_ocinumber_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
1676
+ {
1677
+ obind->value_sz = sizeof(ACINumber);
1678
+ obind->alloc_sz = sizeof(ACINumber);
1679
+ }
1680
+
1681
+ static void bind_ocinumber_init_elem(oci8_bind_t *obind, VALUE svc)
1682
+ {
1683
+ ACIError *errhp = oci8_errhp;
1684
+ ub4 idx = 0;
1685
+
1686
+ do {
1687
+ ACINumberSetZero(errhp, (ACINumber*)obind->valuep + idx);
1688
+ } while (++idx < obind->maxar_sz);
1689
+ }
1690
+
1691
+ static const oci8_bind_data_type_t bind_ocinumber_data_type = {
1692
+ {
1693
+ {
1694
+ "STACI::BindType::OraNumber",
1695
+ {
1696
+ NULL,
1697
+ oci8_handle_cleanup,
1698
+ oci8_handle_size,
1699
+ },
1700
+ &oci8_bind_data_type.rb_data_type, NULL,
1701
+ #ifdef RUBY_TYPED_WB_PROTECTED
1702
+ RUBY_TYPED_WB_PROTECTED,
1703
+ #endif
1704
+ },
1705
+ oci8_bind_free,
1706
+ sizeof(oci8_bind_t)
1707
+ },
1708
+ bind_ocinumber_get,
1709
+ bind_ocinumber_set,
1710
+ bind_ocinumber_init,
1711
+ bind_ocinumber_init_elem,
1712
+ NULL,
1713
+ SQLT_VNU,
1714
+ };
1715
+
1716
+ static VALUE bind_ocinumber_alloc(VALUE klass)
1717
+ {
1718
+ return oci8_allocate_typeddata(klass, &bind_ocinumber_data_type.base);
1719
+ }
1720
+
1721
+ static const oci8_bind_data_type_t bind_integer_data_type = {
1722
+ {
1723
+ {
1724
+ "STACI::BindType::Integer",
1725
+ {
1726
+ NULL,
1727
+ oci8_handle_cleanup,
1728
+ oci8_handle_size,
1729
+ },
1730
+ &oci8_bind_data_type.rb_data_type, NULL,
1731
+ #ifdef RUBY_TYPED_WB_PROTECTED
1732
+ RUBY_TYPED_WB_PROTECTED,
1733
+ #endif
1734
+ },
1735
+ oci8_bind_free,
1736
+ sizeof(oci8_bind_t)
1737
+ },
1738
+ bind_integer_get,
1739
+ bind_integer_set,
1740
+ bind_ocinumber_init,
1741
+ bind_ocinumber_init_elem,
1742
+ NULL,
1743
+ SQLT_VNU,
1744
+ };
1745
+
1746
+ static VALUE bind_integer_alloc(VALUE klass)
1747
+ {
1748
+ return oci8_allocate_typeddata(klass, &bind_integer_data_type.base);
1749
+ }
1750
+
1751
+ static const oci8_bind_data_type_t bind_float_data_type = {
1752
+ {
1753
+ {
1754
+ "STACI::BindType::Float",
1755
+ {
1756
+ NULL,
1757
+ oci8_handle_cleanup,
1758
+ oci8_handle_size,
1759
+ },
1760
+ &oci8_bind_data_type.rb_data_type, NULL,
1761
+ #ifdef RUBY_TYPED_WB_PROTECTED
1762
+ RUBY_TYPED_WB_PROTECTED,
1763
+ #endif
1764
+ },
1765
+ oci8_bind_free,
1766
+ sizeof(oci8_bind_t)
1767
+ },
1768
+ bind_float_get,
1769
+ bind_ocinumber_set,
1770
+ bind_ocinumber_init,
1771
+ bind_ocinumber_init_elem,
1772
+ NULL,
1773
+ SQLT_VNU,
1774
+ };
1775
+
1776
+ static VALUE bind_float_alloc(VALUE klass)
1777
+ {
1778
+ return oci8_allocate_typeddata(klass, &bind_float_data_type.base);
1779
+ }
1780
+
1781
+ void
1782
+ Init_oci_number(VALUE cOCI8, ACIError *errhp)
1783
+ {
1784
+ VALUE mMath;
1785
+ ACINumber num1, num2;
1786
+ VALUE obj_PI;
1787
+ signed long sl;
1788
+
1789
+ id_power = rb_intern("**");
1790
+ id_cmp = rb_intern("<=>");
1791
+ id_finite_p = rb_intern("finite?");
1792
+ id_split = rb_intern("split");
1793
+ id_numerator = rb_intern("numerator");
1794
+ id_denominator = rb_intern("denominator");
1795
+ id_BigDecimal = rb_intern("BigDecimal");
1796
+
1797
+ cOCINumber = rb_define_class("OraNumber", rb_cNumeric);
1798
+ mMath = rb_define_module_under(cOCI8, "Math");
1799
+
1800
+ /* constants for internal use. */
1801
+ /* set const_p1 */
1802
+ sl = 1;
1803
+ ACINumberFromInt(errhp, &sl, sizeof(sl), ACI_NUMBER_SIGNED, &const_p1);
1804
+ /* set const_p10 */
1805
+ sl = 10;
1806
+ ACINumberFromInt(errhp, &sl, sizeof(sl), ACI_NUMBER_SIGNED, &const_p10);
1807
+ /* set const_m1 */
1808
+ sl = -1;
1809
+ ACINumberFromInt(errhp, &sl, sizeof(sl), ACI_NUMBER_SIGNED, &const_m1);
1810
+ /* set const_PI2 */
1811
+ sl = 2;
1812
+ ACINumberSetPi(errhp, &num1);
1813
+ ACINumberFromInt(errhp, &sl, sizeof(sl), ACI_NUMBER_SIGNED, &num2);
1814
+ ACINumberDiv(errhp, &num1 /* PI */, &num2 /* 2 */, &const_PI2);
1815
+ /* set const_mPI2 */
1816
+ ACINumberNeg(errhp, &const_PI2 /* PI/2 */, &const_mPI2);
1817
+
1818
+ /* PI */
1819
+ ACINumberSetPi(errhp, &num1);
1820
+ obj_PI = oci8_make_ocinumber(&num1, errhp);
1821
+
1822
+ /* The ratio of the circumference of a circle to its diameter. */
1823
+ rb_define_const(mMath, "PI", obj_PI);
1824
+
1825
+ /*
1826
+ * module functions of OCI::Math.
1827
+ */
1828
+ rb_define_module_function(mMath, "atan2", omath_atan2, 2);
1829
+
1830
+ rb_define_module_function(mMath, "cos", omath_cos, 1);
1831
+ rb_define_module_function(mMath, "sin", omath_sin, 1);
1832
+ rb_define_module_function(mMath, "tan", omath_tan, 1);
1833
+
1834
+ rb_define_module_function(mMath, "acos", omath_acos, 1);
1835
+ rb_define_module_function(mMath, "asin", omath_asin, 1);
1836
+ rb_define_module_function(mMath, "atan", omath_atan, 1);
1837
+
1838
+ rb_define_module_function(mMath, "cosh", omath_cosh, 1);
1839
+ rb_define_module_function(mMath, "sinh", omath_sinh, 1);
1840
+ rb_define_module_function(mMath, "tanh", omath_tanh, 1);
1841
+
1842
+ rb_define_module_function(mMath, "exp", omath_exp, 1);
1843
+ rb_define_module_function(mMath, "log", omath_log, -1);
1844
+ rb_define_module_function(mMath, "log10", omath_log10, 1);
1845
+ rb_define_module_function(mMath, "sqrt", omath_sqrt, 1);
1846
+
1847
+ rb_define_alloc_func(cOCINumber, onum_s_alloc);
1848
+
1849
+ /* methods of OCI::Number */
1850
+ rb_define_global_function("OraNumber", onum_f_new, -1);
1851
+ rb_define_method(cOCINumber, "initialize", onum_initialize, -1);
1852
+ rb_define_method(cOCINumber, "initialize_copy", onum_initialize_copy, 1);
1853
+ rb_define_method(cOCINumber, "coerce", onum_coerce, 1);
1854
+
1855
+ rb_include_module(cOCINumber, rb_mComparable);
1856
+
1857
+ rb_define_method(cOCINumber, "-@", onum_neg, 0);
1858
+ rb_define_method(cOCINumber, "+", onum_add, 1);
1859
+ rb_define_method(cOCINumber, "-", onum_sub, 1);
1860
+ rb_define_method(cOCINumber, "*", onum_mul, 1);
1861
+ rb_define_method(cOCINumber, "/", onum_div, 1);
1862
+ rb_define_method(cOCINumber, "%", onum_mod, 1);
1863
+ rb_define_method(cOCINumber, "**", onum_power, 1);
1864
+ rb_define_method(cOCINumber, "<=>", onum_cmp, 1);
1865
+
1866
+ rb_define_method(cOCINumber, "floor", onum_floor, 0);
1867
+ rb_define_method(cOCINumber, "ceil", onum_ceil, 0);
1868
+ rb_define_method(cOCINumber, "round", onum_round, -1);
1869
+ rb_define_method(cOCINumber, "truncate", onum_trunc, -1);
1870
+ rb_define_method(cOCINumber, "round_prec", onum_round_prec, 1);
1871
+
1872
+ rb_define_method(cOCINumber, "to_s", onum_to_s, 0);
1873
+ rb_define_method(cOCINumber, "to_char", onum_to_char, -1);
1874
+ rb_define_method(cOCINumber, "to_i", onum_to_i, 0);
1875
+ rb_define_method(cOCINumber, "to_f", onum_to_f, 0);
1876
+ rb_define_method(cOCINumber, "to_r", onum_to_r, 0);
1877
+ rb_define_method(cOCINumber, "to_d", onum_to_d, 0);
1878
+ rb_define_method(cOCINumber, "has_fractional_part?", onum_has_fractional_part_p, 0);
1879
+ rb_define_method(cOCINumber, "to_onum", onum_to_onum, 0);
1880
+
1881
+ rb_define_method(cOCINumber, "zero?", onum_zero_p, 0);
1882
+ rb_define_method(cOCINumber, "abs", onum_abs, 0);
1883
+ rb_define_method(cOCINumber, "shift", onum_shift, 1);
1884
+ rb_define_method(cOCINumber, "dump", onum_dump, 0);
1885
+
1886
+ rb_define_method(cOCINumber, "hash", onum_hash, 0);
1887
+ rb_define_method(cOCINumber, "inspect", onum_inspect, 0);
1888
+
1889
+ /* methods for marshaling */
1890
+ rb_define_method(cOCINumber, "_dump", onum__dump, -1);
1891
+ rb_define_singleton_method(cOCINumber, "_load", onum_s_load, 1);
1892
+
1893
+ oci8_define_bind_class("OraNumber", &bind_ocinumber_data_type, bind_ocinumber_alloc);
1894
+ oci8_define_bind_class("Integer", &bind_integer_data_type, bind_integer_alloc);
1895
+ oci8_define_bind_class("Float", &bind_float_data_type, bind_float_alloc);
1896
+
1897
+ #if 0 /* for rdoc/yard */
1898
+ oci8_cOCIHandle = rb_define_class("ACIHandle", rb_cObject);
1899
+ cOCI8 = rb_define_class("STACI", oci8_cOCIHandle);
1900
+ mOCI8BindType = rb_define_module_under(cOCI8, "BindType");
1901
+ cOCI8BindTypeBase = rb_define_class_under(mOCI8BindType, "Base", oci8_cOCIHandle);
1902
+
1903
+ dummy1 = rb_define_class_under(mOCI8BindType, "OraNumber", cOCI8BindTypeBase);
1904
+ dummy2 = rb_define_class_under(mOCI8BindType, "Integer", cOCI8BindTypeBase);
1905
+ dummy3 = rb_define_class_under(mOCI8BindType, "Float", cOCI8BindTypeBase);
1906
+ #endif
1907
+
1908
+ /* The following method definition is for backward-compatibility.
1909
+ I misunderstood the name of numbers after a decimal point. */
1910
+ rb_define_method_nodoc(cOCINumber, "has_decimal_part?", onum_has_fractional_part_p, 0);
1911
+ }
1912
+
1913
+ /*
1914
+ * OraNumber (ruby object) -> OCINumber (C datatype)
1915
+ */
1916
+ ACINumber *oci8_get_ocinumber(VALUE num)
1917
+ {
1918
+ if (!rb_obj_is_kind_of(num, cOCINumber)) {
1919
+ rb_raise(rb_eTypeError, "invalid argument %s (expect a subclass of %s)", rb_class2name(CLASS_OF(num)), rb_class2name(cOCINumber));
1920
+ }
1921
+ return _NUMBER(num);
1922
+ }