Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

bigdecimal.c
Go to the documentation of this file.
1 /*
2 *
3 * Ruby BigDecimal(Variable decimal precision) extension library.
4 *
5 * Copyright(C) 2002 by Shigeo Kobayashi(shigeo@tinyforest.gr.jp)
6 *
7 */
8
9 /* #define BIGDECIMAL_DEBUG 1 */
10 #ifdef BIGDECIMAL_DEBUG
11 # define BIGDECIMAL_ENABLE_VPRINT 1
12 #endif
13 #include "bigdecimal.h"
14 #include "ruby/util.h"
15
16 #ifndef BIGDECIMAL_DEBUG
17 # define NDEBUG
18 #endif
19 #include <assert.h>
20
21 #include <ctype.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <math.h>
27 #include "math.h"
28
29 #ifdef HAVE_IEEEFP_H
30 #include <ieeefp.h>
31 #endif
32
33 /* #define ENABLE_NUMERIC_STRING */
34
35 #define MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max) ( \
36 (a) == 0 ? 0 : \
37 (a) == -1 ? (b) < -(max) : \
38 (a) > 0 ? \
39 ((b) > 0 ? (max) / (a) < (b) : (min) / (a) > (b)) : \
40 ((b) > 0 ? (min) / (a) < (b) : (max) / (a) > (b)))
41 #define SIGNED_VALUE_MAX INTPTR_MAX
42 #define SIGNED_VALUE_MIN INTPTR_MIN
43 #define MUL_OVERFLOW_SIGNED_VALUE_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, SIGNED_VALUE_MIN, SIGNED_VALUE_MAX)
44
45 VALUE rb_cBigDecimal;
46 VALUE rb_mBigMath;
47
48 static ID id_BigDecimal_exception_mode;
49 static ID id_BigDecimal_rounding_mode;
50 static ID id_BigDecimal_precision_limit;
51
52 static ID id_up;
53 static ID id_down;
54 static ID id_truncate;
55 static ID id_half_up;
56 static ID id_default;
57 static ID id_half_down;
58 static ID id_half_even;
59 static ID id_banker;
60 static ID id_ceiling;
61 static ID id_ceil;
62 static ID id_floor;
63 static ID id_to_r;
64 static ID id_eq;
65 static ID id_half;
66
67 /* MACRO's to guard objects from GC by keeping them in stack */
68 #define ENTER(n) volatile VALUE RB_UNUSED_VAR(vStack[n]);int iStack=0
69 #define PUSH(x) (vStack[iStack++] = (VALUE)(x))
70 #define SAVE(p) PUSH((p)->obj)
71 #define GUARD_OBJ(p,y) ((p)=(y), SAVE(p))
72
73 #define BASE_FIG RMPD_COMPONENT_FIGURES
74 #define BASE RMPD_BASE
75
76 #define HALF_BASE (BASE/2)
77 #define BASE1 (BASE/10)
78
79 #ifndef DBLE_FIG
80 #define DBLE_FIG (DBL_DIG+1) /* figure of double */
81 #endif
82
83 #ifndef RRATIONAL_ZERO_P
84 # define RRATIONAL_ZERO_P(x) (FIXNUM_P(rb_rational_num(x)) && \
85 FIX2LONG(rb_rational_num(x)) == 0)
86 #endif
87
88 #ifndef RRATIONAL_NEGATIVE_P
89 # define RRATIONAL_NEGATIVE_P(x) RTEST(rb_funcall((x), '<', 1, INT2FIX(0)))
90 #endif
91
92 #ifndef DECIMAL_SIZE_OF_BITS
93 #define DECIMAL_SIZE_OF_BITS(n) (((n) * 3010 + 9998) / 9999)
94 /* an approximation of ceil(n * log10(2)), upto 65536 at least */
95 #endif
96
97 #ifdef PRIsVALUE
98 # define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj)
99 # define RB_OBJ_STRING(obj) (obj)
100 #else
101 # define PRIsVALUE "s"
102 # define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj)
103 # define RB_OBJ_STRING(obj) StringValueCStr(obj)
104 #endif
105
106 #ifndef HAVE_RB_RATIONAL_NUM
107 static inline VALUE
108 rb_rational_num(VALUE rat)
109 {
110 #ifdef HAVE_TYPE_STRUCT_RRATIONAL
111 return RRATIONAL(rat)->num;
112 #else
113 return rb_funcall(rat, rb_intern("numerator"), 0);
114 #endif
115 }
116 #endif
117
118 #ifndef HAVE_RB_RATIONAL_DEN
119 static inline VALUE
120 rb_rational_den(VALUE rat)
121 {
122 #ifdef HAVE_TYPE_STRUCT_RRATIONAL
123 return RRATIONAL(rat)->den;
124 #else
125 return rb_funcall(rat, rb_intern("denominator"), 0);
126 #endif
127 }
128 #endif
129
130 #define BIGDECIMAL_POSITIVE_P(bd) ((bd)->sign > 0)
131 #define BIGDECIMAL_NEGATIVE_P(bd) ((bd)->sign < 0)
132
133 /*
134 * ================== Ruby Interface part ==========================
135 */
136 #define DoSomeOne(x,y,f) rb_num_coerce_bin(x,y,f)
137
138 /*
139 * VP routines used in BigDecimal part
140 */
141 static unsigned short VpGetException(void);
142 static void VpSetException(unsigned short f);
143 static void VpInternalRound(Real *c, size_t ixDigit, BDIGIT vPrev, BDIGIT v);
144 static int VpLimitRound(Real *c, size_t ixDigit);
145 static Real *VpCopy(Real *pv, Real const* const x);
146
147 #ifdef BIGDECIMAL_ENABLE_VPRINT
148 static int VPrint(FILE *fp,const char *cntl_chr,Real *a);
149 #endif
150
151 /*
152 * **** BigDecimal part ****
153 */
154
155 static void
156 BigDecimal_delete(void *pv)
157 {
158 VpFree(pv);
159 }
160
161 static size_t
162 BigDecimal_memsize(const void *ptr)
163 {
164 const Real *pv = ptr;
165 return (sizeof(*pv) + pv->MaxPrec * sizeof(BDIGIT));
166 }
167
168 static const rb_data_type_t BigDecimal_data_type = {
169 "BigDecimal",
170 { 0, BigDecimal_delete, BigDecimal_memsize, },
171 #ifdef RUBY_TYPED_FREE_IMMEDIATELY
172 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
173 #endif
174 };
175
176 static inline int
177 is_kind_of_BigDecimal(VALUE const v)
178 {
179 return rb_typeddata_is_kind_of(v, &BigDecimal_data_type);
180 }
181
182 static VALUE
183 ToValue(Real *p)
184 {
185 if (VpIsNaN(p)) {
186 VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'(Not a Number)", 0);
187 }
188 else if (VpIsPosInf(p)) {
189 VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 0);
190 }
191 else if (VpIsNegInf(p)) {
192 VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 0);
193 }
194 return p->obj;
195 }
196
197 NORETURN(static void cannot_be_coerced_into_BigDecimal(VALUE, VALUE));
198
199 static void
200 cannot_be_coerced_into_BigDecimal(VALUE exc_class, VALUE v)
201 {
202 VALUE str;
203
204 if (rb_special_const_p(v)) {
205 str = rb_inspect(v);
206 }
207 else {
208 str = rb_class_name(rb_obj_class(v));
209 }
210
211 str = rb_str_cat2(rb_str_dup(str), " can't be coerced into BigDecimal");
212 rb_exc_raise(rb_exc_new3(exc_class, str));
213 }
214
215 static inline VALUE BigDecimal_div2(VALUE, VALUE, VALUE);
216
217 static Real*
218 GetVpValueWithPrec(VALUE v, long prec, int must)
219 {
220 ENTER(1);
221 Real *pv;
222 VALUE num, bg;
223 char szD[128];
224 VALUE orig = Qundef;
225 double d;
226
227 again:
228 switch(TYPE(v)) {
229 case T_FLOAT:
230 if (prec < 0) goto unable_to_coerce_without_prec;
231 if (prec > DBL_DIG+1) goto SomeOneMayDoIt;
232 d = RFLOAT_VALUE(v);
233 if (!isfinite(d)) {
234 pv = VpCreateRbObject(1, NULL);
235 VpDtoV(pv, d);
236 return pv;
237 }
238 if (d != 0.0) {
239 v = rb_funcall(v, id_to_r, 0);
240 goto again;
241 }
242 if (1/d < 0.0) {
243 return VpCreateRbObject(prec, "-0");
244 }
245 return VpCreateRbObject(prec, "0");
246
247 case T_RATIONAL:
248 if (prec < 0) goto unable_to_coerce_without_prec;
249
250 if (orig == Qundef ? (orig = v, 1) : orig != v) {
251 num = rb_rational_num(v);
252 pv = GetVpValueWithPrec(num, -1, must);
253 if (pv == NULL) goto SomeOneMayDoIt;
254
255 v = BigDecimal_div2(ToValue(pv), rb_rational_den(v), LONG2NUM(prec));
256 goto again;
257 }
258
259 v = orig;
260 goto SomeOneMayDoIt;
261
262 case T_DATA:
263 if (is_kind_of_BigDecimal(v)) {
264 pv = DATA_PTR(v);
265 return pv;
266 }
267 else {
268 goto SomeOneMayDoIt;
269 }
270 break;
271
272 case T_FIXNUM:
273 sprintf(szD, "%ld", FIX2LONG(v));
274 return VpCreateRbObject(VpBaseFig() * 2 + 1, szD);
275
276 #ifdef ENABLE_NUMERIC_STRING
277 case T_STRING:
278 StringValueCStr(v);
279 return VpCreateRbObject(RSTRING_LEN(v) + VpBaseFig() + 1,
280 RSTRING_PTR(v));
281 #endif /* ENABLE_NUMERIC_STRING */
282
283 case T_BIGNUM:
284 bg = rb_big2str(v, 10);
285 PUSH(bg);
286 return VpCreateRbObject(strlen(RSTRING_PTR(bg)) + VpBaseFig() + 1,
287 RSTRING_PTR(bg));
288 default:
289 goto SomeOneMayDoIt;
290 }
291
292 SomeOneMayDoIt:
293 if (must) {
294 cannot_be_coerced_into_BigDecimal(rb_eTypeError, v);
295 }
296 return NULL; /* NULL means to coerce */
297
298 unable_to_coerce_without_prec:
299 if (must) {
300 rb_raise(rb_eArgError,
301 "%"PRIsVALUE" can't be coerced into BigDecimal without a precision",
302 RB_OBJ_CLASSNAME(v));
303 }
304 return NULL;
305 }
306
307 static Real*
308 GetVpValue(VALUE v, int must)
309 {
310 return GetVpValueWithPrec(v, -1, must);
311 }
312
313 /* call-seq:
314 * BigDecimal.double_fig
315 *
316 * The BigDecimal.double_fig class method returns the number of digits a
317 * Float number is allowed to have. The result depends upon the CPU and OS
318 * in use.
319 */
320 static VALUE
321 BigDecimal_double_fig(VALUE self)
322 {
323 return INT2FIX(VpDblFig());
324 }
325
326 /* call-seq:
327 * big_decimal.precs -> array
328 *
329 * Returns an Array of two Integer values.
330 *
331 * The first value is the current number of significant digits in the
332 * BigDecimal. The second value is the maximum number of significant digits
333 * for the BigDecimal.
334 *
335 * BigDecimal('5').precs #=> [9, 18]
336 */
337
338 static VALUE
339 BigDecimal_prec(VALUE self)
340 {
341 ENTER(1);
342 Real *p;
343 VALUE obj;
344
345 GUARD_OBJ(p, GetVpValue(self, 1));
346 obj = rb_assoc_new(INT2NUM(p->Prec*VpBaseFig()),
347 INT2NUM(p->MaxPrec*VpBaseFig()));
348 return obj;
349 }
350
351 /*
352 * call-seq: hash
353 *
354 * Creates a hash for this BigDecimal.
355 *
356 * Two BigDecimals with equal sign,
357 * fractional part and exponent have the same hash.
358 */
359 static VALUE
360 BigDecimal_hash(VALUE self)
361 {
362 ENTER(1);
363 Real *p;
364 st_index_t hash;
365
366 GUARD_OBJ(p, GetVpValue(self, 1));
367 hash = (st_index_t)p->sign;
368 /* hash!=2: the case for 0(1),NaN(0) or +-Infinity(3) is sign itself */
369 if(hash == 2 || hash == (st_index_t)-2) {
370 hash ^= rb_memhash(p->frac, sizeof(BDIGIT)*p->Prec);
371 hash += p->exponent;
372 }
373 return ST2FIX(hash);
374 }
375
376 /*
377 * call-seq: _dump
378 *
379 * Method used to provide marshalling support.
380 *
381 * inf = BigDecimal('Infinity')
382 * #=> Infinity
383 * BigDecimal._load(inf._dump)
384 * #=> Infinity
385 *
386 * See the Marshal module.
387 */
388 static VALUE
389 BigDecimal_dump(int argc, VALUE *argv, VALUE self)
390 {
391 ENTER(5);
392 Real *vp;
393 char *psz;
394 VALUE dummy;
395 volatile VALUE dump;
396
397 rb_scan_args(argc, argv, "01", &dummy);
398 GUARD_OBJ(vp,GetVpValue(self, 1));
399 dump = rb_str_new(0, VpNumOfChars(vp, "E")+50);
400 psz = RSTRING_PTR(dump);
401 sprintf(psz, "%"PRIuSIZE":", VpMaxPrec(vp)*VpBaseFig());
402 VpToString(vp, psz+strlen(psz), 0, 0);
403 rb_str_resize(dump, strlen(psz));
404 return dump;
405 }
406
407 /*
408 * Internal method used to provide marshalling support. See the Marshal module.
409 */
410 static VALUE
411 BigDecimal_load(VALUE self, VALUE str)
412 {
413 ENTER(2);
414 Real *pv;
415 unsigned char *pch;
416 unsigned char ch;
417 unsigned long m=0;
418
419 pch = (unsigned char *)StringValueCStr(str);
420 /* First get max prec */
421 while((*pch) != (unsigned char)'\0' && (ch = *pch++) != (unsigned char)':') {
422 if(!ISDIGIT(ch)) {
423 rb_raise(rb_eTypeError, "load failed: invalid character in the marshaled string");
424 }
425 m = m*10 + (unsigned long)(ch-'0');
426 }
427 if (m > VpBaseFig()) m -= VpBaseFig();
428 GUARD_OBJ(pv, VpNewRbClass(m, (char *)pch, self));
429 m /= VpBaseFig();
430 if (m && pv->MaxPrec > m) {
431 pv->MaxPrec = m+1;
432 }
433 return ToValue(pv);
434 }
435
436 static unsigned short
437 check_rounding_mode_option(VALUE const opts)
438 {
439 VALUE mode;
440 char const *s;
441 long l;
442
443 assert(RB_TYPE_P(opts, T_HASH));
444
445 if (NIL_P(opts))
446 goto noopt;
447
448 mode = rb_hash_lookup2(opts, ID2SYM(id_half), Qundef);
449 if (mode == Qundef || NIL_P(mode))
450 goto noopt;
451
452 if (SYMBOL_P(mode))
453 mode = rb_sym2str(mode);
454 else if (!RB_TYPE_P(mode, T_STRING)) {
455 VALUE str_mode = rb_check_string_type(mode);
456 if (NIL_P(str_mode)) goto invalid;
457 mode = str_mode;
458 }
459 s = RSTRING_PTR(mode);
460 l = RSTRING_LEN(mode);
461 switch (l) {
462 case 2:
463 if (strncasecmp(s, "up", 2) == 0)
464 return VP_ROUND_HALF_UP;
465 break;
466 case 4:
467 if (strncasecmp(s, "even", 4) == 0)
468 return VP_ROUND_HALF_EVEN;
469 else if (strncasecmp(s, "down", 4) == 0)
470 return VP_ROUND_HALF_DOWN;
471 break;
472 default:
473 break;
474 }
475 invalid:
476 if (NIL_P(mode))
477 rb_raise(rb_eArgError, "invalid rounding mode: nil");
478 else
479 rb_raise(rb_eArgError, "invalid rounding mode: %"PRIsVALUE, mode);
480
481 noopt:
482 return VpGetRoundMode();
483 }
484
485 static unsigned short
486 check_rounding_mode(VALUE const v)
487 {
488 unsigned short sw;
489 ID id;
490 switch (TYPE(v)) {
491 case T_SYMBOL:
492 id = SYM2ID(v);
493 if (id == id_up)
494 return VP_ROUND_UP;
495 if (id == id_down || id == id_truncate)
496 return VP_ROUND_DOWN;
497 if (id == id_half_up || id == id_default)
498 return VP_ROUND_HALF_UP;
499 if (id == id_half_down)
500 return VP_ROUND_HALF_DOWN;
501 if (id == id_half_even || id == id_banker)
502 return VP_ROUND_HALF_EVEN;
503 if (id == id_ceiling || id == id_ceil)
504 return VP_ROUND_CEIL;
505 if (id == id_floor)
506 return VP_ROUND_FLOOR;
507 rb_raise(rb_eArgError, "invalid rounding mode");
508
509 default:
510 break;
511 }
512
513 sw = NUM2USHORT(v);
514 if (!VpIsRoundMode(sw)) {
515 rb_raise(rb_eArgError, "invalid rounding mode");
516 }
517 return sw;
518 }
519
520 /* call-seq:
521 * BigDecimal.mode(mode, value)
522 *
523 * Controls handling of arithmetic exceptions and rounding. If no value
524 * is supplied, the current value is returned.
525 *
526 * Six values of the mode parameter control the handling of arithmetic
527 * exceptions:
528 *
529 * BigDecimal::EXCEPTION_NaN
530 * BigDecimal::EXCEPTION_INFINITY
531 * BigDecimal::EXCEPTION_UNDERFLOW
532 * BigDecimal::EXCEPTION_OVERFLOW
533 * BigDecimal::EXCEPTION_ZERODIVIDE
534 * BigDecimal::EXCEPTION_ALL
535 *
536 * For each mode parameter above, if the value set is false, computation
537 * continues after an arithmetic exception of the appropriate type.
538 * When computation continues, results are as follows:
539 *
540 * EXCEPTION_NaN:: NaN
541 * EXCEPTION_INFINITY:: +Infinity or -Infinity
542 * EXCEPTION_UNDERFLOW:: 0
543 * EXCEPTION_OVERFLOW:: +Infinity or -Infinity
544 * EXCEPTION_ZERODIVIDE:: +Infinity or -Infinity
545 *
546 * One value of the mode parameter controls the rounding of numeric values:
547 * BigDecimal::ROUND_MODE. The values it can take are:
548 *
549 * ROUND_UP, :up:: round away from zero
550 * ROUND_DOWN, :down, :truncate:: round towards zero (truncate)
551 * ROUND_HALF_UP, :half_up, :default:: round towards the nearest neighbor, unless both neighbors are equidistant, in which case round away from zero. (default)
552 * ROUND_HALF_DOWN, :half_down:: round towards the nearest neighbor, unless both neighbors are equidistant, in which case round towards zero.
553 * ROUND_HALF_EVEN, :half_even, :banker:: round towards the nearest neighbor, unless both neighbors are equidistant, in which case round towards the even neighbor (Banker's rounding)
554 * ROUND_CEILING, :ceiling, :ceil:: round towards positive infinity (ceil)
555 * ROUND_FLOOR, :floor:: round towards negative infinity (floor)
556 *
557 */
558 static VALUE
559 BigDecimal_mode(int argc, VALUE *argv, VALUE self)
560 {
561 VALUE which;
562 VALUE val;
563 unsigned long f,fo;
564
565 rb_scan_args(argc, argv, "11", &which, &val);
566 f = (unsigned long)NUM2INT(which);
567
568 if (f & VP_EXCEPTION_ALL) {
569 /* Exception mode setting */
570 fo = VpGetException();
571 if (val == Qnil) return INT2FIX(fo);
572 if (val != Qfalse && val!=Qtrue) {
573 rb_raise(rb_eArgError, "second argument must be true or false");
574 return Qnil; /* Not reached */
575 }
576 if (f & VP_EXCEPTION_INFINITY) {
577 VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_INFINITY) :
578 (fo & (~VP_EXCEPTION_INFINITY))));
579 }
580 fo = VpGetException();
581 if (f & VP_EXCEPTION_NaN) {
582 VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_NaN) :
583 (fo & (~VP_EXCEPTION_NaN))));
584 }
585 fo = VpGetException();
586 if (f & VP_EXCEPTION_UNDERFLOW) {
587 VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_UNDERFLOW) :
588 (fo & (~VP_EXCEPTION_UNDERFLOW))));
589 }
590 fo = VpGetException();
591 if(f & VP_EXCEPTION_ZERODIVIDE) {
592 VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_ZERODIVIDE) :
593 (fo & (~VP_EXCEPTION_ZERODIVIDE))));
594 }
595 fo = VpGetException();
596 return INT2FIX(fo);
597 }
598 if (VP_ROUND_MODE == f) {
599 /* Rounding mode setting */
600 unsigned short sw;
601 fo = VpGetRoundMode();
602 if (NIL_P(val)) return INT2FIX(fo);
603 sw = check_rounding_mode(val);
604 fo = VpSetRoundMode(sw);
605 return INT2FIX(fo);
606 }
607 rb_raise(rb_eTypeError, "first argument for BigDecimal.mode invalid");
608 return Qnil;
609 }
610
611 static size_t
612 GetAddSubPrec(Real *a, Real *b)
613 {
614 size_t mxs;
615 size_t mx = a->Prec;
616 SIGNED_VALUE d;
617
618 if (!VpIsDef(a) || !VpIsDef(b)) return (size_t)-1L;
619 if (mx < b->Prec) mx = b->Prec;
620 if (a->exponent != b->exponent) {
621 mxs = mx;
622 d = a->exponent - b->exponent;
623 if (d < 0) d = -d;
624 mx = mx + (size_t)d;
625 if (mx < mxs) {
626 return VpException(VP_EXCEPTION_INFINITY, "Exponent overflow", 0);
627 }
628 }
629 return mx;
630 }
631
632 static SIGNED_VALUE
633 GetPrecisionInt(VALUE v)
634 {
635 SIGNED_VALUE n;
636 n = NUM2INT(v);
637 if (n < 0) {
638 rb_raise(rb_eArgError, "negative precision");
639 }
640 return n;
641 }
642
643 VP_EXPORT Real *
644 VpNewRbClass(size_t mx, const char *str, VALUE klass)
645 {
646 VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
647 Real *pv = VpAlloc(mx, str, 1, 1);
648 RTYPEDDATA_DATA(obj) = pv;
649 pv->obj = obj;
650 RB_OBJ_FREEZE(obj);
651 return pv;
652 }
653
654 VP_EXPORT Real *
655 VpCreateRbObject(size_t mx, const char *str)
656 {
657 return VpNewRbClass(mx, str, rb_cBigDecimal);
658 }
659
660 #define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(BDIGIT))
661 #define VpReallocReal(ptr, prec) (Real *)VpMemRealloc((ptr), offsetof(Real, frac) + (prec) * sizeof(BDIGIT))
662
663 static Real *
664 VpCopy(Real *pv, Real const* const x)
665 {
666 assert(x != NULL);
667
668 pv = VpReallocReal(pv, x->MaxPrec);
669 pv->MaxPrec = x->MaxPrec;
670 pv->Prec = x->Prec;
671 pv->exponent = x->exponent;
672 pv->sign = x->sign;
673 pv->flag = x->flag;
674 MEMCPY(pv->frac, x->frac, BDIGIT, pv->MaxPrec);
675
676 return pv;
677 }
678
679 /* Returns True if the value is Not a Number. */
680 static VALUE
681 BigDecimal_IsNaN(VALUE self)
682 {
683 Real *p = GetVpValue(self, 1);
684 if (VpIsNaN(p)) return Qtrue;
685 return Qfalse;
686 }
687
688 /* Returns nil, -1, or +1 depending on whether the value is finite,
689 * -Infinity, or +Infinity.
690 */
691 static VALUE
692 BigDecimal_IsInfinite(VALUE self)
693 {
694 Real *p = GetVpValue(self, 1);
695 if (VpIsPosInf(p)) return INT2FIX(1);
696 if (VpIsNegInf(p)) return INT2FIX(-1);
697 return Qnil;
698 }
699
700 /* Returns True if the value is finite (not NaN or infinite). */
701 static VALUE
702 BigDecimal_IsFinite(VALUE self)
703 {
704 Real *p = GetVpValue(self, 1);
705 if (VpIsNaN(p)) return Qfalse;
706 if (VpIsInf(p)) return Qfalse;
707 return Qtrue;
708 }
709
710 static void
711 BigDecimal_check_num(Real *p)
712 {
713 if (VpIsNaN(p)) {
714 VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'(Not a Number)", 1);
715 }
716 else if (VpIsPosInf(p)) {
717 VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 1);
718 }
719 else if (VpIsNegInf(p)) {
720 VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 1);
721 }
722 }
723
724 static VALUE BigDecimal_split(VALUE self);
725
726 /* Returns the value as an Integer.
727 *
728 * If the BigDecimal is infinity or NaN, raises FloatDomainError.
729 */
730 static VALUE
731 BigDecimal_to_i(VALUE self)
732 {
733 ENTER(5);
734 ssize_t e, nf;
735 Real *p;
736
737 GUARD_OBJ(p, GetVpValue(self, 1));
738 BigDecimal_check_num(p);
739
740 e = VpExponent10(p);
741 if (e <= 0) return INT2FIX(0);
742 nf = VpBaseFig();
743 if (e <= nf) {
744 return LONG2NUM((long)(VpGetSign(p) * (BDIGIT_DBL_SIGNED)p->frac[0]));
745 }
746 else {
747 VALUE a = BigDecimal_split(self);
748 VALUE digits = RARRAY_AREF(a, 1);
749 VALUE numerator = rb_funcall(digits, rb_intern("to_i"), 0);
750 VALUE ret;
751 ssize_t dpower = e - (ssize_t)RSTRING_LEN(digits);
752
753 if (BIGDECIMAL_NEGATIVE_P(p)) {
754 numerator = rb_funcall(numerator, '*', 1, INT2FIX(-1));
755 }
756 if (dpower < 0) {
757 ret = rb_funcall(numerator, rb_intern("div"), 1,
758 rb_funcall(INT2FIX(10), rb_intern("**"), 1,
759 INT2FIX(-dpower)));
760 }
761 else {
762 ret = rb_funcall(numerator, '*', 1,
763 rb_funcall(INT2FIX(10), rb_intern("**"), 1,
764 INT2FIX(dpower)));
765 }
766 if (RB_TYPE_P(ret, T_FLOAT)) {
767 rb_raise(rb_eFloatDomainError, "Infinity");
768 }
769 return ret;
770 }
771 }
772
773 /* Returns a new Float object having approximately the same value as the
774 * BigDecimal number. Normal accuracy limits and built-in errors of binary
775 * Float arithmetic apply.
776 */
777 static VALUE
778 BigDecimal_to_f(VALUE self)
779 {
780 ENTER(1);
781 Real *p;
782 double d;
783 SIGNED_VALUE e;
784 char *buf;
785 volatile VALUE str;
786
787 GUARD_OBJ(p, GetVpValue(self, 1));
788 if (VpVtoD(&d, &e, p) != 1)
789 return rb_float_new(d);
790 if (e > (SIGNED_VALUE)(DBL_MAX_10_EXP+BASE_FIG))
791 goto overflow;
792 if (e < (SIGNED_VALUE)(DBL_MIN_10_EXP-BASE_FIG))
793 goto underflow;
794
795 str = rb_str_new(0, VpNumOfChars(p, "E"));
796 buf = RSTRING_PTR(str);
797 VpToString(p, buf, 0, 0);
798 errno = 0;
799 d = strtod(buf, 0);
800 if (errno == ERANGE) {
801 if (d == 0.0) goto underflow;
802 if (fabs(d) >= HUGE_VAL) goto overflow;
803 }
804 return rb_float_new(d);
805
806 overflow:
807 VpException(VP_EXCEPTION_OVERFLOW, "BigDecimal to Float conversion", 0);
808 if (BIGDECIMAL_NEGATIVE_P(p))
809 return rb_float_new(VpGetDoubleNegInf());
810 else
811 return rb_float_new(VpGetDoublePosInf());
812
813 underflow:
814 VpException(VP_EXCEPTION_UNDERFLOW, "BigDecimal to Float conversion", 0);
815 if (BIGDECIMAL_NEGATIVE_P(p))
816 return rb_float_new(-0.0);
817 else
818 return rb_float_new(0.0);
819 }
820
821
822 /* Converts a BigDecimal to a Rational.
823 */
824 static VALUE
825 BigDecimal_to_r(VALUE self)
826 {
827 Real *p;
828 ssize_t sign, power, denomi_power;
829 VALUE a, digits, numerator;
830
831 p = GetVpValue(self, 1);
832 BigDecimal_check_num(p);
833
834 sign = VpGetSign(p);
835 power = VpExponent10(p);
836 a = BigDecimal_split(self);
837 digits = RARRAY_AREF(a, 1);
838 denomi_power = power - RSTRING_LEN(digits);
839 numerator = rb_funcall(digits, rb_intern("to_i"), 0);
840
841 if (sign < 0) {
842 numerator = rb_funcall(numerator, '*', 1, INT2FIX(-1));
843 }
844 if (denomi_power < 0) {
845 return rb_Rational(numerator,
846 rb_funcall(INT2FIX(10), rb_intern("**"), 1,
847 INT2FIX(-denomi_power)));
848 }
849 else {
850 return rb_Rational1(rb_funcall(numerator, '*', 1,
851 rb_funcall(INT2FIX(10), rb_intern("**"), 1,
852 INT2FIX(denomi_power))));
853 }
854 }
855
856 /* The coerce method provides support for Ruby type coercion. It is not
857 * enabled by default.
858 *
859 * This means that binary operations like + * / or - can often be performed
860 * on a BigDecimal and an object of another type, if the other object can
861 * be coerced into a BigDecimal value.
862 *
863 * e.g.
864 * a = BigDecimal("1.0")
865 * b = a / 2.0 #=> 0.5
866 *
867 * Note that coercing a String to a BigDecimal is not supported by default;
868 * it requires a special compile-time option when building Ruby.
869 */
870 static VALUE
871 BigDecimal_coerce(VALUE self, VALUE other)
872 {
873 ENTER(2);
874 VALUE obj;
875 Real *b;
876
877 if (RB_TYPE_P(other, T_FLOAT)) {
878 GUARD_OBJ(b, GetVpValueWithPrec(other, DBL_DIG+1, 1));
879 obj = rb_assoc_new(ToValue(b), self);
880 }
881 else {
882 if (RB_TYPE_P(other, T_RATIONAL)) {
883 Real* pv = DATA_PTR(self);
884 GUARD_OBJ(b, GetVpValueWithPrec(other, pv->Prec*VpBaseFig(), 1));
885 }
886 else {
887 GUARD_OBJ(b, GetVpValue(other, 1));
888 }
889 obj = rb_assoc_new(b->obj, self);
890 }
891
892 return obj;
893 }
894
895 /*
896 * call-seq:
897 * +big_decimal -> big_decimal
898 *
899 * Return self.
900 *
901 * +BigDecimal('5') #=> 0.5e1
902 */
903
904 static VALUE
905 BigDecimal_uplus(VALUE self)
906 {
907 return self;
908 }
909
910 /*
911 * Document-method: BigDecimal#add
912 * Document-method: BigDecimal#+
913 *
914 * call-seq:
915 * add(value, digits)
916 *
917 * Add the specified value.
918 *
919 * e.g.
920 * c = a.add(b,n)
921 * c = a + b
922 *
923 * digits:: If specified and less than the number of significant digits of the
924 * result, the result is rounded to that number of digits, according
925 * to BigDecimal.mode.
926 */
927 static VALUE
928 BigDecimal_add(VALUE self, VALUE r)
929 {
930 ENTER(5);
931 Real *c, *a, *b;
932 size_t mx;
933
934 GUARD_OBJ(a, GetVpValue(self, 1));
935 if (RB_TYPE_P(r, T_FLOAT)) {
936 b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
937 }
938 else if (RB_TYPE_P(r, T_RATIONAL)) {
939 b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
940 }
941 else {
942 b = GetVpValue(r, 0);
943 }
944
945 if (!b) return DoSomeOne(self,r,'+');
946 SAVE(b);
947
948 if (VpIsNaN(b)) return b->obj;
949 if (VpIsNaN(a)) return a->obj;
950
951 mx = GetAddSubPrec(a, b);
952 if (mx == (size_t)-1L) {
953 GUARD_OBJ(c,VpCreateRbObject(VpBaseFig() + 1, "0"));
954 VpAddSub(c, a, b, 1);
955 }
956 else {
957 GUARD_OBJ(c, VpCreateRbObject(mx * (VpBaseFig() + 1), "0"));
958 if(!mx) {
959 VpSetInf(c, VpGetSign(a));
960 }
961 else {
962 VpAddSub(c, a, b, 1);
963 }
964 }
965 return ToValue(c);
966 }
967
968 /* call-seq:
969 * a - b -> bigdecimal
970 *
971 * Subtract the specified value.
972 *
973 * e.g.
974 * c = a - b
975 *
976 * The precision of the result value depends on the type of +b+.
977 *
978 * If +b+ is a Float, the precision of the result is Float::DIG+1.
979 *
980 * If +b+ is a BigDecimal, the precision of the result is +b+'s precision of
981 * internal representation from platform. So, it's return value is platform
982 * dependent.
983 *
984 */
985 static VALUE
986 BigDecimal_sub(VALUE self, VALUE r)
987 {
988 ENTER(5);
989 Real *c, *a, *b;
990 size_t mx;
991
992 GUARD_OBJ(a, GetVpValue(self,1));
993 if (RB_TYPE_P(r, T_FLOAT)) {
994 b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
995 }
996 else if (RB_TYPE_P(r, T_RATIONAL)) {
997 b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
998 }
999 else {
1000 b = GetVpValue(r,0);
1001 }
1002
1003 if (!b) return DoSomeOne(self,r,'-');
1004 SAVE(b);
1005
1006 if (VpIsNaN(b)) return b->obj;
1007 if (VpIsNaN(a)) return a->obj;
1008
1009 mx = GetAddSubPrec(a,b);
1010 if (mx == (size_t)-1L) {
1011 GUARD_OBJ(c,VpCreateRbObject(VpBaseFig() + 1, "0"));
1012 VpAddSub(c, a, b, -1);
1013 }
1014 else {
1015 GUARD_OBJ(c,VpCreateRbObject(mx *(VpBaseFig() + 1), "0"));
1016 if (!mx) {
1017 VpSetInf(c,VpGetSign(a));
1018 }
1019 else {
1020 VpAddSub(c, a, b, -1);
1021 }
1022 }
1023 return ToValue(c);
1024 }
1025
1026 static VALUE
1027 BigDecimalCmp(VALUE self, VALUE r,char op)
1028 {
1029 ENTER(5);
1030 SIGNED_VALUE e;
1031 Real *a, *b=0;
1032 GUARD_OBJ(a, GetVpValue(self, 1));
1033 switch (TYPE(r)) {
1034 case T_DATA:
1035 if (!is_kind_of_BigDecimal(r)) break;
1036 /* fall through */
1037 case T_FIXNUM:
1038 /* fall through */
1039 case T_BIGNUM:
1040 GUARD_OBJ(b, GetVpValue(r, 0));
1041 break;
1042
1043 case T_FLOAT:
1044 GUARD_OBJ(b, GetVpValueWithPrec(r, DBL_DIG+1, 0));
1045 break;
1046
1047 case T_RATIONAL:
1048 GUARD_OBJ(b, GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 0));
1049 break;
1050
1051 default:
1052 break;
1053 }
1054 if (b == NULL) {
1055 ID f = 0;
1056
1057 switch (op) {
1058 case '*':
1059 return rb_num_coerce_cmp(self, r, rb_intern("<=>"));
1060
1061 case '=':
1062 return RTEST(rb_num_coerce_cmp(self, r, rb_intern("=="))) ? Qtrue : Qfalse;
1063
1064 case 'G':
1065 f = rb_intern(">=");
1066 break;
1067
1068 case 'L':
1069 f = rb_intern("<=");
1070 break;
1071
1072 case '>':
1073 /* fall through */
1074 case '<':
1075 f = (ID)op;
1076 break;
1077
1078 default:
1079 break;
1080 }
1081 return rb_num_coerce_relop(self, r, f);
1082 }
1083 SAVE(b);
1084 e = VpComp(a, b);
1085 if (e == 999)
1086 return (op == '*') ? Qnil : Qfalse;
1087 switch (op) {
1088 case '*':
1089 return INT2FIX(e); /* any op */
1090
1091 case '=':
1092 if (e == 0) return Qtrue;
1093 return Qfalse;
1094
1095 case 'G':
1096 if (e >= 0) return Qtrue;
1097 return Qfalse;
1098
1099 case '>':
1100 if (e > 0) return Qtrue;
1101 return Qfalse;
1102
1103 case 'L':
1104 if (e <= 0) return Qtrue;
1105 return Qfalse;
1106
1107 case '<':
1108 if (e < 0) return Qtrue;
1109 return Qfalse;
1110
1111 default:
1112 break;
1113 }
1114
1115 rb_bug("Undefined operation in BigDecimalCmp()");
1116
1117 UNREACHABLE;
1118 }
1119
1120 /* Returns True if the value is zero. */
1121 static VALUE
1122 BigDecimal_zero(VALUE self)
1123 {
1124 Real *a = GetVpValue(self, 1);
1125 return VpIsZero(a) ? Qtrue : Qfalse;
1126 }
1127
1128 /* Returns self if the value is non-zero, nil otherwise. */
1129 static VALUE
1130 BigDecimal_nonzero(VALUE self)
1131 {
1132 Real *a = GetVpValue(self, 1);
1133 return VpIsZero(a) ? Qnil : self;
1134 }
1135
1136 /* The comparison operator.
1137 * a <=> b is 0 if a == b, 1 if a > b, -1 if a < b.
1138 */
1139 static VALUE
1140 BigDecimal_comp(VALUE self, VALUE r)
1141 {
1142 return BigDecimalCmp(self, r, '*');
1143 }
1144
1145 /*
1146 * Tests for value equality; returns true if the values are equal.
1147 *
1148 * The == and === operators and the eql? method have the same implementation
1149 * for BigDecimal.
1150 *
1151 * Values may be coerced to perform the comparison:
1152 *
1153 * BigDecimal('1.0') == 1.0 #=> true
1154 */
1155 static VALUE
1156 BigDecimal_eq(VALUE self, VALUE r)
1157 {
1158 return BigDecimalCmp(self, r, '=');
1159 }
1160
1161 /* call-seq:
1162 * a < b
1163 *
1164 * Returns true if a is less than b.
1165 *
1166 * Values may be coerced to perform the comparison (see ==, BigDecimal#coerce).
1167 */
1168 static VALUE
1169 BigDecimal_lt(VALUE self, VALUE r)
1170 {
1171 return BigDecimalCmp(self, r, '<');
1172 }
1173
1174 /* call-seq:
1175 * a <= b
1176 *
1177 * Returns true if a is less than or equal to b.
1178 *
1179 * Values may be coerced to perform the comparison (see ==, BigDecimal#coerce).
1180 */
1181 static VALUE
1182 BigDecimal_le(VALUE self, VALUE r)
1183 {
1184 return BigDecimalCmp(self, r, 'L');
1185 }
1186
1187 /* call-seq:
1188 * a > b
1189 *
1190 * Returns true if a is greater than b.
1191 *
1192 * Values may be coerced to perform the comparison (see ==, BigDecimal#coerce).
1193 */
1194 static VALUE
1195 BigDecimal_gt(VALUE self, VALUE r)
1196 {
1197 return BigDecimalCmp(self, r, '>');
1198 }
1199
1200 /* call-seq:
1201 * a >= b
1202 *
1203 * Returns true if a is greater than or equal to b.
1204 *
1205 * Values may be coerced to perform the comparison (see ==, BigDecimal#coerce)
1206 */
1207 static VALUE
1208 BigDecimal_ge(VALUE self, VALUE r)
1209 {
1210 return BigDecimalCmp(self, r, 'G');
1211 }
1212
1213 /*
1214 * call-seq:
1215 * -big_decimal -> big_decimal
1216 *
1217 * Return the negation of self.
1218 *
1219 * -BigDecimal('5') #=> -0.5e1
1220 */
1221
1222 static VALUE
1223 BigDecimal_neg(VALUE self)
1224 {
1225 ENTER(5);
1226 Real *c, *a;
1227 GUARD_OBJ(a, GetVpValue(self, 1));
1228 GUARD_OBJ(c, VpCreateRbObject(a->Prec *(VpBaseFig() + 1), "0"));
1229 VpAsgn(c, a, -1);
1230 return ToValue(c);
1231 }
1232
1233 /*
1234 * Document-method: BigDecimal#mult
1235 *
1236 * call-seq: mult(value, digits)
1237 *
1238 * Multiply by the specified value.
1239 *
1240 * e.g.
1241 * c = a.mult(b,n)
1242 * c = a * b
1243 *
1244 * digits:: If specified and less than the number of significant digits of the
1245 * result, the result is rounded to that number of digits, according
1246 * to BigDecimal.mode.
1247 */
1248 static VALUE
1249 BigDecimal_mult(VALUE self, VALUE r)
1250 {
1251 ENTER(5);
1252 Real *c, *a, *b;
1253 size_t mx;
1254
1255 GUARD_OBJ(a, GetVpValue(self, 1));
1256 if (RB_TYPE_P(r, T_FLOAT)) {
1257 b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
1258 }
1259 else if (RB_TYPE_P(r, T_RATIONAL)) {
1260 b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
1261 }
1262 else {
1263 b = GetVpValue(r,0);
1264 }
1265
1266 if (!b) return DoSomeOne(self, r, '*');
1267 SAVE(b);
1268
1269 mx = a->Prec + b->Prec;
1270 GUARD_OBJ(c, VpCreateRbObject(mx *(VpBaseFig() + 1), "0"));
1271 VpMult(c, a, b);
1272 return ToValue(c);
1273 }
1274
1275 static VALUE
1276 BigDecimal_divide(Real **c, Real **res, Real **div, VALUE self, VALUE r)
1277 /* For c = self.div(r): with round operation */
1278 {
1279 ENTER(5);
1280 Real *a, *b;
1281 size_t mx;
1282
1283 GUARD_OBJ(a, GetVpValue(self, 1));
1284 if (RB_TYPE_P(r, T_FLOAT)) {
1285 b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
1286 }
1287 else if (RB_TYPE_P(r, T_RATIONAL)) {
1288 b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
1289 }
1290 else {
1291 b = GetVpValue(r, 0);
1292 }
1293
1294 if (!b) return DoSomeOne(self, r, '/');
1295 SAVE(b);
1296
1297 *div = b;
1298 mx = a->Prec + vabs(a->exponent);
1299 if (mx < b->Prec + vabs(b->exponent)) mx = b->Prec + vabs(b->exponent);
1300 mx++; /* NOTE: An additional digit is needed for the compatibility to
1301 the version 1.2.1 and the former. */
1302 mx = (mx + 1) * VpBaseFig();
1303 GUARD_OBJ((*c), VpCreateRbObject(mx, "#0"));
1304 GUARD_OBJ((*res), VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0"));
1305 VpDivd(*c, *res, a, b);
1306 return Qnil;
1307 }
1308
1309 /* call-seq:
1310 * a / b -> bigdecimal
1311 * quo(value) -> bigdecimal
1312 *
1313 * Divide by the specified value.
1314 *
1315 * See BigDecimal#div.
1316 */
1317 static VALUE
1318 BigDecimal_div(VALUE self, VALUE r)
1319 /* For c = self/r: with round operation */
1320 {
1321 ENTER(5);
1322 Real *c=NULL, *res=NULL, *div = NULL;
1323 r = BigDecimal_divide(&c, &res, &div, self, r);
1324 if (!NIL_P(r)) return r; /* coerced by other */
1325 SAVE(c); SAVE(res); SAVE(div);
1326 /* a/b = c + r/b */
1327 /* c xxxxx
1328 r 00000yyyyy ==> (y/b)*BASE >= HALF_BASE
1329 */
1330 /* Round */
1331 if (VpHasVal(div)) { /* frac[0] must be zero for NaN,INF,Zero */
1332 VpInternalRound(c, 0, c->frac[c->Prec-1], (BDIGIT)(VpBaseVal() * (BDIGIT_DBL)res->frac[0] / div->frac[0]));
1333 }
1334 return ToValue(c);
1335 }
1336
1337 /*
1338 * %: mod = a%b = a - (a.to_f/b).floor * b
1339 * div = (a.to_f/b).floor
1340 */
1341 static VALUE
1342 BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
1343 {
1344 ENTER(8);
1345 Real *c=NULL, *d=NULL, *res=NULL;
1346 Real *a, *b;
1347 size_t mx;
1348
1349 GUARD_OBJ(a, GetVpValue(self, 1));
1350 if (RB_TYPE_P(r, T_FLOAT)) {
1351 b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
1352 }
1353 else if (RB_TYPE_P(r, T_RATIONAL)) {
1354 b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
1355 }
1356 else {
1357 b = GetVpValue(r, 0);
1358 }
1359
1360 if (!b) return Qfalse;
1361 SAVE(b);
1362
1363 if (VpIsNaN(a) || VpIsNaN(b)) goto NaN;
1364 if (VpIsInf(a) && VpIsInf(b)) goto NaN;
1365 if (VpIsZero(b)) {
1366 rb_raise(rb_eZeroDivError, "divided by 0");
1367 }
1368 if (VpIsInf(a)) {
1369 GUARD_OBJ(d, VpCreateRbObject(1, "0"));
1370 VpSetInf(d, (SIGNED_VALUE)(VpGetSign(a) == VpGetSign(b) ? 1 : -1));
1371 GUARD_OBJ(c, VpCreateRbObject(1, "NaN"));
1372 *div = d;
1373 *mod = c;
1374 return Qtrue;
1375 }
1376 if (VpIsInf(b)) {
1377 GUARD_OBJ(d, VpCreateRbObject(1, "0"));
1378 *div = d;
1379 *mod = a;
1380 return Qtrue;
1381 }
1382 if (VpIsZero(a)) {
1383 GUARD_OBJ(c, VpCreateRbObject(1, "0"));
1384 GUARD_OBJ(d, VpCreateRbObject(1, "0"));
1385 *div = d;
1386 *mod = c;
1387 return Qtrue;
1388 }
1389
1390 mx = a->Prec + vabs(a->exponent);
1391 if (mx<b->Prec + vabs(b->exponent)) mx = b->Prec + vabs(b->exponent);
1392 mx = (mx + 1) * VpBaseFig();
1393 GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
1394 GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0"));
1395 VpDivd(c, res, a, b);
1396 mx = c->Prec * (VpBaseFig() + 1);
1397 GUARD_OBJ(d, VpCreateRbObject(mx, "0"));
1398 VpActiveRound(d, c, VP_ROUND_DOWN, 0);
1399 VpMult(res, d, b);
1400 VpAddSub(c, a, res, -1);
1401 if (!VpIsZero(c) && (VpGetSign(a) * VpGetSign(b) < 0)) {
1402 VpAddSub(res, d, VpOne(), -1);
1403 GUARD_OBJ(d, VpCreateRbObject(GetAddSubPrec(c, b)*(VpBaseFig() + 1), "0"));
1404 VpAddSub(d, c, b, 1);
1405 *div = res;
1406 *mod = d;
1407 } else {
1408 *div = d;
1409 *mod = c;
1410 }
1411 return Qtrue;
1412
1413 NaN:
1414 GUARD_OBJ(c, VpCreateRbObject(1, "NaN"));
1415 GUARD_OBJ(d, VpCreateRbObject(1, "NaN"));
1416 *div = d;
1417 *mod = c;
1418 return Qtrue;
1419 }
1420
1421 /* call-seq:
1422 * a % b
1423 * a.modulo(b)
1424 *
1425 * Returns the modulus from dividing by b.
1426 *
1427 * See BigDecimal#divmod.
1428 */
1429 static VALUE
1430 BigDecimal_mod(VALUE self, VALUE r) /* %: a%b = a - (a.to_f/b).floor * b */
1431 {
1432 ENTER(3);
1433 Real *div = NULL, *mod = NULL;
1434
1435 if (BigDecimal_DoDivmod(self, r, &div, &mod)) {
1436 SAVE(div); SAVE(mod);
1437 return ToValue(mod);
1438 }
1439 return DoSomeOne(self, r, '%');
1440 }
1441
1442 static VALUE
1443 BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
1444 {
1445 ENTER(10);
1446 size_t mx;
1447 Real *a = NULL, *b = NULL, *c = NULL, *res = NULL, *d = NULL, *rr = NULL, *ff = NULL;
1448 Real *f = NULL;
1449
1450 GUARD_OBJ(a, GetVpValue(self, 1));
1451 if (RB_TYPE_P(r, T_FLOAT)) {
1452 b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
1453 }
1454 else if (RB_TYPE_P(r, T_RATIONAL)) {
1455 b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
1456 }
1457 else {
1458 b = GetVpValue(r, 0);
1459 }
1460
1461 if (!b) return DoSomeOne(self, r, rb_intern("remainder"));
1462 SAVE(b);
1463
1464 mx = (a->MaxPrec + b->MaxPrec) *VpBaseFig();
1465 GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
1466 GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0"));
1467 GUARD_OBJ(rr, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0"));
1468 GUARD_OBJ(ff, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0"));
1469
1470 VpDivd(c, res, a, b);
1471
1472 mx = c->Prec *(VpBaseFig() + 1);
1473
1474 GUARD_OBJ(d, VpCreateRbObject(mx, "0"));
1475 GUARD_OBJ(f, VpCreateRbObject(mx, "0"));
1476
1477 VpActiveRound(d, c, VP_ROUND_DOWN, 0); /* 0: round off */
1478
1479 VpFrac(f, c);
1480 VpMult(rr, f, b);
1481 VpAddSub(ff, res, rr, 1);
1482
1483 *dv = d;
1484 *rv = ff;
1485 return Qnil;
1486 }
1487
1488 /* call-seq:
1489 * remainder(value)
1490 *
1491 * Returns the remainder from dividing by the value.
1492 *
1493 * x.remainder(y) means x-y*(x/y).truncate
1494 */
1495 static VALUE
1496 BigDecimal_remainder(VALUE self, VALUE r) /* remainder */
1497 {
1498 VALUE f;
1499 Real *d, *rv = 0;
1500 f = BigDecimal_divremain(self, r, &d, &rv);
1501 if (!NIL_P(f)) return f;
1502 return ToValue(rv);
1503 }
1504
1505 /* call-seq:
1506 * divmod(value)
1507 *
1508 * Divides by the specified value, and returns the quotient and modulus
1509 * as BigDecimal numbers. The quotient is rounded towards negative infinity.
1510 *
1511 * For example:
1512 *
1513 * require 'bigdecimal'
1514 *
1515 * a = BigDecimal("42")
1516 * b = BigDecimal("9")
1517 *
1518 * q, m = a.divmod(b)
1519 *
1520 * c = q * b + m
1521 *
1522 * a == c #=> true
1523 *
1524 * The quotient q is (a/b).floor, and the modulus is the amount that must be
1525 * added to q * b to get a.
1526 */
1527 static VALUE
1528 BigDecimal_divmod(VALUE self, VALUE r)
1529 {
1530 ENTER(5);
1531 Real *div = NULL, *mod = NULL;
1532
1533 if (BigDecimal_DoDivmod(self, r, &div, &mod)) {
1534 SAVE(div); SAVE(mod);
1535 return rb_assoc_new(ToValue(div), ToValue(mod));
1536 }
1537 return DoSomeOne(self,r,rb_intern("divmod"));
1538 }
1539
1540 /*
1541 * See BigDecimal#quo
1542 */
1543 static inline VALUE
1544 BigDecimal_div2(VALUE self, VALUE b, VALUE n)
1545 {
1546 ENTER(5);
1547 SIGNED_VALUE ix;
1548
1549 if (NIL_P(n)) { /* div in Float sense */
1550 Real *div = NULL;
1551 Real *mod;
1552 if (BigDecimal_DoDivmod(self, b, &div, &mod)) {
1553 return BigDecimal_to_i(ToValue(div));
1554 }
1555 return DoSomeOne(self, b, rb_intern("div"));
1556 }
1557
1558 /* div in BigDecimal sense */
1559 ix = GetPrecisionInt(n);
1560 if (ix == 0) {
1561 return BigDecimal_div(self, b);
1562 }
1563 else {
1564 Real *res = NULL;
1565 Real *av = NULL, *bv = NULL, *cv = NULL;
1566 size_t mx = ix + VpBaseFig()*2;
1567 size_t pl = VpSetPrecLimit(0);
1568
1569 GUARD_OBJ(cv, VpCreateRbObject(mx + VpBaseFig(), "0"));
1570 GUARD_OBJ(av, GetVpValue(self, 1));
1571 GUARD_OBJ(bv, GetVpValue(b, 1));
1572 mx = av->Prec + bv->Prec + 2;
1573 if (mx <= cv->MaxPrec) mx = cv->MaxPrec + 1;
1574 GUARD_OBJ(res, VpCreateRbObject((mx * 2 + 2)*VpBaseFig(), "#0"));
1575 VpDivd(cv, res, av, bv);
1576 VpSetPrecLimit(pl);
1577 VpLeftRound(cv, VpGetRoundMode(), ix);
1578 return ToValue(cv);
1579 }
1580 }
1581
1582 /*
1583 * Document-method: BigDecimal#div
1584 *
1585 * call-seq:
1586 * div(value, digits) -> bigdecimal or integer
1587 *
1588 * Divide by the specified value.
1589 *
1590 * digits:: If specified and less than the number of significant digits of the
1591 * result, the result is rounded to that number of digits, according
1592 * to BigDecimal.mode.
1593 *
1594 * If digits is 0, the result is the same as for the / operator
1595 * or #quo.
1596 *
1597 * If digits is not specified, the result is an integer,
1598 * by analogy with Float#div; see also BigDecimal#divmod.
1599 *
1600 * Examples:
1601 *
1602 * a = BigDecimal("4")
1603 * b = BigDecimal("3")
1604 *
1605 * a.div(b, 3) # => 0.133e1
1606 *
1607 * a.div(b, 0) # => 0.1333333333333333333e1
1608 * a / b # => 0.1333333333333333333e1
1609 * a.quo(b) # => 0.1333333333333333333e1
1610 *
1611 * a.div(b) # => 1
1612 */
1613 static VALUE
1614 BigDecimal_div3(int argc, VALUE *argv, VALUE self)
1615 {
1616 VALUE b,n;
1617
1618 rb_scan_args(argc, argv, "11", &b, &n);
1619
1620 return BigDecimal_div2(self, b, n);
1621 }
1622
1623 static VALUE
1624 BigDecimal_add2(VALUE self, VALUE b, VALUE n)
1625 {
1626 ENTER(2);
1627 Real *cv;
1628 SIGNED_VALUE mx = GetPrecisionInt(n);
1629 if (mx == 0) return BigDecimal_add(self, b);
1630 else {
1631 size_t pl = VpSetPrecLimit(0);
1632 VALUE c = BigDecimal_add(self, b);
1633 VpSetPrecLimit(pl);
1634 GUARD_OBJ(cv, GetVpValue(c, 1));
1635 VpLeftRound(cv, VpGetRoundMode(), mx);
1636 return ToValue(cv);
1637 }
1638 }
1639
1640 /* call-seq:
1641 * sub(value, digits) -> bigdecimal
1642 *
1643 * Subtract the specified value.
1644 *
1645 * e.g.
1646 * c = a.sub(b,n)
1647 *
1648 * digits:: If specified and less than the number of significant digits of the
1649 * result, the result is rounded to that number of digits, according
1650 * to BigDecimal.mode.
1651 *
1652 */
1653 static VALUE
1654 BigDecimal_sub2(VALUE self, VALUE b, VALUE n)
1655 {
1656 ENTER(2);
1657 Real *cv;
1658 SIGNED_VALUE mx = GetPrecisionInt(n);
1659 if (mx == 0) return BigDecimal_sub(self, b);
1660 else {
1661 size_t pl = VpSetPrecLimit(0);
1662 VALUE c = BigDecimal_sub(self, b);
1663 VpSetPrecLimit(pl);
1664 GUARD_OBJ(cv, GetVpValue(c, 1));
1665 VpLeftRound(cv, VpGetRoundMode(), mx);
1666 return ToValue(cv);
1667 }
1668 }
1669
1670
1671 static VALUE
1672 BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
1673 {
1674 ENTER(2);
1675 Real *cv;
1676 SIGNED_VALUE mx = GetPrecisionInt(n);
1677 if (mx == 0) return BigDecimal_mult(self, b);
1678 else {
1679 size_t pl = VpSetPrecLimit(0);
1680 VALUE c = BigDecimal_mult(self, b);
1681 VpSetPrecLimit(pl);
1682 GUARD_OBJ(cv, GetVpValue(c, 1));
1683 VpLeftRound(cv, VpGetRoundMode(), mx);
1684 return ToValue(cv);
1685 }
1686 }
1687
1688 /*
1689 * call-seq:
1690 * big_decimal.abs -> big_decimal
1691 *
1692 * Returns the absolute value, as a BigDecimal.
1693 *
1694 * BigDecimal('5').abs #=> 0.5e1
1695 * BigDecimal('-3').abs #=> 0.3e1
1696 */
1697
1698 static VALUE
1699 BigDecimal_abs(VALUE self)
1700 {
1701 ENTER(5);
1702 Real *c, *a;
1703 size_t mx;
1704
1705 GUARD_OBJ(a, GetVpValue(self, 1));
1706 mx = a->Prec *(VpBaseFig() + 1);
1707 GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
1708 VpAsgn(c, a, 1);
1709 VpChangeSign(c, 1);
1710 return ToValue(c);
1711 }
1712
1713 /* call-seq:
1714 * sqrt(n)
1715 *
1716 * Returns the square root of the value.
1717 *
1718 * Result has at least n significant digits.
1719 */
1720 static VALUE
1721 BigDecimal_sqrt(VALUE self, VALUE nFig)
1722 {
1723 ENTER(5);
1724 Real *c, *a;
1725 size_t mx, n;
1726
1727 GUARD_OBJ(a, GetVpValue(self, 1));
1728 mx = a->Prec * (VpBaseFig() + 1);
1729
1730 n = GetPrecisionInt(nFig) + VpDblFig() + BASE_FIG;
1731 if (mx <= n) mx = n;
1732 GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
1733 VpSqrt(c, a);
1734 return ToValue(c);
1735 }
1736
1737 /* Return the integer part of the number, as a BigDecimal.
1738 */
1739 static VALUE
1740 BigDecimal_fix(VALUE self)
1741 {
1742 ENTER(5);
1743 Real *c, *a;
1744 size_t mx;
1745
1746 GUARD_OBJ(a, GetVpValue(self, 1));
1747 mx = a->Prec *(VpBaseFig() + 1);
1748 GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
1749 VpActiveRound(c, a, VP_ROUND_DOWN, 0); /* 0: round off */
1750 return ToValue(c);
1751 }
1752
1753 /* call-seq:
1754 * round(n, mode)
1755 *
1756 * Round to the nearest integer (by default), returning the result as a
1757 * BigDecimal if n is specified, or as an Integer if it isn't.
1758 *
1759 * BigDecimal('3.14159').round #=> 3
1760 * BigDecimal('8.7').round #=> 9
1761 * BigDecimal('-9.9').round #=> -10
1762 *
1763 * BigDecimal('3.14159').round(2).class.name #=> "BigDecimal"
1764 * BigDecimal('3.14159').round.class.name #=> "Integer"
1765 *
1766 * If n is specified and positive, the fractional part of the result has no
1767 * more than that many digits.
1768 *
1769 * If n is specified and negative, at least that many digits to the left of the
1770 * decimal point will be 0 in the result.
1771 *
1772 * BigDecimal('3.14159').round(3) #=> 3.142
1773 * BigDecimal('13345.234').round(-2) #=> 13300.0
1774 *
1775 * The value of the optional mode argument can be used to determine how
1776 * rounding is performed; see BigDecimal.mode.
1777 */
1778 static VALUE
1779 BigDecimal_round(int argc, VALUE *argv, VALUE self)
1780 {
1781 ENTER(5);
1782 Real *c, *a;
1783 int iLoc = 0;
1784 VALUE vLoc;
1785 VALUE vRound;
1786 size_t mx, pl;
1787
1788 unsigned short sw = VpGetRoundMode();
1789
1790 switch (rb_scan_args(argc, argv, "02", &vLoc, &vRound)) {
1791 case 0:
1792 iLoc = 0;
1793 break;
1794 case 1:
1795 if (RB_TYPE_P(vLoc, T_HASH)) {
1796 sw = check_rounding_mode_option(vLoc);
1797 }
1798 else {
1799 iLoc = NUM2INT(vLoc);
1800 }
1801 break;
1802 case 2:
1803 iLoc = NUM2INT(vLoc);
1804 if (RB_TYPE_P(vRound, T_HASH)) {
1805 sw = check_rounding_mode_option(vRound);
1806 }
1807 else {
1808 sw = check_rounding_mode(vRound);
1809 }
1810 break;
1811 default:
1812 break;
1813 }
1814
1815 pl = VpSetPrecLimit(0);
1816 GUARD_OBJ(a, GetVpValue(self, 1));
1817 mx = a->Prec * (VpBaseFig() + 1);
1818 GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
1819 VpSetPrecLimit(pl);
1820 VpActiveRound(c, a, sw, iLoc);
1821 if (argc == 0) {
1822 return BigDecimal_to_i(ToValue(c));
1823 }
1824 return ToValue(c);
1825 }
1826
1827 /* call-seq:
1828 * truncate(n)
1829 *
1830 * Truncate to the nearest integer (by default), returning the result as a
1831 * BigDecimal.
1832 *
1833 * BigDecimal('3.14159').truncate #=> 3
1834 * BigDecimal('8.7').truncate #=> 8
1835 * BigDecimal('-9.9').truncate #=> -9
1836 *
1837 * If n is specified and positive, the fractional part of the result has no
1838 * more than that many digits.
1839 *
1840 * If n is specified and negative, at least that many digits to the left of the
1841 * decimal point will be 0 in the result.
1842 *
1843 * BigDecimal('3.14159').truncate(3) #=> 3.141
1844 * BigDecimal('13345.234').truncate(-2) #=> 13300.0
1845 */
1846 static VALUE
1847 BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
1848 {
1849 ENTER(5);
1850 Real *c, *a;
1851 int iLoc;
1852 VALUE vLoc;
1853 size_t mx, pl = VpSetPrecLimit(0);
1854
1855 if (rb_scan_args(argc, argv, "01", &vLoc) == 0) {
1856 iLoc = 0;
1857 }
1858 else {
1859 iLoc = NUM2INT(vLoc);
1860 }
1861
1862 GUARD_OBJ(a, GetVpValue(self, 1));
1863 mx = a->Prec * (VpBaseFig() + 1);
1864 GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
1865 VpSetPrecLimit(pl);
1866 VpActiveRound(c, a, VP_ROUND_DOWN, iLoc); /* 0: truncate */
1867 if (argc == 0) {
1868 return BigDecimal_to_i(ToValue(c));
1869 }
1870 return ToValue(c);
1871 }
1872
1873 /* Return the fractional part of the number, as a BigDecimal.
1874 */
1875 static VALUE
1876 BigDecimal_frac(VALUE self)
1877 {
1878 ENTER(5);
1879 Real *c, *a;
1880 size_t mx;
1881
1882 GUARD_OBJ(a, GetVpValue(self, 1));
1883 mx = a->Prec * (VpBaseFig() + 1);
1884 GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
1885 VpFrac(c, a);
1886 return ToValue(c);
1887 }
1888
1889 /* call-seq:
1890 * floor(n)
1891 *
1892 * Return the largest integer less than or equal to the value, as a BigDecimal.
1893 *
1894 * BigDecimal('3.14159').floor #=> 3
1895 * BigDecimal('-9.1').floor #=> -10
1896 *
1897 * If n is specified and positive, the fractional part of the result has no
1898 * more than that many digits.
1899 *
1900 * If n is specified and negative, at least that
1901 * many digits to the left of the decimal point will be 0 in the result.
1902 *
1903 * BigDecimal('3.14159').floor(3) #=> 3.141
1904 * BigDecimal('13345.234').floor(-2) #=> 13300.0
1905 */
1906 static VALUE
1907 BigDecimal_floor(int argc, VALUE *argv, VALUE self)
1908 {
1909 ENTER(5);
1910 Real *c, *a;
1911 int iLoc;
1912 VALUE vLoc;
1913 size_t mx, pl = VpSetPrecLimit(0);
1914
1915 if (rb_scan_args(argc, argv, "01", &vLoc)==0) {
1916 iLoc = 0;
1917 }
1918 else {
1919 iLoc = NUM2INT(vLoc);
1920 }
1921
1922 GUARD_OBJ(a, GetVpValue(self, 1));
1923 mx = a->Prec * (VpBaseFig() + 1);
1924 GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
1925 VpSetPrecLimit(pl);
1926 VpActiveRound(c, a, VP_ROUND_FLOOR, iLoc);
1927 #ifdef BIGDECIMAL_DEBUG
1928 VPrint(stderr, "floor: c=%\n", c);
1929 #endif
1930 if (argc == 0) {
1931 return BigDecimal_to_i(ToValue(c));
1932 }
1933 return ToValue(c);
1934 }
1935
1936 /* call-seq:
1937 * ceil(n)
1938 *
1939 * Return the smallest integer greater than or equal to the value, as a BigDecimal.
1940 *
1941 * BigDecimal('3.14159').ceil #=> 4
1942 * BigDecimal('-9.1').ceil #=> -9
1943 *
1944 * If n is specified and positive, the fractional part of the result has no
1945 * more than that many digits.
1946 *
1947 * If n is specified and negative, at least that
1948 * many digits to the left of the decimal point will be 0 in the result.
1949 *
1950 * BigDecimal('3.14159').ceil(3) #=> 3.142
1951 * BigDecimal('13345.234').ceil(-2) #=> 13400.0
1952 */
1953 static VALUE
1954 BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
1955 {
1956 ENTER(5);
1957 Real *c, *a;
1958 int iLoc;
1959 VALUE vLoc;
1960 size_t mx, pl = VpSetPrecLimit(0);
1961
1962 if (rb_scan_args(argc, argv, "01", &vLoc) == 0) {
1963 iLoc = 0;
1964 } else {
1965 iLoc = NUM2INT(vLoc);
1966 }
1967
1968 GUARD_OBJ(a, GetVpValue(self, 1));
1969 mx = a->Prec * (VpBaseFig() + 1);
1970 GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
1971 VpSetPrecLimit(pl);
1972 VpActiveRound(c, a, VP_ROUND_CEIL, iLoc);
1973 if (argc == 0) {
1974 return BigDecimal_to_i(ToValue(c));
1975 }
1976 return ToValue(c);
1977 }
1978
1979 /* call-seq:
1980 * to_s(s)
1981 *
1982 * Converts the value to a string.
1983 *
1984 * The default format looks like 0.xxxxEnn.
1985 *
1986 * The optional parameter s consists of either an integer; or an optional '+'
1987 * or ' ', followed by an optional number, followed by an optional 'E' or 'F'.
1988 *
1989 * If there is a '+' at the start of s, positive values are returned with
1990 * a leading '+'.
1991 *
1992 * A space at the start of s returns positive values with a leading space.
1993 *
1994 * If s contains a number, a space is inserted after each group of that many
1995 * fractional digits.
1996 *
1997 * If s ends with an 'E', engineering notation (0.xxxxEnn) is used.
1998 *
1999 * If s ends with an 'F', conventional floating point notation is used.
2000 *
2001 * Examples:
2002 *
2003 * BigDecimal('-123.45678901234567890').to_s('5F')
2004 * #=> '-123.45678 90123 45678 9'
2005 *
2006 * BigDecimal('123.45678901234567890').to_s('+8F')
2007 * #=> '+123.45678901 23456789'
2008 *
2009 * BigDecimal('123.45678901234567890').to_s(' F')
2010 * #=> ' 123.4567890123456789'
2011 */
2012 static VALUE
2013 BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
2014 {
2015 ENTER(5);
2016 int fmt = 0; /* 0: E format, 1: F format */
2017 int fPlus = 0; /* 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
2018 Real *vp;
2019 volatile VALUE str;
2020 char *psz;
2021 char ch;
2022 size_t nc, mc = 0;
2023 SIGNED_VALUE m;
2024 VALUE f;
2025
2026 GUARD_OBJ(vp, GetVpValue(self, 1));
2027
2028 if (rb_scan_args(argc, argv, "01", &f) == 1) {
2029 if (RB_TYPE_P(f, T_STRING)) {
2030 psz = StringValueCStr(f);
2031 if (*psz == ' ') {
2032 fPlus = 1;
2033 psz++;
2034 }
2035 else if (*psz == '+') {
2036 fPlus = 2;
2037 psz++;
2038 }
2039 while ((ch = *psz++) != 0) {
2040 if (ISSPACE(ch)) {
2041 continue;
2042 }
2043 if (!ISDIGIT(ch)) {
2044 if (ch == 'F' || ch == 'f') {
2045 fmt = 1; /* F format */
2046 }
2047 break;
2048 }
2049 mc = mc*10 + ch - '0';
2050 }
2051 }
2052 else {
2053 m = NUM2INT(f);
2054 if (m <= 0) {
2055 rb_raise(rb_eArgError, "argument must be positive");
2056 }
2057 mc = (size_t)m;
2058 }
2059 }
2060 if (fmt) {
2061 nc = VpNumOfChars(vp, "F");
2062 }
2063 else {
2064 nc = VpNumOfChars(vp, "E");
2065 }
2066 if (mc > 0) {
2067 nc += (nc + mc - 1) / mc + 1;
2068 }
2069
2070 str = rb_str_new(0, nc);
2071 psz = RSTRING_PTR(str);
2072
2073 if (fmt) {
2074 VpToFString(vp, psz, mc, fPlus);
2075 }
2076 else {
2077 VpToString (vp, psz, mc, fPlus);
2078 }
2079 rb_str_resize(str, strlen(psz));
2080 return str;
2081 }
2082
2083 /* Splits a BigDecimal number into four parts, returned as an array of values.
2084 *
2085 * The first value represents the sign of the BigDecimal, and is -1 or 1, or 0
2086 * if the BigDecimal is Not a Number.
2087 *
2088 * The second value is a string representing the significant digits of the
2089 * BigDecimal, with no leading zeros.
2090 *
2091 * The third value is the base used for arithmetic (currently always 10) as an
2092 * Integer.
2093 *
2094 * The fourth value is an Integer exponent.
2095 *
2096 * If the BigDecimal can be represented as 0.xxxxxx*10**n, then xxxxxx is the
2097 * string of significant digits with no leading zeros, and n is the exponent.
2098 *
2099 * From these values, you can translate a BigDecimal to a float as follows:
2100 *
2101 * sign, significant_digits, base, exponent = a.split
2102 * f = sign * "0.#{significant_digits}".to_f * (base ** exponent)
2103 *
2104 * (Note that the to_f method is provided as a more convenient way to translate
2105 * a BigDecimal to a Float.)
2106 */
2107 static VALUE
2108 BigDecimal_split(VALUE self)
2109 {
2110 ENTER(5);
2111 Real *vp;
2112 VALUE obj,str;
2113 ssize_t e, s;
2114 char *psz1;
2115
2116 GUARD_OBJ(vp, GetVpValue(self, 1));
2117 str = rb_str_new(0, VpNumOfChars(vp, "E"));
2118 psz1 = RSTRING_PTR(str);
2119 VpSzMantissa(vp, psz1);
2120 s = 1;
2121 if(psz1[0] == '-') {
2122 size_t len = strlen(psz1 + 1);
2123
2124 memmove(psz1, psz1 + 1, len);
2125 psz1[len] = '\0';
2126 s = -1;
2127 }
2128 if (psz1[0] == 'N') s = 0; /* NaN */
2129 e = VpExponent10(vp);
2130 obj = rb_ary_new2(4);
2131 rb_ary_push(obj, INT2FIX(s));
2132 rb_ary_push(obj, str);
2133 rb_str_resize(str, strlen(psz1));
2134 rb_ary_push(obj, INT2FIX(10));
2135 rb_ary_push(obj, INT2NUM(e));
2136 return obj;
2137 }
2138
2139 /* Returns the exponent of the BigDecimal number, as an Integer.
2140 *
2141 * If the number can be represented as 0.xxxxxx*10**n where xxxxxx is a string
2142 * of digits with no leading zeros, then n is the exponent.
2143 */
2144 static VALUE
2145 BigDecimal_exponent(VALUE self)
2146 {
2147 ssize_t e = VpExponent10(GetVpValue(self, 1));
2148 return INT2NUM(e);
2149 }
2150
2151 /* Returns a string representation of self.
2152 *
2153 * BigDecimal("1234.5678").inspect
2154 * #=> "0.12345678e4"
2155 */
2156 static VALUE
2157 BigDecimal_inspect(VALUE self)
2158 {
2159 ENTER(5);
2160 Real *vp;
2161 volatile VALUE str;
2162 size_t nc;
2163
2164 GUARD_OBJ(vp, GetVpValue(self, 1));
2165 nc = VpNumOfChars(vp, "E");
2166
2167 str = rb_str_new(0, nc);
2168 VpToString(vp, RSTRING_PTR(str), 0, 0);
2169 rb_str_resize(str, strlen(RSTRING_PTR(str)));
2170 return str;
2171 }
2172
2173 static VALUE BigMath_s_exp(VALUE, VALUE, VALUE);
2174 static VALUE BigMath_s_log(VALUE, VALUE, VALUE);
2175
2176 #define BigMath_exp(x, n) BigMath_s_exp(rb_mBigMath, (x), (n))
2177 #define BigMath_log(x, n) BigMath_s_log(rb_mBigMath, (x), (n))
2178
2179 inline static int
2180 is_integer(VALUE x)
2181 {
2182 return (RB_TYPE_P(x, T_FIXNUM) || RB_TYPE_P(x, T_BIGNUM));
2183 }
2184
2185 inline static int
2186 is_negative(VALUE x)
2187 {
2188 if (FIXNUM_P(x)) {
2189 return FIX2LONG(x) < 0;
2190 }
2191 else if (RB_TYPE_P(x, T_BIGNUM)) {
2192 return FIX2INT(rb_big_cmp(x, INT2FIX(0))) < 0;
2193 }
2194 else if (RB_TYPE_P(x, T_FLOAT)) {
2195 return RFLOAT_VALUE(x) < 0.0;
2196 }
2197 return RTEST(rb_funcall(x, '<', 1, INT2FIX(0)));
2198 }
2199
2200 #define is_positive(x) (!is_negative(x))
2201
2202 inline static int
2203 is_zero(VALUE x)
2204 {
2205 VALUE num;
2206
2207 switch (TYPE(x)) {
2208 case T_FIXNUM:
2209 return FIX2LONG(x) == 0;
2210
2211 case T_BIGNUM:
2212 return Qfalse;
2213
2214 case T_RATIONAL:
2215 num = rb_rational_num(x);
2216 return FIXNUM_P(num) && FIX2LONG(num) == 0;
2217
2218 default:
2219 break;
2220 }
2221
2222 return RTEST(rb_funcall(x, id_eq, 1, INT2FIX(0)));
2223 }
2224
2225 inline static int
2226 is_one(VALUE x)
2227 {
2228 VALUE num, den;
2229
2230 switch (TYPE(x)) {
2231 case T_FIXNUM:
2232 return FIX2LONG(x) == 1;
2233
2234 case T_BIGNUM:
2235 return Qfalse;
2236
2237 case T_RATIONAL:
2238 num = rb_rational_num(x);
2239 den = rb_rational_den(x);
2240 return FIXNUM_P(den) && FIX2LONG(den) == 1 &&
2241 FIXNUM_P(num) && FIX2LONG(num) == 1;
2242
2243 default:
2244 break;
2245 }
2246
2247 return RTEST(rb_funcall(x, id_eq, 1, INT2FIX(1)));
2248 }
2249
2250 inline static int
2251 is_even(VALUE x)
2252 {
2253 switch (TYPE(x)) {
2254 case T_FIXNUM:
2255 return (FIX2LONG(x) % 2) == 0;
2256
2257 case T_BIGNUM:
2258 {
2259 unsigned long l;
2260 rb_big_pack(x, &l, 1);
2261 return l % 2 == 0;
2262 }
2263
2264 default:
2265 break;
2266 }
2267
2268 return 0;
2269 }
2270
2271 static VALUE
2272 rmpd_power_by_big_decimal(Real const* x, Real const* exp, ssize_t const n)
2273 {
2274 VALUE log_x, multiplied, y;
2275 volatile VALUE obj = exp->obj;
2276
2277 if (VpIsZero(exp)) {
2278 return ToValue(VpCreateRbObject(n, "1"));
2279 }
2280
2281 log_x = BigMath_log(x->obj, SSIZET2NUM(n+1));
2282 multiplied = BigDecimal_mult2(exp->obj, log_x, SSIZET2NUM(n+1));
2283 y = BigMath_exp(multiplied, SSIZET2NUM(n));
2284 RB_GC_GUARD(obj);
2285
2286 return y;
2287 }
2288
2289 /* call-seq:
2290 * power(n)
2291 * power(n, prec)
2292 *
2293 * Returns the value raised to the power of n.
2294 *
2295 * Note that n must be an Integer.
2296 *
2297 * Also available as the operator **.
2298 */
2299 static VALUE
2300 BigDecimal_power(int argc, VALUE*argv, VALUE self)
2301 {
2302 ENTER(5);
2303 VALUE vexp, prec;
2304 Real* exp = NULL;
2305 Real *x, *y;
2306 ssize_t mp, ma, n;
2307 SIGNED_VALUE int_exp;
2308 double d;
2309
2310 rb_scan_args(argc, argv, "11", &vexp, &prec);
2311
2312 GUARD_OBJ(x, GetVpValue(self, 1));
2313 n = NIL_P(prec) ? (ssize_t)(x->Prec*VpBaseFig()) : NUM2SSIZET(prec);
2314
2315 if (VpIsNaN(x)) {
2316 y = VpCreateRbObject(n, "0");
2317 RB_GC_GUARD(y->obj);
2318 VpSetNaN(y);
2319 return ToValue(y);
2320 }
2321
2322 retry:
2323 switch (TYPE(vexp)) {
2324 case T_FIXNUM:
2325 break;
2326
2327 case T_BIGNUM:
2328 break;
2329
2330 case T_FLOAT:
2331 d = RFLOAT_VALUE(vexp);
2332 if (d == round(d)) {
2333 if (FIXABLE(d)) {
2334 vexp = LONG2FIX((long)d);
2335 }
2336 else {
2337 vexp = rb_dbl2big(d);
2338 }
2339 goto retry;
2340 }
2341 exp = GetVpValueWithPrec(vexp, DBL_DIG+1, 1);
2342 break;
2343
2344 case T_RATIONAL:
2345 if (is_zero(rb_rational_num(vexp))) {
2346 if (is_positive(vexp)) {
2347 vexp = INT2FIX(0);
2348 goto retry;
2349 }
2350 }
2351 else if (is_one(rb_rational_den(vexp))) {
2352 vexp = rb_rational_num(vexp);
2353 goto retry;
2354 }
2355 exp = GetVpValueWithPrec(vexp, n, 1);
2356 break;
2357
2358 case T_DATA:
2359 if (is_kind_of_BigDecimal(vexp)) {
2360 VALUE zero = INT2FIX(0);
2361 VALUE rounded = BigDecimal_round(1, &zero, vexp);
2362 if (RTEST(BigDecimal_eq(vexp, rounded))) {
2363 vexp = BigDecimal_to_i(vexp);
2364 goto retry;
2365 }
2366 exp = DATA_PTR(vexp);
2367 break;
2368 }
2369 /* fall through */
2370 default:
2371 rb_raise(rb_eTypeError,
2372 "wrong argument type %"PRIsVALUE" (expected scalar Numeric)",
2373 RB_OBJ_CLASSNAME(vexp));
2374 }
2375
2376 if (VpIsZero(x)) {
2377 if (is_negative(vexp)) {
2378 y = VpCreateRbObject(n, "#0");
2379 RB_GC_GUARD(y->obj);
2380 if (BIGDECIMAL_NEGATIVE_P(x)) {
2381 if (is_integer(vexp)) {
2382 if (is_even(vexp)) {
2383 /* (-0) ** (-even_integer) -> Infinity */
2384 VpSetPosInf(y);
2385 }
2386 else {
2387 /* (-0) ** (-odd_integer) -> -Infinity */
2388 VpSetNegInf(y);
2389 }
2390 }
2391 else {
2392 /* (-0) ** (-non_integer) -> Infinity */
2393 VpSetPosInf(y);
2394 }
2395 }
2396 else {
2397 /* (+0) ** (-num) -> Infinity */
2398 VpSetPosInf(y);
2399 }
2400 return ToValue(y);
2401 }
2402 else if (is_zero(vexp)) {
2403 return ToValue(VpCreateRbObject(n, "1"));
2404 }
2405 else {
2406 return ToValue(VpCreateRbObject(n, "0"));
2407 }
2408 }
2409
2410 if (is_zero(vexp)) {
2411 return ToValue(VpCreateRbObject(n, "1"));
2412 }
2413 else if (is_one(vexp)) {
2414 return self;
2415 }
2416
2417 if (VpIsInf(x)) {
2418 if (is_negative(vexp)) {
2419 if (BIGDECIMAL_NEGATIVE_P(x)) {
2420 if (is_integer(vexp)) {
2421 if (is_even(vexp)) {
2422 /* (-Infinity) ** (-even_integer) -> +0 */
2423 return ToValue(VpCreateRbObject(n, "0"));
2424 }
2425 else {
2426 /* (-Infinity) ** (-odd_integer) -> -0 */
2427 return ToValue(VpCreateRbObject(n, "-0"));
2428 }
2429 }
2430 else {
2431 /* (-Infinity) ** (-non_integer) -> -0 */
2432 return ToValue(VpCreateRbObject(n, "-0"));
2433 }
2434 }
2435 else {
2436 return ToValue(VpCreateRbObject(n, "0"));
2437 }
2438 }
2439 else {
2440 y = VpCreateRbObject(n, "0");
2441 if (BIGDECIMAL_NEGATIVE_P(x)) {
2442 if (is_integer(vexp)) {
2443 if (is_even(vexp)) {
2444 VpSetPosInf(y);
2445 }
2446 else {
2447 VpSetNegInf(y);
2448 }
2449 }
2450 else {
2451 /* TODO: support complex */
2452 rb_raise(rb_eMathDomainError,
2453 "a non-integral exponent for a negative base");
2454 }
2455 }
2456 else {
2457 VpSetPosInf(y);
2458 }
2459 return ToValue(y);
2460 }
2461 }
2462
2463 if (exp != NULL) {
2464 return rmpd_power_by_big_decimal(x, exp, n);
2465 }
2466 else if (RB_TYPE_P(vexp, T_BIGNUM)) {
2467 VALUE abs_value = BigDecimal_abs(self);
2468 if (is_one(abs_value)) {
2469 return ToValue(VpCreateRbObject(n, "1"));
2470 }
2471 else if (RTEST(rb_funcall(abs_value, '<', 1, INT2FIX(1)))) {
2472 if (is_negative(vexp)) {
2473 y = VpCreateRbObject(n, "0");
2474 if (is_even(vexp)) {
2475 VpSetInf(y, VpGetSign(x));
2476 }
2477 else {
2478 VpSetInf(y, -VpGetSign(x));
2479 }
2480 return ToValue(y);
2481 }
2482 else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
2483 return ToValue(VpCreateRbObject(n, "-0"));
2484 }
2485 else {
2486 return ToValue(VpCreateRbObject(n, "0"));
2487 }
2488 }
2489 else {
2490 if (is_positive(vexp)) {
2491 y = VpCreateRbObject(n, "0");
2492 if (is_even(vexp)) {
2493 VpSetInf(y, VpGetSign(x));
2494 }
2495 else {
2496 VpSetInf(y, -VpGetSign(x));
2497 }
2498 return ToValue(y);
2499 }
2500 else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
2501 return ToValue(VpCreateRbObject(n, "-0"));
2502 }
2503 else {
2504 return ToValue(VpCreateRbObject(n, "0"));
2505 }
2506 }
2507 }
2508
2509 int_exp = FIX2LONG(vexp);
2510 ma = int_exp;
2511 if (ma < 0) ma = -ma;
2512 if (ma == 0) ma = 1;
2513
2514 if (VpIsDef(x)) {
2515 mp = x->Prec * (VpBaseFig() + 1);
2516 GUARD_OBJ(y, VpCreateRbObject(mp * (ma + 1), "0"));
2517 }
2518 else {
2519 GUARD_OBJ(y, VpCreateRbObject(1, "0"));
2520 }
2521 VpPower(y, x, int_exp);
2522 if (!NIL_P(prec) && VpIsDef(y)) {
2523 VpMidRound(y, VpGetRoundMode(), n);
2524 }
2525 return ToValue(y);
2526 }
2527
2528 /* call-seq:
2529 * a ** n -> bigdecimal
2530 *
2531 * Returns the value raised to the power of n.
2532 *
2533 * See BigDecimal#power.
2534 */
2535 static VALUE
2536 BigDecimal_power_op(VALUE self, VALUE exp)
2537 {
2538 return BigDecimal_power(1, &exp, self);
2539 }
2540
2541 /* :nodoc:
2542 *
2543 * private method for dup and clone the provided BigDecimal +other+
2544 */
2545 static VALUE
2546 BigDecimal_initialize_copy(VALUE self, VALUE other)
2547 {
2548 Real *pv = rb_check_typeddata(self, &BigDecimal_data_type);
2549 Real *x = rb_check_typeddata(other, &BigDecimal_data_type);
2550
2551 if (self != other) {
2552 DATA_PTR(self) = VpCopy(pv, x);
2553 }
2554 return self;
2555 }
2556
2557 static VALUE
2558 BigDecimal_clone(VALUE self)
2559 {
2560 return self;
2561 }
2562
2563 #ifdef HAVE_RB_OPTS_EXCEPTION_P
2564 int rb_opts_exception_p(VALUE opts, int default_value);
2565 #define opts_exception_p(opts) rb_opts_exception_p((opts), 1)
2566 #else
2567 static int
2568 opts_exception_p(VALUE opts)
2569 {
2570 static ID kwds[1];
2571 VALUE exception;
2572 if (!kwds[0]) {
2573 kwds[0] = rb_intern_const("exception");
2574 }
2575 if (!rb_get_kwargs(opts, kwds, 0, 1, &exception)) return 1;
2576 switch (exception) {
2577 case Qtrue: case Qfalse:
2578 break;
2579 default:
2580 rb_raise(rb_eArgError, "true or false is expected as exception: %+"PRIsVALUE,
2581 exception);
2582 }
2583 return exception != Qfalse;
2584 }
2585 #endif
2586
2587 static Real *
2588 VpNewVarArg(int argc, VALUE *argv)
2589 {
2590 size_t mf;
2591 VALUE opts = Qnil;
2592 VALUE nFig;
2593 VALUE iniValue;
2594 double d;
2595 int exc;
2596
2597 argc = rb_scan_args(argc, argv, "11:", &iniValue, &nFig, &opts);
2598 exc = opts_exception_p(opts);
2599
2600 if (argc == 1) {
2601 mf = 0;
2602 }
2603 else {
2604 /* expand GetPrecisionInt for exception suppression */
2605 ssize_t n = NUM2INT(nFig);
2606 if (n < 0) {
2607 if (!exc) {
2608 return NULL;
2609 }
2610 rb_raise(rb_eArgError, "negative precision");
2611 }
2612 mf = (size_t)n;
2613 }
2614
2615 if (SPECIAL_CONST_P(iniValue)) {
2616 switch (iniValue) {
2617 case Qnil:
2618 if (!exc) return NULL;
2619 rb_raise(rb_eTypeError, "can't convert nil into BigDecimal");
2620 case Qtrue:
2621 if (!exc) return NULL;
2622 rb_raise(rb_eTypeError, "can't convert true into BigDecimal");
2623 case Qfalse:
2624 if (!exc) return NULL;
2625 rb_raise(rb_eTypeError, "can't convert false into BigDecimal");
2626 default:
2627 break;
2628 }
2629 }
2630
2631 switch (TYPE(iniValue)) {
2632 case T_DATA:
2633 if (is_kind_of_BigDecimal(iniValue)) {
2634 return DATA_PTR(iniValue);
2635 }
2636 break;
2637
2638 case T_FIXNUM:
2639 /* fall through */
2640 case T_BIGNUM:
2641 return GetVpValue(iniValue, 1);
2642
2643 case T_FLOAT:
2644 d = RFLOAT_VALUE(iniValue);
2645 if (!isfinite(d)) {
2646 Real *pv = VpCreateRbObject(1, NULL);
2647 VpDtoV(pv, d);
2648 return pv;
2649 }
2650 if (mf > DBL_DIG+1) {
2651 if (!exc) {
2652 return NULL;
2653 }
2654 rb_raise(rb_eArgError, "precision too large.");
2655 }
2656 /* fall through */
2657 case T_RATIONAL:
2658 if (NIL_P(nFig)) {
2659 if (!exc) {
2660 return NULL;
2661 }
2662 rb_raise(rb_eArgError,
2663 "can't omit precision for a %"PRIsVALUE".",
2664 RB_OBJ_CLASSNAME(iniValue));
2665 }
2666 return GetVpValueWithPrec(iniValue, mf, 1);
2667
2668 case T_STRING:
2669 /* fall through */
2670 default:
2671 break;
2672 }
2673 /* TODO: support to_d */
2674 if (!exc) {
2675 iniValue = rb_check_convert_type(iniValue, T_STRING, "String", "to_str");
2676 if (NIL_P(iniValue)) return NULL;
2677 }
2678 StringValueCStr(iniValue);
2679 return VpAlloc(mf, RSTRING_PTR(iniValue), 1, exc);
2680 }
2681
2682 /* call-seq:
2683 * BigDecimal(initial, digits, exception: true)
2684 *
2685 * Create a new BigDecimal object.
2686 *
2687 * initial:: The initial value, as an Integer, a Float, a Rational,
2688 * a BigDecimal, or a String.
2689 *
2690 * If it is a String, spaces are ignored and unrecognized characters
2691 * terminate the value.
2692 *
2693 * digits:: The number of significant digits, as an Integer. If omitted or 0,
2694 * the number of significant digits is determined from the initial
2695 * value.
2696 *
2697 * The actual number of significant digits used in computation is
2698 * usually larger than the specified number.
2699 *
2700 * exception:: Whether an exception should be raised on invalid arguments.
2701 * +true+ by default, if passed +false+, just returns +nil+
2702 * for invalid.
2703 *
2704 *
2705 * ==== Exceptions
2706 *
2707 * TypeError:: If the +initial+ type is neither Integer, Float,
2708 * Rational, nor BigDecimal, this exception is raised.
2709 *
2710 * TypeError:: If the +digits+ is not an Integer, this exception is raised.
2711 *
2712 * ArgumentError:: If +initial+ is a Float, and the +digits+ is larger than
2713 * Float::DIG + 1, this exception is raised.
2714 *
2715 * ArgumentError:: If the +initial+ is a Float or Rational, and the +digits+
2716 * value is omitted, this exception is raised.
2717 */
2718 static VALUE
2719 f_BigDecimal(int argc, VALUE *argv, VALUE self)
2720 {
2721 ENTER(1);
2722 Real *pv;
2723 VALUE obj;
2724
2725 if (argc > 0 && CLASS_OF(argv[0]) == rb_cBigDecimal) {
2726 if (argc == 1 || (argc == 2 && RB_TYPE_P(argv[1], T_HASH))) return argv[0];
2727 }
2728 obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0);
2729 pv = VpNewVarArg(argc, argv);
2730 if (pv == NULL) return Qnil;
2731 SAVE(pv);
2732 if (ToValue(pv)) pv = VpCopy(NULL, pv);
2733 RTYPEDDATA_DATA(obj) = pv;
2734 RB_OBJ_FREEZE(obj);
2735 return pv->obj = obj;
2736 }
2737
2738 static VALUE
2739 BigDecimal_s_interpret_loosely(VALUE klass, VALUE str)
2740 {
2741 ENTER(1);
2742 char const *c_str;
2743 Real *pv;
2744
2745 c_str = StringValueCStr(str);
2746 GUARD_OBJ(pv, VpAlloc(0, c_str, 0, 1));
2747 pv->obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, pv);
2748 RB_OBJ_FREEZE(pv->obj);
2749 return pv->obj;
2750 }
2751
2752 /* call-seq:
2753 * BigDecimal.limit(digits)
2754 *
2755 * Limit the number of significant digits in newly created BigDecimal
2756 * numbers to the specified value. Rounding is performed as necessary,
2757 * as specified by BigDecimal.mode.
2758 *
2759 * A limit of 0, the default, means no upper limit.
2760 *
2761 * The limit specified by this method takes less priority over any limit
2762 * specified to instance methods such as ceil, floor, truncate, or round.
2763 */
2764 static VALUE
2765 BigDecimal_limit(int argc, VALUE *argv, VALUE self)
2766 {
2767 VALUE nFig;
2768 VALUE nCur = INT2NUM(VpGetPrecLimit());
2769
2770 if (rb_scan_args(argc, argv, "01", &nFig) == 1) {
2771 int nf;
2772 if (NIL_P(nFig)) return nCur;
2773 nf = NUM2INT(nFig);
2774 if (nf < 0) {
2775 rb_raise(rb_eArgError, "argument must be positive");
2776 }
2777 VpSetPrecLimit(nf);
2778 }
2779 return nCur;
2780 }
2781
2782 /* Returns the sign of the value.
2783 *
2784 * Returns a positive value if > 0, a negative value if < 0, and a
2785 * zero if == 0.
2786 *
2787 * The specific value returned indicates the type and sign of the BigDecimal,
2788 * as follows:
2789 *
2790 * BigDecimal::SIGN_NaN:: value is Not a Number
2791 * BigDecimal::SIGN_POSITIVE_ZERO:: value is +0
2792 * BigDecimal::SIGN_NEGATIVE_ZERO:: value is -0
2793 * BigDecimal::SIGN_POSITIVE_INFINITE:: value is +Infinity
2794 * BigDecimal::SIGN_NEGATIVE_INFINITE:: value is -Infinity
2795 * BigDecimal::SIGN_POSITIVE_FINITE:: value is positive
2796 * BigDecimal::SIGN_NEGATIVE_FINITE:: value is negative
2797 */
2798 static VALUE
2799 BigDecimal_sign(VALUE self)
2800 { /* sign */
2801 int s = GetVpValue(self, 1)->sign;
2802 return INT2FIX(s);
2803 }
2804
2805 /*
2806 * call-seq: BigDecimal.save_exception_mode { ... }
2807 *
2808 * Execute the provided block, but preserve the exception mode
2809 *
2810 * BigDecimal.save_exception_mode do
2811 * BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
2812 * BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
2813 *
2814 * BigDecimal(BigDecimal('Infinity'))
2815 * BigDecimal(BigDecimal('-Infinity'))
2816 * BigDecimal(BigDecimal('NaN'))
2817 * end
2818 *
2819 * For use with the BigDecimal::EXCEPTION_*
2820 *
2821 * See BigDecimal.mode
2822 */
2823 static VALUE
2824 BigDecimal_save_exception_mode(VALUE self)
2825 {
2826 unsigned short const exception_mode = VpGetException();
2827 int state;
2828 VALUE ret = rb_protect(rb_yield, Qnil, &state);
2829 VpSetException(exception_mode);
2830 if (state) rb_jump_tag(state);
2831 return ret;
2832 }
2833
2834 /*
2835 * call-seq: BigDecimal.save_rounding_mode { ... }
2836 *
2837 * Execute the provided block, but preserve the rounding mode
2838 *
2839 * BigDecimal.save_rounding_mode do
2840 * BigDecimal.mode(BigDecimal::ROUND_MODE, :up)
2841 * puts BigDecimal.mode(BigDecimal::ROUND_MODE)
2842 * end
2843 *
2844 * For use with the BigDecimal::ROUND_*
2845 *
2846 * See BigDecimal.mode
2847 */
2848 static VALUE
2849 BigDecimal_save_rounding_mode(VALUE self)
2850 {
2851 unsigned short const round_mode = VpGetRoundMode();
2852 int state;
2853 VALUE ret = rb_protect(rb_yield, Qnil, &state);
2854 VpSetRoundMode(round_mode);
2855 if (state) rb_jump_tag(state);
2856 return ret;
2857 }
2858
2859 /*
2860 * call-seq: BigDecimal.save_limit { ... }
2861 *
2862 * Execute the provided block, but preserve the precision limit
2863 *
2864 * BigDecimal.limit(100)
2865 * puts BigDecimal.limit
2866 * BigDecimal.save_limit do
2867 * BigDecimal.limit(200)
2868 * puts BigDecimal.limit
2869 * end
2870 * puts BigDecimal.limit
2871 *
2872 */
2873 static VALUE
2874 BigDecimal_save_limit(VALUE self)
2875 {
2876 size_t const limit = VpGetPrecLimit();
2877 int state;
2878 VALUE ret = rb_protect(rb_yield, Qnil, &state);
2879 VpSetPrecLimit(limit);
2880 if (state) rb_jump_tag(state);
2881 return ret;
2882 }
2883
2884 /* call-seq:
2885 * BigMath.exp(decimal, numeric) -> BigDecimal
2886 *
2887 * Computes the value of e (the base of natural logarithms) raised to the
2888 * power of +decimal+, to the specified number of digits of precision.
2889 *
2890 * If +decimal+ is infinity, returns Infinity.
2891 *
2892 * If +decimal+ is NaN, returns NaN.
2893 */
2894 static VALUE
2895 BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
2896 {
2897 ssize_t prec, n, i;
2898 Real* vx = NULL;
2899 VALUE one, d, y;
2900 int negative = 0;
2901 int infinite = 0;
2902 int nan = 0;
2903 double flo;
2904
2905 prec = NUM2SSIZET(vprec);
2906 if (prec <= 0) {
2907 rb_raise(rb_eArgError, "Zero or negative precision for exp");
2908 }
2909
2910 /* TODO: the following switch statement is almost same as one in the
2911 * BigDecimalCmp function. */
2912 switch (TYPE(x)) {
2913 case T_DATA:
2914 if (!is_kind_of_BigDecimal(x)) break;
2915 vx = DATA_PTR(x);
2916 negative = BIGDECIMAL_NEGATIVE_P(vx);
2917 infinite = VpIsPosInf(vx) || VpIsNegInf(vx);
2918 nan = VpIsNaN(vx);
2919 break;
2920
2921 case T_FIXNUM:
2922 /* fall through */
2923 case T_BIGNUM:
2924 vx = GetVpValue(x, 0);
2925 break;
2926
2927 case T_FLOAT:
2928 flo = RFLOAT_VALUE(x);
2929 negative = flo < 0;
2930 infinite = isinf(flo);
2931 nan = isnan(flo);
2932 if (!infinite && !nan) {
2933 vx = GetVpValueWithPrec(x, DBL_DIG+1, 0);
2934 }
2935 break;
2936
2937 case T_RATIONAL:
2938 vx = GetVpValueWithPrec(x, prec, 0);
2939 break;
2940
2941 default:
2942 break;
2943 }
2944 if (infinite) {
2945 if (negative) {
2946 return ToValue(GetVpValueWithPrec(INT2FIX(0), prec, 1));
2947 }
2948 else {
2949 Real* vy;
2950 vy = VpCreateRbObject(prec, "#0");
2951 VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
2952 RB_GC_GUARD(vy->obj);
2953 return ToValue(vy);
2954 }
2955 }
2956 else if (nan) {
2957 Real* vy;
2958 vy = VpCreateRbObject(prec, "#0");
2959 VpSetNaN(vy);
2960 RB_GC_GUARD(vy->obj);
2961 return ToValue(vy);
2962 }
2963 else if (vx == NULL) {
2964 cannot_be_coerced_into_BigDecimal(rb_eArgError, x);
2965 }
2966 x = vx->obj;
2967
2968 n = prec + rmpd_double_figures();
2969 negative = BIGDECIMAL_NEGATIVE_P(vx);
2970 if (negative) {
2971 VALUE x_zero = INT2NUM(1);
2972 VALUE x_copy = f_BigDecimal(1, &x_zero, klass);
2973 x = BigDecimal_initialize_copy(x_copy, x);
2974 vx = DATA_PTR(x);
2975 VpSetSign(vx, 1);
2976 }
2977
2978 one = ToValue(VpCreateRbObject(1, "1"));
2979 y = one;
2980 d = y;
2981 i = 1;
2982
2983 while (!VpIsZero((Real*)DATA_PTR(d))) {
2984 SIGNED_VALUE const ey = VpExponent10(DATA_PTR(y));
2985 SIGNED_VALUE const ed = VpExponent10(DATA_PTR(d));
2986 ssize_t m = n - vabs(ey - ed);
2987
2988 rb_thread_check_ints();
2989
2990 if (m <= 0) {
2991 break;
2992 }
2993 else if ((size_t)m < rmpd_double_figures()) {
2994 m = rmpd_double_figures();
2995 }
2996
2997 d = BigDecimal_mult(d, x); /* d <- d * x */
2998 d = BigDecimal_div2(d, SSIZET2NUM(i), SSIZET2NUM(m)); /* d <- d / i */
2999 y = BigDecimal_add(y, d); /* y <- y + d */
3000 ++i; /* i <- i + 1 */
3001 }
3002
3003 if (negative) {
3004 return BigDecimal_div2(one, y, vprec);
3005 }
3006 else {
3007 vprec = SSIZET2NUM(prec - VpExponent10(DATA_PTR(y)));
3008 return BigDecimal_round(1, &vprec, y);
3009 }
3010
3011 RB_GC_GUARD(one);
3012 RB_GC_GUARD(x);
3013 RB_GC_GUARD(y);
3014 RB_GC_GUARD(d);
3015 }
3016
3017 /* call-seq:
3018 * BigMath.log(decimal, numeric) -> BigDecimal
3019 *
3020 * Computes the natural logarithm of +decimal+ to the specified number of
3021 * digits of precision, +numeric+.
3022 *
3023 * If +decimal+ is zero or negative, raises Math::DomainError.
3024 *
3025 * If +decimal+ is positive infinity, returns Infinity.
3026 *
3027 * If +decimal+ is NaN, returns NaN.
3028 */
3029 static VALUE
3030 BigMath_s_log(VALUE klass, VALUE x, VALUE vprec)
3031 {
3032 ssize_t prec, n, i;
3033 SIGNED_VALUE expo;
3034 Real* vx = NULL;
3035 VALUE vn, one, two, w, x2, y, d;
3036 int zero = 0;
3037 int negative = 0;
3038 int infinite = 0;
3039 int nan = 0;
3040 double flo;
3041 long fix;
3042
3043 if (!is_integer(vprec)) {
3044 rb_raise(rb_eArgError, "precision must be an Integer");
3045 }
3046
3047 prec = NUM2SSIZET(vprec);
3048 if (prec <= 0) {
3049 rb_raise(rb_eArgError, "Zero or negative precision for exp");
3050 }
3051
3052 /* TODO: the following switch statement is almost same as one in the
3053 * BigDecimalCmp function. */
3054 switch (TYPE(x)) {
3055 case T_DATA:
3056 if (!is_kind_of_BigDecimal(x)) break;
3057 vx = DATA_PTR(x);
3058 zero = VpIsZero(vx);
3059 negative = BIGDECIMAL_NEGATIVE_P(vx);
3060 infinite = VpIsPosInf(vx) || VpIsNegInf(vx);
3061 nan = VpIsNaN(vx);
3062 break;
3063
3064 case T_FIXNUM:
3065 fix = FIX2LONG(x);
3066 zero = fix == 0;
3067 negative = fix < 0;
3068 goto get_vp_value;
3069
3070 case T_BIGNUM:
3071 i = FIX2INT(rb_big_cmp(x, INT2FIX(0)));
3072 zero = i == 0;
3073 negative = i < 0;
3074 get_vp_value:
3075 if (zero || negative) break;
3076 vx = GetVpValue(x, 0);
3077 break;
3078
3079 case T_FLOAT:
3080 flo = RFLOAT_VALUE(x);
3081 zero = flo == 0;
3082 negative = flo < 0;
3083 infinite = isinf(flo);
3084 nan = isnan(flo);
3085 if (!zero && !negative && !infinite && !nan) {
3086 vx = GetVpValueWithPrec(x, DBL_DIG+1, 1);
3087 }
3088 break;
3089
3090 case T_RATIONAL:
3091 zero = RRATIONAL_ZERO_P(x);
3092 negative = RRATIONAL_NEGATIVE_P(x);
3093 if (zero || negative) break;
3094 vx = GetVpValueWithPrec(x, prec, 1);
3095 break;
3096
3097 case T_COMPLEX:
3098 rb_raise(rb_eMathDomainError,
3099 "Complex argument for BigMath.log");
3100
3101 default:
3102 break;
3103 }
3104 if (infinite && !negative) {
3105 Real* vy;
3106 vy = VpCreateRbObject(prec, "#0");
3107 RB_GC_GUARD(vy->obj);
3108 VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
3109 return ToValue(vy);
3110 }
3111 else if (nan) {
3112 Real* vy;
3113 vy = VpCreateRbObject(prec, "#0");
3114 RB_GC_GUARD(vy->obj);
3115 VpSetNaN(vy);
3116 return ToValue(vy);
3117 }
3118 else if (zero || negative) {
3119 rb_raise(rb_eMathDomainError,
3120 "Zero or negative argument for log");
3121 }
3122 else if (vx == NULL) {
3123 cannot_be_coerced_into_BigDecimal(rb_eArgError, x);
3124 }
3125 x = ToValue(vx);
3126
3127 RB_GC_GUARD(one) = ToValue(VpCreateRbObject(1, "1"));
3128 RB_GC_GUARD(two) = ToValue(VpCreateRbObject(1, "2"));
3129
3130 n = prec + rmpd_double_figures();
3131 RB_GC_GUARD(vn) = SSIZET2NUM(n);
3132 expo = VpExponent10(vx);
3133 if (expo < 0 || expo >= 3) {
3134 char buf[DECIMAL_SIZE_OF_BITS(SIZEOF_VALUE * CHAR_BIT) + 4];
3135 snprintf(buf, sizeof(buf), "1E%"PRIdVALUE, -expo);
3136 x = BigDecimal_mult2(x, ToValue(VpCreateRbObject(1, buf)), vn);
3137 }
3138 else {
3139 expo = 0;
3140 }
3141 w = BigDecimal_sub(x, one);
3142 x = BigDecimal_div2(w, BigDecimal_add(x, one), vn);
3143 RB_GC_GUARD(x2) = BigDecimal_mult2(x, x, vn);
3144 RB_GC_GUARD(y) = x;
3145 RB_GC_GUARD(d) = y;
3146 i = 1;
3147 while (!VpIsZero((Real*)DATA_PTR(d))) {
3148 SIGNED_VALUE const ey = VpExponent10(DATA_PTR(y));
3149 SIGNED_VALUE const ed = VpExponent10(DATA_PTR(d));
3150 ssize_t m = n - vabs(ey - ed);
3151 if (m <= 0) {
3152 break;
3153 }
3154 else if ((size_t)m < rmpd_double_figures()) {
3155 m = rmpd_double_figures();
3156 }
3157
3158 x = BigDecimal_mult2(x2, x, vn);
3159 i += 2;
3160 d = BigDecimal_div2(x, SSIZET2NUM(i), SSIZET2NUM(m));
3161 y = BigDecimal_add(y, d);
3162 }
3163
3164 y = BigDecimal_mult(y, two);
3165 if (expo != 0) {
3166 VALUE log10, vexpo, dy;
3167 log10 = BigMath_s_log(klass, INT2FIX(10), vprec);
3168 vexpo = ToValue(GetVpValue(SSIZET2NUM(expo), 1));
3169 dy = BigDecimal_mult(log10, vexpo);
3170 y = BigDecimal_add(y, dy);
3171 }
3172
3173 return y;
3174 }
3175
3176 /* Document-class: BigDecimal
3177 * BigDecimal provides arbitrary-precision floating point decimal arithmetic.
3178 *
3179 * == Introduction
3180 *
3181 * Ruby provides built-in support for arbitrary precision integer arithmetic.
3182 *
3183 * For example:
3184 *
3185 * 42**13 #=> 1265437718438866624512
3186 *
3187 * BigDecimal provides similar support for very large or very accurate floating
3188 * point numbers.
3189 *
3190 * Decimal arithmetic is also useful for general calculation, because it
3191 * provides the correct answers people expect--whereas normal binary floating
3192 * point arithmetic often introduces subtle errors because of the conversion
3193 * between base 10 and base 2.
3194 *
3195 * For example, try:
3196 *
3197 * sum = 0
3198 * 10_000.times do
3199 * sum = sum + 0.0001
3200 * end
3201 * print sum #=> 0.9999999999999062
3202 *
3203 * and contrast with the output from:
3204 *
3205 * require 'bigdecimal'
3206 *
3207 * sum = BigDecimal("0")
3208 * 10_000.times do
3209 * sum = sum + BigDecimal("0.0001")
3210 * end
3211 * print sum #=> 0.1E1
3212 *
3213 * Similarly:
3214 *
3215 * (BigDecimal("1.2") - BigDecimal("1.0")) == BigDecimal("0.2") #=> true
3216 *
3217 * (1.2 - 1.0) == 0.2 #=> false
3218 *
3219 * == Special features of accurate decimal arithmetic
3220 *
3221 * Because BigDecimal is more accurate than normal binary floating point
3222 * arithmetic, it requires some special values.
3223 *
3224 * === Infinity
3225 *
3226 * BigDecimal sometimes needs to return infinity, for example if you divide
3227 * a value by zero.
3228 *
3229 * BigDecimal("1.0") / BigDecimal("0.0") #=> Infinity
3230 * BigDecimal("-1.0") / BigDecimal("0.0") #=> -Infinity
3231 *
3232 * You can represent infinite numbers to BigDecimal using the strings
3233 * <code>'Infinity'</code>, <code>'+Infinity'</code> and
3234 * <code>'-Infinity'</code> (case-sensitive)
3235 *
3236 * === Not a Number
3237 *
3238 * When a computation results in an undefined value, the special value +NaN+
3239 * (for 'not a number') is returned.
3240 *
3241 * Example:
3242 *
3243 * BigDecimal("0.0") / BigDecimal("0.0") #=> NaN
3244 *
3245 * You can also create undefined values.
3246 *
3247 * NaN is never considered to be the same as any other value, even NaN itself:
3248 *
3249 * n = BigDecimal('NaN')
3250 * n == 0.0 #=> false
3251 * n == n #=> false
3252 *
3253 * === Positive and negative zero
3254 *
3255 * If a computation results in a value which is too small to be represented as
3256 * a BigDecimal within the currently specified limits of precision, zero must
3257 * be returned.
3258 *
3259 * If the value which is too small to be represented is negative, a BigDecimal
3260 * value of negative zero is returned.
3261 *
3262 * BigDecimal("1.0") / BigDecimal("-Infinity") #=> -0.0
3263 *
3264 * If the value is positive, a value of positive zero is returned.
3265 *
3266 * BigDecimal("1.0") / BigDecimal("Infinity") #=> 0.0
3267 *
3268 * (See BigDecimal.mode for how to specify limits of precision.)
3269 *
3270 * Note that +-0.0+ and +0.0+ are considered to be the same for the purposes of
3271 * comparison.
3272 *
3273 * Note also that in mathematics, there is no particular concept of negative
3274 * or positive zero; true mathematical zero has no sign.
3275 *
3276 * == bigdecimal/util
3277 *
3278 * When you require +bigdecimal/util+, the #to_d method will be
3279 * available on BigDecimal and the native Integer, Float, Rational,
3280 * and String classes:
3281 *
3282 * require 'bigdecimal/util'
3283 *
3284 * 42.to_d # => 0.42e2
3285 * 0.5.to_d # => 0.5e0
3286 * (2/3r).to_d(3) # => 0.667e0
3287 * "0.5".to_d # => 0.5e0
3288 *
3289 * == License
3290 *
3291 * Copyright (C) 2002 by Shigeo Kobayashi <shigeo@tinyforest.gr.jp>.
3292 *
3293 * BigDecimal is released under the Ruby and 2-clause BSD licenses.
3294 * See LICENSE.txt for details.
3295 *
3296 * Maintained by mrkn <mrkn@mrkn.jp> and ruby-core members.
3297 *
3298 * Documented by zzak <zachary@zacharyscott.net>, mathew <meta@pobox.com>, and
3299 * many other contributors.
3300 */
3301 void
3302 Init_bigdecimal(void)
3303 {
3304 VALUE arg;
3305
3306 id_BigDecimal_exception_mode = rb_intern_const("BigDecimal.exception_mode");
3307 id_BigDecimal_rounding_mode = rb_intern_const("BigDecimal.rounding_mode");
3308 id_BigDecimal_precision_limit = rb_intern_const("BigDecimal.precision_limit");
3309
3310 /* Initialize VP routines */
3311 VpInit(0UL);
3312
3313 /* Class and method registration */
3314 rb_cBigDecimal = rb_define_class("BigDecimal", rb_cNumeric);
3315
3316 /* Global function */
3317 rb_define_global_function("BigDecimal", f_BigDecimal, -1);
3318
3319 /* Class methods */
3320 rb_undef_method(CLASS_OF(rb_cBigDecimal), "allocate");
3321 rb_undef_method(CLASS_OF(rb_cBigDecimal), "new");
3322 rb_define_singleton_method(rb_cBigDecimal, "interpret_loosely", BigDecimal_s_interpret_loosely, 1);
3323 rb_define_singleton_method(rb_cBigDecimal, "mode", BigDecimal_mode, -1);
3324 rb_define_singleton_method(rb_cBigDecimal, "limit", BigDecimal_limit, -1);
3325 rb_define_singleton_method(rb_cBigDecimal, "double_fig", BigDecimal_double_fig, 0);
3326 rb_define_singleton_method(rb_cBigDecimal, "_load", BigDecimal_load, 1);
3327
3328 rb_define_singleton_method(rb_cBigDecimal, "save_exception_mode", BigDecimal_save_exception_mode, 0);
3329 rb_define_singleton_method(rb_cBigDecimal, "save_rounding_mode", BigDecimal_save_rounding_mode, 0);
3330 rb_define_singleton_method(rb_cBigDecimal, "save_limit", BigDecimal_save_limit, 0);
3331
3332 /* Constants definition */
3333
3334 #ifndef RUBY_BIGDECIMAL_VERSION
3335 # error RUBY_BIGDECIMAL_VERSION is not defined
3336 #endif
3337 /*
3338 * The version of bigdecimal library
3339 */
3340 rb_define_const(rb_cBigDecimal, "VERSION", rb_str_new2(RUBY_BIGDECIMAL_VERSION));
3341
3342 /*
3343 * Base value used in internal calculations. On a 32 bit system, BASE
3344 * is 10000, indicating that calculation is done in groups of 4 digits.
3345 * (If it were larger, BASE**2 wouldn't fit in 32 bits, so you couldn't
3346 * guarantee that two groups could always be multiplied together without
3347 * overflow.)
3348 */
3349 rb_define_const(rb_cBigDecimal, "BASE", INT2FIX((SIGNED_VALUE)VpBaseVal()));
3350
3351 /* Exceptions */
3352
3353 /*
3354 * 0xff: Determines whether overflow, underflow or zero divide result in
3355 * an exception being thrown. See BigDecimal.mode.
3356 */
3357 rb_define_const(rb_cBigDecimal, "EXCEPTION_ALL", INT2FIX(VP_EXCEPTION_ALL));
3358
3359 /*
3360 * 0x02: Determines what happens when the result of a computation is not a
3361 * number (NaN). See BigDecimal.mode.
3362 */
3363 rb_define_const(rb_cBigDecimal, "EXCEPTION_NaN", INT2FIX(VP_EXCEPTION_NaN));
3364
3365 /*
3366 * 0x01: Determines what happens when the result of a computation is
3367 * infinity. See BigDecimal.mode.
3368 */
3369 rb_define_const(rb_cBigDecimal, "EXCEPTION_INFINITY", INT2FIX(VP_EXCEPTION_INFINITY));
3370
3371 /*
3372 * 0x04: Determines what happens when the result of a computation is an
3373 * underflow (a result too small to be represented). See BigDecimal.mode.
3374 */
3375 rb_define_const(rb_cBigDecimal, "EXCEPTION_UNDERFLOW", INT2FIX(VP_EXCEPTION_UNDERFLOW));
3376
3377 /*
3378 * 0x01: Determines what happens when the result of a computation is an
3379 * overflow (a result too large to be represented). See BigDecimal.mode.
3380 */
3381 rb_define_const(rb_cBigDecimal, "EXCEPTION_OVERFLOW", INT2FIX(VP_EXCEPTION_OVERFLOW));
3382
3383 /*
3384 * 0x10: Determines what happens when a division by zero is performed.
3385 * See BigDecimal.mode.
3386 */
3387 rb_define_const(rb_cBigDecimal, "EXCEPTION_ZERODIVIDE", INT2FIX(VP_EXCEPTION_ZERODIVIDE));
3388
3389 /*
3390 * 0x100: Determines what happens when a result must be rounded in order to
3391 * fit in the appropriate number of significant digits. See
3392 * BigDecimal.mode.
3393 */
3394 rb_define_const(rb_cBigDecimal, "ROUND_MODE", INT2FIX(VP_ROUND_MODE));
3395
3396 /* 1: Indicates that values should be rounded away from zero. See
3397 * BigDecimal.mode.
3398 */
3399 rb_define_const(rb_cBigDecimal, "ROUND_UP", INT2FIX(VP_ROUND_UP));
3400
3401 /* 2: Indicates that values should be rounded towards zero. See
3402 * BigDecimal.mode.
3403 */
3404 rb_define_const(rb_cBigDecimal, "ROUND_DOWN", INT2FIX(VP_ROUND_DOWN));
3405
3406 /* 3: Indicates that digits >= 5 should be rounded up, others rounded down.
3407 * See BigDecimal.mode. */
3408 rb_define_const(rb_cBigDecimal, "ROUND_HALF_UP", INT2FIX(VP_ROUND_HALF_UP));
3409
3410 /* 4: Indicates that digits >= 6 should be rounded up, others rounded down.
3411 * See BigDecimal.mode.
3412 */
3413 rb_define_const(rb_cBigDecimal, "ROUND_HALF_DOWN", INT2FIX(VP_ROUND_HALF_DOWN));
3414 /* 5: Round towards +Infinity. See BigDecimal.mode. */
3415 rb_define_const(rb_cBigDecimal, "ROUND_CEILING", INT2FIX(VP_ROUND_CEIL));
3416
3417 /* 6: Round towards -Infinity. See BigDecimal.mode. */
3418 rb_define_const(rb_cBigDecimal, "ROUND_FLOOR", INT2FIX(VP_ROUND_FLOOR));
3419
3420 /* 7: Round towards the even neighbor. See BigDecimal.mode. */
3421 rb_define_const(rb_cBigDecimal, "ROUND_HALF_EVEN", INT2FIX(VP_ROUND_HALF_EVEN));
3422
3423 /* 0: Indicates that a value is not a number. See BigDecimal.sign. */
3424 rb_define_const(rb_cBigDecimal, "SIGN_NaN", INT2FIX(VP_SIGN_NaN));
3425
3426 /* 1: Indicates that a value is +0. See BigDecimal.sign. */
3427 rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_ZERO", INT2FIX(VP_SIGN_POSITIVE_ZERO));
3428
3429 /* -1: Indicates that a value is -0. See BigDecimal.sign. */
3430 rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_ZERO", INT2FIX(VP_SIGN_NEGATIVE_ZERO));
3431
3432 /* 2: Indicates that a value is positive and finite. See BigDecimal.sign. */
3433 rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_FINITE", INT2FIX(VP_SIGN_POSITIVE_FINITE));
3434
3435 /* -2: Indicates that a value is negative and finite. See BigDecimal.sign. */
3436 rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_FINITE", INT2FIX(VP_SIGN_NEGATIVE_FINITE));
3437
3438 /* 3: Indicates that a value is positive and infinite. See BigDecimal.sign. */
3439 rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_INFINITE", INT2FIX(VP_SIGN_POSITIVE_INFINITE));
3440
3441 /* -3: Indicates that a value is negative and infinite. See BigDecimal.sign. */
3442 rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_INFINITE", INT2FIX(VP_SIGN_NEGATIVE_INFINITE));
3443
3444 arg = rb_str_new2("+Infinity");
3445 /* Positive infinity value. */
3446 rb_define_const(rb_cBigDecimal, "INFINITY", f_BigDecimal(1, &arg, rb_cBigDecimal));
3447 arg = rb_str_new2("NaN");
3448 /* 'Not a Number' value. */
3449 rb_define_const(rb_cBigDecimal, "NAN", f_BigDecimal(1, &arg, rb_cBigDecimal));
3450
3451
3452 /* instance methods */
3453 rb_define_method(rb_cBigDecimal, "initialize_copy", BigDecimal_initialize_copy, 1);
3454 rb_define_method(rb_cBigDecimal, "precs", BigDecimal_prec, 0);
3455
3456 rb_define_method(rb_cBigDecimal, "add", BigDecimal_add2, 2);
3457 rb_define_method(rb_cBigDecimal, "sub", BigDecimal_sub2, 2);
3458 rb_define_method(rb_cBigDecimal, "mult", BigDecimal_mult2, 2);
3459 rb_define_method(rb_cBigDecimal, "div", BigDecimal_div3, -1);
3460 rb_define_method(rb_cBigDecimal, "hash", BigDecimal_hash, 0);
3461 rb_define_method(rb_cBigDecimal, "to_s", BigDecimal_to_s, -1);
3462 rb_define_method(rb_cBigDecimal, "to_i", BigDecimal_to_i, 0);
3463 rb_define_method(rb_cBigDecimal, "to_int", BigDecimal_to_i, 0);
3464 rb_define_method(rb_cBigDecimal, "to_r", BigDecimal_to_r, 0);
3465 rb_define_method(rb_cBigDecimal, "split", BigDecimal_split, 0);
3466 rb_define_method(rb_cBigDecimal, "+", BigDecimal_add, 1);
3467 rb_define_method(rb_cBigDecimal, "-", BigDecimal_sub, 1);
3468 rb_define_method(rb_cBigDecimal, "+@", BigDecimal_uplus, 0);
3469 rb_define_method(rb_cBigDecimal, "-@", BigDecimal_neg, 0);
3470 rb_define_method(rb_cBigDecimal, "*", BigDecimal_mult, 1);
3471 rb_define_method(rb_cBigDecimal, "/", BigDecimal_div, 1);
3472 rb_define_method(rb_cBigDecimal, "quo", BigDecimal_div, 1);
3473 rb_define_method(rb_cBigDecimal, "%", BigDecimal_mod, 1);
3474 rb_define_method(rb_cBigDecimal, "modulo", BigDecimal_mod, 1);
3475 rb_define_method(rb_cBigDecimal, "remainder", BigDecimal_remainder, 1);
3476 rb_define_method(rb_cBigDecimal, "divmod", BigDecimal_divmod, 1);
3477 rb_define_method(rb_cBigDecimal, "clone", BigDecimal_clone, 0);
3478 rb_define_method(rb_cBigDecimal, "dup", BigDecimal_clone, 0);
3479 rb_define_method(rb_cBigDecimal, "to_f", BigDecimal_to_f, 0);
3480 rb_define_method(rb_cBigDecimal, "abs", BigDecimal_abs, 0);
3481 rb_define_method(rb_cBigDecimal, "sqrt", BigDecimal_sqrt, 1);
3482 rb_define_method(rb_cBigDecimal, "fix", BigDecimal_fix, 0);
3483 rb_define_method(rb_cBigDecimal, "round", BigDecimal_round, -1);
3484 rb_define_method(rb_cBigDecimal, "frac", BigDecimal_frac, 0);
3485 rb_define_method(rb_cBigDecimal, "floor", BigDecimal_floor, -1);
3486 rb_define_method(rb_cBigDecimal, "ceil", BigDecimal_ceil, -1);
3487 rb_define_method(rb_cBigDecimal, "power", BigDecimal_power, -1);
3488 rb_define_method(rb_cBigDecimal, "**", BigDecimal_power_op, 1);
3489 rb_define_method(rb_cBigDecimal, "<=>", BigDecimal_comp, 1);
3490 rb_define_method(rb_cBigDecimal, "==", BigDecimal_eq, 1);
3491 rb_define_method(rb_cBigDecimal, "===", BigDecimal_eq, 1);
3492 rb_define_method(rb_cBigDecimal, "eql?", BigDecimal_eq, 1);
3493 rb_define_method(rb_cBigDecimal, "<", BigDecimal_lt, 1);
3494 rb_define_method(rb_cBigDecimal, "<=", BigDecimal_le, 1);
3495 rb_define_method(rb_cBigDecimal, ">", BigDecimal_gt, 1);
3496 rb_define_method(rb_cBigDecimal, ">=", BigDecimal_ge, 1);
3497 rb_define_method(rb_cBigDecimal, "zero?", BigDecimal_zero, 0);
3498 rb_define_method(rb_cBigDecimal, "nonzero?", BigDecimal_nonzero, 0);
3499 rb_define_method(rb_cBigDecimal, "coerce", BigDecimal_coerce, 1);
3500 rb_define_method(rb_cBigDecimal, "inspect", BigDecimal_inspect, 0);
3501 rb_define_method(rb_cBigDecimal, "exponent", BigDecimal_exponent, 0);
3502 rb_define_method(rb_cBigDecimal, "sign", BigDecimal_sign, 0);
3503 rb_define_method(rb_cBigDecimal, "nan?", BigDecimal_IsNaN, 0);
3504 rb_define_method(rb_cBigDecimal, "infinite?", BigDecimal_IsInfinite, 0);
3505 rb_define_method(rb_cBigDecimal, "finite?", BigDecimal_IsFinite, 0);
3506 rb_define_method(rb_cBigDecimal, "truncate", BigDecimal_truncate, -1);
3507 rb_define_method(rb_cBigDecimal, "_dump", BigDecimal_dump, -1);
3508
3509 rb_mBigMath = rb_define_module("BigMath");
3510 rb_define_singleton_method(rb_mBigMath, "exp", BigMath_s_exp, 2);
3511 rb_define_singleton_method(rb_mBigMath, "log", BigMath_s_log, 2);
3512
3513 id_up = rb_intern_const("up");
3514 id_down = rb_intern_const("down");
3515 id_truncate = rb_intern_const("truncate");
3516 id_half_up = rb_intern_const("half_up");
3517 id_default = rb_intern_const("default");
3518 id_half_down = rb_intern_const("half_down");
3519 id_half_even = rb_intern_const("half_even");
3520 id_banker = rb_intern_const("banker");
3521 id_ceiling = rb_intern_const("ceiling");
3522 id_ceil = rb_intern_const("ceil");
3523 id_floor = rb_intern_const("floor");
3524 id_to_r = rb_intern_const("to_r");
3525 id_eq = rb_intern_const("==");
3526 id_half = rb_intern_const("half");
3527 }
3528
3529 /*
3530 *
3531 * ============================================================================
3532 *
3533 * vp_ routines begin from here.
3534 *
3535 * ============================================================================
3536 *
3537 */
3538 #ifdef BIGDECIMAL_DEBUG
3539 static int gfDebug = 1; /* Debug switch */
3540 #if 0
3541 static int gfCheckVal = 1; /* Value checking flag in VpNmlz() */
3542 #endif
3543 #endif /* BIGDECIMAL_DEBUG */
3544
3545 static Real *VpConstOne; /* constant 1.0 */
3546 static Real *VpPt5; /* constant 0.5 */
3547 #define maxnr 100UL /* Maximum iterations for calculating sqrt. */
3548 /* used in VpSqrt() */
3549
3550 /* ETC */
3551 #define MemCmp(x,y,z) memcmp(x,y,z)
3552 #define StrCmp(x,y) strcmp(x,y)
3553
3554 enum op_sw {
3555 OP_SW_ADD = 1, /* + */
3556 OP_SW_SUB, /* - */
3557 OP_SW_MULT, /* * */
3558 OP_SW_DIV /* / */
3559 };
3560
3561 static int VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw);
3562 static int AddExponent(Real *a, SIGNED_VALUE n);
3563 static BDIGIT VpAddAbs(Real *a,Real *b,Real *c);
3564 static BDIGIT VpSubAbs(Real *a,Real *b,Real *c);
3565 static size_t VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos, BDIGIT *av, BDIGIT *bv);
3566 static int VpNmlz(Real *a);
3567 static void VpFormatSt(char *psz, size_t fFmt);
3568 static int VpRdup(Real *m, size_t ind_m);
3569
3570 #ifdef BIGDECIMAL_DEBUG
3571 static int gnAlloc = 0; /* Memory allocation counter */
3572 #endif /* BIGDECIMAL_DEBUG */
3573
3574 VP_EXPORT void *
3575 VpMemAlloc(size_t mb)
3576 {
3577 void *p = xmalloc(mb);
3578 if (!p) {
3579 VpException(VP_EXCEPTION_MEMORY, "failed to allocate memory", 1);
3580 }
3581 memset(p, 0, mb);
3582 #ifdef BIGDECIMAL_DEBUG
3583 gnAlloc++; /* Count allocation call */
3584 #endif /* BIGDECIMAL_DEBUG */
3585 return p;
3586 }
3587
3588 VP_EXPORT void *
3589 VpMemRealloc(void *ptr, size_t mb)
3590 {
3591 void *p = xrealloc(ptr, mb);
3592 if (!p) {
3593 VpException(VP_EXCEPTION_MEMORY, "failed to allocate memory", 1);
3594 }
3595 return p;
3596 }
3597
3598 VP_EXPORT void
3599 VpFree(Real *pv)
3600 {
3601 if (pv != NULL) {
3602 xfree(pv);
3603 #ifdef BIGDECIMAL_DEBUG
3604 gnAlloc--; /* Decrement allocation count */
3605 if (gnAlloc == 0) {
3606 printf(" *************** All memories allocated freed ****************\n");
3607 /*getchar();*/
3608 }
3609 if (gnAlloc < 0) {
3610 printf(" ??????????? Too many memory free calls(%d) ?????????????\n", gnAlloc);
3611 /*getchar();*/
3612 }
3613 #endif /* BIGDECIMAL_DEBUG */
3614 }
3615 }
3616
3617 /*
3618 * EXCEPTION Handling.
3619 */
3620
3621 #define rmpd_set_thread_local_exception_mode(mode) \
3622 rb_thread_local_aset( \
3623 rb_thread_current(), \
3624 id_BigDecimal_exception_mode, \
3625 INT2FIX((int)(mode)) \
3626 )
3627
3628 static unsigned short
3629 VpGetException (void)
3630 {
3631 VALUE const vmode = rb_thread_local_aref(
3632 rb_thread_current(),
3633 id_BigDecimal_exception_mode
3634 );
3635
3636 if (NIL_P(vmode)) {
3637 rmpd_set_thread_local_exception_mode(RMPD_EXCEPTION_MODE_DEFAULT);
3638 return RMPD_EXCEPTION_MODE_DEFAULT;
3639 }
3640
3641 return NUM2USHORT(vmode);
3642 }
3643
3644 static void
3645 VpSetException(unsigned short f)
3646 {
3647 rmpd_set_thread_local_exception_mode(f);
3648 }
3649
3650 /*
3651 * Precision limit.
3652 */
3653
3654 #define rmpd_set_thread_local_precision_limit(limit) \
3655 rb_thread_local_aset( \
3656 rb_thread_current(), \
3657 id_BigDecimal_precision_limit, \
3658 SIZET2NUM(limit) \
3659 )
3660 #define RMPD_PRECISION_LIMIT_DEFAULT ((size_t)0)
3661
3662 /* These 2 functions added at v1.1.7 */
3663 VP_EXPORT size_t
3664 VpGetPrecLimit(void)
3665 {
3666 VALUE const vlimit = rb_thread_local_aref(
3667 rb_thread_current(),
3668 id_BigDecimal_precision_limit
3669 );
3670
3671 if (NIL_P(vlimit)) {
3672 rmpd_set_thread_local_precision_limit(RMPD_PRECISION_LIMIT_DEFAULT);
3673 return RMPD_PRECISION_LIMIT_DEFAULT;
3674 }
3675
3676 return NUM2SIZET(vlimit);
3677 }
3678
3679 VP_EXPORT size_t
3680 VpSetPrecLimit(size_t n)
3681 {
3682 size_t const s = VpGetPrecLimit();
3683 rmpd_set_thread_local_precision_limit(n);
3684 return s;
3685 }
3686
3687 /*
3688 * Rounding mode.
3689 */
3690
3691 #define rmpd_set_thread_local_rounding_mode(mode) \
3692 rb_thread_local_aset( \
3693 rb_thread_current(), \
3694 id_BigDecimal_rounding_mode, \
3695 INT2FIX((int)(mode)) \
3696 )
3697
3698 VP_EXPORT unsigned short
3699 VpGetRoundMode(void)
3700 {
3701 VALUE const vmode = rb_thread_local_aref(
3702 rb_thread_current(),
3703 id_BigDecimal_rounding_mode
3704 );
3705
3706 if (NIL_P(vmode)) {
3707 rmpd_set_thread_local_rounding_mode(RMPD_ROUNDING_MODE_DEFAULT);
3708 return RMPD_ROUNDING_MODE_DEFAULT;
3709 }
3710
3711 return NUM2USHORT(vmode);
3712 }
3713
3714 VP_EXPORT int
3715 VpIsRoundMode(unsigned short n)
3716 {
3717 switch (n) {
3718 case VP_ROUND_UP:
3719 case VP_ROUND_DOWN:
3720 case VP_ROUND_HALF_UP:
3721 case VP_ROUND_HALF_DOWN:
3722 case VP_ROUND_CEIL:
3723 case VP_ROUND_FLOOR:
3724 case VP_ROUND_HALF_EVEN:
3725 return 1;
3726
3727 default:
3728 return 0;
3729 }
3730 }
3731
3732 VP_EXPORT unsigned short
3733 VpSetRoundMode(unsigned short n)
3734 {
3735 if (VpIsRoundMode(n)) {
3736 rmpd_set_thread_local_rounding_mode(n);
3737 return n;
3738 }
3739
3740 return VpGetRoundMode();
3741 }
3742
3743 /*
3744 * 0.0 & 1.0 generator
3745 * These gZero_..... and gOne_..... can be any name
3746 * referenced from nowhere except Zero() and One().
3747 * gZero_..... and gOne_..... must have global scope
3748 * (to let the compiler know they may be changed in outside
3749 * (... but not actually..)).
3750 */
3751 volatile const double gOne_ABCED9B4_CE73__00400511F31D = 1.0;
3752
3753 static double
3754 One(void)
3755 {
3756 return gOne_ABCED9B4_CE73__00400511F31D;
3757 }
3758
3759 /*
3760 ----------------------------------------------------------------
3761 Value of sign in Real structure is reserved for future use.
3762 short sign;
3763 ==0 : NaN
3764 1 : Positive zero
3765 -1 : Negative zero
3766 2 : Positive number
3767 -2 : Negative number
3768 3 : Positive infinite number
3769 -3 : Negative infinite number
3770 ----------------------------------------------------------------
3771 */
3772
3773 VP_EXPORT double
3774 VpGetDoubleNaN(void) /* Returns the value of NaN */
3775 {
3776 return nan("");
3777 }
3778
3779 VP_EXPORT double
3780 VpGetDoublePosInf(void) /* Returns the value of +Infinity */
3781 {
3782 return HUGE_VAL;
3783 }
3784
3785 VP_EXPORT double
3786 VpGetDoubleNegInf(void) /* Returns the value of -Infinity */
3787 {
3788 return -HUGE_VAL;
3789 }
3790
3791 VP_EXPORT double
3792 VpGetDoubleNegZero(void) /* Returns the value of -0 */
3793 {
3794 static double nzero = 1000.0;
3795 if (nzero != 0.0) nzero = (One()/VpGetDoubleNegInf());
3796 return nzero;
3797 }
3798
3799 #if 0 /* unused */
3800 VP_EXPORT int
3801 VpIsNegDoubleZero(double v)
3802 {
3803 double z = VpGetDoubleNegZero();
3804 return MemCmp(&v,&z,sizeof(v))==0;
3805 }
3806 #endif
3807
3808 VP_EXPORT int
3809 VpException(unsigned short f, const char *str,int always)
3810 {
3811 unsigned short const exception_mode = VpGetException();
3812
3813 if (f == VP_EXCEPTION_OP || f == VP_EXCEPTION_MEMORY) always = 1;
3814
3815 if (always || (exception_mode & f)) {
3816 switch(f) {
3817 /* case VP_EXCEPTION_OVERFLOW: */
3818 case VP_EXCEPTION_ZERODIVIDE:
3819 case VP_EXCEPTION_INFINITY:
3820 case VP_EXCEPTION_NaN:
3821 case VP_EXCEPTION_UNDERFLOW:
3822 case VP_EXCEPTION_OP:
3823 rb_raise(rb_eFloatDomainError, "%s", str);
3824 break;
3825 case VP_EXCEPTION_MEMORY:
3826 default:
3827 rb_fatal("%s", str);
3828 }
3829 }
3830 return 0; /* 0 Means VpException() raised no exception */
3831 }
3832
3833 /* Throw exception or returns 0,when resulting c is Inf or NaN */
3834 /* sw=1:+ 2:- 3:* 4:/ */
3835 static int
3836 VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw)
3837 {
3838 if (VpIsNaN(a) || VpIsNaN(b)) {
3839 /* at least a or b is NaN */
3840 VpSetNaN(c);
3841 goto NaN;
3842 }
3843
3844 if (VpIsInf(a)) {
3845 if (VpIsInf(b)) {
3846 switch(sw) {
3847 case OP_SW_ADD: /* + */
3848 if (VpGetSign(a) == VpGetSign(b)) {
3849 VpSetInf(c, VpGetSign(a));
3850 goto Inf;
3851 }
3852 else {
3853 VpSetNaN(c);
3854 goto NaN;
3855 }
3856 case OP_SW_SUB: /* - */
3857 if (VpGetSign(a) != VpGetSign(b)) {
3858 VpSetInf(c, VpGetSign(a));
3859 goto Inf;
3860 }
3861 else {
3862 VpSetNaN(c);
3863 goto NaN;
3864 }
3865 case OP_SW_MULT: /* * */
3866 VpSetInf(c, VpGetSign(a)*VpGetSign(b));
3867 goto Inf;
3868 case OP_SW_DIV: /* / */
3869 VpSetNaN(c);
3870 goto NaN;
3871 }
3872 VpSetNaN(c);
3873 goto NaN;
3874 }
3875 /* Inf op Finite */
3876 switch(sw) {
3877 case OP_SW_ADD: /* + */
3878 case OP_SW_SUB: /* - */
3879 VpSetInf(c, VpGetSign(a));
3880 break;
3881 case OP_SW_MULT: /* * */
3882 if (VpIsZero(b)) {
3883 VpSetNaN(c);
3884 goto NaN;
3885 }
3886 VpSetInf(c, VpGetSign(a)*VpGetSign(b));
3887 break;
3888 case OP_SW_DIV: /* / */
3889 VpSetInf(c, VpGetSign(a)*VpGetSign(b));
3890 }
3891 goto Inf;
3892 }
3893
3894 if (VpIsInf(b)) {
3895 switch(sw) {
3896 case OP_SW_ADD: /* + */
3897 VpSetInf(c, VpGetSign(b));
3898 break;
3899 case OP_SW_SUB: /* - */
3900 VpSetInf(c, -VpGetSign(b));
3901 break;
3902 case OP_SW_MULT: /* * */
3903 if (VpIsZero(a)) {
3904 VpSetNaN(c);
3905 goto NaN;
3906 }
3907 VpSetInf(c, VpGetSign(a)*VpGetSign(b));
3908 break;
3909 case OP_SW_DIV: /* / */
3910 VpSetZero(c, VpGetSign(a)*VpGetSign(b));
3911 }
3912 goto Inf;
3913 }
3914 return 1; /* Results OK */
3915
3916 Inf:
3917 if (VpIsPosInf(c)) {
3918 return VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 0);
3919 }
3920 else {
3921 return VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 0);
3922 }
3923
3924 NaN:
3925 return VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'", 0);
3926 }
3927
3928 /*
3929 ----------------------------------------------------------------
3930 */
3931
3932 /*
3933 * returns number of chars needed to represent vp in specified format.
3934 */
3935 VP_EXPORT size_t
3936 VpNumOfChars(Real *vp,const char *pszFmt)
3937 {
3938 SIGNED_VALUE ex;
3939 size_t nc;
3940
3941 if (vp == NULL) return BASE_FIG*2+6;
3942 if (!VpIsDef(vp)) return 32; /* not sure,may be OK */
3943
3944 switch(*pszFmt) {
3945 case 'F':
3946 nc = BASE_FIG*(vp->Prec + 1)+2;
3947 ex = vp->exponent;
3948 if (ex < 0) {
3949 nc += BASE_FIG*(size_t)(-ex);
3950 }
3951 else {
3952 if ((size_t)ex > vp->Prec) {
3953 nc += BASE_FIG*((size_t)ex - vp->Prec);
3954 }
3955 }
3956 break;
3957 case 'E':
3958 /* fall through */
3959 default:
3960 nc = BASE_FIG*(vp->Prec + 2)+6; /* 3: sign + exponent chars */
3961 }
3962 return nc;
3963 }
3964
3965 /*
3966 * Initializer for Vp routines and constants used.
3967 * [Input]
3968 * BaseVal: Base value(assigned to BASE) for Vp calculation.
3969 * It must be the form BaseVal=10**n.(n=1,2,3,...)
3970 * If Base <= 0L,then the BASE will be calculated so
3971 * that BASE is as large as possible satisfying the
3972 * relation MaxVal <= BASE*(BASE+1). Where the value
3973 * MaxVal is the largest value which can be represented
3974 * by one BDIGIT word in the computer used.
3975 *
3976 * [Returns]
3977 * 1+DBL_DIG ... OK
3978 */
3979 VP_EXPORT size_t
3980 VpInit(BDIGIT BaseVal)
3981 {
3982 /* Setup +/- Inf NaN -0 */
3983 VpGetDoubleNegZero();
3984
3985 /* Allocates Vp constants. */
3986 VpConstOne = VpAlloc(1UL, "1", 1, 1);
3987 VpPt5 = VpAlloc(1UL, ".5", 1, 1);
3988
3989 #ifdef BIGDECIMAL_DEBUG
3990 gnAlloc = 0;
3991 #endif /* BIGDECIMAL_DEBUG */
3992
3993 #ifdef BIGDECIMAL_DEBUG
3994 if (gfDebug) {
3995 printf("VpInit: BaseVal = %"PRIuBDIGIT"\n", BaseVal);
3996 printf("\tBASE = %"PRIuBDIGIT"\n", BASE);
3997 printf("\tHALF_BASE = %"PRIuBDIGIT"\n", HALF_BASE);
3998 printf("\tBASE1 = %"PRIuBDIGIT"\n", BASE1);
3999 printf("\tBASE_FIG = %u\n", BASE_FIG);
4000 printf("\tDBLE_FIG = %d\n", DBLE_FIG);
4001 }
4002 #endif /* BIGDECIMAL_DEBUG */
4003
4004 return rmpd_double_figures();
4005 }
4006
4007 VP_EXPORT Real *
4008 VpOne(void)
4009 {
4010 return VpConstOne;
4011 }
4012
4013 /* If exponent overflows,then raise exception or returns 0 */
4014 static int
4015 AddExponent(Real *a, SIGNED_VALUE n)
4016 {
4017 SIGNED_VALUE e = a->exponent;
4018 SIGNED_VALUE m = e+n;
4019 SIGNED_VALUE eb, mb;
4020 if (e > 0) {
4021 if (n > 0) {
4022 if (MUL_OVERFLOW_SIGNED_VALUE_P(m, (SIGNED_VALUE)BASE_FIG) ||
4023 MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG))
4024 goto overflow;
4025 mb = m*(SIGNED_VALUE)BASE_FIG;
4026 eb = e*(SIGNED_VALUE)BASE_FIG;
4027 if (eb - mb > 0) goto overflow;
4028 }
4029 }
4030 else if (n < 0) {
4031 if (MUL_OVERFLOW_SIGNED_VALUE_P(m, (SIGNED_VALUE)BASE_FIG) ||
4032 MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG))
4033 goto underflow;
4034 mb = m*(SIGNED_VALUE)BASE_FIG;
4035 eb = e*(SIGNED_VALUE)BASE_FIG;
4036 if (mb - eb > 0) goto underflow;
4037 }
4038 a->exponent = m;
4039 return 1;
4040
4041 /* Overflow/Underflow ==> Raise exception or returns 0 */
4042 underflow:
4043 VpSetZero(a, VpGetSign(a));
4044 return VpException(VP_EXCEPTION_UNDERFLOW, "Exponent underflow", 0);
4045
4046 overflow:
4047 VpSetInf(a, VpGetSign(a));
4048 return VpException(VP_EXCEPTION_OVERFLOW, "Exponent overflow", 0);
4049 }
4050
4051 Real *
4052 rmpd_parse_special_string(const char *str)
4053 {
4054 static const struct {
4055 const char *str;
4056 size_t len;
4057 int sign;
4058 } table[] = {
4059 { SZ_INF, sizeof(SZ_INF) - 1, VP_SIGN_POSITIVE_INFINITE },
4060 { SZ_PINF, sizeof(SZ_PINF) - 1, VP_SIGN_POSITIVE_INFINITE },
4061 { SZ_NINF, sizeof(SZ_NINF) - 1, VP_SIGN_NEGATIVE_INFINITE },
4062 { SZ_NaN, sizeof(SZ_NaN) - 1, VP_SIGN_NaN }
4063 };
4064 static const size_t table_length = sizeof(table) / sizeof(table[0]);
4065 size_t i;
4066
4067 for (i = 0; i < table_length; ++i) {
4068 const char *p;
4069 if (strncmp(str, table[i].str, table[i].len) != 0) {
4070 continue;
4071 }
4072
4073 p = str + table[i].len;
4074 while (*p && ISSPACE(*p)) ++p;
4075 if (*p == '\0') {
4076 Real *vp = VpAllocReal(1);
4077 vp->MaxPrec = 1;
4078 switch (table[i].sign) {
4079 default:
4080 UNREACHABLE; break;
4081 case VP_SIGN_POSITIVE_INFINITE:
4082 VpSetPosInf(vp);
4083 return vp;
4084 case VP_SIGN_NEGATIVE_INFINITE:
4085 VpSetNegInf(vp);
4086 return vp;
4087 case VP_SIGN_NaN:
4088 VpSetNaN(vp);
4089 return vp;
4090 }
4091 }
4092 }
4093
4094 return NULL;
4095 }
4096
4097 /*
4098 * Allocates variable.
4099 * [Input]
4100 * mx ... allocation unit, if zero then mx is determined by szVal.
4101 * The mx is the number of effective digits can to be stored.
4102 * szVal ... value assigned(char). If szVal==NULL,then zero is assumed.
4103 * If szVal[0]=='#' then Max. Prec. will not be considered(1.1.7),
4104 * full precision specified by szVal is allocated.
4105 *
4106 * [Returns]
4107 * Pointer to the newly allocated variable, or
4108 * NULL be returned if memory allocation is failed,or any error.
4109 */
4110 VP_EXPORT Real *
4111 VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
4112 {
4113 const char *orig_szVal = szVal;
4114 size_t i, j, ni, ipf, nf, ipe, ne, dot_seen, exp_seen, nalloc;
4115 char v, *psz;
4116 int sign=1;
4117 Real *vp = NULL;
4118 size_t mf = VpGetPrecLimit();
4119 VALUE buf;
4120
4121 mx = (mx + BASE_FIG - 1) / BASE_FIG; /* Determine allocation unit. */
4122 if (mx == 0) ++mx;
4123
4124 if (szVal) {
4125 /* Skipping leading spaces */
4126 while (ISSPACE(*szVal)) szVal++;
4127
4128 /* Processing the leading one `#` */
4129 if (*szVal != '#') {
4130 if (mf) {
4131 mf = (mf + BASE_FIG - 1) / BASE_FIG + 2; /* Needs 1 more for div */
4132 if (mx > mf) {
4133 mx = mf;
4134 }
4135 }
4136 }
4137 else {
4138 ++szVal;
4139 }
4140 }
4141 else {
4142 return_zero:
4143 /* necessary to be able to store */
4144 /* at least mx digits. */
4145 /* szVal==NULL ==> allocate zero value. */
4146 vp = VpAllocReal(mx);
4147 /* xmalloc() alway returns(or throw interruption) */
4148 vp->MaxPrec = mx; /* set max precision */
4149 VpSetZero(vp, 1); /* initialize vp to zero. */
4150 return vp;
4151 }
4152
4153 /* Check on Inf & NaN */
4154 if ((vp = rmpd_parse_special_string(szVal)) != NULL) {
4155 return vp;
4156 }
4157
4158 /* Scanning digits */
4159
4160 /* A buffer for keeping scanned digits */
4161 buf = rb_str_tmp_new(strlen(szVal) + 1);
4162 psz = RSTRING_PTR(buf);
4163
4164 /* cursor: i for psz, and j for szVal */
4165 i = j = 0;
4166
4167 /* Scanning: sign part */
4168 v = psz[i] = szVal[j];
4169 if ((v == '-') || (v == '+')) {
4170 sign = -(v == '-');
4171 ++i;
4172 ++j;
4173 }
4174
4175 /* Scanning: integer part */
4176 ni = 0; /* number of digits in the integer part */
4177 while ((v = psz[i] = szVal[j]) != '\0') {
4178 if (!strict_p && ISSPACE(v)) {
4179 v = psz[i] = '\0';
4180 break;
4181 }
4182 if (v == '_') {
4183 if (ni > 0) {
4184 v = szVal[j+1];
4185 if (v == '\0' || ISSPACE(v) || ISDIGIT(v)) {
4186 ++j;
4187 continue;
4188 }
4189 if (!strict_p) {
4190 v = psz[i] = '\0';
4191 break;
4192 }
4193 }
4194 goto invalid_value;
4195 }
4196 if (!ISDIGIT(v)) {
4197 break;
4198 }
4199 ++ni;
4200 ++i;
4201 ++j;
4202 }
4203
4204 /* Scanning: fractional part */
4205 nf = 0; /* number of digits in the fractional part */
4206 ne = 0; /* number of digits in the exponential part */
4207 ipf = 0; /* index of the beginning of the fractional part */
4208 ipe = 0; /* index of the beginning of the exponential part */
4209 dot_seen = 0;
4210 exp_seen = 0;
4211
4212 if (v != '\0') {
4213 /* Scanning fractional part */
4214 if ((psz[i] = szVal[j]) == '.') {
4215 dot_seen = 1;
4216 ++i;
4217 ++j;
4218 ipf = i;
4219 while ((v = psz[i] = szVal[j]) != '\0') {
4220 if (!strict_p && ISSPACE(v)) {
4221 v = psz[i] = '\0';
4222 break;
4223 }
4224 if (v == '_') {
4225 if (nf > 0 && ISDIGIT(szVal[j+1])) {
4226 ++j;
4227 continue;
4228 }
4229 if (!strict_p) {
4230 v = psz[i] = '\0';
4231 if (nf == 0) {
4232 dot_seen = 0;
4233 }
4234 break;
4235 }
4236 goto invalid_value;
4237 }
4238 if (!ISDIGIT(v)) break;
4239 ++i;
4240 ++j;
4241 ++nf;
4242 }
4243 }
4244
4245 /* Scanning exponential part */
4246 if (v != '\0') {
4247 switch ((psz[i] = szVal[j])) {
4248 case '\0':
4249 break;
4250 case 'e': case 'E':
4251 case 'd': case 'D':
4252 exp_seen = 1;
4253 ++i;
4254 ++j;
4255 ipe = i;
4256 v = psz[i] = szVal[j];
4257 if ((v == '-') || (v == '+')) {
4258 ++i;
4259 ++j;
4260 }
4261 while ((v = psz[i] = szVal[j]) != '\0') {
4262 if (!strict_p && ISSPACE(v)) {
4263 v = psz[i] = '\0';
4264 break;
4265 }
4266 if (v == '_') {
4267 if (ne > 0 && ISDIGIT(szVal[j+1])) {
4268 ++j;
4269 continue;
4270 }
4271 if (!strict_p) {
4272 v = psz[i] = '\0';
4273 if (ne == 0) {
4274 exp_seen = 0;
4275 }
4276 break;
4277 }
4278 goto invalid_value;
4279 }
4280 if (!ISDIGIT(v)) break;
4281 ++i;
4282 ++j;
4283 ++ne;
4284 }
4285 break;
4286 default:
4287 break;
4288 }
4289 }
4290
4291 if (v != '\0') {
4292 /* Scanning trailing spaces */
4293 while (ISSPACE(szVal[j])) ++j;
4294
4295 /* Invalid character */
4296 if (szVal[j] && strict_p) {
4297 goto invalid_value;
4298 }
4299 }
4300 }
4301
4302 psz[i] = '\0';
4303
4304 if (strict_p && (((ni == 0 || dot_seen) && nf == 0) || (exp_seen && ne == 0))) {
4305 VALUE str;
4306 invalid_value:
4307 if (!strict_p) {
4308 goto return_zero;
4309 }
4310 if (!exc) {
4311 return NULL;
4312 }
4313 str = rb_str_new2(orig_szVal);
4314 rb_raise(rb_eArgError, "invalid value for BigDecimal(): \"%"PRIsVALUE"\"", str);
4315 }
4316
4317 nalloc = (ni + nf + BASE_FIG - 1) / BASE_FIG + 1; /* set effective allocation */
4318 /* units for szVal[] */
4319 if (mx == 0) mx = 1;
4320 nalloc = Max(nalloc, mx);
4321 mx = nalloc;
4322 vp = VpAllocReal(mx);
4323 /* xmalloc() alway returns(or throw interruption) */
4324 vp->MaxPrec = mx; /* set max precision */
4325 VpSetZero(vp, sign);
4326 VpCtoV(vp, psz, ni, psz + ipf, nf, psz + ipe, ne);
4327 rb_str_resize(buf, 0);
4328 return vp;
4329 }
4330
4331 /*
4332 * Assignment(c=a).
4333 * [Input]
4334 * a ... RHSV
4335 * isw ... switch for assignment.
4336 * c = a when isw > 0
4337 * c = -a when isw < 0
4338 * if c->MaxPrec < a->Prec,then round operation
4339 * will be performed.
4340 * [Output]
4341 * c ... LHSV
4342 */
4343 VP_EXPORT size_t
4344 VpAsgn(Real *c, Real *a, int isw)
4345 {
4346 size_t n;
4347 if (VpIsNaN(a)) {
4348 VpSetNaN(c);
4349 return 0;
4350 }
4351 if (VpIsInf(a)) {
4352 VpSetInf(c, isw * VpGetSign(a));
4353 return 0;
4354 }
4355
4356 /* check if the RHS is zero */
4357 if (!VpIsZero(a)) {
4358 c->exponent = a->exponent; /* store exponent */
4359 VpSetSign(c, isw * VpGetSign(a)); /* set sign */
4360 n = (a->Prec < c->MaxPrec) ? (a->Prec) : (c->MaxPrec);
4361 c->Prec = n;
4362 memcpy(c->frac, a->frac, n * sizeof(BDIGIT));
4363 /* Needs round ? */
4364 if (isw != 10) {
4365 /* Not in ActiveRound */
4366 if(c->Prec < a->Prec) {
4367 VpInternalRound(c, n, (n>0) ? a->frac[n-1] : 0, a->frac[n]);
4368 }
4369 else {
4370 VpLimitRound(c,0);
4371 }
4372 }
4373 }
4374 else {
4375 /* The value of 'a' is zero. */
4376 VpSetZero(c, isw * VpGetSign(a));
4377 return 1;
4378 }
4379 return c->Prec * BASE_FIG;
4380 }
4381
4382 /*
4383 * c = a + b when operation = 1 or 2
4384 * c = a - b when operation = -1 or -2.
4385 * Returns number of significant digits of c
4386 */
4387 VP_EXPORT size_t
4388 VpAddSub(Real *c, Real *a, Real *b, int operation)
4389 {
4390 short sw, isw;
4391 Real *a_ptr, *b_ptr;
4392 size_t n, na, nb, i;
4393 BDIGIT mrv;
4394
4395 #ifdef BIGDECIMAL_DEBUG
4396 if (gfDebug) {
4397 VPrint(stdout, "VpAddSub(enter) a=% \n", a);
4398 VPrint(stdout, " b=% \n", b);
4399 printf(" operation=%d\n", operation);
4400 }
4401 #endif /* BIGDECIMAL_DEBUG */
4402
4403 if (!VpIsDefOP(c, a, b, (operation > 0) ? OP_SW_ADD : OP_SW_SUB)) return 0; /* No significant digits */
4404
4405 /* check if a or b is zero */
4406 if (VpIsZero(a)) {
4407 /* a is zero,then assign b to c */
4408 if (!VpIsZero(b)) {
4409 VpAsgn(c, b, operation);
4410 }
4411 else {
4412 /* Both a and b are zero. */
4413 if (VpGetSign(a) < 0 && operation * VpGetSign(b) < 0) {
4414 /* -0 -0 */
4415 VpSetZero(c, -1);
4416 }
4417 else {
4418 VpSetZero(c, 1);
4419 }
4420 return 1; /* 0: 1 significant digits */
4421 }
4422 return c->Prec * BASE_FIG;
4423 }
4424 if (VpIsZero(b)) {
4425 /* b is zero,then assign a to c. */
4426 VpAsgn(c, a, 1);
4427 return c->Prec*BASE_FIG;
4428 }
4429
4430 if (operation < 0) sw = -1;
4431 else sw = 1;
4432
4433 /* compare absolute value. As a result,|a_ptr|>=|b_ptr| */
4434 if (a->exponent > b->exponent) {
4435 a_ptr = a;
4436 b_ptr = b;
4437 } /* |a|>|b| */
4438 else if (a->exponent < b->exponent) {
4439 a_ptr = b;
4440 b_ptr = a;
4441 } /* |a|<|b| */
4442 else {
4443 /* Exponent part of a and b is the same,then compare fraction */
4444 /* part */
4445 na = a->Prec;
4446 nb = b->Prec;
4447 n = Min(na, nb);
4448 for (i=0; i < n; ++i) {
4449 if (a->frac[i] > b->frac[i]) {
4450 a_ptr = a;
4451 b_ptr = b;
4452 goto end_if;
4453 }
4454 else if (a->frac[i] < b->frac[i]) {
4455 a_ptr = b;
4456 b_ptr = a;
4457 goto end_if;
4458 }
4459 }
4460 if (na > nb) {
4461 a_ptr = a;
4462 b_ptr = b;
4463 goto end_if;
4464 }
4465 else if (na < nb) {
4466 a_ptr = b;
4467 b_ptr = a;
4468 goto end_if;
4469 }
4470 /* |a| == |b| */
4471 if (VpGetSign(a) + sw *VpGetSign(b) == 0) {
4472 VpSetZero(c, 1); /* abs(a)=abs(b) and operation = '-' */
4473 return c->Prec * BASE_FIG;
4474 }
4475 a_ptr = a;
4476 b_ptr = b;
4477 }
4478
4479 end_if:
4480 isw = VpGetSign(a) + sw *VpGetSign(b);
4481 /*
4482 * isw = 0 ...( 1)+(-1),( 1)-( 1),(-1)+(1),(-1)-(-1)
4483 * = 2 ...( 1)+( 1),( 1)-(-1)
4484 * =-2 ...(-1)+(-1),(-1)-( 1)
4485 * If isw==0, then c =(Sign a_ptr)(|a_ptr|-|b_ptr|)
4486 * else c =(Sign ofisw)(|a_ptr|+|b_ptr|)
4487 */
4488 if (isw) { /* addition */
4489 VpSetSign(c, 1);
4490 mrv = VpAddAbs(a_ptr, b_ptr, c);
4491 VpSetSign(c, isw / 2);
4492 }
4493 else { /* subtraction */
4494 VpSetSign(c, 1);
4495 mrv = VpSubAbs(a_ptr, b_ptr, c);
4496 if (a_ptr == a) {
4497 VpSetSign(c,VpGetSign(a));
4498 }
4499 else {
4500 VpSetSign(c, VpGetSign(a_ptr) * sw);
4501 }
4502 }
4503 VpInternalRound(c, 0, (c->Prec > 0) ? c->frac[c->Prec-1] : 0, mrv);
4504
4505 #ifdef BIGDECIMAL_DEBUG
4506 if (gfDebug) {
4507 VPrint(stdout, "VpAddSub(result) c=% \n", c);
4508 VPrint(stdout, " a=% \n", a);
4509 VPrint(stdout, " b=% \n", b);
4510 printf(" operation=%d\n", operation);
4511 }
4512 #endif /* BIGDECIMAL_DEBUG */
4513 return c->Prec * BASE_FIG;
4514 }
4515
4516 /*
4517 * Addition of two values with variable precision
4518 * a and b assuming abs(a)>abs(b).
4519 * c = abs(a) + abs(b) ; where |a|>=|b|
4520 */
4521 static BDIGIT
4522 VpAddAbs(Real *a, Real *b, Real *c)
4523 {
4524 size_t word_shift;
4525 size_t ap;
4526 size_t bp;
4527 size_t cp;
4528 size_t a_pos;
4529 size_t b_pos, b_pos_with_word_shift;
4530 size_t c_pos;
4531 BDIGIT av, bv, carry, mrv;
4532
4533 #ifdef BIGDECIMAL_DEBUG
4534 if (gfDebug) {
4535 VPrint(stdout, "VpAddAbs called: a = %\n", a);
4536 VPrint(stdout, " b = %\n", b);
4537 }
4538 #endif /* BIGDECIMAL_DEBUG */
4539
4540 word_shift = VpSetPTR(a, b, c, &ap, &bp, &cp, &av, &bv);
4541 a_pos = ap;
4542 b_pos = bp;
4543 c_pos = cp;
4544
4545 if (word_shift == (size_t)-1L) return 0; /* Overflow */
4546 if (b_pos == (size_t)-1L) goto Assign_a;
4547
4548 mrv = av + bv; /* Most right val. Used for round. */
4549
4550 /* Just assign the last few digits of b to c because a has no */
4551 /* corresponding digits to be added. */
4552 if (b_pos > 0) {
4553 while (b_pos > 0 && b_pos + word_shift > a_pos) {
4554 c->frac[--c_pos] = b->frac[--b_pos];
4555 }
4556 }
4557 if (b_pos == 0 && word_shift > a_pos) {
4558 while (word_shift-- > a_pos) {
4559 c->frac[--c_pos] = 0;
4560 }
4561 }
4562
4563 /* Just assign the last few digits of a to c because b has no */
4564 /* corresponding digits to be added. */
4565 b_pos_with_word_shift = b_pos + word_shift;
4566 while (a_pos > b_pos_with_word_shift) {
4567 c->frac[--c_pos] = a->frac[--a_pos];
4568 }
4569 carry = 0; /* set first carry be zero */
4570
4571 /* Now perform addition until every digits of b will be */
4572 /* exhausted. */
4573 while (b_pos > 0) {
4574 c->frac[--c_pos] = a->frac[--a_pos] + b->frac[--b_pos] + carry;
4575 if (c->frac[c_pos] >= BASE) {
4576 c->frac[c_pos] -= BASE;
4577 carry = 1;
4578 }
4579 else {
4580 carry = 0;
4581 }
4582 }
4583
4584 /* Just assign the first few digits of a with considering */
4585 /* the carry obtained so far because b has been exhausted. */
4586 while (a_pos > 0) {
4587 c->frac[--c_pos] = a->frac[--a_pos] + carry;
4588 if (c->frac[c_pos] >= BASE) {
4589 c->frac[c_pos] -= BASE;
4590 carry = 1;
4591 }
4592 else {
4593 carry = 0;
4594 }
4595 }
4596 if (c_pos) c->frac[c_pos - 1] += carry;
4597 goto Exit;
4598
4599 Assign_a:
4600 VpAsgn(c, a, 1);
4601 mrv = 0;
4602
4603 Exit:
4604
4605 #ifdef BIGDECIMAL_DEBUG
4606 if (gfDebug) {
4607 VPrint(stdout, "VpAddAbs exit: c=% \n", c);
4608 }
4609 #endif /* BIGDECIMAL_DEBUG */
4610 return mrv;
4611 }
4612
4613 /*
4614 * c = abs(a) - abs(b)
4615 */
4616 static BDIGIT
4617 VpSubAbs(Real *a, Real *b, Real *c)
4618 {
4619 size_t word_shift;
4620 size_t ap;
4621 size_t bp;
4622 size_t cp;
4623 size_t a_pos;
4624 size_t b_pos, b_pos_with_word_shift;
4625 size_t c_pos;
4626 BDIGIT av, bv, borrow, mrv;
4627
4628 #ifdef BIGDECIMAL_DEBUG
4629 if (gfDebug) {
4630 VPrint(stdout, "VpSubAbs called: a = %\n", a);
4631 VPrint(stdout, " b = %\n", b);
4632 }
4633 #endif /* BIGDECIMAL_DEBUG */
4634
4635 word_shift = VpSetPTR(a, b, c, &ap, &bp, &cp, &av, &bv);
4636 a_pos = ap;
4637 b_pos = bp;
4638 c_pos = cp;
4639 if (word_shift == (size_t)-1L) return 0; /* Overflow */
4640 if (b_pos == (size_t)-1L) goto Assign_a;
4641
4642 if (av >= bv) {
4643 mrv = av - bv;
4644 borrow = 0;
4645 }
4646 else {
4647 mrv = 0;
4648 borrow = 1;
4649 }
4650
4651 /* Just assign the values which are the BASE subtracted by */
4652 /* each of the last few digits of the b because the a has no */
4653 /* corresponding digits to be subtracted. */
4654 if (b_pos + word_shift > a_pos) {
4655 while (b_pos > 0 && b_pos + word_shift > a_pos) {
4656 c->frac[--c_pos] = BASE - b->frac[--b_pos] - borrow;
4657 borrow = 1;
4658 }
4659 if (b_pos == 0) {
4660 while (word_shift > a_pos) {
4661 --word_shift;
4662 c->frac[--c_pos] = BASE - borrow;
4663 borrow = 1;
4664 }
4665 }
4666 }
4667 /* Just assign the last few digits of a to c because b has no */
4668 /* corresponding digits to subtract. */
4669
4670 b_pos_with_word_shift = b_pos + word_shift;
4671 while (a_pos > b_pos_with_word_shift) {
4672 c->frac[--c_pos] = a->frac[--a_pos];
4673 }
4674
4675 /* Now perform subtraction until every digits of b will be */
4676 /* exhausted. */
4677 while (b_pos > 0) {
4678 --c_pos;
4679 if (a->frac[--a_pos] < b->frac[--b_pos] + borrow) {
4680 c->frac[c_pos] = BASE + a->frac[a_pos] - b->frac[b_pos] - borrow;
4681 borrow = 1;
4682 }
4683 else {
4684 c->frac[c_pos] = a->frac[a_pos] - b->frac[b_pos] - borrow;
4685 borrow = 0;
4686 }
4687 }
4688
4689 /* Just assign the first few digits of a with considering */
4690 /* the borrow obtained so far because b has been exhausted. */
4691 while (a_pos > 0) {
4692 --c_pos;
4693 if (a->frac[--a_pos] < borrow) {
4694 c->frac[c_pos] = BASE + a->frac[a_pos] - borrow;
4695 borrow = 1;
4696 }
4697 else {
4698 c->frac[c_pos] = a->frac[a_pos] - borrow;
4699 borrow = 0;
4700 }
4701 }
4702 if (c_pos) c->frac[c_pos - 1] -= borrow;
4703 goto Exit;
4704
4705 Assign_a:
4706 VpAsgn(c, a, 1);
4707 mrv = 0;
4708
4709 Exit:
4710 #ifdef BIGDECIMAL_DEBUG
4711 if (gfDebug) {
4712 VPrint(stdout, "VpSubAbs exit: c=% \n", c);
4713 }
4714 #endif /* BIGDECIMAL_DEBUG */
4715 return mrv;
4716 }
4717
4718 /*
4719 * Note: If(av+bv)>= HALF_BASE,then 1 will be added to the least significant
4720 * digit of c(In case of addition).
4721 * ------------------------- figure of output -----------------------------------
4722 * a = xxxxxxxxxxx
4723 * b = xxxxxxxxxx
4724 * c =xxxxxxxxxxxxxxx
4725 * word_shift = | |
4726 * right_word = | | (Total digits in RHSV)
4727 * left_word = | | (Total digits in LHSV)
4728 * a_pos = |
4729 * b_pos = |
4730 * c_pos = |
4731 */
4732 static size_t
4733 VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos, BDIGIT *av, BDIGIT *bv)
4734 {
4735 size_t left_word, right_word, word_shift;
4736
4737 size_t const round_limit = (VpGetPrecLimit() + BASE_FIG - 1) / BASE_FIG;
4738
4739 assert(a->exponent >= b->exponent);
4740
4741 c->frac[0] = 0;
4742 *av = *bv = 0;
4743
4744 word_shift = (a->exponent - b->exponent);
4745 left_word = b->Prec + word_shift;
4746 right_word = Max(a->Prec, left_word);
4747 left_word = c->MaxPrec - 1; /* -1 ... prepare for round up */
4748
4749 /*
4750 * check if 'round' is needed.
4751 */
4752 if (right_word > left_word) { /* round ? */
4753 /*---------------------------------
4754 * Actual size of a = xxxxxxAxx
4755 * Actual size of b = xxxBxxxxx
4756 * Max. size of c = xxxxxx
4757 * Round off = |-----|
4758 * c_pos = |
4759 * right_word = |
4760 * a_pos = |
4761 */
4762 *c_pos = right_word = left_word + 1; /* Set resulting precision */
4763 /* be equal to that of c */
4764 if (a->Prec >= c->MaxPrec) {
4765 /*
4766 * a = xxxxxxAxxx
4767 * c = xxxxxx
4768 * a_pos = |
4769 */
4770 *a_pos = left_word;
4771 if (*a_pos <= round_limit) {
4772 *av = a->frac[*a_pos]; /* av is 'A' shown in above. */
4773 }
4774 }
4775 else {
4776 /*
4777 * a = xxxxxxx
4778 * c = xxxxxxxxxx
4779 * a_pos = |
4780 */
4781 *a_pos = a->Prec;
4782 }
4783 if (b->Prec + word_shift >= c->MaxPrec) {
4784 /*
4785 * a = xxxxxxxxx
4786 * b = xxxxxxxBxxx
4787 * c = xxxxxxxxxxx
4788 * b_pos = |
4789 */
4790 if (c->MaxPrec >= word_shift + 1) {
4791 *b_pos = c->MaxPrec - word_shift - 1;
4792 if (*b_pos + word_shift <= round_limit) {
4793 *bv = b->frac[*b_pos];
4794 }
4795 }
4796 else {
4797 *b_pos = -1L;
4798 }
4799 }
4800 else {
4801 /*
4802 * a = xxxxxxxxxxxxxxxx
4803 * b = xxxxxx
4804 * c = xxxxxxxxxxxxx
4805 * b_pos = |
4806 */
4807 *b_pos = b->Prec;
4808 }
4809 }
4810 else { /* The MaxPrec of c - 1 > The Prec of a + b */
4811 /*
4812 * a = xxxxxxx
4813 * b = xxxxxx
4814 * c = xxxxxxxxxxx
4815 * c_pos = |
4816 */
4817 *b_pos = b->Prec;
4818 *a_pos = a->Prec;
4819 *c_pos = right_word + 1;
4820 }
4821 c->Prec = *c_pos;
4822 c->exponent = a->exponent;
4823 if (!AddExponent(c, 1)) return (size_t)-1L;
4824 return word_shift;
4825 }
4826
4827 /*
4828 * Return number of significant digits
4829 * c = a * b , Where a = a0a1a2 ... an
4830 * b = b0b1b2 ... bm
4831 * c = c0c1c2 ... cl
4832 * a0 a1 ... an * bm
4833 * a0 a1 ... an * bm-1
4834 * . . .
4835 * . . .
4836 * a0 a1 .... an * b0
4837 * +_____________________________
4838 * c0 c1 c2 ...... cl
4839 * nc <---|
4840 * MaxAB |--------------------|
4841 */
4842 VP_EXPORT size_t
4843 VpMult(Real *c, Real *a, Real *b)
4844 {
4845 size_t MxIndA, MxIndB, MxIndAB, MxIndC;
4846 size_t ind_c, i, ii, nc;
4847 size_t ind_as, ind_ae, ind_bs;
4848 BDIGIT carry;
4849 BDIGIT_DBL s;
4850 Real *w;
4851
4852 #ifdef BIGDECIMAL_DEBUG
4853 if (gfDebug) {
4854 VPrint(stdout, "VpMult(Enter): a=% \n", a);
4855 VPrint(stdout, " b=% \n", b);
4856 }
4857 #endif /* BIGDECIMAL_DEBUG */
4858
4859 if (!VpIsDefOP(c, a, b, OP_SW_MULT)) return 0; /* No significant digit */
4860
4861 if (VpIsZero(a) || VpIsZero(b)) {
4862 /* at least a or b is zero */
4863 VpSetZero(c, VpGetSign(a) * VpGetSign(b));
4864 return 1; /* 0: 1 significant digit */
4865 }
4866
4867 if (VpIsOne(a)) {
4868 VpAsgn(c, b, VpGetSign(a));
4869 goto Exit;
4870 }
4871 if (VpIsOne(b)) {
4872 VpAsgn(c, a, VpGetSign(b));
4873 goto Exit;
4874 }
4875 if (b->Prec > a->Prec) {
4876 /* Adjust so that digits(a)>digits(b) */
4877 w = a;
4878 a = b;
4879 b = w;
4880 }
4881 w = NULL;
4882 MxIndA = a->Prec - 1;
4883 MxIndB = b->Prec - 1;
4884 MxIndC = c->MaxPrec - 1;
4885 MxIndAB = a->Prec + b->Prec - 1;
4886
4887 if (MxIndC < MxIndAB) { /* The Max. prec. of c < Prec(a)+Prec(b) */
4888 w = c;
4889 c = VpAlloc((size_t)((MxIndAB + 1) * BASE_FIG), "#0", 1, 1);
4890 MxIndC = MxIndAB;
4891 }
4892
4893 /* set LHSV c info */
4894
4895 c->exponent = a->exponent; /* set exponent */
4896 if (!AddExponent(c, b->exponent)) {
4897 if (w) VpFree(c);
4898 return 0;
4899 }
4900 VpSetSign(c, VpGetSign(a) * VpGetSign(b)); /* set sign */
4901 carry = 0;
4902 nc = ind_c = MxIndAB;
4903 memset(c->frac, 0, (nc + 1) * sizeof(BDIGIT)); /* Initialize c */
4904 c->Prec = nc + 1; /* set precision */
4905 for (nc = 0; nc < MxIndAB; ++nc, --ind_c) {
4906 if (nc < MxIndB) { /* The left triangle of the Fig. */
4907 ind_as = MxIndA - nc;
4908 ind_ae = MxIndA;
4909 ind_bs = MxIndB;
4910 }
4911 else if (nc <= MxIndA) { /* The middle rectangular of the Fig. */
4912 ind_as = MxIndA - nc;
4913 ind_ae = MxIndA - (nc - MxIndB);
4914 ind_bs = MxIndB;
4915 }
4916 else /* if (nc > MxIndA) */ { /* The right triangle of the Fig. */
4917 ind_as = 0;
4918 ind_ae = MxIndAB - nc - 1;
4919 ind_bs = MxIndB - (nc - MxIndA);
4920 }
4921
4922 for (i = ind_as; i <= ind_ae; ++i) {
4923 s = (BDIGIT_DBL)a->frac[i] * b->frac[ind_bs--];
4924 carry = (BDIGIT)(s / BASE);
4925 s -= (BDIGIT_DBL)carry * BASE;
4926 c->frac[ind_c] += (BDIGIT)s;
4927 if (c->frac[ind_c] >= BASE) {
4928 s = c->frac[ind_c] / BASE;
4929 carry += (BDIGIT)s;
4930 c->frac[ind_c] -= (BDIGIT)(s * BASE);
4931 }
4932 if (carry) {
4933 ii = ind_c;
4934 while (ii-- > 0) {
4935 c->frac[ii] += carry;
4936 if (c->frac[ii] >= BASE) {
4937 carry = c->frac[ii] / BASE;
4938 c->frac[ii] -= (carry * BASE);
4939 }
4940 else {
4941 break;
4942 }
4943 }
4944 }
4945 }
4946 }
4947 if (w != NULL) { /* free work variable */
4948 VpNmlz(c);
4949 VpAsgn(w, c, 1);
4950 VpFree(c);
4951 c = w;
4952 }
4953 else {
4954 VpLimitRound(c,0);
4955 }
4956
4957 Exit:
4958 #ifdef BIGDECIMAL_DEBUG
4959 if (gfDebug) {
4960 VPrint(stdout, "VpMult(c=a*b): c=% \n", c);
4961 VPrint(stdout, " a=% \n", a);
4962 VPrint(stdout, " b=% \n", b);
4963 }
4964 #endif /*BIGDECIMAL_DEBUG */
4965 return c->Prec*BASE_FIG;
4966 }
4967
4968 /*
4969 * c = a / b, remainder = r
4970 */
4971 VP_EXPORT size_t
4972 VpDivd(Real *c, Real *r, Real *a, Real *b)
4973 {
4974 size_t word_a, word_b, word_c, word_r;
4975 size_t i, n, ind_a, ind_b, ind_c, ind_r;
4976 size_t nLoop;
4977 BDIGIT_DBL q, b1, b1p1, b1b2, b1b2p1, r1r2;
4978 BDIGIT borrow, borrow1, borrow2;
4979 BDIGIT_DBL qb;
4980
4981 #ifdef BIGDECIMAL_DEBUG
4982 if (gfDebug) {
4983 VPrint(stdout, " VpDivd(c=a/b) a=% \n", a);
4984 VPrint(stdout, " b=% \n", b);
4985 }
4986 #endif /*BIGDECIMAL_DEBUG */
4987
4988 VpSetNaN(r);
4989 if (!VpIsDefOP(c, a, b, OP_SW_DIV)) goto Exit;
4990 if (VpIsZero(a) && VpIsZero(b)) {
4991 VpSetNaN(c);
4992 return VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'", 0);
4993 }
4994 if (VpIsZero(b)) {
4995 VpSetInf(c, VpGetSign(a) * VpGetSign(b));
4996 return VpException(VP_EXCEPTION_ZERODIVIDE, "Divide by zero", 0);
4997 }
4998 if (VpIsZero(a)) {
4999 /* numerator a is zero */
5000 VpSetZero(c, VpGetSign(a) * VpGetSign(b));
5001 VpSetZero(r, VpGetSign(a) * VpGetSign(b));
5002 goto Exit;
5003 }
5004 if (VpIsOne(b)) {
5005 /* divide by one */
5006 VpAsgn(c, a, VpGetSign(b));
5007 VpSetZero(r, VpGetSign(a));
5008 goto Exit;
5009 }
5010
5011 word_a = a->Prec;
5012 word_b = b->Prec;
5013 word_c = c->MaxPrec;
5014 word_r = r->MaxPrec;
5015
5016 ind_c = 0;
5017 ind_r = 1;
5018
5019 if (word_a >= word_r) goto space_error;
5020
5021 r->frac[0] = 0;
5022 while (ind_r <= word_a) {
5023 r->frac[ind_r] = a->frac[ind_r - 1];
5024 ++ind_r;
5025 }
5026
5027 while (ind_r < word_r) r->frac[ind_r++] = 0;
5028 while (ind_c < word_c) c->frac[ind_c++] = 0;
5029
5030 /* initial procedure */
5031 b1 = b1p1 = b->frac[0];
5032 if (b->Prec <= 1) {
5033 b1b2p1 = b1b2 = b1p1 * BASE;
5034 }
5035 else {
5036 b1p1 = b1 + 1;
5037 b1b2p1 = b1b2 = b1 * BASE + b->frac[1];
5038 if (b->Prec > 2) ++b1b2p1;
5039 }
5040
5041 /* */
5042 /* loop start */
5043 ind_c = word_r - 1;
5044 nLoop = Min(word_c,ind_c);
5045 ind_c = 1;
5046 while (ind_c < nLoop) {
5047 if (r->frac[ind_c] == 0) {
5048 ++ind_c;
5049 continue;
5050 }
5051 r1r2 = (BDIGIT_DBL)r->frac[ind_c] * BASE + r->frac[ind_c + 1];
5052 if (r1r2 == b1b2) {
5053 /* The first two word digits is the same */
5054 ind_b = 2;
5055 ind_a = ind_c + 2;
5056 while (ind_b < word_b) {
5057 if (r->frac[ind_a] < b->frac[ind_b]) goto div_b1p1;
5058 if (r->frac[ind_a] > b->frac[ind_b]) break;
5059 ++ind_a;
5060 ++ind_b;
5061 }
5062 /* The first few word digits of r and b is the same and */
5063 /* the first different word digit of w is greater than that */
5064 /* of b, so quotient is 1 and just subtract b from r. */
5065 borrow = 0; /* quotient=1, then just r-b */
5066 ind_b = b->Prec - 1;
5067 ind_r = ind_c + ind_b;
5068 if (ind_r >= word_r) goto space_error;
5069 n = ind_b;
5070 for (i = 0; i <= n; ++i) {
5071 if (r->frac[ind_r] < b->frac[ind_b] + borrow) {
5072 r->frac[ind_r] += (BASE - (b->frac[ind_b] + borrow));
5073 borrow = 1;
5074 }
5075 else {
5076 r->frac[ind_r] = r->frac[ind_r] - b->frac[ind_b] - borrow;
5077 borrow = 0;
5078 }
5079 --ind_r;
5080 --ind_b;
5081 }
5082 ++c->frac[ind_c];
5083 goto carry;
5084 }
5085 /* The first two word digits is not the same, */
5086 /* then compare magnitude, and divide actually. */
5087 if (r1r2 >= b1b2p1) {
5088 q = r1r2 / b1b2p1; /* q == (BDIGIT)q */
5089 c->frac[ind_c] += (BDIGIT)q;
5090 ind_r = b->Prec + ind_c - 1;
5091 goto sub_mult;
5092 }
5093
5094 div_b1p1:
5095 if (ind_c + 1 >= word_c) goto out_side;
5096 q = r1r2 / b1p1; /* q == (BDIGIT)q */
5097 c->frac[ind_c + 1] += (BDIGIT)q;
5098 ind_r = b->Prec + ind_c;
5099
5100 sub_mult:
5101 borrow1 = borrow2 = 0;
5102 ind_b = word_b - 1;
5103 if (ind_r >= word_r) goto space_error;
5104 n = ind_b;
5105 for (i = 0; i <= n; ++i) {
5106 /* now, perform r = r - q * b */
5107 qb = q * b->frac[ind_b];
5108 if (qb < BASE) borrow1 = 0;
5109 else {
5110 borrow1 = (BDIGIT)(qb / BASE);
5111 qb -= (BDIGIT_DBL)borrow1 * BASE; /* get qb < BASE */
5112 }
5113 if(r->frac[ind_r] < qb) {
5114 r->frac[ind_r] += (BDIGIT)(BASE - qb);
5115 borrow2 = borrow2 + borrow1 + 1;
5116 }
5117 else {
5118 r->frac[ind_r] -= (BDIGIT)qb;
5119 borrow2 += borrow1;
5120 }
5121 if (borrow2) {
5122 if(r->frac[ind_r - 1] < borrow2) {
5123 r->frac[ind_r - 1] += (BASE - borrow2);
5124 borrow2 = 1;
5125 }
5126 else {
5127 r->frac[ind_r - 1] -= borrow2;
5128 borrow2 = 0;
5129 }
5130 }
5131 --ind_r;
5132 --ind_b;
5133 }
5134
5135 r->frac[ind_r] -= borrow2;
5136 carry:
5137 ind_r = ind_c;
5138 while (c->frac[ind_r] >= BASE) {
5139 c->frac[ind_r] -= BASE;
5140 --ind_r;
5141 ++c->frac[ind_r];
5142 }
5143 }
5144 /* End of operation, now final arrangement */
5145 out_side:
5146 c->Prec = word_c;
5147 c->exponent = a->exponent;
5148 if (!AddExponent(c, 2)) return 0;
5149 if (!AddExponent(c, -(b->exponent))) return 0;
5150
5151 VpSetSign(c, VpGetSign(a) * VpGetSign(b));
5152 VpNmlz(c); /* normalize c */
5153 r->Prec = word_r;
5154 r->exponent = a->exponent;
5155 if (!AddExponent(r, 1)) return 0;
5156 VpSetSign(r, VpGetSign(a));
5157 VpNmlz(r); /* normalize r(remainder) */
5158 goto Exit;
5159
5160 space_error:
5161 #ifdef BIGDECIMAL_DEBUG
5162 if (gfDebug) {
5163 printf(" word_a=%"PRIuSIZE"\n", word_a);
5164 printf(" word_b=%"PRIuSIZE"\n", word_b);
5165 printf(" word_c=%"PRIuSIZE"\n", word_c);
5166 printf(" word_r=%"PRIuSIZE"\n", word_r);
5167 printf(" ind_r =%"PRIuSIZE"\n", ind_r);
5168 }
5169 #endif /* BIGDECIMAL_DEBUG */
5170 rb_bug("ERROR(VpDivd): space for remainder too small.");
5171
5172 Exit:
5173 #ifdef BIGDECIMAL_DEBUG
5174 if (gfDebug) {
5175 VPrint(stdout, " VpDivd(c=a/b), c=% \n", c);
5176 VPrint(stdout, " r=% \n", r);
5177 }
5178 #endif /* BIGDECIMAL_DEBUG */
5179 return c->Prec * BASE_FIG;
5180 }
5181
5182 /*
5183 * Input a = 00000xxxxxxxx En(5 preceding zeros)
5184 * Output a = xxxxxxxx En-5
5185 */
5186 static int
5187 VpNmlz(Real *a)
5188 {
5189 size_t ind_a, i;
5190
5191 if (!VpIsDef(a)) goto NoVal;
5192 if (VpIsZero(a)) goto NoVal;
5193
5194 ind_a = a->Prec;
5195 while (ind_a--) {
5196 if (a->frac[ind_a]) {
5197 a->Prec = ind_a + 1;
5198 i = 0;
5199 while (a->frac[i] == 0) ++i; /* skip the first few zeros */
5200 if (i) {
5201 a->Prec -= i;
5202 if (!AddExponent(a, -(SIGNED_VALUE)i)) return 0;
5203 memmove(&a->frac[0], &a->frac[i], a->Prec*sizeof(BDIGIT));
5204 }
5205 return 1;
5206 }
5207 }
5208 /* a is zero(no non-zero digit) */
5209 VpSetZero(a, VpGetSign(a));
5210 return 0;
5211
5212 NoVal:
5213 a->frac[0] = 0;
5214 a->Prec = 1;
5215 return 0;
5216 }
5217
5218 /*
5219 * VpComp = 0 ... if a=b,
5220 * Pos ... a>b,
5221 * Neg ... a<b.
5222 * 999 ... result undefined(NaN)
5223 */
5224 VP_EXPORT int
5225 VpComp(Real *a, Real *b)
5226 {
5227 int val;
5228 size_t mx, ind;
5229 int e;
5230 val = 0;
5231 if (VpIsNaN(a) || VpIsNaN(b)) return 999;
5232 if (!VpIsDef(a)) {
5233 if (!VpIsDef(b)) e = a->sign - b->sign;
5234 else e = a->sign;
5235
5236 if (e > 0) return 1;
5237 else if (e < 0) return -1;
5238 else return 0;
5239 }
5240 if (!VpIsDef(b)) {
5241 e = -b->sign;
5242 if (e > 0) return 1;
5243 else return -1;
5244 }
5245 /* Zero check */
5246 if (VpIsZero(a)) {
5247 if (VpIsZero(b)) return 0; /* both zero */
5248 val = -VpGetSign(b);
5249 goto Exit;
5250 }
5251 if (VpIsZero(b)) {
5252 val = VpGetSign(a);
5253 goto Exit;
5254 }
5255
5256 /* compare sign */
5257 if (VpGetSign(a) > VpGetSign(b)) {
5258 val = 1; /* a>b */
5259 goto Exit;
5260 }
5261 if (VpGetSign(a) < VpGetSign(b)) {
5262 val = -1; /* a<b */
5263 goto Exit;
5264 }
5265
5266 /* a and b have same sign, && sign!=0,then compare exponent */
5267 if (a->exponent > b->exponent) {
5268 val = VpGetSign(a);
5269 goto Exit;
5270 }
5271 if (a->exponent < b->exponent) {
5272 val = -VpGetSign(b);
5273 goto Exit;
5274 }
5275
5276 /* a and b have same exponent, then compare their significand. */
5277 mx = (a->Prec < b->Prec) ? a->Prec : b->Prec;
5278 ind = 0;
5279 while (ind < mx) {
5280 if (a->frac[ind] > b->frac[ind]) {
5281 val = VpGetSign(a);
5282 goto Exit;
5283 }
5284 if (a->frac[ind] < b->frac[ind]) {
5285 val = -VpGetSign(b);
5286 goto Exit;
5287 }
5288 ++ind;
5289 }
5290 if (a->Prec > b->Prec) {
5291 val = VpGetSign(a);
5292 }
5293 else if (a->Prec < b->Prec) {
5294 val = -VpGetSign(b);
5295 }
5296
5297 Exit:
5298 if (val > 1) val = 1;
5299 else if (val < -1) val = -1;
5300
5301 #ifdef BIGDECIMAL_DEBUG
5302 if (gfDebug) {
5303 VPrint(stdout, " VpComp a=%\n", a);
5304 VPrint(stdout, " b=%\n", b);
5305 printf(" ans=%d\n", val);
5306 }
5307 #endif /* BIGDECIMAL_DEBUG */
5308 return (int)val;
5309 }
5310
5311 /*
5312 * cntl_chr ... ASCIIZ Character, print control characters
5313 * Available control codes:
5314 * % ... VP variable. To print '%', use '%%'.
5315 * \n ... new line
5316 * \b ... backspace
5317 * \t ... tab
5318 * Note: % must not appear more than once
5319 * a ... VP variable to be printed
5320 */
5321 #ifdef BIGDECIMAL_ENABLE_VPRINT
5322 static int
5323 VPrint(FILE *fp, const char *cntl_chr, Real *a)
5324 {
5325 size_t i, j, nc, nd, ZeroSup, sep = 10;
5326 BDIGIT m, e, nn;
5327
5328 j = 0;
5329 nd = nc = 0; /* nd : number of digits in fraction part(every 10 digits, */
5330 /* nd<=10). */
5331 /* nc : number of characters printed */
5332 ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
5333 while (*(cntl_chr + j)) {
5334 if (*(cntl_chr + j) == '%' && *(cntl_chr + j + 1) != '%') {
5335 nc = 0;
5336 if (VpIsNaN(a)) {
5337 fprintf(fp, SZ_NaN);
5338 nc += 8;
5339 }
5340 else if (VpIsPosInf(a)) {
5341 fprintf(fp, SZ_INF);
5342 nc += 8;
5343 }
5344 else if (VpIsNegInf(a)) {
5345 fprintf(fp, SZ_NINF);
5346 nc += 9;
5347 }
5348 else if (!VpIsZero(a)) {
5349 if (BIGDECIMAL_NEGATIVE_P(a)) {
5350 fprintf(fp, "-");
5351 ++nc;
5352 }
5353 nc += fprintf(fp, "0.");
5354 switch (*(cntl_chr + j + 1)) {
5355 default:
5356 break;
5357
5358 case '0': case 'z':
5359 ZeroSup = 0;
5360 ++j;
5361 sep = cntl_chr[j] == 'z' ? RMPD_COMPONENT_FIGURES : 10;
5362 break;
5363 }
5364 for (i = 0; i < a->Prec; ++i) {
5365 m = BASE1;
5366 e = a->frac[i];
5367 while (m) {
5368 nn = e / m;
5369 if (!ZeroSup || nn) {
5370 nc += fprintf(fp, "%lu", (unsigned long)nn); /* The leading zero(s) */
5371 /* as 0.00xx will not */
5372 /* be printed. */
5373 ++nd;
5374 ZeroSup = 0; /* Set to print succeeding zeros */
5375 }
5376 if (nd >= sep) { /* print ' ' after every 10 digits */
5377 nd = 0;
5378 nc += fprintf(fp, " ");
5379 }
5380 e = e - nn * m;
5381 m /= 10;
5382 }
5383 }
5384 nc += fprintf(fp, "E%"PRIdSIZE, VpExponent10(a));
5385 nc += fprintf(fp, " (%"PRIdVALUE", %lu, %lu)", a->exponent, a->Prec, a->MaxPrec);
5386 }
5387 else {
5388 nc += fprintf(fp, "0.0");
5389 }
5390 }
5391 else {
5392 ++nc;
5393 if (*(cntl_chr + j) == '\\') {
5394 switch (*(cntl_chr + j + 1)) {
5395 case 'n':
5396 fprintf(fp, "\n");
5397 ++j;
5398 break;
5399 case 't':
5400 fprintf(fp, "\t");
5401 ++j;
5402 break;
5403 case 'b':
5404 fprintf(fp, "\n");
5405 ++j;
5406 break;
5407 default:
5408 fprintf(fp, "%c", *(cntl_chr + j));
5409 break;
5410 }
5411 }
5412 else {
5413 fprintf(fp, "%c", *(cntl_chr + j));
5414 if (*(cntl_chr + j) == '%') ++j;
5415 }
5416 }
5417 j++;
5418 }
5419
5420 return (int)nc;
5421 }
5422 #endif
5423
5424 static void
5425 VpFormatSt(char *psz, size_t fFmt)
5426 {
5427 size_t ie, i, nf = 0;
5428 char ch;
5429
5430 if (fFmt == 0) return;
5431
5432 ie = strlen(psz);
5433 for (i = 0; i < ie; ++i) {
5434 ch = psz[i];
5435 if (!ch) break;
5436 if (ISSPACE(ch) || ch=='-' || ch=='+') continue;
5437 if (ch == '.') { nf = 0; continue; }
5438 if (ch == 'E' || ch == 'e') break;
5439
5440 if (++nf > fFmt) {
5441 memmove(psz + i + 1, psz + i, ie - i + 1);
5442 ++ie;
5443 nf = 0;
5444 psz[i] = ' ';
5445 }
5446 }
5447 }
5448
5449 VP_EXPORT ssize_t
5450 VpExponent10(Real *a)
5451 {
5452 ssize_t ex;
5453 size_t n;
5454
5455 if (!VpHasVal(a)) return 0;
5456
5457 ex = a->exponent * (ssize_t)BASE_FIG;
5458 n = BASE1;
5459 while ((a->frac[0] / n) == 0) {
5460 --ex;
5461 n /= 10;
5462 }
5463 return ex;
5464 }
5465
5466 VP_EXPORT void
5467 VpSzMantissa(Real *a,char *psz)
5468 {
5469 size_t i, n, ZeroSup;
5470 BDIGIT_DBL m, e, nn;
5471
5472 if (VpIsNaN(a)) {
5473 sprintf(psz, SZ_NaN);
5474 return;
5475 }
5476 if (VpIsPosInf(a)) {
5477 sprintf(psz, SZ_INF);
5478 return;
5479 }
5480 if (VpIsNegInf(a)) {
5481 sprintf(psz, SZ_NINF);
5482 return;
5483 }
5484
5485 ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
5486 if (!VpIsZero(a)) {
5487 if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
5488 n = a->Prec;
5489 for (i = 0; i < n; ++i) {
5490 m = BASE1;
5491 e = a->frac[i];
5492 while (m) {
5493 nn = e / m;
5494 if (!ZeroSup || nn) {
5495 sprintf(psz, "%lu", (unsigned long)nn); /* The leading zero(s) */
5496 psz += strlen(psz);
5497 /* as 0.00xx will be ignored. */
5498 ZeroSup = 0; /* Set to print succeeding zeros */
5499 }
5500 e = e - nn * m;
5501 m /= 10;
5502 }
5503 }
5504 *psz = 0;
5505 while (psz[-1] == '0') *(--psz) = 0;
5506 }
5507 else {
5508 if (VpIsPosZero(a)) sprintf(psz, "0");
5509 else sprintf(psz, "-0");
5510 }
5511 }
5512
5513 VP_EXPORT int
5514 VpToSpecialString(Real *a,char *psz,int fPlus)
5515 /* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
5516 {
5517 if (VpIsNaN(a)) {
5518 sprintf(psz,SZ_NaN);
5519 return 1;
5520 }
5521
5522 if (VpIsPosInf(a)) {
5523 if (fPlus == 1) {
5524 *psz++ = ' ';
5525 }
5526 else if (fPlus == 2) {
5527 *psz++ = '+';
5528 }
5529 sprintf(psz, SZ_INF);
5530 return 1;
5531 }
5532 if (VpIsNegInf(a)) {
5533 sprintf(psz, SZ_NINF);
5534 return 1;
5535 }
5536 if (VpIsZero(a)) {
5537 if (VpIsPosZero(a)) {
5538 if (fPlus == 1) sprintf(psz, " 0.0");
5539 else if (fPlus == 2) sprintf(psz, "+0.0");
5540 else sprintf(psz, "0.0");
5541 }
5542 else sprintf(psz, "-0.0");
5543 return 1;
5544 }
5545 return 0;
5546 }
5547
5548 VP_EXPORT void
5549 VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
5550 /* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
5551 {
5552 size_t i, n, ZeroSup;
5553 BDIGIT shift, m, e, nn;
5554 char *pszSav = psz;
5555 ssize_t ex;
5556
5557 if (VpToSpecialString(a, psz, fPlus)) return;
5558
5559 ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
5560
5561 if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
5562 else if (fPlus == 1) *psz++ = ' ';
5563 else if (fPlus == 2) *psz++ = '+';
5564
5565 *psz++ = '0';
5566 *psz++ = '.';
5567 n = a->Prec;
5568 for (i = 0; i < n; ++i) {
5569 m = BASE1;
5570 e = a->frac[i];
5571 while (m) {
5572 nn = e / m;
5573 if (!ZeroSup || nn) {
5574 sprintf(psz, "%lu", (unsigned long)nn); /* The reading zero(s) */
5575 psz += strlen(psz);
5576 /* as 0.00xx will be ignored. */
5577 ZeroSup = 0; /* Set to print succeeding zeros */
5578 }
5579 e = e - nn * m;
5580 m /= 10;
5581 }
5582 }
5583 ex = a->exponent * (ssize_t)BASE_FIG;
5584 shift = BASE1;
5585 while (a->frac[0] / shift == 0) {
5586 --ex;
5587 shift /= 10;
5588 }
5589 while (psz[-1] == '0') {
5590 *(--psz) = 0;
5591 }
5592 sprintf(psz, "e%"PRIdSIZE, ex);
5593 if (fFmt) VpFormatSt(pszSav, fFmt);
5594 }
5595
5596 VP_EXPORT void
5597 VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
5598 /* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
5599 {
5600 size_t i, n;
5601 BDIGIT m, e, nn;
5602 char *pszSav = psz;
5603 ssize_t ex;
5604
5605 if (VpToSpecialString(a, psz, fPlus)) return;
5606
5607 if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
5608 else if (fPlus == 1) *psz++ = ' ';
5609 else if (fPlus == 2) *psz++ = '+';
5610
5611 n = a->Prec;
5612 ex = a->exponent;
5613 if (ex <= 0) {
5614 *psz++ = '0';*psz++ = '.';
5615 while (ex < 0) {
5616 for (i=0; i < BASE_FIG; ++i) *psz++ = '0';
5617 ++ex;
5618 }
5619 ex = -1;
5620 }
5621
5622 for (i = 0; i < n; ++i) {
5623 --ex;
5624 if (i == 0 && ex >= 0) {
5625 sprintf(psz, "%lu", (unsigned long)a->frac[i]);
5626 psz += strlen(psz);
5627 }
5628 else {
5629 m = BASE1;
5630 e = a->frac[i];
5631 while (m) {
5632 nn = e / m;
5633 *psz++ = (char)(nn + '0');
5634 e = e - nn * m;
5635 m /= 10;
5636 }
5637 }
5638 if (ex == 0) *psz++ = '.';
5639 }
5640 while (--ex>=0) {
5641 m = BASE;
5642 while (m /= 10) *psz++ = '0';
5643 if (ex == 0) *psz++ = '.';
5644 }
5645 *psz = 0;
5646 while (psz[-1] == '0') *(--psz) = 0;
5647 if (psz[-1] == '.') sprintf(psz, "0");
5648 if (fFmt) VpFormatSt(pszSav, fFmt);
5649 }
5650
5651 /*
5652 * [Output]
5653 * a[] ... variable to be assigned the value.
5654 * [Input]
5655 * int_chr[] ... integer part(may include '+/-').
5656 * ni ... number of characters in int_chr[],not including '+/-'.
5657 * frac[] ... fraction part.
5658 * nf ... number of characters in frac[].
5659 * exp_chr[] ... exponent part(including '+/-').
5660 * ne ... number of characters in exp_chr[],not including '+/-'.
5661 */
5662 VP_EXPORT int
5663 VpCtoV(Real *a, const char *int_chr, size_t ni, const char *frac, size_t nf, const char *exp_chr, size_t ne)
5664 {
5665 size_t i, j, ind_a, ma, mi, me;
5666 SIGNED_VALUE e, es, eb, ef;
5667 int sign, signe, exponent_overflow;
5668
5669 /* get exponent part */
5670 e = 0;
5671 ma = a->MaxPrec;
5672 mi = ni;
5673 me = ne;
5674 signe = 1;
5675 exponent_overflow = 0;
5676 memset(a->frac, 0, ma * sizeof(BDIGIT));
5677 if (ne > 0) {
5678 i = 0;
5679 if (exp_chr[0] == '-') {
5680 signe = -1;
5681 ++i;
5682 ++me;
5683 }
5684 else if (exp_chr[0] == '+') {
5685 ++i;
5686 ++me;
5687 }
5688 while (i < me) {
5689 if (MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG)) {
5690 es = e;
5691 goto exp_overflow;
5692 }
5693 es = e * (SIGNED_VALUE)BASE_FIG;
5694 if (MUL_OVERFLOW_SIGNED_VALUE_P(e, 10) ||
5695 SIGNED_VALUE_MAX - (exp_chr[i] - '0') < e * 10)
5696 goto exp_overflow;
5697 e = e * 10 + exp_chr[i] - '0';
5698 if (MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG))
5699 goto exp_overflow;
5700 if (es > (SIGNED_VALUE)(e * BASE_FIG)) {
5701 exp_overflow:
5702 exponent_overflow = 1;
5703 e = es; /* keep sign */
5704 break;
5705 }
5706 ++i;
5707 }
5708 }
5709
5710 /* get integer part */
5711 i = 0;
5712 sign = 1;
5713 if (1 /*ni >= 0*/) {
5714 if (int_chr[0] == '-') {
5715 sign = -1;
5716 ++i;
5717 ++mi;
5718 }
5719 else if (int_chr[0] == '+') {
5720 ++i;
5721 ++mi;
5722 }
5723 }
5724
5725 e = signe * e; /* e: The value of exponent part. */
5726 e = e + ni; /* set actual exponent size. */
5727
5728 if (e > 0) signe = 1;
5729 else signe = -1;
5730
5731 /* Adjust the exponent so that it is the multiple of BASE_FIG. */
5732 j = 0;
5733 ef = 1;
5734 while (ef) {
5735 if (e >= 0) eb = e;
5736 else eb = -e;
5737 ef = eb / (SIGNED_VALUE)BASE_FIG;
5738 ef = eb - ef * (SIGNED_VALUE)BASE_FIG;
5739 if (ef) {
5740 ++j; /* Means to add one more preceding zero */
5741 ++e;
5742 }
5743 }
5744
5745 eb = e / (SIGNED_VALUE)BASE_FIG;
5746
5747 if (exponent_overflow) {
5748 int zero = 1;
5749 for ( ; i < mi && zero; i++) zero = int_chr[i] == '0';
5750 for (i = 0; i < nf && zero; i++) zero = frac[i] == '0';
5751 if (!zero && signe > 0) {
5752 VpSetInf(a, sign);
5753 VpException(VP_EXCEPTION_INFINITY, "exponent overflow",0);
5754 }
5755 else VpSetZero(a, sign);
5756 return 1;
5757 }
5758
5759 ind_a = 0;
5760 while (i < mi) {
5761 a->frac[ind_a] = 0;
5762 while (j < BASE_FIG && i < mi) {
5763 a->frac[ind_a] = a->frac[ind_a] * 10 + int_chr[i] - '0';
5764 ++j;
5765 ++i;
5766 }
5767 if (i < mi) {
5768 ++ind_a;
5769 if (ind_a >= ma) goto over_flow;
5770 j = 0;
5771 }
5772 }
5773
5774 /* get fraction part */
5775
5776 i = 0;
5777 while (i < nf) {
5778 while (j < BASE_FIG && i < nf) {
5779 a->frac[ind_a] = a->frac[ind_a] * 10 + frac[i] - '0';
5780 ++j;
5781 ++i;
5782 }
5783 if (i < nf) {
5784 ++ind_a;
5785 if (ind_a >= ma) goto over_flow;
5786 j = 0;
5787 }
5788 }
5789 goto Final;
5790
5791 over_flow:
5792 rb_warn("Conversion from String to BigDecimal overflow (last few digits discarded).");
5793
5794 Final:
5795 if (ind_a >= ma) ind_a = ma - 1;
5796 while (j < BASE_FIG) {
5797 a->frac[ind_a] = a->frac[ind_a] * 10;
5798 ++j;
5799 }
5800 a->Prec = ind_a + 1;
5801 a->exponent = eb;
5802 VpSetSign(a, sign);
5803 VpNmlz(a);
5804 return 1;
5805 }
5806
5807 /*
5808 * [Input]
5809 * *m ... Real
5810 * [Output]
5811 * *d ... fraction part of m(d = 0.xxxxxxx). where # of 'x's is fig.
5812 * *e ... exponent of m.
5813 * DBLE_FIG ... Number of digits in a double variable.
5814 *
5815 * m -> d*10**e, 0<d<BASE
5816 * [Returns]
5817 * 0 ... Zero
5818 * 1 ... Normal
5819 * 2 ... Infinity
5820 * -1 ... NaN
5821 */
5822 VP_EXPORT int
5823 VpVtoD(double *d, SIGNED_VALUE *e, Real *m)
5824 {
5825 size_t ind_m, mm, fig;
5826 double div;
5827 int f = 1;
5828
5829 if (VpIsNaN(m)) {
5830 *d = VpGetDoubleNaN();
5831 *e = 0;
5832 f = -1; /* NaN */
5833 goto Exit;
5834 }
5835 else if (VpIsPosZero(m)) {
5836 *d = 0.0;
5837 *e = 0;
5838 f = 0;
5839 goto Exit;
5840 }
5841 else if (VpIsNegZero(m)) {
5842 *d = VpGetDoubleNegZero();
5843 *e = 0;
5844 f = 0;
5845 goto Exit;
5846 }
5847 else if (VpIsPosInf(m)) {
5848 *d = VpGetDoublePosInf();
5849 *e = 0;
5850 f = 2;
5851 goto Exit;
5852 }
5853 else if (VpIsNegInf(m)) {
5854 *d = VpGetDoubleNegInf();
5855 *e = 0;
5856 f = 2;
5857 goto Exit;
5858 }
5859 /* Normal number */
5860 fig = (DBLE_FIG + BASE_FIG - 1) / BASE_FIG;
5861 ind_m = 0;
5862 mm = Min(fig, m->Prec);
5863 *d = 0.0;
5864 div = 1.;
5865 while (ind_m < mm) {
5866 div /= (double)BASE;
5867 *d = *d + (double)m->frac[ind_m++] * div;
5868 }
5869 *e = m->exponent * (SIGNED_VALUE)BASE_FIG;
5870 *d *= VpGetSign(m);
5871
5872 Exit:
5873 #ifdef BIGDECIMAL_DEBUG
5874 if (gfDebug) {
5875 VPrint(stdout, " VpVtoD: m=%\n", m);
5876 printf(" d=%e * 10 **%ld\n", *d, *e);
5877 printf(" DBLE_FIG = %d\n", DBLE_FIG);
5878 }
5879 #endif /*BIGDECIMAL_DEBUG */
5880 return f;
5881 }
5882
5883 /*
5884 * m <- d
5885 */
5886 VP_EXPORT void
5887 VpDtoV(Real *m, double d)
5888 {
5889 size_t ind_m, mm;
5890 SIGNED_VALUE ne;
5891 BDIGIT i;
5892 double val, val2;
5893
5894 if (isnan(d)) {
5895 VpSetNaN(m);
5896 goto Exit;
5897 }
5898 if (isinf(d)) {
5899 if (d > 0.0) VpSetPosInf(m);
5900 else VpSetNegInf(m);
5901 goto Exit;
5902 }
5903
5904 if (d == 0.0) {
5905 VpSetZero(m, 1);
5906 goto Exit;
5907 }
5908 val = (d > 0.) ? d : -d;
5909 ne = 0;
5910 if (val >= 1.0) {
5911 while (val >= 1.0) {
5912 val /= (double)BASE;
5913 ++ne;
5914 }
5915 }
5916 else {
5917 val2 = 1.0 / (double)BASE;
5918 while (val < val2) {
5919 val *= (double)BASE;
5920 --ne;
5921 }
5922 }
5923 /* Now val = 0.xxxxx*BASE**ne */
5924
5925 mm = m->MaxPrec;
5926 memset(m->frac, 0, mm * sizeof(BDIGIT));
5927 for (ind_m = 0; val > 0.0 && ind_m < mm; ind_m++) {
5928 val *= (double)BASE;
5929 i = (BDIGIT)val;
5930 val -= (double)i;
5931 m->frac[ind_m] = i;
5932 }
5933 if (ind_m >= mm) ind_m = mm - 1;
5934 VpSetSign(m, (d > 0.0) ? 1 : -1);
5935 m->Prec = ind_m + 1;
5936 m->exponent = ne;
5937
5938 VpInternalRound(m, 0, (m->Prec > 0) ? m->frac[m->Prec-1] : 0,
5939 (BDIGIT)(val*(double)BASE));
5940
5941 Exit:
5942 #ifdef BIGDECIMAL_DEBUG
5943 if (gfDebug) {
5944 printf("VpDtoV d=%30.30e\n", d);
5945 VPrint(stdout, " m=%\n", m);
5946 }
5947 #endif /* BIGDECIMAL_DEBUG */
5948 return;
5949 }
5950
5951 /*
5952 * m <- ival
5953 */
5954 #if 0 /* unused */
5955 VP_EXPORT void
5956 VpItoV(Real *m, SIGNED_VALUE ival)
5957 {
5958 size_t mm, ind_m;
5959 size_t val, v1, v2, v;
5960 int isign;
5961 SIGNED_VALUE ne;
5962
5963 if (ival == 0) {
5964 VpSetZero(m, 1);
5965 goto Exit;
5966 }
5967 isign = 1;
5968 val = ival;
5969 if (ival < 0) {
5970 isign = -1;
5971 val =(size_t)(-ival);
5972 }
5973 ne = 0;
5974 ind_m = 0;
5975 mm = m->MaxPrec;
5976 while (ind_m < mm) {
5977 m->frac[ind_m] = 0;
5978 ++ind_m;
5979 }
5980 ind_m = 0;
5981 while (val > 0) {
5982 if (val) {
5983 v1 = val;
5984 v2 = 1;
5985 while (v1 >= BASE) {
5986 v1 /= BASE;
5987 v2 *= BASE;
5988 }
5989 val = val - v2 * v1;
5990 v = v1;
5991 }
5992 else {
5993 v = 0;
5994 }
5995 m->frac[ind_m] = v;
5996 ++ind_m;
5997 ++ne;
5998 }
5999 m->Prec = ind_m - 1;
6000 m->exponent = ne;
6001 VpSetSign(m, isign);
6002 VpNmlz(m);
6003
6004 Exit:
6005 #ifdef BIGDECIMAL_DEBUG
6006 if (gfDebug) {
6007 printf(" VpItoV i=%d\n", ival);
6008 VPrint(stdout, " m=%\n", m);
6009 }
6010 #endif /* BIGDECIMAL_DEBUG */
6011 return;
6012 }
6013 #endif
6014
6015 /*
6016 * y = SQRT(x), y*y - x =>0
6017 */
6018 VP_EXPORT int
6019 VpSqrt(Real *y, Real *x)
6020 {
6021 Real *f = NULL;
6022 Real *r = NULL;
6023 size_t y_prec;
6024 SIGNED_VALUE n, e;
6025 SIGNED_VALUE prec;
6026 ssize_t nr;
6027 double val;
6028
6029 /* Zero or +Infinity ? */
6030 if (VpIsZero(x) || VpIsPosInf(x)) {
6031 VpAsgn(y,x,1);
6032 goto Exit;
6033 }
6034
6035 /* Negative ? */
6036 if (BIGDECIMAL_NEGATIVE_P(x)) {
6037 VpSetNaN(y);
6038 return VpException(VP_EXCEPTION_OP, "sqrt of negative value", 0);
6039 }
6040
6041 /* NaN ? */
6042 if (VpIsNaN(x)) {
6043 VpSetNaN(y);
6044 return VpException(VP_EXCEPTION_OP, "sqrt of 'NaN'(Not a Number)", 0);
6045 }
6046
6047 /* One ? */
6048 if (VpIsOne(x)) {
6049 VpSetOne(y);
6050 goto Exit;
6051 }
6052
6053 n = (SIGNED_VALUE)y->MaxPrec;
6054 if (x->MaxPrec > (size_t)n) n = (ssize_t)x->MaxPrec;
6055
6056 /* allocate temporally variables */
6057 f = VpAlloc(y->MaxPrec * (BASE_FIG + 2), "#1", 1, 1);
6058 r = VpAlloc((n + n) * (BASE_FIG + 2), "#1", 1, 1);
6059
6060 nr = 0;
6061 y_prec = y->MaxPrec;
6062
6063 prec = x->exponent - (ssize_t)y_prec;
6064 if (x->exponent > 0)
6065 ++prec;
6066 else
6067 --prec;
6068
6069 VpVtoD(&val, &e, x); /* val <- x */
6070 e /= (SIGNED_VALUE)BASE_FIG;
6071 n = e / 2;
6072 if (e - n * 2 != 0) {
6073 val /= BASE;
6074 n = (e + 1) / 2;
6075 }
6076 VpDtoV(y, sqrt(val)); /* y <- sqrt(val) */
6077 y->exponent += n;
6078 n = (SIGNED_VALUE)((DBLE_FIG + BASE_FIG - 1) / BASE_FIG);
6079 y->MaxPrec = Min((size_t)n , y_prec);
6080 f->MaxPrec = y->MaxPrec + 1;
6081 n = (SIGNED_VALUE)(y_prec * BASE_FIG);
6082 if (n < (SIGNED_VALUE)maxnr) n = (SIGNED_VALUE)maxnr;
6083 do {
6084 y->MaxPrec *= 2;
6085 if (y->MaxPrec > y_prec) y->MaxPrec = y_prec;
6086 f->MaxPrec = y->MaxPrec;
6087 VpDivd(f, r, x, y); /* f = x/y */
6088 VpAddSub(r, f, y, -1); /* r = f - y */
6089 VpMult(f, VpPt5, r); /* f = 0.5*r */
6090 if (VpIsZero(f)) goto converge;
6091 VpAddSub(r, f, y, 1); /* r = y + f */
6092 VpAsgn(y, r, 1); /* y = r */
6093 } while (++nr < n);
6094
6095 #ifdef BIGDECIMAL_DEBUG
6096 if (gfDebug) {
6097 printf("ERROR(VpSqrt): did not converge within %ld iterations.\n", nr);
6098 }
6099 #endif /* BIGDECIMAL_DEBUG */
6100 y->MaxPrec = y_prec;
6101
6102 converge:
6103 VpChangeSign(y, 1);
6104 #ifdef BIGDECIMAL_DEBUG
6105 if (gfDebug) {
6106 VpMult(r, y, y);
6107 VpAddSub(f, x, r, -1);
6108 printf("VpSqrt: iterations = %"PRIdSIZE"\n", nr);
6109 VPrint(stdout, " y =% \n", y);
6110 VPrint(stdout, " x =% \n", x);
6111 VPrint(stdout, " x-y*y = % \n", f);
6112 }
6113 #endif /* BIGDECIMAL_DEBUG */
6114 y->MaxPrec = y_prec;
6115
6116 Exit:
6117 VpFree(f);
6118 VpFree(r);
6119 return 1;
6120 }
6121
6122 /*
6123 * Round relatively from the decimal point.
6124 * f: rounding mode
6125 * nf: digit location to round from the decimal point.
6126 */
6127 VP_EXPORT int
6128 VpMidRound(Real *y, unsigned short f, ssize_t nf)
6129 {
6130 /* fracf: any positive digit under rounding position? */
6131 /* fracf_1further: any positive digits under one further than the rounding position? */
6132 /* exptoadd: number of digits needed to compensate negative nf */
6133 int fracf, fracf_1further;
6134 ssize_t n,i,ix,ioffset, exptoadd;
6135 BDIGIT v, shifter;
6136 BDIGIT div;
6137
6138 nf += y->exponent * (ssize_t)BASE_FIG;
6139 exptoadd=0;
6140 if (nf < 0) {
6141 /* rounding position too left(large). */
6142 if (f != VP_ROUND_CEIL && f != VP_ROUND_FLOOR) {
6143 VpSetZero(y, VpGetSign(y)); /* truncate everything */
6144 return 0;
6145 }
6146 exptoadd = -nf;
6147 nf = 0;
6148 }
6149
6150 ix = nf / (ssize_t)BASE_FIG;
6151 if ((size_t)ix >= y->Prec) return 0; /* rounding position too right(small). */
6152 v = y->frac[ix];
6153
6154 ioffset = nf - ix*(ssize_t)BASE_FIG;
6155 n = (ssize_t)BASE_FIG - ioffset - 1;
6156 for (shifter = 1, i = 0; i < n; ++i) shifter *= 10;
6157
6158 /* so the representation used (in y->frac) is an array of BDIGIT, where
6159 each BDIGIT contains a value between 0 and BASE-1, consisting of BASE_FIG
6160 decimal places.
6161
6162 (that numbers of decimal places are typed as ssize_t is somewhat confusing)
6163
6164 nf is now position (in decimal places) of the digit from the start of
6165 the array.
6166
6167 ix is the position (in BDIGITS) of the BDIGIT containing the decimal digit,
6168 from the start of the array.
6169
6170 v is the value of this BDIGIT
6171
6172 ioffset is the number of extra decimal places along of this decimal digit
6173 within v.
6174
6175 n is the number of decimal digits remaining within v after this decimal digit
6176 shifter is 10**n,
6177
6178 v % shifter are the remaining digits within v
6179 v % (shifter * 10) are the digit together with the remaining digits within v
6180 v / shifter are the digit's predecessors together with the digit
6181 div = v / shifter / 10 is just the digit's precessors
6182 (v / shifter) - div*10 is just the digit, which is what v ends up being reassigned to.
6183 */
6184
6185 fracf = (v % (shifter * 10) > 0);
6186 fracf_1further = ((v % shifter) > 0);
6187
6188 v /= shifter;
6189 div = v / 10;
6190 v = v - div*10;
6191 /* now v is just the digit required.
6192 now fracf is whether the digit or any of the remaining digits within v are non-zero
6193 now fracf_1further is whether any of the remaining digits within v are non-zero
6194 */
6195
6196 /* now check all the remaining BDIGITS for zero-ness a whole BDIGIT at a time.
6197 if we spot any non-zeroness, that means that we found a positive digit under
6198 rounding position, and we also found a positive digit under one further than
6199 the rounding position, so both searches (to see if any such non-zero digit exists)
6200 can stop */
6201
6202 for (i = ix + 1; (size_t)i < y->Prec; i++) {
6203 if (y->frac[i] % BASE) {
6204 fracf = fracf_1further = 1;
6205 break;
6206 }
6207 }
6208
6209 /* now fracf = does any positive digit exist under the rounding position?
6210 now fracf_1further = does any positive digit exist under one further than the
6211 rounding position?
6212 now v = the first digit under the rounding position */
6213
6214 /* drop digits after pointed digit */
6215 memset(y->frac + ix + 1, 0, (y->Prec - (ix + 1)) * sizeof(BDIGIT));
6216
6217 switch (f) {
6218 case VP_ROUND_DOWN: /* Truncate */
6219 break;
6220 case VP_ROUND_UP: /* Roundup */
6221 if (fracf) ++div;
6222 break;
6223 case VP_ROUND_HALF_UP:
6224 if (v>=5) ++div;
6225 break;
6226 case VP_ROUND_HALF_DOWN:
6227 if (v > 5 || (v == 5 && fracf_1further)) ++div;
6228 break;
6229 case VP_ROUND_CEIL:
6230 if (fracf && BIGDECIMAL_POSITIVE_P(y)) ++div;
6231 break;
6232 case VP_ROUND_FLOOR:
6233 if (fracf && BIGDECIMAL_NEGATIVE_P(y)) ++div;
6234 break;
6235 case VP_ROUND_HALF_EVEN: /* Banker's rounding */
6236 if (v > 5) ++div;
6237 else if (v == 5) {
6238 if (fracf_1further) {
6239 ++div;
6240 }
6241 else {
6242 if (ioffset == 0) {
6243 /* v is the first decimal digit of its BDIGIT;
6244 need to grab the previous BDIGIT if present
6245 to check for evenness of the previous decimal
6246 digit (which is same as that of the BDIGIT since
6247 base 10 has a factor of 2) */
6248 if (ix && (y->frac[ix-1] % 2)) ++div;
6249 }
6250 else {
6251 if (div % 2) ++div;
6252 }
6253 }
6254 }
6255 break;
6256 }
6257 for (i = 0; i <= n; ++i) div *= 10;
6258 if (div >= BASE) {
6259 if (ix) {
6260 y->frac[ix] = 0;
6261 VpRdup(y, ix);
6262 }
6263 else {
6264 short s = VpGetSign(y);
6265 SIGNED_VALUE e = y->exponent;
6266 VpSetOne(y);
6267 VpSetSign(y, s);
6268 y->exponent = e + 1;
6269 }
6270 }
6271 else {
6272 y->frac[ix] = div;
6273 VpNmlz(y);
6274 }
6275 if (exptoadd > 0) {
6276 y->exponent += (SIGNED_VALUE)(exptoadd / BASE_FIG);
6277 exptoadd %= (ssize_t)BASE_FIG;
6278 for (i = 0; i < exptoadd; i++) {
6279 y->frac[0] *= 10;
6280 if (y->frac[0] >= BASE) {
6281 y->frac[0] /= BASE;
6282 y->exponent++;
6283 }
6284 }
6285 }
6286 return 1;
6287 }
6288
6289 VP_EXPORT int
6290 VpLeftRound(Real *y, unsigned short f, ssize_t nf)
6291 /*
6292 * Round from the left hand side of the digits.
6293 */
6294 {
6295 BDIGIT v;
6296 if (!VpHasVal(y)) return 0; /* Unable to round */
6297 v = y->frac[0];
6298 nf -= VpExponent(y) * (ssize_t)BASE_FIG;
6299 while ((v /= 10) != 0) nf--;
6300 nf += (ssize_t)BASE_FIG-1;
6301 return VpMidRound(y, f, nf);
6302 }
6303
6304 VP_EXPORT int
6305 VpActiveRound(Real *y, Real *x, unsigned short f, ssize_t nf)
6306 {
6307 /* First,assign whole value in truncation mode */
6308 if (VpAsgn(y, x, 10) <= 1) return 0; /* Zero,NaN,or Infinity */
6309 return VpMidRound(y, f, nf);
6310 }
6311
6312 static int
6313 VpLimitRound(Real *c, size_t ixDigit)
6314 {
6315 size_t ix = VpGetPrecLimit();
6316 if (!VpNmlz(c)) return -1;
6317 if (!ix) return 0;
6318 if (!ixDigit) ixDigit = c->Prec-1;
6319 if ((ix + BASE_FIG - 1) / BASE_FIG > ixDigit + 1) return 0;
6320 return VpLeftRound(c, VpGetRoundMode(), (ssize_t)ix);
6321 }
6322
6323 /* If I understand correctly, this is only ever used to round off the final decimal
6324 digit of precision */
6325 static void
6326 VpInternalRound(Real *c, size_t ixDigit, BDIGIT vPrev, BDIGIT v)
6327 {
6328 int f = 0;
6329
6330 unsigned short const rounding_mode = VpGetRoundMode();
6331
6332 if (VpLimitRound(c, ixDigit)) return;
6333 if (!v) return;
6334
6335 v /= BASE1;
6336 switch (rounding_mode) {
6337 case VP_ROUND_DOWN:
6338 break;
6339 case VP_ROUND_UP:
6340 if (v) f = 1;
6341 break;
6342 case VP_ROUND_HALF_UP:
6343 if (v >= 5) f = 1;
6344 break;
6345 case VP_ROUND_HALF_DOWN:
6346 /* this is ok - because this is the last digit of precision,
6347 the case where v == 5 and some further digits are nonzero
6348 will never occur */
6349 if (v >= 6) f = 1;
6350 break;
6351 case VP_ROUND_CEIL:
6352 if (v && BIGDECIMAL_POSITIVE_P(c)) f = 1;
6353 break;
6354 case VP_ROUND_FLOOR:
6355 if (v && BIGDECIMAL_NEGATIVE_P(c)) f = 1;
6356 break;
6357 case VP_ROUND_HALF_EVEN: /* Banker's rounding */
6358 /* as per VP_ROUND_HALF_DOWN, because this is the last digit of precision,
6359 there is no case to worry about where v == 5 and some further digits are nonzero */
6360 if (v > 5) f = 1;
6361 else if (v == 5 && vPrev % 2) f = 1;
6362 break;
6363 }
6364 if (f) {
6365 VpRdup(c, ixDigit);
6366 VpNmlz(c);
6367 }
6368 }
6369
6370 /*
6371 * Rounds up m(plus one to final digit of m).
6372 */
6373 static int
6374 VpRdup(Real *m, size_t ind_m)
6375 {
6376 BDIGIT carry;
6377
6378 if (!ind_m) ind_m = m->Prec;
6379
6380 carry = 1;
6381 while (carry > 0 && ind_m--) {
6382 m->frac[ind_m] += carry;
6383 if (m->frac[ind_m] >= BASE) m->frac[ind_m] -= BASE;
6384 else carry = 0;
6385 }
6386 if (carry > 0) { /* Overflow,count exponent and set fraction part be 1 */
6387 if (!AddExponent(m, 1)) return 0;
6388 m->Prec = m->frac[0] = 1;
6389 }
6390 else {
6391 VpNmlz(m);
6392 }
6393 return 1;
6394 }
6395
6396 /*
6397 * y = x - fix(x)
6398 */
6399 VP_EXPORT void
6400 VpFrac(Real *y, Real *x)
6401 {
6402 size_t my, ind_y, ind_x;
6403
6404 if (!VpHasVal(x)) {
6405 VpAsgn(y, x, 1);
6406 goto Exit;
6407 }
6408
6409 if (x->exponent > 0 && (size_t)x->exponent >= x->Prec) {
6410 VpSetZero(y, VpGetSign(x));
6411 goto Exit;
6412 }
6413 else if (x->exponent <= 0) {
6414 VpAsgn(y, x, 1);
6415 goto Exit;
6416 }
6417
6418 /* satisfy: x->exponent > 0 */
6419
6420 y->Prec = x->Prec - (size_t)x->exponent;
6421 y->Prec = Min(y->Prec, y->MaxPrec);
6422 y->exponent = 0;
6423 VpSetSign(y, VpGetSign(x));
6424 ind_y = 0;
6425 my = y->Prec;
6426 ind_x = x->exponent;
6427 while (ind_y < my) {
6428 y->frac[ind_y] = x->frac[ind_x];
6429 ++ind_y;
6430 ++ind_x;
6431 }
6432 VpNmlz(y);
6433
6434 Exit:
6435 #ifdef BIGDECIMAL_DEBUG
6436 if (gfDebug) {
6437 VPrint(stdout, "VpFrac y=%\n", y);
6438 VPrint(stdout, " x=%\n", x);
6439 }
6440 #endif /* BIGDECIMAL_DEBUG */
6441 return;
6442 }
6443
6444 /*
6445 * y = x ** n
6446 */
6447 VP_EXPORT int
6448 VpPower(Real *y, Real *x, SIGNED_VALUE n)
6449 {
6450 size_t s, ss;
6451 ssize_t sign;
6452 Real *w1 = NULL;
6453 Real *w2 = NULL;
6454
6455 if (VpIsZero(x)) {
6456 if (n == 0) {
6457 VpSetOne(y);
6458 goto Exit;
6459 }
6460 sign = VpGetSign(x);
6461 if (n < 0) {
6462 n = -n;
6463 if (sign < 0) sign = (n % 2) ? -1 : 1;
6464 VpSetInf(y, sign);
6465 }
6466 else {
6467 if (sign < 0) sign = (n % 2) ? -1 : 1;
6468 VpSetZero(y,sign);
6469 }
6470 goto Exit;
6471 }
6472 if (VpIsNaN(x)) {
6473 VpSetNaN(y);
6474 goto Exit;
6475 }
6476 if (VpIsInf(x)) {
6477 if (n == 0) {
6478 VpSetOne(y);
6479 goto Exit;
6480 }
6481 if (n > 0) {
6482 VpSetInf(y, (n % 2 == 0 || VpIsPosInf(x)) ? 1 : -1);
6483 goto Exit;
6484 }
6485 VpSetZero(y, (n % 2 == 0 || VpIsPosInf(x)) ? 1 : -1);
6486 goto Exit;
6487 }
6488
6489 if (x->exponent == 1 && x->Prec == 1 && x->frac[0] == 1) {
6490 /* abs(x) = 1 */
6491 VpSetOne(y);
6492 if (BIGDECIMAL_POSITIVE_P(x)) goto Exit;
6493 if ((n % 2) == 0) goto Exit;
6494 VpSetSign(y, -1);
6495 goto Exit;
6496 }
6497
6498 if (n > 0) sign = 1;
6499 else if (n < 0) {
6500 sign = -1;
6501 n = -n;
6502 }
6503 else {
6504 VpSetOne(y);
6505 goto Exit;
6506 }
6507
6508 /* Allocate working variables */
6509
6510 w1 = VpAlloc((y->MaxPrec + 2) * BASE_FIG, "#0", 1, 1);
6511 w2 = VpAlloc((w1->MaxPrec * 2 + 1) * BASE_FIG, "#0", 1, 1);
6512 /* calculation start */
6513
6514 VpAsgn(y, x, 1);
6515 --n;
6516 while (n > 0) {
6517 VpAsgn(w1, x, 1);
6518 s = 1;
6519 while (ss = s, (s += s) <= (size_t)n) {
6520 VpMult(w2, w1, w1);
6521 VpAsgn(w1, w2, 1);
6522 }
6523 n -= (SIGNED_VALUE)ss;
6524 VpMult(w2, y, w1);
6525 VpAsgn(y, w2, 1);
6526 }
6527 if (sign < 0) {
6528 VpDivd(w1, w2, VpConstOne, y);
6529 VpAsgn(y, w1, 1);
6530 }
6531
6532 Exit:
6533 #ifdef BIGDECIMAL_DEBUG
6534 if (gfDebug) {
6535 VPrint(stdout, "VpPower y=%\n", y);
6536 VPrint(stdout, "VpPower x=%\n", x);
6537 printf(" n=%"PRIdVALUE"\n", n);
6538 }
6539 #endif /* BIGDECIMAL_DEBUG */
6540 VpFree(w2);
6541 VpFree(w1);
6542 return 1;
6543 }
6544
6545 #ifdef BIGDECIMAL_DEBUG
6546 int
6547 VpVarCheck(Real * v)
6548 /*
6549 * Checks the validity of the Real variable v.
6550 * [Input]
6551 * v ... Real *, variable to be checked.
6552 * [Returns]
6553 * 0 ... correct v.
6554 * other ... error
6555 */
6556 {
6557 size_t i;
6558
6559 if (v->MaxPrec == 0) {
6560 printf("ERROR(VpVarCheck): Illegal Max. Precision(=%"PRIuSIZE")\n",
6561 v->MaxPrec);
6562 return 1;
6563 }
6564 if (v->Prec == 0 || v->Prec > v->MaxPrec) {
6565 printf("ERROR(VpVarCheck): Illegal Precision(=%"PRIuSIZE")\n", v->Prec);
6566 printf(" Max. Prec.=%"PRIuSIZE"\n", v->MaxPrec);
6567 return 2;
6568 }
6569 for (i = 0; i < v->Prec; ++i) {
6570 if (v->frac[i] >= BASE) {
6571 printf("ERROR(VpVarCheck): Illegal fraction\n");
6572 printf(" Frac[%"PRIuSIZE"]=%"PRIuBDIGIT"\n", i, v->frac[i]);
6573 printf(" Prec. =%"PRIuSIZE"\n", v->Prec);
6574 printf(" Exp. =%"PRIdVALUE"\n", v->exponent);
6575 printf(" BASE =%"PRIuBDIGIT"\n", BASE);
6576 return 3;
6577 }
6578 }
6579 return 0;
6580 }
6581 #endif /* BIGDECIMAL_DEBUG */
VpMemRealloc
VP_EXPORT void * VpMemRealloc(void *ptr, size_t mb)
Definition: bigdecimal.c:3589
rb_get_kwargs
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Definition: class.c:1886
ID
unsigned long ID
Definition: ruby.h:103
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:649
VpAddSub
VP_EXPORT size_t VpAddSub(Real *c, Real *a, Real *b, int operation)
Definition: bigdecimal.c:4388
BigMath_exp
#define BigMath_exp(x, n)
Definition: bigdecimal.c:2176
VpGetDoublePosInf
VP_EXPORT double VpGetDoublePosInf(void)
Definition: bigdecimal.c:3780
rb_mBigMath
VALUE rb_mBigMath
Definition: bigdecimal.c:46
VpIsDef
#define VpIsDef(a)
Definition: bigdecimal.h:379
rb_thread_check_ints
void rb_thread_check_ints(void)
Definition: thread.c:1362
T_FLOAT
#define T_FLOAT
Definition: ruby.h:527
rb_assoc_new
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:896
rb_str_new2
#define rb_str_new2
Definition: intern.h:903
strtod
#define strtod(s, e)
Definition: util.h:76
gOne_ABCED9B4_CE73__00400511F31D
const volatile double gOne_ABCED9B4_CE73__00400511F31D
Definition: bigdecimal.c:3751
VpAsgn
VP_EXPORT size_t VpAsgn(Real *c, Real *a, int isw)
Definition: bigdecimal.c:4344
assert
#define assert(x)
Definition: dlmalloc.c:1176
DBL_DIG
#define DBL_DIG
Definition: numeric.c:55
id
const int id
Definition: nkf.c:209
rb_exc_new3
#define rb_exc_new3
Definition: intern.h:293
rb_opts_exception_p
int rb_opts_exception_p(VALUE opts, int default_value)
Definition: object.c:3125
FIX2INT
#define FIX2INT(x)
Definition: ruby.h:717
VP_ROUND_HALF_UP
#define VP_ROUND_HALF_UP
Definition: bigdecimal.h:214
VP_ROUND_HALF_DOWN
#define VP_ROUND_HALF_DOWN
Definition: bigdecimal.h:215
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:313
memset
void * memset(void *, int, size_t)
ISDIGIT
#define ISDIGIT(c)
Definition: ruby.h:2312
size_t
long unsigned int size_t
Definition: rb_mjit_min_header-2.7.0.h:666
VpHasVal
#define VpHasVal(a)
Definition: bigdecimal.h:383
rb_cNumeric
RUBY_EXTERN VALUE rb_cNumeric
Definition: ruby.h:2037
BDIGIT_DBL_SIGNED
#define BDIGIT_DBL_SIGNED
Definition: bigdecimal.h:50
strncasecmp
int strncasecmp(const char *, const char *, size_t) __attribute__((__pure__))
rb_scan_args
#define rb_scan_args(argc, argvp, fmt,...)
Definition: rb_mjit_min_header-2.7.0.h:6372
RMPD_ROUNDING_MODE_DEFAULT
#define RMPD_ROUNDING_MODE_DEFAULT
Definition: bigdecimal.h:220
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
VpIsNaN
#define VpIsNaN(a)
Definition: bigdecimal.h:372
snprintf
int snprintf(char *__restrict, size_t, const char *__restrict,...) __attribute__((__format__(__printf__
bp
#define bp()
Definition: internal.h:1445
VP_ROUND_FLOOR
#define VP_ROUND_FLOOR
Definition: bigdecimal.h:217
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:1009
rb_dbl2big
VALUE rb_dbl2big(double d)
Definition: bignum.c:5249
div
void div_t div(int __numer, int __denom)
RMPD_COMPONENT_FIGURES
#define RMPD_COMPONENT_FIGURES
Definition: bigdecimal.h:174
VpOne
VP_EXPORT Real * VpOne(void)
Definition: bigdecimal.c:4008
ne
#define ne(x, y)
Definition: time.c:82
VpToString
VP_EXPORT void VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
Definition: bigdecimal.c:5549
VALUE
unsigned long VALUE
Definition: ruby.h:102
rb_eArgError
VALUE rb_eArgError
Definition: error.c:923
rb_intern
#define rb_intern(str)
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:560
rb_intern_const
#define rb_intern_const(str)
Definition: ruby.h:1879
VpDtoV
VP_EXPORT void VpDtoV(Real *m, double d)
Definition: bigdecimal.c:5887
TYPE
#define TYPE(x)
Definition: ruby.h:554
rb_thread_current
VALUE rb_thread_current(void)
Definition: thread.c:2676
OP_SW_SUB
@ OP_SW_SUB
Definition: bigdecimal.c:3556
HALF_BASE
#define HALF_BASE
Definition: bigdecimal.c:76
ERANGE
#define ERANGE
Definition: rb_mjit_min_header-2.7.0.h:10971
VpMaxPrec
#define VpMaxPrec(a)
Definition: bigdecimal.h:347
VpIsPosInf
#define VpIsPosInf(a)
Definition: bigdecimal.h:376
VpGetDoubleNaN
VP_EXPORT double VpGetDoubleNaN(void)
Definition: bigdecimal.c:3774
rb_check_convert_type
VALUE rb_check_convert_type(VALUE, int, const char *, const char *)
Tries to convert an object into another type.
Definition: object.c:2941
VpSetNaN
#define VpSetNaN(a)
Definition: bigdecimal.h:373
rb_define_module
VALUE rb_define_module(const char *name)
Definition: class.c:772
VpVtoD
VP_EXPORT int VpVtoD(double *d, SIGNED_VALUE *e, Real *m)
Definition: bigdecimal.c:5823
SIGNED_VALUE
#define SIGNED_VALUE
Definition: ruby.h:104
rb_define_global_function
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:1787
vabs
#define vabs
Definition: bigdecimal.h:155
VpMult
VP_EXPORT size_t VpMult(Real *c, Real *a, Real *b)
Definition: bigdecimal.c:4843
OP_SW_ADD
@ OP_SW_ADD
Definition: bigdecimal.c:3555
assert.h
rb_inspect
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:551
Real::frac
BDIGIT frac[FLEXIBLE_ARRAY_SIZE]
Definition: bigdecimal.h:262
VP_SIGN_POSITIVE_INFINITE
#define VP_SIGN_POSITIVE_INFINITE
Definition: bigdecimal.h:227
rb_Rational
VALUE rb_Rational(VALUE, VALUE)
Definition: rational.c:1951
RRATIONAL_NEGATIVE_P
#define RRATIONAL_NEGATIVE_P(x)
Definition: bigdecimal.c:89
VpGetPrecLimit
VP_EXPORT size_t VpGetPrecLimit(void)
Definition: bigdecimal.c:3664
rb_str_dup
VALUE rb_str_dup(VALUE)
Definition: string.c:1516
RRATIONAL
#define RRATIONAL(obj)
Definition: internal.h:794
rb_str_cat2
#define rb_str_cat2
Definition: intern.h:912
VpIsOne
#define VpIsOne(a)
Definition: bigdecimal.h:384
rb_hash_lookup2
VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
Definition: hash.c:1977
rb_check_string_type
VALUE rb_check_string_type(VALUE)
Definition: string.c:2314
rb_big_pack
void rb_big_pack(VALUE val, unsigned long *buf, long num_longs)
Definition: bignum.c:3215
VpMemAlloc
VP_EXPORT void * VpMemAlloc(size_t mb)
Definition: bigdecimal.c:3575
Qundef
#define Qundef
Definition: ruby.h:470
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1755
T_RATIONAL
#define T_RATIONAL
Definition: ruby.h:541
CHAR_BIT
#define CHAR_BIT
Definition: ruby.h:227
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
INT2NUM
#define INT2NUM(x)
Definition: ruby.h:1609
VpException
VP_EXPORT int VpException(unsigned short f, const char *str, int always)
Definition: bigdecimal.c:3809
ptr
struct RIMemo * ptr
Definition: debug.c:74
T_DATA
#define T_DATA
Definition: ruby.h:538
Qfalse
#define Qfalse
Definition: ruby.h:467
VpIsInf
#define VpIsInf(a)
Definition: bigdecimal.h:378
DoSomeOne
#define DoSomeOne(x, y, f)
Definition: bigdecimal.c:136
ssize_t
_ssize_t ssize_t
Definition: rb_mjit_min_header-2.7.0.h:1329
VP_SIGN_NEGATIVE_ZERO
#define VP_SIGN_NEGATIVE_ZERO
Definition: bigdecimal.h:224
fabs
double fabs(double)
SPECIAL_CONST_P
#define SPECIAL_CONST_P(x)
Definition: ruby.h:1313
BIGDECIMAL_POSITIVE_P
#define BIGDECIMAL_POSITIVE_P(bd)
Definition: bigdecimal.c:130
printf
int int int printf(const char *__restrict,...) __attribute__((__format__(__printf__
NULL
#define NULL
Definition: _sdbm.c:101
T_COMPLEX
#define T_COMPLEX
Definition: ruby.h:542
maxnr
#define maxnr
Definition: bigdecimal.c:3547
NUM2SSIZET
#define NUM2SSIZET(x)
Definition: ruby.h:770
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:166
rb_fatal
void rb_fatal(const char *fmt,...)
Definition: error.c:2720
FIX2LONG
#define FIX2LONG(x)
Definition: ruby.h:394
ID2SYM
#define ID2SYM(x)
Definition: ruby.h:414
is_positive
#define is_positive(x)
Definition: bigdecimal.c:2200
rmpd_parse_special_string
Real * rmpd_parse_special_string(const char *str)
Definition: bigdecimal.c:4052
strlen
size_t strlen(const char *)
T_SYMBOL
#define T_SYMBOL
Definition: ruby.h:540
strncmp
int strncmp(const char *, const char *, size_t)
rb_num_coerce_cmp
VALUE rb_num_coerce_cmp(VALUE, VALUE, ID)
Definition: numeric.c:453
VP_SIGN_POSITIVE_FINITE
#define VP_SIGN_POSITIVE_FINITE
Definition: bigdecimal.h:225
VpToFString
VP_EXPORT void VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
Definition: bigdecimal.c:5597
L
#define L(x)
Definition: asm.h:125
rb_undef_method
void rb_undef_method(VALUE klass, const char *name)
Definition: class.c:1575
rb_protect
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
Definition: eval.c:1071
VpGetRoundMode
VP_EXPORT unsigned short VpGetRoundMode(void)
Definition: bigdecimal.c:3699
rb_memhash
st_index_t rb_memhash(const void *ptr, long len)
Definition: random.c:1440
VpAllocReal
#define VpAllocReal(prec)
Definition: bigdecimal.c:660
VP_ROUND_DOWN
#define VP_ROUND_DOWN
Definition: bigdecimal.h:213
v
int VALUE v
Definition: rb_mjit_min_header-2.7.0.h:12332
VpSetRoundMode
VP_EXPORT unsigned short VpSetRoundMode(unsigned short n)
Definition: bigdecimal.c:3733
VpDblFig
#define VpDblFig()
Definition: bigdecimal.h:284
rb_str_resize
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2709
VpExponent
#define VpExponent(a)
Definition: bigdecimal.h:385
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2669
VP_SIGN_NEGATIVE_FINITE
#define VP_SIGN_NEGATIVE_FINITE
Definition: bigdecimal.h:226
MemCmp
#define MemCmp(x, y, z)
Definition: bigdecimal.c:3551
VpFree
VP_EXPORT void VpFree(Real *pv)
Definition: bigdecimal.c:3599
DBL_MAX_10_EXP
#define DBL_MAX_10_EXP
Definition: numeric.c:52
BIGDECIMAL_NEGATIVE_P
#define BIGDECIMAL_NEGATIVE_P(bd)
Definition: bigdecimal.c:131
VP_SIGN_POSITIVE_ZERO
#define VP_SIGN_POSITIVE_ZERO
Definition: bigdecimal.h:223
sqrt
double sqrt(double)
VP_EXPORT
#define VP_EXPORT
Definition: bigdecimal.h:194
if
if((ID)(DISPID) nameid !=nameid)
Definition: win32ole.c:357
rmpd_set_thread_local_rounding_mode
#define rmpd_set_thread_local_rounding_mode(mode)
Definition: bigdecimal.c:3691
MUL_OVERFLOW_SIGNED_VALUE_P
#define MUL_OVERFLOW_SIGNED_VALUE_P(a, b)
Definition: bigdecimal.c:43
SZ_INF
#define SZ_INF
Definition: bigdecimal.h:186
VpInit
VP_EXPORT size_t VpInit(BDIGIT BaseVal)
Definition: bigdecimal.c:3980
LONG2NUM
#define LONG2NUM(x)
Definition: ruby.h:1644
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.0.h:5742
rb_obj_class
VALUE rb_obj_class(VALUE)
Equivalent to Object#class in Ruby.
Definition: object.c:217
SIZEOF_VALUE
#define SIZEOF_VALUE
Definition: ruby.h:105
VP_EXCEPTION_INFINITY
#define VP_EXCEPTION_INFINITY
Definition: bigdecimal.h:198
PRIuSIZE
#define PRIuSIZE
Definition: ruby.h:208
memcpy
void * memcpy(void *__restrict, const void *__restrict, size_t)
HUGE_VAL
#define HUGE_VAL
Definition: missing.h:161
round
RUBY_EXTERN double round(double)
Definition: numeric.c:80
double
double
Definition: rb_mjit_min_header-2.7.0.h:5923
DATA_PTR
#define DATA_PTR(dta)
Definition: ruby.h:1175
fprintf
int fprintf(FILE *__restrict, const char *__restrict,...) __attribute__((__format__(__printf__
NORETURN
NORETURN(static void cannot_be_coerced_into_BigDecimal(VALUE, VALUE))
Real
Definition: bigdecimal.h:242
VpCtoV
VP_EXPORT int VpCtoV(Real *a, const char *int_chr, size_t ni, const char *frac, size_t nf, const char *exp_chr, size_t ne)
Definition: bigdecimal.c:5663
rb_Rational1
#define rb_Rational1(x)
Definition: intern.h:182
VpAlloc
VP_EXPORT Real * VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
Definition: bigdecimal.c:4111
VpNewRbClass
VP_EXPORT Real * VpNewRbClass(size_t mx, const char *str, VALUE klass)
Definition: bigdecimal.c:644
memmove
#define memmove(dst, src, len)
Definition: rb_mjit_min_header-2.7.0.h:2848
rb_big_cmp
VALUE rb_big_cmp(VALUE x, VALUE y)
Definition: bignum.c:5419
VP_ROUND_UP
#define VP_ROUND_UP
Definition: bigdecimal.h:212
T_FIXNUM
#define T_FIXNUM
Definition: ruby.h:535
Real::MaxPrec
size_t MaxPrec
Definition: bigdecimal.h:244
VP_EXCEPTION_ZERODIVIDE
#define VP_EXCEPTION_ZERODIVIDE
Definition: bigdecimal.h:202
rmpd_set_thread_local_exception_mode
#define rmpd_set_thread_local_exception_mode(mode)
Definition: bigdecimal.c:3621
NUM2SIZET
#define NUM2SIZET(x)
Definition: ruby.h:769
VpGetDoubleNegInf
VP_EXPORT double VpGetDoubleNegInf(void)
Definition: bigdecimal.c:3786
i
uint32_t i
Definition: rb_mjit_min_header-2.7.0.h:5464
rb_jump_tag
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
Definition: eval.c:883
rb_eFloatDomainError
RUBY_EXTERN VALUE rb_eFloatDomainError
Definition: ruby.h:2075
bigdecimal.h
Real::Prec
size_t Prec
Definition: bigdecimal.h:247
long
#define long
Definition: rb_mjit_min_header-2.7.0.h:2880
VpSetZero
#define VpSetZero(a, s)
Definition: bigdecimal.h:369
rmpd_set_thread_local_precision_limit
#define rmpd_set_thread_local_precision_limit(limit)
Definition: bigdecimal.c:3654
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1195
VP_SIGN_NaN
#define VP_SIGN_NaN
Definition: bigdecimal.h:222
st_index_t
st_data_t st_index_t
Definition: st.h:50
rb_eZeroDivError
RUBY_EXTERN VALUE rb_eZeroDivError
Definition: ruby.h:2071
sprintf
int sprintf(char *__restrict, const char *__restrict,...) __attribute__((__format__(__printf__
VpIsPosZero
#define VpIsPosZero(a)
Definition: bigdecimal.h:364
TypedData_Wrap_Struct
#define TypedData_Wrap_Struct(klass, data_type, sval)
Definition: ruby.h:1231
stderr
#define stderr
Definition: rb_mjit_min_header-2.7.0.h:1485
VpNumOfChars
VP_EXPORT size_t VpNumOfChars(Real *vp, const char *pszFmt)
Definition: bigdecimal.c:3936
nan
RUBY_EXTERN double nan(const char *)
Definition: nan.c:7
isnan
#define isnan(x)
Definition: win32.h:369
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:922
VpComp
VP_EXPORT int VpComp(Real *a, Real *b)
Definition: bigdecimal.c:5225
ENTER
#define ENTER(n)
Definition: bigdecimal.c:68
mod
#define mod(x, y)
Definition: date_strftime.c:28
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: ruby.h:1101
RTYPEDDATA_DATA
#define RTYPEDDATA_DATA(v)
Definition: ruby.h:1179
VpFrac
VP_EXPORT void VpFrac(Real *y, Real *x)
Definition: bigdecimal.c:6400
id_eq
#define id_eq
Definition: numeric.c:178
isinf
#define isinf(__x)
Definition: rb_mjit_min_header-2.7.0.h:3673
FIXNUM_P
#define FIXNUM_P(f)
Definition: ruby.h:396
VpBaseVal
#define VpBaseVal()
Definition: bigdecimal.h:285
Init_bigdecimal
void Init_bigdecimal(void)
Definition: bigdecimal.c:3302
ISSPACE
#define ISSPACE(c)
Definition: ruby.h:2307
VpSetSign
#define VpSetSign(a, s)
Definition: bigdecimal.h:358
VpPower
VP_EXPORT int VpPower(Real *y, Real *x, SIGNED_VALUE n)
Definition: bigdecimal.c:6448
VP_EXCEPTION_OVERFLOW
#define VP_EXCEPTION_OVERFLOW
Definition: bigdecimal.h:201
VpSetPrecLimit
VP_EXPORT size_t VpSetPrecLimit(size_t n)
Definition: bigdecimal.c:3680
me
const rb_callable_method_entry_t * me
Definition: rb_mjit_min_header-2.7.0.h:13226
VpCreateRbObject
VP_EXPORT Real * VpCreateRbObject(size_t mx, const char *str)
Definition: bigdecimal.c:655
rb_eMathDomainError
RUBY_EXTERN VALUE rb_eMathDomainError
Definition: ruby.h:2088
VpExponent10
VP_EXPORT ssize_t VpExponent10(Real *a)
Definition: bigdecimal.c:5450
StringValueCStr
#define StringValueCStr(v)
Definition: ruby.h:604
NUM2USHORT
#define NUM2USHORT(x)
Definition: ruby.h:738
T_HASH
#define T_HASH
Definition: ruby.h:531
BASE1
#define BASE1
Definition: bigdecimal.c:77
VP_EXCEPTION_UNDERFLOW
#define VP_EXCEPTION_UNDERFLOW
Definition: bigdecimal.h:200
VpBaseFig
#define VpBaseFig()
Definition: bigdecimal.h:283
SZ_NINF
#define SZ_NINF
Definition: bigdecimal.h:188
rb_typeddata_is_kind_of
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:872
VpSetPosInf
#define VpSetPosInf(a)
Definition: bigdecimal.h:380
CLASS_OF
#define CLASS_OF(v)
Definition: ruby.h:484
VpToSpecialString
VP_EXPORT int VpToSpecialString(Real *a, char *psz, int fPlus)
Definition: bigdecimal.c:5514
fmt
const VALUE int int int int int int VALUE char * fmt
Definition: rb_mjit_min_header-2.7.0.h:6462
GUARD_OBJ
#define GUARD_OBJ(p, y)
Definition: bigdecimal.c:71
VpSetInf
#define VpSetInf(a, s)
Definition: bigdecimal.h:382
char
#define char
Definition: rb_mjit_min_header-2.7.0.h:2876
rb_ary_new2
#define rb_ary_new2
Definition: intern.h:103
isfinite
#define isfinite(x)
Definition: missing.h:192
Max
#define Max(a, b)
Definition: bigdecimal.h:344
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4322
n
const char size_t n
Definition: rb_mjit_min_header-2.7.0.h:5456
VpMidRound
VP_EXPORT int VpMidRound(Real *y, unsigned short f, ssize_t nf)
Definition: bigdecimal.c:6128
rb_exc_raise
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition: eval.c:667
VpActiveRound
VP_EXPORT int VpActiveRound(Real *y, Real *x, unsigned short f, ssize_t nf)
Definition: bigdecimal.c:6305
T_BIGNUM
#define T_BIGNUM
Definition: ruby.h:533
rb_funcall
#define rb_funcall(recv, mid, argc,...)
Definition: rb_mjit_min_header-2.7.0.h:6585
DBLE_FIG
#define DBLE_FIG
Definition: bigdecimal.c:80
OP_SW_DIV
@ OP_SW_DIV
Definition: bigdecimal.c:3558
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:634
VP_EXCEPTION_ALL
#define VP_EXCEPTION_ALL
Definition: bigdecimal.h:197
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.0.h:5601
argv
char ** argv
Definition: ruby.c:223
f
#define f
id_ceil
#define id_ceil
Definition: rational.c:1594
stdout
#define stdout
Definition: rb_mjit_min_header-2.7.0.h:1484
xmalloc
#define xmalloc
Definition: defines.h:211
xrealloc
#define xrealloc
Definition: defines.h:214
UNREACHABLE
#define UNREACHABLE
Definition: ruby.h:63
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.0.h:13254
VpLeftRound
VP_EXPORT int VpLeftRound(Real *y, unsigned short f, ssize_t nf)
Definition: bigdecimal.c:6290
BDIGIT_DBL
#define BDIGIT_DBL
Definition: bigdecimal.h:49
BDIGIT
#define BDIGIT
Definition: bigdecimal.h:48
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
exp
double exp(double)
Real::sign
short sign
Definition: bigdecimal.h:251
VP_SIGN_NEGATIVE_INFINITE
#define VP_SIGN_NEGATIVE_INFINITE
Definition: bigdecimal.h:228
RB_OBJ_CLASSNAME
#define RB_OBJ_CLASSNAME(obj)
Definition: bigdecimal.c:98
SZ_NaN
#define SZ_NaN
Definition: bigdecimal.h:185
RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1207
log10
double log10(double)
DBL_MIN_10_EXP
#define DBL_MIN_10_EXP
Definition: numeric.c:49
MEMCPY
#define MEMCPY(p1, p2, type, n)
Definition: ruby.h:1753
BigMath_log
#define BigMath_log(x, n)
Definition: bigdecimal.c:2177
BASE
#define BASE
Definition: bigdecimal.c:74
id_to_r
#define id_to_r
Definition: complex.c:41
VpIsNegInf
#define VpIsNegInf(a)
Definition: bigdecimal.h:377
VP_ROUND_CEIL
#define VP_ROUND_CEIL
Definition: bigdecimal.h:216
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
PRIdSIZE
#define PRIdSIZE
Definition: ruby.h:205
VpGetDoubleNegZero
VP_EXPORT double VpGetDoubleNegZero(void)
Definition: bigdecimal.c:3792
OP_SW_MULT
@ OP_SW_MULT
Definition: bigdecimal.c:3557
RB_OBJ_FREEZE
#define RB_OBJ_FREEZE(x)
Definition: ruby.h:1344
argc
int argc
Definition: ruby.c:222
rb_big2str
VALUE rb_big2str(VALUE x, int base)
Definition: bignum.c:5091
rb_cBigDecimal
VALUE rb_cBigDecimal
Definition: bigdecimal.c:45
rb_define_const
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2880
VP_EXCEPTION_NaN
#define VP_EXCEPTION_NaN
Definition: bigdecimal.h:199
RMPD_PRECISION_LIMIT_DEFAULT
#define RMPD_PRECISION_LIMIT_DEFAULT
Definition: bigdecimal.c:3660
rb_data_type_struct
Definition: ruby.h:1148
RFLOAT_VALUE
#define RFLOAT_VALUE(v)
Definition: ruby.h:966
xfree
#define xfree
Definition: defines.h:216
VpSetOne
#define VpSetOne(a)
Definition: bigdecimal.h:361
rb_str_new
#define rb_str_new(str, len)
Definition: rb_mjit_min_header-2.7.0.h:6116
VpGetSign
#define VpGetSign(a)
Definition: bigdecimal.h:354
rb_check_typeddata
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:889
VpIsZero
#define VpIsZero(a)
Definition: bigdecimal.h:366
Qtrue
#define Qtrue
Definition: ruby.h:468
errno
int errno
opts_exception_p
#define opts_exception_p(opts)
Definition: object.c:3134
rb_class_name
VALUE rb_class_name(VALUE)
Definition: variable.c:274
PRIuBDIGIT
#define PRIuBDIGIT
Definition: bigdecimal.h:59
len
uint8_t len
Definition: escape.c:17
SYMBOL_P
#define SYMBOL_P(x)
Definition: ruby.h:413
Real::obj
VALUE obj
Definition: bigdecimal.h:243
RRATIONAL_ZERO_P
#define RRATIONAL_ZERO_P(x)
Definition: bigdecimal.c:84
PRIdVALUE
#define PRIdVALUE
Definition: ruby.h:161
VpSzMantissa
VP_EXPORT void VpSzMantissa(Real *a, char *psz)
Definition: bigdecimal.c:5467
LONG2FIX
#define LONG2FIX(i)
Definition: ruby.h:265
T_STRING
#define T_STRING
Definition: ruby.h:528
VP_EXCEPTION_MEMORY
#define VP_EXCEPTION_MEMORY
Definition: bigdecimal.h:206
rb_sym2str
VALUE rb_sym2str(VALUE)
Definition: symbol.c:784
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:1237
VpChangeSign
#define VpChangeSign(a, s)
Definition: bigdecimal.h:356
FIXABLE
#define FIXABLE(f)
Definition: ruby.h:399
DECIMAL_SIZE_OF_BITS
#define DECIMAL_SIZE_OF_BITS(n)
Definition: util.h:50
ST2FIX
#define ST2FIX(h)
Definition: ruby_missing.h:21
VP_ROUND_MODE
#define VP_ROUND_MODE
Definition: bigdecimal.h:211
Min
#define Min(a, b)
Definition: bigdecimal.h:345
NUM2INT
#define NUM2INT(x)
Definition: ruby.h:715
Qnil
#define Qnil
Definition: ruby.h:469
rb_num_coerce_relop
VALUE rb_num_coerce_relop(VALUE, VALUE, ID)
Definition: numeric.c:461
BASE_FIG
#define BASE_FIG
Definition: bigdecimal.c:73
exc
const rb_iseq_t const VALUE exc
Definition: rb_mjit_min_header-2.7.0.h:13504
VpReallocReal
#define VpReallocReal(ptr, prec)
Definition: bigdecimal.c:661
VP_ROUND_HALF_EVEN
#define VP_ROUND_HALF_EVEN
Definition: bigdecimal.h:218
SAVE
#define SAVE(p)
Definition: bigdecimal.c:70
op_sw
op_sw
Definition: bigdecimal.c:3554
VpIsNegZero
#define VpIsNegZero(a)
Definition: bigdecimal.h:365
VpSqrt
VP_EXPORT int VpSqrt(Real *y, Real *x)
Definition: bigdecimal.c:6019
VpDivd
VP_EXPORT size_t VpDivd(Real *c, Real *r, Real *a, Real *b)
Definition: bigdecimal.c:4972
util.h
VP_EXCEPTION_OP
#define VP_EXCEPTION_OP
Definition: bigdecimal.h:205
rb_float_new
#define rb_float_new(d)
Definition: internal.h:1960
Real::exponent
SIGNED_VALUE exponent
Definition: bigdecimal.h:250
RB_GC_GUARD
#define RB_GC_GUARD(v)
Definition: ruby.h:585
rb_str_tmp_new
VALUE rb_str_tmp_new(long)
Definition: string.c:1343
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:1005
SZ_PINF
#define SZ_PINF
Definition: bigdecimal.h:187
PUSH
#define PUSH(x)
Definition: bigdecimal.c:69
RTEST
#define RTEST(v)
Definition: ruby.h:481
VpSetNegInf
#define VpSetNegInf(a)
Definition: bigdecimal.h:381
SSIZET2NUM
#define SSIZET2NUM(v)
Definition: ruby.h:296
rb_thread_local_aref
VALUE rb_thread_local_aref(VALUE, ID)
Definition: thread.c:3216
SYM2ID
#define SYM2ID(x)
Definition: ruby.h:415
rb_special_const_p
#define rb_special_const_p(obj)
Definition: rb_mjit_min_header-2.7.0.h:5357
RMPD_EXCEPTION_MODE_DEFAULT
#define RMPD_EXCEPTION_MODE_DEFAULT
Definition: bigdecimal.h:208
__sFILE
Definition: vsnprintf.c:169
SIGNED_VALUE_MAX
#define SIGNED_VALUE_MAX
Definition: bigdecimal.c:41
Real::flag
short flag
Definition: bigdecimal.h:261
VpIsRoundMode
VP_EXPORT int VpIsRoundMode(unsigned short n)
Definition: bigdecimal.c:3715