Ruby 2.1.5p273(2014-11-13revision48405)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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