Ruby 2.7.6p219 (2022-04-12 revision c9c2245c0a25176072e02db9254f0e0c84c805cd)
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
47
48static ID id_BigDecimal_exception_mode;
49static ID id_BigDecimal_rounding_mode;
50static ID id_BigDecimal_precision_limit;
51
52static ID id_up;
53static ID id_down;
54static ID id_truncate;
55static ID id_half_up;
56static ID id_default;
57static ID id_half_down;
58static ID id_half_even;
59static ID id_banker;
60static ID id_ceiling;
61static ID id_ceil;
62static ID id_floor;
63static ID id_to_r;
64static ID id_eq;
65static 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
107static inline VALUE
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
119static inline VALUE
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 */
141static unsigned short VpGetException(void);
142static void VpSetException(unsigned short f);
143static void VpInternalRound(Real *c, size_t ixDigit, BDIGIT vPrev, BDIGIT v);
144static int VpLimitRound(Real *c, size_t ixDigit);
145static Real *VpCopy(Real *pv, Real const* const x);
146
147#ifdef BIGDECIMAL_ENABLE_VPRINT
148static int VPrint(FILE *fp,const char *cntl_chr,Real *a);
149#endif
150
151/*
152 * **** BigDecimal part ****
153 */
154
155static void
156BigDecimal_delete(void *pv)
157{
158 VpFree(pv);
159}
160
161static size_t
162BigDecimal_memsize(const void *ptr)
163{
164 const Real *pv = ptr;
165 return (sizeof(*pv) + pv->MaxPrec * sizeof(BDIGIT));
166}
167
168static const rb_data_type_t BigDecimal_data_type = {
169 "BigDecimal",
170 { 0, BigDecimal_delete, BigDecimal_memsize, },
171#ifdef RUBY_TYPED_FREE_IMMEDIATELY
173#endif
174};
175
176static inline int
177is_kind_of_BigDecimal(VALUE const v)
178{
179 return rb_typeddata_is_kind_of(v, &BigDecimal_data_type);
180}
181
182static VALUE
183ToValue(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
197NORETURN(static void cannot_be_coerced_into_BigDecimal(VALUE, VALUE));
198
199static void
200cannot_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 {
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
215static inline VALUE BigDecimal_div2(VALUE, VALUE, VALUE);
216
217static Real*
218GetVpValueWithPrec(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
227again:
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:
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
292SomeOneMayDoIt:
293 if (must) {
294 cannot_be_coerced_into_BigDecimal(rb_eTypeError, v);
295 }
296 return NULL; /* NULL means to coerce */
297
298unable_to_coerce_without_prec:
299 if (must) {
301 "%"PRIsVALUE" can't be coerced into BigDecimal without a precision",
303 }
304 return NULL;
305}
306
307static Real*
308GetVpValue(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 */
320static VALUE
321BigDecimal_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
338static VALUE
339BigDecimal_prec(VALUE self)
340{
341 ENTER(1);
342 Real *p;
343 VALUE obj;
344
345 GUARD_OBJ(p, GetVpValue(self, 1));
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 */
359static VALUE
360BigDecimal_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 */
388static VALUE
389BigDecimal_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 */
410static VALUE
411BigDecimal_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
436static unsigned short
437check_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
485static unsigned short
486check_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 */
558static VALUE
559BigDecimal_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();
587 VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_UNDERFLOW) :
588 (fo & (~VP_EXCEPTION_UNDERFLOW))));
589 }
590 fo = VpGetException();
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
611static size_t
612GetAddSubPrec(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
632static SIGNED_VALUE
633GetPrecisionInt(VALUE v)
634{
636 n = NUM2INT(v);
637 if (n < 0) {
638 rb_raise(rb_eArgError, "negative precision");
639 }
640 return n;
641}
642
644VpNewRbClass(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;
651 return pv;
652}
653
655VpCreateRbObject(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
663static Real *
664VpCopy(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. */
680static VALUE
681BigDecimal_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 */
691static VALUE
692BigDecimal_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). */
701static VALUE
702BigDecimal_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
710static void
711BigDecimal_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
724static 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 */
730static VALUE
731BigDecimal_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 */
777static VALUE
778BigDecimal_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);
791 goto overflow;
793 goto underflow;
794
795 str = rb_str_new(0, VpNumOfChars(p, "E"));
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
806overflow:
807 VpException(VP_EXCEPTION_OVERFLOW, "BigDecimal to Float conversion", 0);
810 else
812
813underflow:
814 VpException(VP_EXCEPTION_UNDERFLOW, "BigDecimal to Float conversion", 0);
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 */
824static VALUE
825BigDecimal_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 */
870static VALUE
871BigDecimal_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
904static VALUE
905BigDecimal_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 */
927static VALUE
928BigDecimal_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 */
985static VALUE
986BigDecimal_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
1026static VALUE
1027BigDecimalCmp(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
1118}
1119
1120/* Returns True if the value is zero. */
1121static VALUE
1122BigDecimal_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. */
1129static VALUE
1130BigDecimal_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 */
1139static VALUE
1140BigDecimal_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 */
1155static VALUE
1156BigDecimal_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 */
1168static VALUE
1169BigDecimal_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 */
1181static VALUE
1182BigDecimal_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 */
1194static VALUE
1195BigDecimal_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 */
1207static VALUE
1208BigDecimal_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
1222static VALUE
1223BigDecimal_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 */
1248static VALUE
1249BigDecimal_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
1275static VALUE
1276BigDecimal_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 */
1317static VALUE
1318BigDecimal_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 */
1341static VALUE
1342BigDecimal_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
1413NaN:
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 */
1429static VALUE
1430BigDecimal_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
1442static VALUE
1443BigDecimal_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 */
1495static VALUE
1496BigDecimal_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 */
1527static VALUE
1528BigDecimal_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 */
1543static inline VALUE
1544BigDecimal_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 */
1613static VALUE
1614BigDecimal_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
1623static VALUE
1624BigDecimal_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 */
1653static VALUE
1654BigDecimal_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
1671static VALUE
1672BigDecimal_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
1698static VALUE
1699BigDecimal_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 */
1720static VALUE
1721BigDecimal_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 */
1739static VALUE
1740BigDecimal_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 */
1778static VALUE
1779BigDecimal_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 */
1846static VALUE
1847BigDecimal_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 */
1875static VALUE
1876BigDecimal_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 */
1906static VALUE
1907BigDecimal_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 */
1953static VALUE
1954BigDecimal_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 */
2012static VALUE
2013BigDecimal_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 */
2107static VALUE
2108BigDecimal_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));
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 */
2144static VALUE
2145BigDecimal_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 */
2156static VALUE
2157BigDecimal_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);
2170 return str;
2171}
2172
2173static VALUE BigMath_s_exp(VALUE, VALUE, VALUE);
2174static 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
2179inline static int
2180is_integer(VALUE x)
2181{
2182 return (RB_TYPE_P(x, T_FIXNUM) || RB_TYPE_P(x, T_BIGNUM));
2183}
2184
2185inline static int
2186is_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
2202inline static int
2203is_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
2225inline static int
2226is_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
2250inline static int
2251is_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
2271static VALUE
2272rmpd_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));
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 */
2299static VALUE
2300BigDecimal_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:
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 */
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)) {
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 */
2535static VALUE
2536BigDecimal_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 */
2545static VALUE
2546BigDecimal_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
2557static VALUE
2558BigDecimal_clone(VALUE self)
2559{
2560 return self;
2561}
2562
2563#ifdef HAVE_RB_OPTS_EXCEPTION_P
2564int rb_opts_exception_p(VALUE opts, int default_value);
2565#define opts_exception_p(opts) rb_opts_exception_p((opts), 1)
2566#else
2567static int
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
2587static Real *
2588VpNewVarArg(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 }
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 */
2718static VALUE
2719f_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;
2735 return pv->obj = obj;
2736}
2737
2738static VALUE
2739BigDecimal_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 */
2764static VALUE
2765BigDecimal_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 */
2798static VALUE
2799BigDecimal_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 */
2823static VALUE
2824BigDecimal_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 */
2848static VALUE
2849BigDecimal_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 */
2873static VALUE
2874BigDecimal_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 */
2894static VALUE
2895BigMath_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");
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
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 */
3029static VALUE
3030BigMath_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;
3074get_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:
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);
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) {
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) {
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 */
3301void
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 */
3315
3316 /* Global function */
3317 rb_define_global_function("BigDecimal", f_BigDecimal, -1);
3318
3319 /* Class methods */
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 */
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 */
3358
3359 /*
3360 * 0x02: Determines what happens when the result of a computation is not a
3361 * number (NaN). See BigDecimal.mode.
3362 */
3364
3365 /*
3366 * 0x01: Determines what happens when the result of a computation is
3367 * infinity. See BigDecimal.mode.
3368 */
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 */
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 */
3382
3383 /*
3384 * 0x10: Determines what happens when a division by zero is performed.
3385 * See BigDecimal.mode.
3386 */
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 */
3395
3396 /* 1: Indicates that values should be rounded away from zero. See
3397 * BigDecimal.mode.
3398 */
3400
3401 /* 2: Indicates that values should be rounded towards zero. See
3402 * BigDecimal.mode.
3403 */
3405
3406 /* 3: Indicates that digits >= 5 should be rounded up, others rounded down.
3407 * See BigDecimal.mode. */
3409
3410 /* 4: Indicates that digits >= 6 should be rounded up, others rounded down.
3411 * See BigDecimal.mode.
3412 */
3414 /* 5: Round towards +Infinity. See BigDecimal.mode. */
3416
3417 /* 6: Round towards -Infinity. See BigDecimal.mode. */
3419
3420 /* 7: Round towards the even neighbor. See BigDecimal.mode. */
3422
3423 /* 0: Indicates that a value is not a number. See BigDecimal.sign. */
3425
3426 /* 1: Indicates that a value is +0. See BigDecimal.sign. */
3428
3429 /* -1: Indicates that a value is -0. See BigDecimal.sign. */
3431
3432 /* 2: Indicates that a value is positive and finite. See BigDecimal.sign. */
3434
3435 /* -2: Indicates that a value is negative and finite. See BigDecimal.sign. */
3437
3438 /* 3: Indicates that a value is positive and infinite. See BigDecimal.sign. */
3440
3441 /* -3: Indicates that a value is negative and infinite. See BigDecimal.sign. */
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
3539static int gfDebug = 1; /* Debug switch */
3540#if 0
3541static int gfCheckVal = 1; /* Value checking flag in VpNmlz() */
3542#endif
3543#endif /* BIGDECIMAL_DEBUG */
3544
3545static Real *VpConstOne; /* constant 1.0 */
3546static 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
3554enum op_sw {
3555 OP_SW_ADD = 1, /* + */
3556 OP_SW_SUB, /* - */
3557 OP_SW_MULT, /* * */
3558 OP_SW_DIV /* / */
3560
3561static int VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw);
3562static int AddExponent(Real *a, SIGNED_VALUE n);
3563static BDIGIT VpAddAbs(Real *a,Real *b,Real *c);
3564static BDIGIT VpSubAbs(Real *a,Real *b,Real *c);
3565static 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);
3566static int VpNmlz(Real *a);
3567static void VpFormatSt(char *psz, size_t fFmt);
3568static int VpRdup(Real *m, size_t ind_m);
3569
3570#ifdef BIGDECIMAL_DEBUG
3571static int gnAlloc = 0; /* Memory allocation counter */
3572#endif /* BIGDECIMAL_DEBUG */
3573
3574VP_EXPORT void *
3575VpMemAlloc(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
3588VP_EXPORT void *
3589VpMemRealloc(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
3598VP_EXPORT void
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
3628static unsigned short
3629VpGetException (void)
3630{
3631 VALUE const vmode = rb_thread_local_aref(
3633 id_BigDecimal_exception_mode
3634 );
3635
3636 if (NIL_P(vmode)) {
3639 }
3640
3641 return NUM2USHORT(vmode);
3642}
3643
3644static void
3645VpSetException(unsigned short f)
3646{
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 */
3663VP_EXPORT size_t
3665{
3666 VALUE const vlimit = rb_thread_local_aref(
3668 id_BigDecimal_precision_limit
3669 );
3670
3671 if (NIL_P(vlimit)) {
3674 }
3675
3676 return NUM2SIZET(vlimit);
3677}
3678
3679VP_EXPORT size_t
3681{
3682 size_t const s = VpGetPrecLimit();
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
3698VP_EXPORT unsigned short
3700{
3701 VALUE const vmode = rb_thread_local_aref(
3703 id_BigDecimal_rounding_mode
3704 );
3705
3706 if (NIL_P(vmode)) {
3709 }
3710
3711 return NUM2USHORT(vmode);
3712}
3713
3714VP_EXPORT int
3715VpIsRoundMode(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
3732VP_EXPORT unsigned short
3733VpSetRoundMode(unsigned short n)
3734{
3735 if (VpIsRoundMode(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 */
3751volatile const double gOne_ABCED9B4_CE73__00400511F31D = 1.0;
3752
3753static double
3754One(void)
3755{
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
3773VP_EXPORT double
3774VpGetDoubleNaN(void) /* Returns the value of NaN */
3775{
3776 return nan("");
3777}
3778
3779VP_EXPORT double
3780VpGetDoublePosInf(void) /* Returns the value of +Infinity */
3781{
3782 return HUGE_VAL;
3783}
3784
3785VP_EXPORT double
3786VpGetDoubleNegInf(void) /* Returns the value of -Infinity */
3787{
3788 return -HUGE_VAL;
3789}
3790
3791VP_EXPORT double
3792VpGetDoubleNegZero(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 */
3800VP_EXPORT int
3801VpIsNegDoubleZero(double v)
3802{
3803 double z = VpGetDoubleNegZero();
3804 return MemCmp(&v,&z,sizeof(v))==0;
3805}
3806#endif
3807
3808VP_EXPORT int
3809VpException(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: */
3820 case VP_EXCEPTION_NaN:
3822 case VP_EXCEPTION_OP:
3824 break;
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:/ */
3835static int
3836VpIsDefOP(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
3916Inf:
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
3924NaN:
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 */
3935VP_EXPORT size_t
3936VpNumOfChars(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 */
3979VP_EXPORT size_t
3981{
3982 /* Setup +/- Inf NaN -0 */
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
4009{
4010 return VpConstOne;
4011}
4012
4013/* If exponent overflows,then raise exception or returns 0 */
4014static int
4015AddExponent(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) {
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) {
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 */
4042underflow:
4043 VpSetZero(a, VpGetSign(a));
4044 return VpException(VP_EXCEPTION_UNDERFLOW, "Exponent underflow", 0);
4045
4046overflow:
4047 VpSetInf(a, VpGetSign(a));
4048 return VpException(VP_EXCEPTION_OVERFLOW, "Exponent overflow", 0);
4049}
4050
4051Real *
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;
4082 VpSetPosInf(vp);
4083 return vp;
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 */
4111VpAlloc(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 */
4343VP_EXPORT size_t
4344VpAsgn(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 */
4387VP_EXPORT size_t
4388VpAddSub(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
4479end_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 */
4521static BDIGIT
4522VpAddAbs(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
4599Assign_a:
4600 VpAsgn(c, a, 1);
4601 mrv = 0;
4602
4603Exit:
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 */
4616static BDIGIT
4617VpSubAbs(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
4705Assign_a:
4706 VpAsgn(c, a, 1);
4707 mrv = 0;
4708
4709Exit:
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 */
4732static size_t
4733VpSetPTR(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 */
4842VP_EXPORT size_t
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
4957Exit:
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 */
4971VP_EXPORT size_t
4972VpDivd(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
5094div_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
5100sub_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;
5136carry:
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 */
5145out_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
5160space_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
5172Exit:
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 */
5186static int
5187VpNmlz(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
5212NoVal:
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 */
5224VP_EXPORT int
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
5297Exit:
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
5322static int
5323VPrint(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
5424static void
5425VpFormatSt(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
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
5466VP_EXPORT void
5467VpSzMantissa(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
5513VP_EXPORT int
5514VpToSpecialString(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
5548VP_EXPORT void
5549VpToString(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
5596VP_EXPORT void
5597VpToFString(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 */
5662VP_EXPORT int
5663VpCtoV(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) {
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';
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
5791over_flow:
5792 rb_warn("Conversion from String to BigDecimal overflow (last few digits discarded).");
5793
5794Final:
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 */
5822VP_EXPORT int
5823VpVtoD(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
5872Exit:
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 */
5886VP_EXPORT void
5887VpDtoV(Real *m, double d)
5888{
5889 size_t ind_m, mm;
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
5941Exit:
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 */
5955VP_EXPORT void
5956VpItoV(Real *m, SIGNED_VALUE ival)
5957{
5958 size_t mm, ind_m;
5959 size_t val, v1, v2, v;
5960 int isign;
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
6004Exit:
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 */
6018VP_EXPORT int
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);
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
6102converge:
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
6116Exit:
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 */
6127VP_EXPORT int
6128VpMidRound(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
6289VP_EXPORT int
6290VpLeftRound(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
6304VP_EXPORT int
6305VpActiveRound(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
6312static int
6313VpLimitRound(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 */
6325static void
6326VpInternalRound(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 */
6373static int
6374VpRdup(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 */
6399VP_EXPORT void
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
6434Exit:
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 */
6447VP_EXPORT int
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
6532Exit:
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
6546int
6547VpVarCheck(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 */
int errno
VP_EXPORT double VpGetDoubleNegZero(void)
Definition: bigdecimal.c:3792
VP_EXPORT size_t VpDivd(Real *c, Real *r, Real *a, Real *b)
Definition: bigdecimal.c:4972
#define PUSH(x)
Definition: bigdecimal.c:69
VP_EXPORT Real * VpCreateRbObject(size_t mx, const char *str)
Definition: bigdecimal.c:655
#define RB_OBJ_CLASSNAME(obj)
Definition: bigdecimal.c:98
#define GUARD_OBJ(p, y)
Definition: bigdecimal.c:71
#define BigMath_exp(x, n)
Definition: bigdecimal.c:2176
#define SIGNED_VALUE_MAX
Definition: bigdecimal.c:41
VP_EXPORT int VpIsRoundMode(unsigned short n)
Definition: bigdecimal.c:3715
VP_EXPORT void VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
Definition: bigdecimal.c:5549
VP_EXPORT size_t VpInit(BDIGIT BaseVal)
Definition: bigdecimal.c:3980
#define rmpd_set_thread_local_rounding_mode(mode)
Definition: bigdecimal.c:3691
VP_EXPORT double VpGetDoubleNaN(void)
Definition: bigdecimal.c:3774
VALUE rb_cBigDecimal
Definition: bigdecimal.c:45
VP_EXPORT double VpGetDoubleNegInf(void)
Definition: bigdecimal.c:3786
#define SAVE(p)
Definition: bigdecimal.c:70
#define ENTER(n)
Definition: bigdecimal.c:68
#define MUL_OVERFLOW_SIGNED_VALUE_P(a, b)
Definition: bigdecimal.c:43
VP_EXPORT unsigned short VpGetRoundMode(void)
Definition: bigdecimal.c:3699
VP_EXPORT void VpDtoV(Real *m, double d)
Definition: bigdecimal.c:5887
#define maxnr
Definition: bigdecimal.c:3547
VP_EXPORT size_t VpMult(Real *c, Real *a, Real *b)
Definition: bigdecimal.c:4843
VP_EXPORT int VpActiveRound(Real *y, Real *x, unsigned short f, ssize_t nf)
Definition: bigdecimal.c:6305
#define RMPD_PRECISION_LIMIT_DEFAULT
Definition: bigdecimal.c:3660
#define VpAllocReal(prec)
Definition: bigdecimal.c:660
#define BIGDECIMAL_NEGATIVE_P(bd)
Definition: bigdecimal.c:131
VP_EXPORT void VpFrac(Real *y, Real *x)
Definition: bigdecimal.c:6400
void Init_bigdecimal(void)
Definition: bigdecimal.c:3302
VP_EXPORT ssize_t VpExponent10(Real *a)
Definition: bigdecimal.c:5450
VP_EXPORT int VpLeftRound(Real *y, unsigned short f, ssize_t nf)
Definition: bigdecimal.c:6290
VP_EXPORT Real * VpOne(void)
Definition: bigdecimal.c:4008
VP_EXPORT size_t VpAddSub(Real *c, Real *a, Real *b, int operation)
Definition: bigdecimal.c:4388
VP_EXPORT size_t VpGetPrecLimit(void)
Definition: bigdecimal.c:3664
VP_EXPORT unsigned short VpSetRoundMode(unsigned short n)
Definition: bigdecimal.c:3733
#define BASE
Definition: bigdecimal.c:74
VP_EXPORT size_t VpSetPrecLimit(size_t n)
Definition: bigdecimal.c:3680
VP_EXPORT Real * VpNewRbClass(size_t mx, const char *str, VALUE klass)
Definition: bigdecimal.c:644
VP_EXPORT void VpSzMantissa(Real *a, char *psz)
Definition: bigdecimal.c:5467
VP_EXPORT size_t VpNumOfChars(Real *vp, const char *pszFmt)
Definition: bigdecimal.c:3936
VP_EXPORT int VpSqrt(Real *y, Real *x)
Definition: bigdecimal.c:6019
op_sw
Definition: bigdecimal.c:3554
@ OP_SW_ADD
Definition: bigdecimal.c:3555
@ OP_SW_DIV
Definition: bigdecimal.c:3558
@ OP_SW_SUB
Definition: bigdecimal.c:3556
@ OP_SW_MULT
Definition: bigdecimal.c:3557
#define BASE_FIG
Definition: bigdecimal.c:73
volatile const double gOne_ABCED9B4_CE73__00400511F31D
Definition: bigdecimal.c:3751
#define RRATIONAL_NEGATIVE_P(x)
Definition: bigdecimal.c:89
VP_EXPORT Real * VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
Definition: bigdecimal.c:4111
Real * rmpd_parse_special_string(const char *str)
Definition: bigdecimal.c:4052
#define BIGDECIMAL_POSITIVE_P(bd)
Definition: bigdecimal.c:130
VP_EXPORT void * VpMemAlloc(size_t mb)
Definition: bigdecimal.c:3575
VP_EXPORT int VpComp(Real *a, Real *b)
Definition: bigdecimal.c:5225
#define DoSomeOne(x, y, f)
Definition: bigdecimal.c:136
VP_EXPORT int VpMidRound(Real *y, unsigned short f, ssize_t nf)
Definition: bigdecimal.c:6128
#define is_positive(x)
Definition: bigdecimal.c:2200
NORETURN(static void cannot_be_coerced_into_BigDecimal(VALUE, VALUE))
#define DBLE_FIG
Definition: bigdecimal.c:80
#define HALF_BASE
Definition: bigdecimal.c:76
#define BigMath_log(x, n)
Definition: bigdecimal.c:2177
VALUE rb_mBigMath
Definition: bigdecimal.c:46
#define rmpd_set_thread_local_precision_limit(limit)
Definition: bigdecimal.c:3654
#define RRATIONAL_ZERO_P(x)
Definition: bigdecimal.c:84
VP_EXPORT int VpException(unsigned short f, const char *str, int always)
Definition: bigdecimal.c:3809
VP_EXPORT void * VpMemRealloc(void *ptr, size_t mb)
Definition: bigdecimal.c:3589
#define BASE1
Definition: bigdecimal.c:77
VP_EXPORT int VpPower(Real *y, Real *x, SIGNED_VALUE n)
Definition: bigdecimal.c:6448
VP_EXPORT int VpVtoD(double *d, SIGNED_VALUE *e, Real *m)
Definition: bigdecimal.c:5823
VP_EXPORT void VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
Definition: bigdecimal.c:5597
#define MemCmp(x, y, z)
Definition: bigdecimal.c:3551
#define rmpd_set_thread_local_exception_mode(mode)
Definition: bigdecimal.c:3621
VP_EXPORT size_t VpAsgn(Real *c, Real *a, int isw)
Definition: bigdecimal.c:4344
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
#define VpReallocReal(ptr, prec)
Definition: bigdecimal.c:661
VP_EXPORT void VpFree(Real *pv)
Definition: bigdecimal.c:3599
VP_EXPORT int VpToSpecialString(Real *a, char *psz, int fPlus)
Definition: bigdecimal.c:5514
VP_EXPORT double VpGetDoublePosInf(void)
Definition: bigdecimal.c:3780
#define VP_SIGN_NaN
Definition: bigdecimal.h:222
#define SZ_NINF
Definition: bigdecimal.h:188
#define VP_EXCEPTION_ZERODIVIDE
Definition: bigdecimal.h:202
#define VpMaxPrec(a)
Definition: bigdecimal.h:347
#define VpIsInf(a)
Definition: bigdecimal.h:378
#define VpIsNaN(a)
Definition: bigdecimal.h:372
#define SZ_INF
Definition: bigdecimal.h:186
#define VpIsDef(a)
Definition: bigdecimal.h:379
#define VP_EXPORT
Definition: bigdecimal.h:194
#define VP_ROUND_DOWN
Definition: bigdecimal.h:213
#define VP_ROUND_FLOOR
Definition: bigdecimal.h:217
#define VP_SIGN_NEGATIVE_INFINITE
Definition: bigdecimal.h:228
#define VP_SIGN_POSITIVE_ZERO
Definition: bigdecimal.h:223
#define VP_ROUND_HALF_EVEN
Definition: bigdecimal.h:218
#define VpExponent(a)
Definition: bigdecimal.h:385
#define VpChangeSign(a, s)
Definition: bigdecimal.h:356
#define VpSetNaN(a)
Definition: bigdecimal.h:373
#define VpBaseVal()
Definition: bigdecimal.h:285
#define VP_EXCEPTION_OP
Definition: bigdecimal.h:205
#define Max(a, b)
Definition: bigdecimal.h:344
#define VP_EXCEPTION_UNDERFLOW
Definition: bigdecimal.h:200
#define VpIsZero(a)
Definition: bigdecimal.h:366
#define VpSetInf(a, s)
Definition: bigdecimal.h:382
#define VpDblFig()
Definition: bigdecimal.h:284
#define VpSetPosInf(a)
Definition: bigdecimal.h:380
#define VP_ROUND_CEIL
Definition: bigdecimal.h:216
#define VpIsPosInf(a)
Definition: bigdecimal.h:376
#define VP_ROUND_HALF_DOWN
Definition: bigdecimal.h:215
#define VpSetSign(a, s)
Definition: bigdecimal.h:358
#define RMPD_ROUNDING_MODE_DEFAULT
Definition: bigdecimal.h:220
#define VP_SIGN_NEGATIVE_FINITE
Definition: bigdecimal.h:226
#define VpHasVal(a)
Definition: bigdecimal.h:383
#define VpGetSign(a)
Definition: bigdecimal.h:354
#define VpSetNegInf(a)
Definition: bigdecimal.h:381
#define RMPD_EXCEPTION_MODE_DEFAULT
Definition: bigdecimal.h:208
#define Min(a, b)
Definition: bigdecimal.h:345
#define VpIsNegZero(a)
Definition: bigdecimal.h:365
#define VpIsNegInf(a)
Definition: bigdecimal.h:377
#define VP_SIGN_NEGATIVE_ZERO
Definition: bigdecimal.h:224
#define VpBaseFig()
Definition: bigdecimal.h:283
#define VP_SIGN_POSITIVE_INFINITE
Definition: bigdecimal.h:227
#define VP_EXCEPTION_OVERFLOW
Definition: bigdecimal.h:201
#define VpSetOne(a)
Definition: bigdecimal.h:361
#define VP_EXCEPTION_ALL
Definition: bigdecimal.h:197
#define vabs
Definition: bigdecimal.h:155
#define SZ_NaN
Definition: bigdecimal.h:185
#define VP_ROUND_UP
Definition: bigdecimal.h:212
#define VP_SIGN_POSITIVE_FINITE
Definition: bigdecimal.h:225
#define SZ_PINF
Definition: bigdecimal.h:187
#define VpIsPosZero(a)
Definition: bigdecimal.h:364
#define VP_EXCEPTION_MEMORY
Definition: bigdecimal.h:206
#define VP_EXCEPTION_NaN
Definition: bigdecimal.h:199
#define VP_EXCEPTION_INFINITY
Definition: bigdecimal.h:198
#define VpIsOne(a)
Definition: bigdecimal.h:384
#define VP_ROUND_MODE
Definition: bigdecimal.h:211
#define RMPD_COMPONENT_FIGURES
Definition: bigdecimal.h:174
#define VP_ROUND_HALF_UP
Definition: bigdecimal.h:214
#define VpSetZero(a, s)
Definition: bigdecimal.h:369
#define id_to_r
Definition: complex.c:41
#define mod(x, y)
Definition: date_strftime.c:28
struct RIMemo * ptr
Definition: debug.c:65
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
VALUE rb_define_class(const char *, VALUE)
Defines a top-level class.
Definition: class.c:662
VALUE rb_define_module(const char *)
Definition: class.c:785
void rb_undef_method(VALUE, const char *)
Definition: class.c:1593
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *)
Definition: class.c:1904
VALUE rb_eZeroDivError
Definition: ruby.h:2073
VALUE rb_cNumeric
Definition: ruby.h:2039
VALUE rb_eFloatDomainError
Definition: ruby.h:2077
VALUE rb_eMathDomainError
Definition: ruby.h:2090
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2671
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition: eval.c:668
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:874
void rb_bug(const char *fmt,...)
Definition: error.c:636
VALUE rb_eTypeError
Definition: error.c:924
void rb_fatal(const char *fmt,...)
Definition: error.c:2722
VALUE rb_protect(VALUE(*)(VALUE), VALUE, int *)
Protects a function call from potential global escapes from the function.
Definition: eval.c:1072
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:891
void rb_warn(const char *fmt,...)
Definition: error.c:315
VALUE rb_eArgError
Definition: error.c:925
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
Definition: eval.c:884
#define opts_exception_p(opts)
Definition: object.c:3134
VALUE rb_check_convert_type(VALUE, int, const char *, const char *)
Tries to convert an object into another type.
Definition: object.c:2941
int rb_opts_exception_p(VALUE opts, int default_value)
Definition: object.c:3125
VALUE rb_obj_class(VALUE)
Equivalent to Object#class in Ruby.
Definition: object.c:217
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:551
#define DBL_MIN_10_EXP
Definition: numeric.c:49
#define DBL_MAX_10_EXP
Definition: numeric.c:52
#define id_eq
Definition: numeric.c:178
#define DBL_DIG
Definition: numeric.c:55
#define id_ceil
Definition: rational.c:1606
double round(double)
Definition: numeric.c:80
VALUE rb_class_name(VALUE)
Definition: variable.c:274
#define rb_str_new2
#define MEMCPY(p1, p2, type, n)
#define T_COMPLEX
int strncasecmp(const char *, const char *, size_t) __attribute__((__pure__))
#define NULL
#define BDIGIT_DBL
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2709
void div_t div(int __numer, int __denom)
#define stdout
#define RSTRING_LEN(str)
#define RTEST(v)
double fabs(double)
#define PRIdVALUE
VALUE rb_thread_local_aref(VALUE, ID)
Definition: thread.c:3215
int sprintf(char *__restrict__, const char *__restrict__,...) __attribute__((__format__(__printf__
VALUE rb_Rational(VALUE, VALUE)
Definition: rational.c:1963
#define bp()
size_t strlen(const char *)
#define T_STRING
VALUE rb_assoc_new(VALUE, VALUE)
Definition: array.c:896
#define PRIuSIZE
#define xfree
void rb_define_global_function(const char *, VALUE(*)(), int)
#define LONG2FIX(i)
#define Qundef
#define CHAR_BIT
#define rb_str_cat2
VALUE rb_dbl2big(double)
Definition: bignum.c:5249
const VALUE VALUE obj
#define TYPE(x)
#define UNREACHABLE
#define SSIZET2NUM(v)
#define T_FLOAT
#define RSTRING_PTR(str)
#define xrealloc
#define T_BIGNUM
int snprintf(char *__restrict__, size_t, const char *__restrict__,...) __attribute__((__format__(__printf__
#define RTYPEDDATA_DATA(v)
int int int printf(const char *__restrict__,...) __attribute__((__format__(__printf__
st_index_t rb_memhash(const void *ptr, long len)
Definition: random.c:1444
#define rb_str_new(str, len)
#define NIL_P(v)
const rb_callable_method_entry_t * me
#define RB_OBJ_FREEZE(x)
#define rb_special_const_p(obj)
#define ID2SYM(x)
#define T_FIXNUM
int fprintf(FILE *__restrict__, const char *__restrict__,...) __attribute__((__format__(__printf__
const char size_t n
#define T_DATA
#define rb_intern_const(str)
#define BDIGIT_DBL_SIGNED
#define SYM2ID(x)
#define NUM2SSIZET(x)
unsigned long VALUE
VALUE rb_ary_push(VALUE, VALUE)
Definition: array.c:1195
#define stderr
VALUE rb_sym2str(VALUE)
Definition: symbol.c:784
VALUE rb_hash_lookup2(VALUE, VALUE, VALUE)
Definition: hash.c:2050
VALUE rb_check_string_type(VALUE)
Definition: string.c:2314
#define rb_Rational1(x)
#define rb_float_new(d)
#define xmalloc
#define isinf(__x)
uint32_t i
#define char
VALUE rb_rational_num(VALUE rat)
Definition: rational.c:1972
#define isnan(__x)
int strncmp(const char *, const char *, size_t)
__inline__ const void *__restrict__ size_t len
const VALUE int int int int int int VALUE char * fmt
#define isfinite(__x)
while(!(((VALUE)(klass) &(VALUE)~((VALUE) RUBY_Qnil))==0))
#define INT2NUM(x)
#define T_RATIONAL
#define T_HASH
#define LONG2NUM(x)
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2891
#define long
#define NUM2INT(x)
void rb_define_singleton_method(VALUE, const char *, VALUE(*)(), int)
#define RB_GC_GUARD(v)
#define RUBY_TYPED_FREE_IMMEDIATELY
double nan(const char *)
Definition: nan.c:7
#define PRIsVALUE
void * memset(void *, int, size_t)
#define rb_funcall(recv, mid, argc,...)
#define FIX2INT(x)
int VALUE v
#define rb_scan_args(argc, argvp, fmt,...)
#define rb_exc_new3
#define NUM2USHORT(x)
VALUE rb_str_tmp_new(long)
Definition: string.c:1343
void rb_thread_check_ints(void)
Definition: thread.c:1361
#define rb_intern(str)
double log10(double)
#define ERANGE
#define TypedData_Wrap_Struct(klass, data_type, sval)
#define RRATIONAL(obj)
#define RFLOAT_VALUE(v)
#define NUM2SIZET(x)
VALUE rb_num_coerce_cmp(VALUE, VALUE, ID)
Definition: numeric.c:453
#define Qtrue
long unsigned int size_t
#define BDIGIT
struct rb_call_cache buf
VALUE rb_big_cmp(VALUE, VALUE)
Definition: bignum.c:5419
#define memmove(dst, src, len)
#define ISDIGIT(c)
#define Qnil
#define Qfalse
#define DATA_PTR(dta)
void * memcpy(void *__restrict__, const void *__restrict__, size_t)
#define SIGNED_VALUE
st_data_t st_index_t
VALUE rb_thread_current(void)
Definition: thread.c:2675
#define FIXABLE(f)
#define RB_TYPE_P(obj, type)
#define INT2FIX(i)
#define SPECIAL_CONST_P(x)
VALUE rb_num_coerce_relop(VALUE, VALUE, ID)
Definition: numeric.c:461
#define T_SYMBOL
const VALUE * argv
#define SYMBOL_P(x)
_ssize_t ssize_t
double sqrt(double)
#define FIXNUM_P(f)
#define CLASS_OF(v)
void rb_big_pack(VALUE val, unsigned long *buf, long num_longs)
Definition: bignum.c:3215
if((__builtin_expect(!!(!me), 0)))
#define assert
#define PRIdSIZE
VALUE rb_big2str(VALUE, int)
Definition: bignum.c:5091
#define PRIuBDIGIT
VALUE rb_str_dup(VALUE)
Definition: string.c:1516
unsigned long ID
VALUE rb_yield(VALUE)
Definition: vm_eval.c:1237
double exp(double)
#define ISSPACE(c)
VALUE ID id
#define FIX2LONG(x)
const rb_iseq_t const VALUE exc
void rb_define_method(VALUE, const char *, VALUE(*)(), int)
#define rb_ary_new2
#define RARRAY_AREF(a, i)
#define SIZEOF_VALUE
#define HUGE_VAL
#define ST2FIX(h)
VALUE rb_rational_den(VALUE rat)
Definition: rational.c:1978
#define StringValueCStr(v)
#define f
size_t MaxPrec
Definition: bigdecimal.h:244
SIGNED_VALUE exponent
Definition: bigdecimal.h:250
size_t Prec
Definition: bigdecimal.h:247
short flag
Definition: bigdecimal.h:261
BDIGIT frac[FLEXIBLE_ARRAY_SIZE]
Definition: bigdecimal.h:262
VALUE obj
Definition: bigdecimal.h:243
short sign
Definition: bigdecimal.h:251
#define ne(x, y)
Definition: time.c:82
#define strtod(s, e)
Definition: util.h:76
#define DECIMAL_SIZE_OF_BITS(n)
Definition: util.h:50