bigdecimal 3.1.1 → 3.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bigdecimal.gemspec +28 -12
- data/ext/bigdecimal/bigdecimal.c +832 -594
- data/ext/bigdecimal/bigdecimal.h +32 -16
- data/ext/bigdecimal/extconf.rb +0 -29
- data/ext/bigdecimal/missing.h +6 -45
- data/lib/bigdecimal/jacobian.rb +3 -3
- data/lib/bigdecimal/util.rb +5 -1
- data/lib/bigdecimal.rb +5 -1
- metadata +4 -3
data/ext/bigdecimal/bigdecimal.c
CHANGED
@@ -7,9 +7,7 @@
|
|
7
7
|
*/
|
8
8
|
|
9
9
|
/* #define BIGDECIMAL_DEBUG 1 */
|
10
|
-
|
11
|
-
# define BIGDECIMAL_ENABLE_VPRINT 1
|
12
|
-
#endif
|
10
|
+
|
13
11
|
#include "bigdecimal.h"
|
14
12
|
#include "ruby/util.h"
|
15
13
|
|
@@ -33,6 +31,8 @@
|
|
33
31
|
#include "bits.h"
|
34
32
|
#include "static_assert.h"
|
35
33
|
|
34
|
+
#define BIGDECIMAL_VERSION "3.1.4"
|
35
|
+
|
36
36
|
/* #define ENABLE_NUMERIC_STRING */
|
37
37
|
|
38
38
|
#define SIGNED_VALUE_MAX INTPTR_MAX
|
@@ -61,6 +61,13 @@ static ID id_to_r;
|
|
61
61
|
static ID id_eq;
|
62
62
|
static ID id_half;
|
63
63
|
|
64
|
+
#define RBD_NUM_ROUNDING_MODES 11
|
65
|
+
|
66
|
+
static struct {
|
67
|
+
ID id;
|
68
|
+
uint8_t mode;
|
69
|
+
} rbd_rounding_modes[RBD_NUM_ROUNDING_MODES];
|
70
|
+
|
64
71
|
/* MACRO's to guard objects from GC by keeping them in stack */
|
65
72
|
#ifdef RBIMPL_ATTR_MAYBE_UNUSED
|
66
73
|
#define ENTER(n) RBIMPL_ATTR_MAYBE_UNUSED() volatile VALUE vStack[n];int iStack=0
|
@@ -102,9 +109,163 @@ static ID id_half;
|
|
102
109
|
# define RB_OBJ_STRING(obj) StringValueCStr(obj)
|
103
110
|
#endif
|
104
111
|
|
112
|
+
#ifndef MAYBE_UNUSED
|
113
|
+
# define MAYBE_UNUSED(x) x
|
114
|
+
#endif
|
115
|
+
|
105
116
|
#define BIGDECIMAL_POSITIVE_P(bd) ((bd)->sign > 0)
|
106
117
|
#define BIGDECIMAL_NEGATIVE_P(bd) ((bd)->sign < 0)
|
107
118
|
|
119
|
+
/*
|
120
|
+
* ================== Memory allocation ============================
|
121
|
+
*/
|
122
|
+
|
123
|
+
#ifdef BIGDECIMAL_DEBUG
|
124
|
+
static size_t rbd_allocation_count = 0; /* Memory allocation counter */
|
125
|
+
static inline void
|
126
|
+
atomic_allocation_count_inc(void)
|
127
|
+
{
|
128
|
+
RUBY_ATOMIC_SIZE_INC(rbd_allocation_count);
|
129
|
+
}
|
130
|
+
static inline void
|
131
|
+
atomic_allocation_count_dec_nounderflow(void)
|
132
|
+
{
|
133
|
+
if (rbd_allocation_count == 0) return;
|
134
|
+
RUBY_ATOMIC_SIZE_DEC(rbd_allocation_count);
|
135
|
+
}
|
136
|
+
static void
|
137
|
+
check_allocation_count_nonzero(void)
|
138
|
+
{
|
139
|
+
if (rbd_allocation_count != 0) return;
|
140
|
+
rb_bug("[bigdecimal][rbd_free_struct] Too many memory free calls");
|
141
|
+
}
|
142
|
+
#else
|
143
|
+
# define atomic_allocation_count_inc() /* nothing */
|
144
|
+
# define atomic_allocation_count_dec_nounderflow() /* nothing */
|
145
|
+
# define check_allocation_count_nonzero() /* nothing */
|
146
|
+
#endif /* BIGDECIMAL_DEBUG */
|
147
|
+
|
148
|
+
PUREFUNC(static inline size_t rbd_struct_size(size_t const));
|
149
|
+
|
150
|
+
static inline size_t
|
151
|
+
rbd_struct_size(size_t const internal_digits)
|
152
|
+
{
|
153
|
+
size_t const frac_len = (internal_digits == 0) ? 1 : internal_digits;
|
154
|
+
return offsetof(Real, frac) + frac_len * sizeof(DECDIG);
|
155
|
+
}
|
156
|
+
|
157
|
+
static inline Real *
|
158
|
+
rbd_allocate_struct(size_t const internal_digits)
|
159
|
+
{
|
160
|
+
size_t const size = rbd_struct_size(internal_digits);
|
161
|
+
Real *real = ruby_xcalloc(1, size);
|
162
|
+
atomic_allocation_count_inc();
|
163
|
+
real->MaxPrec = internal_digits;
|
164
|
+
return real;
|
165
|
+
}
|
166
|
+
|
167
|
+
static size_t
|
168
|
+
rbd_calculate_internal_digits(size_t const digits, bool limit_precision)
|
169
|
+
{
|
170
|
+
size_t const len = roomof(digits, BASE_FIG);
|
171
|
+
if (limit_precision) {
|
172
|
+
size_t const prec_limit = VpGetPrecLimit();
|
173
|
+
if (prec_limit > 0) {
|
174
|
+
/* NOTE: 2 more digits for rounding and division */
|
175
|
+
size_t const max_len = roomof(prec_limit, BASE_FIG) + 2;
|
176
|
+
if (len > max_len)
|
177
|
+
return max_len;
|
178
|
+
}
|
179
|
+
}
|
180
|
+
|
181
|
+
return len;
|
182
|
+
}
|
183
|
+
|
184
|
+
static inline Real *
|
185
|
+
rbd_allocate_struct_decimal_digits(size_t const decimal_digits, bool limit_precision)
|
186
|
+
{
|
187
|
+
size_t const internal_digits = rbd_calculate_internal_digits(decimal_digits, limit_precision);
|
188
|
+
return rbd_allocate_struct(internal_digits);
|
189
|
+
}
|
190
|
+
|
191
|
+
static VALUE BigDecimal_wrap_struct(VALUE obj, Real *vp);
|
192
|
+
|
193
|
+
static Real *
|
194
|
+
rbd_reallocate_struct(Real *real, size_t const internal_digits)
|
195
|
+
{
|
196
|
+
size_t const size = rbd_struct_size(internal_digits);
|
197
|
+
VALUE obj = real ? real->obj : 0;
|
198
|
+
Real *new_real = (Real *)ruby_xrealloc(real, size);
|
199
|
+
new_real->MaxPrec = internal_digits;
|
200
|
+
if (obj) {
|
201
|
+
new_real->obj = 0;
|
202
|
+
BigDecimal_wrap_struct(obj, new_real);
|
203
|
+
}
|
204
|
+
return new_real;
|
205
|
+
}
|
206
|
+
|
207
|
+
static void
|
208
|
+
rbd_free_struct(Real *real)
|
209
|
+
{
|
210
|
+
if (real != NULL) {
|
211
|
+
check_allocation_count_nonzero();
|
212
|
+
ruby_xfree(real);
|
213
|
+
atomic_allocation_count_dec_nounderflow();
|
214
|
+
}
|
215
|
+
}
|
216
|
+
|
217
|
+
#define NewZero rbd_allocate_struct_zero
|
218
|
+
static Real *
|
219
|
+
rbd_allocate_struct_zero(int sign, size_t const digits, bool limit_precision)
|
220
|
+
{
|
221
|
+
Real *real = rbd_allocate_struct_decimal_digits(digits, limit_precision);
|
222
|
+
VpSetZero(real, sign);
|
223
|
+
return real;
|
224
|
+
}
|
225
|
+
|
226
|
+
MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_limited(int sign, size_t const digits));
|
227
|
+
#define NewZeroLimited rbd_allocate_struct_zero_limited
|
228
|
+
static inline Real *
|
229
|
+
rbd_allocate_struct_zero_limited(int sign, size_t const digits)
|
230
|
+
{
|
231
|
+
return rbd_allocate_struct_zero(sign, digits, true);
|
232
|
+
}
|
233
|
+
|
234
|
+
MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_nolimit(int sign, size_t const digits));
|
235
|
+
#define NewZeroNolimit rbd_allocate_struct_zero_nolimit
|
236
|
+
static inline Real *
|
237
|
+
rbd_allocate_struct_zero_nolimit(int sign, size_t const digits)
|
238
|
+
{
|
239
|
+
return rbd_allocate_struct_zero(sign, digits, false);
|
240
|
+
}
|
241
|
+
|
242
|
+
#define NewOne rbd_allocate_struct_one
|
243
|
+
static Real *
|
244
|
+
rbd_allocate_struct_one(int sign, size_t const digits, bool limit_precision)
|
245
|
+
{
|
246
|
+
Real *real = rbd_allocate_struct_decimal_digits(digits, limit_precision);
|
247
|
+
VpSetOne(real);
|
248
|
+
if (sign < 0)
|
249
|
+
VpSetSign(real, VP_SIGN_NEGATIVE_FINITE);
|
250
|
+
return real;
|
251
|
+
}
|
252
|
+
|
253
|
+
MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_limited(int sign, size_t const digits));
|
254
|
+
#define NewOneLimited rbd_allocate_struct_one_limited
|
255
|
+
static inline Real *
|
256
|
+
rbd_allocate_struct_one_limited(int sign, size_t const digits)
|
257
|
+
{
|
258
|
+
return rbd_allocate_struct_one(sign, digits, true);
|
259
|
+
}
|
260
|
+
|
261
|
+
MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_nolimit(int sign, size_t const digits));
|
262
|
+
#define NewOneNolimit rbd_allocate_struct_one_nolimit
|
263
|
+
static inline Real *
|
264
|
+
rbd_allocate_struct_one_nolimit(int sign, size_t const digits)
|
265
|
+
{
|
266
|
+
return rbd_allocate_struct_one(sign, digits, false);
|
267
|
+
}
|
268
|
+
|
108
269
|
/*
|
109
270
|
* ================== Ruby Interface part ==========================
|
110
271
|
*/
|
@@ -120,10 +281,7 @@ static VALUE VpCheckGetValue(Real *p);
|
|
120
281
|
static void VpInternalRound(Real *c, size_t ixDigit, DECDIG vPrev, DECDIG v);
|
121
282
|
static int VpLimitRound(Real *c, size_t ixDigit);
|
122
283
|
static Real *VpCopy(Real *pv, Real const* const x);
|
123
|
-
|
124
|
-
#ifdef BIGDECIMAL_ENABLE_VPRINT
|
125
284
|
static int VPrint(FILE *fp,const char *cntl_chr,Real *a);
|
126
|
-
#endif
|
127
285
|
|
128
286
|
/*
|
129
287
|
* **** BigDecimal part ****
|
@@ -138,7 +296,7 @@ static VALUE BigDecimal_negative_zero(void);
|
|
138
296
|
static void
|
139
297
|
BigDecimal_delete(void *pv)
|
140
298
|
{
|
141
|
-
|
299
|
+
rbd_free_struct(pv);
|
142
300
|
}
|
143
301
|
|
144
302
|
static size_t
|
@@ -157,10 +315,64 @@ static const rb_data_type_t BigDecimal_data_type = {
|
|
157
315
|
"BigDecimal",
|
158
316
|
{ 0, BigDecimal_delete, BigDecimal_memsize, },
|
159
317
|
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
|
160
|
-
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE
|
318
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE | RUBY_TYPED_WB_PROTECTED
|
161
319
|
#endif
|
162
320
|
};
|
163
321
|
|
322
|
+
static Real *
|
323
|
+
rbd_allocate_struct_zero_wrap_klass(VALUE klass, int sign, size_t const digits, bool limit_precision)
|
324
|
+
{
|
325
|
+
Real *real = rbd_allocate_struct_zero(sign, digits, limit_precision);
|
326
|
+
if (real != NULL) {
|
327
|
+
VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
|
328
|
+
BigDecimal_wrap_struct(obj, real);
|
329
|
+
}
|
330
|
+
return real;
|
331
|
+
}
|
332
|
+
|
333
|
+
MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_limited_wrap(int sign, size_t const digits));
|
334
|
+
#define NewZeroWrapLimited rbd_allocate_struct_zero_limited_wrap
|
335
|
+
static inline Real *
|
336
|
+
rbd_allocate_struct_zero_limited_wrap(int sign, size_t const digits)
|
337
|
+
{
|
338
|
+
return rbd_allocate_struct_zero_wrap_klass(rb_cBigDecimal, sign, digits, true);
|
339
|
+
}
|
340
|
+
|
341
|
+
MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_nolimit_wrap(int sign, size_t const digits));
|
342
|
+
#define NewZeroWrapNolimit rbd_allocate_struct_zero_nolimit_wrap
|
343
|
+
static inline Real *
|
344
|
+
rbd_allocate_struct_zero_nolimit_wrap(int sign, size_t const digits)
|
345
|
+
{
|
346
|
+
return rbd_allocate_struct_zero_wrap_klass(rb_cBigDecimal, sign, digits, false);
|
347
|
+
}
|
348
|
+
|
349
|
+
static Real *
|
350
|
+
rbd_allocate_struct_one_wrap_klass(VALUE klass, int sign, size_t const digits, bool limit_precision)
|
351
|
+
{
|
352
|
+
Real *real = rbd_allocate_struct_one(sign, digits, limit_precision);
|
353
|
+
if (real != NULL) {
|
354
|
+
VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
|
355
|
+
BigDecimal_wrap_struct(obj, real);
|
356
|
+
}
|
357
|
+
return real;
|
358
|
+
}
|
359
|
+
|
360
|
+
MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_limited_wrap(int sign, size_t const digits));
|
361
|
+
#define NewOneWrapLimited rbd_allocate_struct_one_limited_wrap
|
362
|
+
static inline Real *
|
363
|
+
rbd_allocate_struct_one_limited_wrap(int sign, size_t const digits)
|
364
|
+
{
|
365
|
+
return rbd_allocate_struct_one_wrap_klass(rb_cBigDecimal, sign, digits, true);
|
366
|
+
}
|
367
|
+
|
368
|
+
MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_nolimit_wrap(int sign, size_t const digits));
|
369
|
+
#define NewOneWrapNolimit rbd_allocate_struct_one_nolimit_wrap
|
370
|
+
static inline Real *
|
371
|
+
rbd_allocate_struct_one_nolimit_wrap(int sign, size_t const digits)
|
372
|
+
{
|
373
|
+
return rbd_allocate_struct_one_wrap_klass(rb_cBigDecimal, sign, digits, false);
|
374
|
+
}
|
375
|
+
|
164
376
|
static inline int
|
165
377
|
is_kind_of_BigDecimal(VALUE const v)
|
166
378
|
{
|
@@ -214,7 +426,7 @@ GetVpValueWithPrec(VALUE v, long prec, int must)
|
|
214
426
|
|
215
427
|
case T_FIXNUM: {
|
216
428
|
char szD[128];
|
217
|
-
|
429
|
+
snprintf(szD, 128, "%ld", FIX2LONG(v));
|
218
430
|
v = rb_cstr_convert_to_BigDecimal(szD, VpBaseFig() * 2 + 1, must);
|
219
431
|
break;
|
220
432
|
}
|
@@ -249,7 +461,7 @@ SomeOneMayDoIt:
|
|
249
461
|
return NULL; /* NULL means to coerce */
|
250
462
|
}
|
251
463
|
|
252
|
-
static Real*
|
464
|
+
static inline Real*
|
253
465
|
GetVpValue(VALUE v, int must)
|
254
466
|
{
|
255
467
|
return GetVpValueWithPrec(v, -1, must);
|
@@ -264,7 +476,7 @@ GetVpValue(VALUE v, int must)
|
|
264
476
|
* BigDecimal.double_fig # => 16
|
265
477
|
*
|
266
478
|
*/
|
267
|
-
static VALUE
|
479
|
+
static inline VALUE
|
268
480
|
BigDecimal_double_fig(VALUE self)
|
269
481
|
{
|
270
482
|
return INT2FIX(VpDblFig());
|
@@ -486,15 +698,15 @@ BigDecimal_precision_scale(VALUE self)
|
|
486
698
|
*
|
487
699
|
* Returns the number of decimal significant digits in +self+.
|
488
700
|
*
|
489
|
-
* BigDecimal("0").
|
490
|
-
* BigDecimal("1").
|
491
|
-
* BigDecimal("1.1").
|
492
|
-
* BigDecimal("3.1415").
|
493
|
-
* BigDecimal("-1e20").
|
494
|
-
* BigDecimal("1e-20").
|
495
|
-
* BigDecimal("Infinity").
|
496
|
-
* BigDecimal("-Infinity").
|
497
|
-
* BigDecimal("NaN").
|
701
|
+
* BigDecimal("0").n_significant_digits # => 0
|
702
|
+
* BigDecimal("1").n_significant_digits # => 1
|
703
|
+
* BigDecimal("1.1").n_significant_digits # => 2
|
704
|
+
* BigDecimal("3.1415").n_significant_digits # => 5
|
705
|
+
* BigDecimal("-1e20").n_significant_digits # => 1
|
706
|
+
* BigDecimal("1e-20").n_significant_digits # => 1
|
707
|
+
* BigDecimal("Infinity").n_significant_digits # => 0
|
708
|
+
* BigDecimal("-Infinity").n_significant_digits # => 0
|
709
|
+
* BigDecimal("NaN").n_significant_digits # => 0
|
498
710
|
*/
|
499
711
|
static VALUE
|
500
712
|
BigDecimal_n_significant_digits(VALUE self)
|
@@ -573,13 +785,15 @@ BigDecimal_dump(int argc, VALUE *argv, VALUE self)
|
|
573
785
|
char *psz;
|
574
786
|
VALUE dummy;
|
575
787
|
volatile VALUE dump;
|
788
|
+
size_t len;
|
576
789
|
|
577
790
|
rb_scan_args(argc, argv, "01", &dummy);
|
578
791
|
GUARD_OBJ(vp,GetVpValue(self, 1));
|
579
792
|
dump = rb_str_new(0, VpNumOfChars(vp, "E")+50);
|
580
793
|
psz = RSTRING_PTR(dump);
|
581
|
-
|
582
|
-
|
794
|
+
snprintf(psz, RSTRING_LEN(dump), "%"PRIuSIZE":", VpMaxPrec(vp)*VpBaseFig());
|
795
|
+
len = strlen(psz);
|
796
|
+
VpToString(vp, psz+len, RSTRING_LEN(dump)-len, 0, 0);
|
583
797
|
rb_str_resize(dump, strlen(psz));
|
584
798
|
return dump;
|
585
799
|
}
|
@@ -623,18 +837,19 @@ check_rounding_mode_option(VALUE const opts)
|
|
623
837
|
assert(RB_TYPE_P(opts, T_HASH));
|
624
838
|
|
625
839
|
if (NIL_P(opts))
|
626
|
-
goto
|
840
|
+
goto no_opt;
|
627
841
|
|
628
842
|
mode = rb_hash_lookup2(opts, ID2SYM(id_half), Qundef);
|
629
843
|
if (mode == Qundef || NIL_P(mode))
|
630
|
-
goto
|
844
|
+
goto no_opt;
|
631
845
|
|
632
846
|
if (SYMBOL_P(mode))
|
633
847
|
mode = rb_sym2str(mode);
|
634
848
|
else if (!RB_TYPE_P(mode, T_STRING)) {
|
635
|
-
|
636
|
-
|
637
|
-
|
849
|
+
VALUE str_mode = rb_check_string_type(mode);
|
850
|
+
if (NIL_P(str_mode))
|
851
|
+
goto invalid;
|
852
|
+
mode = str_mode;
|
638
853
|
}
|
639
854
|
s = RSTRING_PTR(mode);
|
640
855
|
l = RSTRING_LEN(mode);
|
@@ -652,13 +867,11 @@ check_rounding_mode_option(VALUE const opts)
|
|
652
867
|
default:
|
653
868
|
break;
|
654
869
|
}
|
870
|
+
|
655
871
|
invalid:
|
656
|
-
|
657
|
-
rb_raise(rb_eArgError, "invalid rounding mode: nil");
|
658
|
-
else
|
659
|
-
rb_raise(rb_eArgError, "invalid rounding mode: %"PRIsVALUE, mode);
|
872
|
+
rb_raise(rb_eArgError, "invalid rounding mode (%"PRIsVALUE")", mode);
|
660
873
|
|
661
|
-
|
874
|
+
no_opt:
|
662
875
|
return VpGetRoundMode();
|
663
876
|
}
|
664
877
|
|
@@ -667,34 +880,23 @@ check_rounding_mode(VALUE const v)
|
|
667
880
|
{
|
668
881
|
unsigned short sw;
|
669
882
|
ID id;
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
if (id == id_half_down)
|
680
|
-
return VP_ROUND_HALF_DOWN;
|
681
|
-
if (id == id_half_even || id == id_banker)
|
682
|
-
return VP_ROUND_HALF_EVEN;
|
683
|
-
if (id == id_ceiling || id == id_ceil)
|
684
|
-
return VP_ROUND_CEIL;
|
685
|
-
if (id == id_floor)
|
686
|
-
return VP_ROUND_FLOOR;
|
687
|
-
rb_raise(rb_eArgError, "invalid rounding mode");
|
688
|
-
|
689
|
-
default:
|
690
|
-
break;
|
883
|
+
if (RB_TYPE_P(v, T_SYMBOL)) {
|
884
|
+
int i;
|
885
|
+
id = SYM2ID(v);
|
886
|
+
for (i = 0; i < RBD_NUM_ROUNDING_MODES; ++i) {
|
887
|
+
if (rbd_rounding_modes[i].id == id) {
|
888
|
+
return rbd_rounding_modes[i].mode;
|
889
|
+
}
|
890
|
+
}
|
891
|
+
rb_raise(rb_eArgError, "invalid rounding mode (%"PRIsVALUE")", v);
|
691
892
|
}
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
893
|
+
else {
|
894
|
+
sw = NUM2USHORT(v);
|
895
|
+
if (!VpIsRoundMode(sw)) {
|
896
|
+
rb_raise(rb_eArgError, "invalid rounding mode (%"PRIsVALUE")", v);
|
897
|
+
}
|
898
|
+
return sw;
|
696
899
|
}
|
697
|
-
return sw;
|
698
900
|
}
|
699
901
|
|
700
902
|
/* call-seq:
|
@@ -933,11 +1135,17 @@ GetAddSubPrec(Real *a, Real *b)
|
|
933
1135
|
return mx;
|
934
1136
|
}
|
935
1137
|
|
936
|
-
static SIGNED_VALUE
|
937
|
-
|
1138
|
+
static inline SIGNED_VALUE
|
1139
|
+
check_int_precision(VALUE v)
|
938
1140
|
{
|
939
1141
|
SIGNED_VALUE n;
|
940
|
-
|
1142
|
+
#if SIZEOF_VALUE <= SIZEOF_LONG
|
1143
|
+
n = (SIGNED_VALUE)NUM2LONG(v);
|
1144
|
+
#elif SIZEOF_VALUE <= SIZEOF_LONG_LONG
|
1145
|
+
n = (SIGNED_VALUE)NUM2LL(v);
|
1146
|
+
#else
|
1147
|
+
# error SIZEOF_VALUE is too large
|
1148
|
+
#endif
|
941
1149
|
if (n < 0) {
|
942
1150
|
rb_raise(rb_eArgError, "negative precision");
|
943
1151
|
}
|
@@ -979,26 +1187,12 @@ VpCreateRbObject(size_t mx, const char *str, bool raise_exception)
|
|
979
1187
|
return VpNewRbClass(mx, str, rb_cBigDecimal, true, raise_exception);
|
980
1188
|
}
|
981
1189
|
|
982
|
-
#define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(DECDIG))
|
983
|
-
|
984
|
-
static Real *
|
985
|
-
VpReallocReal(Real *pv, size_t prec)
|
986
|
-
{
|
987
|
-
VALUE obj = pv ? pv->obj : 0;
|
988
|
-
Real *new_pv = (Real *)VpMemRealloc(pv, offsetof(Real, frac) + prec * sizeof(DECDIG));
|
989
|
-
if (obj) {
|
990
|
-
new_pv->obj = 0;
|
991
|
-
BigDecimal_wrap_struct(obj, new_pv);
|
992
|
-
}
|
993
|
-
return new_pv;
|
994
|
-
}
|
995
|
-
|
996
1190
|
static Real *
|
997
1191
|
VpCopy(Real *pv, Real const* const x)
|
998
1192
|
{
|
999
1193
|
assert(x != NULL);
|
1000
1194
|
|
1001
|
-
pv =
|
1195
|
+
pv = rbd_reallocate_struct(pv, x->MaxPrec);
|
1002
1196
|
pv->MaxPrec = x->MaxPrec;
|
1003
1197
|
pv->Prec = x->Prec;
|
1004
1198
|
pv->exponent = x->exponent;
|
@@ -1119,7 +1313,7 @@ BigDecimal_to_f(VALUE self)
|
|
1119
1313
|
|
1120
1314
|
str = rb_str_new(0, VpNumOfChars(p, "E"));
|
1121
1315
|
buf = RSTRING_PTR(str);
|
1122
|
-
VpToString(p, buf, 0, 0);
|
1316
|
+
VpToString(p, buf, RSTRING_LEN(str), 0, 0);
|
1123
1317
|
errno = 0;
|
1124
1318
|
d = strtod(buf, 0);
|
1125
1319
|
if (errno == ERANGE) {
|
@@ -1276,17 +1470,17 @@ BigDecimal_add(VALUE self, VALUE r)
|
|
1276
1470
|
|
1277
1471
|
mx = GetAddSubPrec(a, b);
|
1278
1472
|
if (mx == (size_t)-1L) {
|
1279
|
-
GUARD_OBJ(c,
|
1280
|
-
|
1473
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, VpBaseFig() + 1));
|
1474
|
+
VpAddSub(c, a, b, 1);
|
1281
1475
|
}
|
1282
1476
|
else {
|
1283
|
-
GUARD_OBJ(c,
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1477
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx * (VpBaseFig() + 1)));
|
1478
|
+
if (!mx) {
|
1479
|
+
VpSetInf(c, VpGetSign(a));
|
1480
|
+
}
|
1481
|
+
else {
|
1482
|
+
VpAddSub(c, a, b, 1);
|
1483
|
+
}
|
1290
1484
|
}
|
1291
1485
|
return VpCheckGetValue(c);
|
1292
1486
|
}
|
@@ -1331,17 +1525,17 @@ BigDecimal_sub(VALUE self, VALUE r)
|
|
1331
1525
|
|
1332
1526
|
mx = GetAddSubPrec(a,b);
|
1333
1527
|
if (mx == (size_t)-1L) {
|
1334
|
-
GUARD_OBJ(c,
|
1335
|
-
|
1528
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, VpBaseFig() + 1));
|
1529
|
+
VpAddSub(c, a, b, -1);
|
1336
1530
|
}
|
1337
1531
|
else {
|
1338
|
-
GUARD_OBJ(c,
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1344
|
-
|
1532
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx *(VpBaseFig() + 1)));
|
1533
|
+
if (!mx) {
|
1534
|
+
VpSetInf(c,VpGetSign(a));
|
1535
|
+
}
|
1536
|
+
else {
|
1537
|
+
VpAddSub(c, a, b, -1);
|
1538
|
+
}
|
1345
1539
|
}
|
1346
1540
|
return VpCheckGetValue(c);
|
1347
1541
|
}
|
@@ -1581,7 +1775,7 @@ BigDecimal_neg(VALUE self)
|
|
1581
1775
|
ENTER(5);
|
1582
1776
|
Real *c, *a;
|
1583
1777
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1584
|
-
GUARD_OBJ(c,
|
1778
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, a->Prec *(VpBaseFig() + 1)));
|
1585
1779
|
VpAsgn(c, a, -1);
|
1586
1780
|
return VpCheckGetValue(c);
|
1587
1781
|
}
|
@@ -1608,7 +1802,7 @@ BigDecimal_mult(VALUE self, VALUE r)
|
|
1608
1802
|
SAVE(b);
|
1609
1803
|
|
1610
1804
|
mx = a->Prec + b->Prec;
|
1611
|
-
GUARD_OBJ(c,
|
1805
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx * (VpBaseFig() + 1)));
|
1612
1806
|
VpMult(c, a, b);
|
1613
1807
|
return VpCheckGetValue(c);
|
1614
1808
|
}
|
@@ -1618,7 +1812,7 @@ BigDecimal_divide(VALUE self, VALUE r, Real **c, Real **res, Real **div)
|
|
1618
1812
|
/* For c = self.div(r): with round operation */
|
1619
1813
|
{
|
1620
1814
|
ENTER(5);
|
1621
|
-
Real *a, *b
|
1815
|
+
Real *a, *b;
|
1622
1816
|
ssize_t a_prec, b_prec;
|
1623
1817
|
size_t mx;
|
1624
1818
|
|
@@ -1647,18 +1841,16 @@ BigDecimal_divide(VALUE self, VALUE r, Real **c, Real **res, Real **div)
|
|
1647
1841
|
SAVE(b);
|
1648
1842
|
*div = b;
|
1649
1843
|
|
1650
|
-
mx = (a->Prec > b->Prec) ? a->Prec : b->Prec;
|
1651
|
-
mx *= BASE_FIG;
|
1652
|
-
|
1653
1844
|
BigDecimal_count_precision_and_scale(self, &a_prec, NULL);
|
1654
1845
|
BigDecimal_count_precision_and_scale(rr, &b_prec, NULL);
|
1655
1846
|
mx = (a_prec > b_prec) ? a_prec : b_prec;
|
1847
|
+
mx *= 2;
|
1656
1848
|
|
1657
1849
|
if (2*BIGDECIMAL_DOUBLE_FIGURES > mx)
|
1658
1850
|
mx = 2*BIGDECIMAL_DOUBLE_FIGURES;
|
1659
1851
|
|
1660
|
-
GUARD_OBJ((*c),
|
1661
|
-
GUARD_OBJ((*res),
|
1852
|
+
GUARD_OBJ((*c), NewZeroWrapNolimit(1, mx + 2*BASE_FIG));
|
1853
|
+
GUARD_OBJ((*res), NewZeroWrapNolimit(1, (mx + 1)*2 + 2*BASE_FIG));
|
1662
1854
|
VpDivd(*c, *res, a, b);
|
1663
1855
|
|
1664
1856
|
return Qnil;
|
@@ -1723,7 +1915,7 @@ BigDecimal_quo(int argc, VALUE *argv, VALUE self)
|
|
1723
1915
|
|
1724
1916
|
argc = rb_scan_args(argc, argv, "11", &value, &digits);
|
1725
1917
|
if (argc > 1) {
|
1726
|
-
n =
|
1918
|
+
n = check_int_precision(digits);
|
1727
1919
|
}
|
1728
1920
|
|
1729
1921
|
if (n > 0) {
|
@@ -1808,15 +2000,17 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
|
|
1808
2000
|
BigDecimal_count_precision_and_scale(rr, &b_prec, NULL);
|
1809
2001
|
|
1810
2002
|
mx = (a_prec > b_prec) ? a_prec : b_prec;
|
2003
|
+
mx *= 2;
|
2004
|
+
|
1811
2005
|
if (2*BIGDECIMAL_DOUBLE_FIGURES > mx)
|
1812
2006
|
mx = 2*BIGDECIMAL_DOUBLE_FIGURES;
|
1813
2007
|
|
1814
|
-
GUARD_OBJ(c,
|
1815
|
-
GUARD_OBJ(res,
|
2008
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx + 2*BASE_FIG));
|
2009
|
+
GUARD_OBJ(res, NewZeroWrapNolimit(1, mx*2 + 2*BASE_FIG));
|
1816
2010
|
VpDivd(c, res, a, b);
|
1817
2011
|
|
1818
2012
|
mx = c->Prec * BASE_FIG;
|
1819
|
-
GUARD_OBJ(d,
|
2013
|
+
GUARD_OBJ(d, NewZeroWrapLimited(1, mx));
|
1820
2014
|
VpActiveRound(d, c, VP_ROUND_DOWN, 0);
|
1821
2015
|
|
1822
2016
|
VpMult(res, d, b);
|
@@ -1824,10 +2018,10 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
|
|
1824
2018
|
|
1825
2019
|
if (!VpIsZero(c) && (VpGetSign(a) * VpGetSign(b) < 0)) {
|
1826
2020
|
/* result adjustment for negative case */
|
1827
|
-
res =
|
2021
|
+
res = rbd_reallocate_struct(res, d->MaxPrec);
|
1828
2022
|
res->MaxPrec = d->MaxPrec;
|
1829
2023
|
VpAddSub(res, d, VpOne(), -1);
|
1830
|
-
GUARD_OBJ(d,
|
2024
|
+
GUARD_OBJ(d, NewZeroWrapLimited(1, GetAddSubPrec(c, b) * 2*BASE_FIG));
|
1831
2025
|
VpAddSub(d, c, b, 1);
|
1832
2026
|
*div = res;
|
1833
2027
|
*mod = d;
|
@@ -1890,18 +2084,25 @@ BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
|
|
1890
2084
|
if (!b) return DoSomeOne(self, r, rb_intern("remainder"));
|
1891
2085
|
SAVE(b);
|
1892
2086
|
|
2087
|
+
if (VpIsPosInf(b) || VpIsNegInf(b)) {
|
2088
|
+
GUARD_OBJ(*dv, NewZeroWrapLimited(1, 1));
|
2089
|
+
VpSetZero(*dv, 1);
|
2090
|
+
*rv = a;
|
2091
|
+
return Qnil;
|
2092
|
+
}
|
2093
|
+
|
1893
2094
|
mx = (a->MaxPrec + b->MaxPrec) *VpBaseFig();
|
1894
|
-
GUARD_OBJ(c,
|
1895
|
-
GUARD_OBJ(res,
|
1896
|
-
GUARD_OBJ(rr,
|
1897
|
-
GUARD_OBJ(ff,
|
2095
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
|
2096
|
+
GUARD_OBJ(res, NewZeroWrapNolimit(1, (mx+1) * 2 + (VpBaseFig() + 1)));
|
2097
|
+
GUARD_OBJ(rr, NewZeroWrapNolimit(1, (mx+1) * 2 + (VpBaseFig() + 1)));
|
2098
|
+
GUARD_OBJ(ff, NewZeroWrapNolimit(1, (mx+1) * 2 + (VpBaseFig() + 1)));
|
1898
2099
|
|
1899
2100
|
VpDivd(c, res, a, b);
|
1900
2101
|
|
1901
2102
|
mx = c->Prec *(VpBaseFig() + 1);
|
1902
2103
|
|
1903
|
-
GUARD_OBJ(d,
|
1904
|
-
GUARD_OBJ(f,
|
2104
|
+
GUARD_OBJ(d, NewZeroWrapLimited(1, mx));
|
2105
|
+
GUARD_OBJ(f, NewZeroWrapLimited(1, mx));
|
1905
2106
|
|
1906
2107
|
VpActiveRound(d, c, VP_ROUND_DOWN, 0); /* 0: round off */
|
1907
2108
|
|
@@ -1986,7 +2187,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
|
1986
2187
|
}
|
1987
2188
|
|
1988
2189
|
/* div in BigDecimal sense */
|
1989
|
-
ix =
|
2190
|
+
ix = check_int_precision(n);
|
1990
2191
|
if (ix == 0) {
|
1991
2192
|
return BigDecimal_div(self, b);
|
1992
2193
|
}
|
@@ -1997,7 +2198,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
|
1997
2198
|
size_t b_prec = ix;
|
1998
2199
|
size_t pl = VpSetPrecLimit(0);
|
1999
2200
|
|
2000
|
-
GUARD_OBJ(cv,
|
2201
|
+
GUARD_OBJ(cv, NewZeroWrapLimited(1, mx + VpBaseFig()));
|
2001
2202
|
GUARD_OBJ(av, GetVpValue(self, 1));
|
2002
2203
|
/* TODO: I want to refactor this precision control for a float value later
|
2003
2204
|
* by introducing an implicit conversion function instead of
|
@@ -2008,7 +2209,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
|
2008
2209
|
GUARD_OBJ(bv, GetVpValueWithPrec(b, b_prec, 1));
|
2009
2210
|
mx = av->Prec + bv->Prec + 2;
|
2010
2211
|
if (mx <= cv->MaxPrec) mx = cv->MaxPrec + 1;
|
2011
|
-
GUARD_OBJ(res,
|
2212
|
+
GUARD_OBJ(res, NewZeroWrapNolimit(1, (mx * 2 + 2)*VpBaseFig()));
|
2012
2213
|
VpDivd(cv, res, av, bv);
|
2013
2214
|
VpSetPrecLimit(pl);
|
2014
2215
|
VpLeftRound(cv, VpGetRoundMode(), ix);
|
@@ -2091,7 +2292,7 @@ BigDecimal_add2(VALUE self, VALUE b, VALUE n)
|
|
2091
2292
|
{
|
2092
2293
|
ENTER(2);
|
2093
2294
|
Real *cv;
|
2094
|
-
SIGNED_VALUE mx =
|
2295
|
+
SIGNED_VALUE mx = check_int_precision(n);
|
2095
2296
|
if (mx == 0) return BigDecimal_add(self, b);
|
2096
2297
|
else {
|
2097
2298
|
size_t pl = VpSetPrecLimit(0);
|
@@ -2121,7 +2322,7 @@ BigDecimal_sub2(VALUE self, VALUE b, VALUE n)
|
|
2121
2322
|
{
|
2122
2323
|
ENTER(2);
|
2123
2324
|
Real *cv;
|
2124
|
-
SIGNED_VALUE mx =
|
2325
|
+
SIGNED_VALUE mx = check_int_precision(n);
|
2125
2326
|
if (mx == 0) return BigDecimal_sub(self, b);
|
2126
2327
|
else {
|
2127
2328
|
size_t pl = VpSetPrecLimit(0);
|
@@ -2164,7 +2365,7 @@ BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
|
|
2164
2365
|
{
|
2165
2366
|
ENTER(2);
|
2166
2367
|
Real *cv;
|
2167
|
-
SIGNED_VALUE mx =
|
2368
|
+
SIGNED_VALUE mx = check_int_precision(n);
|
2168
2369
|
if (mx == 0) return BigDecimal_mult(self, b);
|
2169
2370
|
else {
|
2170
2371
|
size_t pl = VpSetPrecLimit(0);
|
@@ -2196,7 +2397,7 @@ BigDecimal_abs(VALUE self)
|
|
2196
2397
|
|
2197
2398
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
2198
2399
|
mx = a->Prec *(VpBaseFig() + 1);
|
2199
|
-
GUARD_OBJ(c,
|
2400
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
|
2200
2401
|
VpAsgn(c, a, 1);
|
2201
2402
|
VpChangeSign(c, 1);
|
2202
2403
|
return VpCheckGetValue(c);
|
@@ -2219,9 +2420,10 @@ BigDecimal_sqrt(VALUE self, VALUE nFig)
|
|
2219
2420
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
2220
2421
|
mx = a->Prec * (VpBaseFig() + 1);
|
2221
2422
|
|
2222
|
-
n =
|
2423
|
+
n = check_int_precision(nFig);
|
2424
|
+
n += VpDblFig() + VpBaseFig();
|
2223
2425
|
if (mx <= n) mx = n;
|
2224
|
-
GUARD_OBJ(c,
|
2426
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
|
2225
2427
|
VpSqrt(c, a);
|
2226
2428
|
return VpCheckGetValue(c);
|
2227
2429
|
}
|
@@ -2237,7 +2439,7 @@ BigDecimal_fix(VALUE self)
|
|
2237
2439
|
|
2238
2440
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
2239
2441
|
mx = a->Prec *(VpBaseFig() + 1);
|
2240
|
-
GUARD_OBJ(c,
|
2442
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
|
2241
2443
|
VpActiveRound(c, a, VP_ROUND_DOWN, 0); /* 0: round off */
|
2242
2444
|
return VpCheckGetValue(c);
|
2243
2445
|
}
|
@@ -2310,7 +2512,7 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
|
|
2310
2512
|
pl = VpSetPrecLimit(0);
|
2311
2513
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
2312
2514
|
mx = a->Prec * (VpBaseFig() + 1);
|
2313
|
-
GUARD_OBJ(c,
|
2515
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
|
2314
2516
|
VpSetPrecLimit(pl);
|
2315
2517
|
VpActiveRound(c, a, sw, iLoc);
|
2316
2518
|
if (round_to_int) {
|
@@ -2356,7 +2558,7 @@ BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
|
|
2356
2558
|
|
2357
2559
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
2358
2560
|
mx = a->Prec * (VpBaseFig() + 1);
|
2359
|
-
GUARD_OBJ(c,
|
2561
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
|
2360
2562
|
VpSetPrecLimit(pl);
|
2361
2563
|
VpActiveRound(c, a, VP_ROUND_DOWN, iLoc); /* 0: truncate */
|
2362
2564
|
if (argc == 0) {
|
@@ -2376,7 +2578,7 @@ BigDecimal_frac(VALUE self)
|
|
2376
2578
|
|
2377
2579
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
2378
2580
|
mx = a->Prec * (VpBaseFig() + 1);
|
2379
|
-
GUARD_OBJ(c,
|
2581
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
|
2380
2582
|
VpFrac(c, a);
|
2381
2583
|
return VpCheckGetValue(c);
|
2382
2584
|
}
|
@@ -2416,7 +2618,7 @@ BigDecimal_floor(int argc, VALUE *argv, VALUE self)
|
|
2416
2618
|
|
2417
2619
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
2418
2620
|
mx = a->Prec * (VpBaseFig() + 1);
|
2419
|
-
GUARD_OBJ(c,
|
2621
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
|
2420
2622
|
VpSetPrecLimit(pl);
|
2421
2623
|
VpActiveRound(c, a, VP_ROUND_FLOOR, iLoc);
|
2422
2624
|
#ifdef BIGDECIMAL_DEBUG
|
@@ -2462,7 +2664,7 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
|
|
2462
2664
|
|
2463
2665
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
2464
2666
|
mx = a->Prec * (VpBaseFig() + 1);
|
2465
|
-
GUARD_OBJ(c,
|
2667
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
|
2466
2668
|
VpSetPrecLimit(pl);
|
2467
2669
|
VpActiveRound(c, a, VP_ROUND_CEIL, iLoc);
|
2468
2670
|
if (argc == 0) {
|
@@ -2566,10 +2768,10 @@ BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
|
|
2566
2768
|
psz = RSTRING_PTR(str);
|
2567
2769
|
|
2568
2770
|
if (fmt) {
|
2569
|
-
VpToFString(vp, psz, mc, fPlus);
|
2771
|
+
VpToFString(vp, psz, RSTRING_LEN(str), mc, fPlus);
|
2570
2772
|
}
|
2571
2773
|
else {
|
2572
|
-
VpToString (vp, psz, mc, fPlus);
|
2774
|
+
VpToString (vp, psz, RSTRING_LEN(str), mc, fPlus);
|
2573
2775
|
}
|
2574
2776
|
rb_str_resize(str, strlen(psz));
|
2575
2777
|
return str;
|
@@ -2611,7 +2813,7 @@ BigDecimal_split(VALUE self)
|
|
2611
2813
|
GUARD_OBJ(vp, GetVpValue(self, 1));
|
2612
2814
|
str = rb_str_new(0, VpNumOfChars(vp, "E"));
|
2613
2815
|
psz1 = RSTRING_PTR(str);
|
2614
|
-
VpSzMantissa(vp, psz1);
|
2816
|
+
VpSzMantissa(vp, psz1, RSTRING_LEN(str));
|
2615
2817
|
s = 1;
|
2616
2818
|
if(psz1[0] == '-') {
|
2617
2819
|
size_t len = strlen(psz1 + 1);
|
@@ -2660,7 +2862,7 @@ BigDecimal_inspect(VALUE self)
|
|
2660
2862
|
nc = VpNumOfChars(vp, "E");
|
2661
2863
|
|
2662
2864
|
str = rb_str_new(0, nc);
|
2663
|
-
VpToString(vp, RSTRING_PTR(str), 0, 0);
|
2865
|
+
VpToString(vp, RSTRING_PTR(str), RSTRING_LEN(str), 0, 0);
|
2664
2866
|
rb_str_resize(str, strlen(RSTRING_PTR(str)));
|
2665
2867
|
return str;
|
2666
2868
|
}
|
@@ -2770,7 +2972,7 @@ bigdecimal_power_by_bigdecimal(Real const* x, Real const* exp, ssize_t const n)
|
|
2770
2972
|
volatile VALUE obj = exp->obj;
|
2771
2973
|
|
2772
2974
|
if (VpIsZero(exp)) {
|
2773
|
-
return VpCheckGetValue(
|
2975
|
+
return VpCheckGetValue(NewOneWrapLimited(1, n));
|
2774
2976
|
}
|
2775
2977
|
|
2776
2978
|
log_x = BigMath_log(x->obj, SSIZET2NUM(n+1));
|
@@ -2808,9 +3010,9 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2808
3010
|
n = NIL_P(prec) ? (ssize_t)(x->Prec*VpBaseFig()) : NUM2SSIZET(prec);
|
2809
3011
|
|
2810
3012
|
if (VpIsNaN(x)) {
|
2811
|
-
y =
|
2812
|
-
|
2813
|
-
|
3013
|
+
y = NewZeroWrapLimited(1, n);
|
3014
|
+
VpSetNaN(y);
|
3015
|
+
RB_GC_GUARD(y->obj);
|
2814
3016
|
return VpCheckGetValue(y);
|
2815
3017
|
}
|
2816
3018
|
|
@@ -2879,136 +3081,126 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2879
3081
|
}
|
2880
3082
|
|
2881
3083
|
if (VpIsZero(x)) {
|
2882
|
-
|
2883
|
-
y =
|
2884
|
-
|
2885
|
-
|
2886
|
-
|
2887
|
-
|
2888
|
-
|
2889
|
-
|
2890
|
-
|
2891
|
-
|
2892
|
-
|
2893
|
-
|
2894
|
-
|
2895
|
-
|
2896
|
-
|
2897
|
-
|
2898
|
-
|
2899
|
-
|
2900
|
-
|
2901
|
-
|
2902
|
-
|
2903
|
-
|
2904
|
-
|
3084
|
+
if (is_negative(vexp)) {
|
3085
|
+
y = NewZeroWrapNolimit(1, n);
|
3086
|
+
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
3087
|
+
if (is_integer(vexp)) {
|
3088
|
+
if (is_even(vexp)) {
|
3089
|
+
/* (-0) ** (-even_integer) -> Infinity */
|
3090
|
+
VpSetPosInf(y);
|
3091
|
+
}
|
3092
|
+
else {
|
3093
|
+
/* (-0) ** (-odd_integer) -> -Infinity */
|
3094
|
+
VpSetNegInf(y);
|
3095
|
+
}
|
3096
|
+
}
|
3097
|
+
else {
|
3098
|
+
/* (-0) ** (-non_integer) -> Infinity */
|
3099
|
+
VpSetPosInf(y);
|
3100
|
+
}
|
3101
|
+
}
|
3102
|
+
else {
|
3103
|
+
/* (+0) ** (-num) -> Infinity */
|
3104
|
+
VpSetPosInf(y);
|
3105
|
+
}
|
3106
|
+
RB_GC_GUARD(y->obj);
|
2905
3107
|
return VpCheckGetValue(y);
|
2906
|
-
|
2907
|
-
|
2908
|
-
return VpCheckGetValue(
|
2909
|
-
|
2910
|
-
|
2911
|
-
return VpCheckGetValue(
|
2912
|
-
|
3108
|
+
}
|
3109
|
+
else if (is_zero(vexp)) {
|
3110
|
+
return VpCheckGetValue(NewOneWrapLimited(1, n));
|
3111
|
+
}
|
3112
|
+
else {
|
3113
|
+
return VpCheckGetValue(NewZeroWrapLimited(1, n));
|
3114
|
+
}
|
2913
3115
|
}
|
2914
3116
|
|
2915
3117
|
if (is_zero(vexp)) {
|
2916
|
-
return VpCheckGetValue(
|
3118
|
+
return VpCheckGetValue(NewOneWrapLimited(1, n));
|
2917
3119
|
}
|
2918
3120
|
else if (is_one(vexp)) {
|
2919
|
-
|
3121
|
+
return self;
|
2920
3122
|
}
|
2921
3123
|
|
2922
3124
|
if (VpIsInf(x)) {
|
2923
|
-
|
2924
|
-
|
2925
|
-
|
2926
|
-
|
2927
|
-
|
2928
|
-
return VpCheckGetValue(
|
2929
|
-
|
2930
|
-
|
2931
|
-
|
2932
|
-
return VpCheckGetValue(
|
2933
|
-
|
2934
|
-
|
2935
|
-
|
2936
|
-
|
2937
|
-
return VpCheckGetValue(
|
2938
|
-
|
2939
|
-
|
2940
|
-
|
2941
|
-
return VpCheckGetValue(
|
2942
|
-
|
2943
|
-
|
2944
|
-
|
2945
|
-
y =
|
2946
|
-
|
2947
|
-
|
2948
|
-
|
2949
|
-
|
2950
|
-
|
2951
|
-
|
2952
|
-
|
2953
|
-
|
2954
|
-
|
2955
|
-
|
2956
|
-
|
2957
|
-
|
2958
|
-
|
2959
|
-
|
2960
|
-
|
2961
|
-
|
2962
|
-
|
2963
|
-
|
3125
|
+
if (is_negative(vexp)) {
|
3126
|
+
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
3127
|
+
if (is_integer(vexp)) {
|
3128
|
+
if (is_even(vexp)) {
|
3129
|
+
/* (-Infinity) ** (-even_integer) -> +0 */
|
3130
|
+
return VpCheckGetValue(NewZeroWrapLimited(1, n));
|
3131
|
+
}
|
3132
|
+
else {
|
3133
|
+
/* (-Infinity) ** (-odd_integer) -> -0 */
|
3134
|
+
return VpCheckGetValue(NewZeroWrapLimited(-1, n));
|
3135
|
+
}
|
3136
|
+
}
|
3137
|
+
else {
|
3138
|
+
/* (-Infinity) ** (-non_integer) -> -0 */
|
3139
|
+
return VpCheckGetValue(NewZeroWrapLimited(-1, n));
|
3140
|
+
}
|
3141
|
+
}
|
3142
|
+
else {
|
3143
|
+
return VpCheckGetValue(NewZeroWrapLimited(1, n));
|
3144
|
+
}
|
3145
|
+
}
|
3146
|
+
else {
|
3147
|
+
y = NewZeroWrapLimited(1, n);
|
3148
|
+
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
3149
|
+
if (is_integer(vexp)) {
|
3150
|
+
if (is_even(vexp)) {
|
3151
|
+
VpSetPosInf(y);
|
3152
|
+
}
|
3153
|
+
else {
|
3154
|
+
VpSetNegInf(y);
|
3155
|
+
}
|
3156
|
+
}
|
3157
|
+
else {
|
3158
|
+
/* TODO: support complex */
|
3159
|
+
rb_raise(rb_eMathDomainError,
|
3160
|
+
"a non-integral exponent for a negative base");
|
3161
|
+
}
|
3162
|
+
}
|
3163
|
+
else {
|
3164
|
+
VpSetPosInf(y);
|
3165
|
+
}
|
2964
3166
|
return VpCheckGetValue(y);
|
2965
|
-
|
3167
|
+
}
|
2966
3168
|
}
|
2967
3169
|
|
2968
3170
|
if (exp != NULL) {
|
2969
|
-
|
3171
|
+
return bigdecimal_power_by_bigdecimal(x, exp, n);
|
2970
3172
|
}
|
2971
3173
|
else if (RB_TYPE_P(vexp, T_BIGNUM)) {
|
2972
|
-
|
2973
|
-
|
2974
|
-
return VpCheckGetValue(
|
2975
|
-
|
2976
|
-
|
2977
|
-
|
2978
|
-
y =
|
2979
|
-
|
2980
|
-
VpSetInf(y, VpGetSign(x));
|
2981
|
-
}
|
2982
|
-
else {
|
2983
|
-
VpSetInf(y, -VpGetSign(x));
|
2984
|
-
}
|
3174
|
+
VALUE abs_value = BigDecimal_abs(self);
|
3175
|
+
if (is_one(abs_value)) {
|
3176
|
+
return VpCheckGetValue(NewOneWrapLimited(1, n));
|
3177
|
+
}
|
3178
|
+
else if (RTEST(rb_funcall(abs_value, '<', 1, INT2FIX(1)))) {
|
3179
|
+
if (is_negative(vexp)) {
|
3180
|
+
y = NewZeroWrapLimited(1, n);
|
3181
|
+
VpSetInf(y, (is_even(vexp) ? 1 : -1) * VpGetSign(x));
|
2985
3182
|
return VpCheckGetValue(y);
|
2986
|
-
|
2987
|
-
|
2988
|
-
return VpCheckGetValue(
|
2989
|
-
|
2990
|
-
|
2991
|
-
return VpCheckGetValue(
|
2992
|
-
|
2993
|
-
|
2994
|
-
|
2995
|
-
|
2996
|
-
y =
|
2997
|
-
|
2998
|
-
VpSetInf(y, VpGetSign(x));
|
2999
|
-
}
|
3000
|
-
else {
|
3001
|
-
VpSetInf(y, -VpGetSign(x));
|
3002
|
-
}
|
3183
|
+
}
|
3184
|
+
else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
|
3185
|
+
return VpCheckGetValue(NewZeroWrapLimited(-1, n));
|
3186
|
+
}
|
3187
|
+
else {
|
3188
|
+
return VpCheckGetValue(NewZeroWrapLimited(1, n));
|
3189
|
+
}
|
3190
|
+
}
|
3191
|
+
else {
|
3192
|
+
if (is_positive(vexp)) {
|
3193
|
+
y = NewZeroWrapLimited(1, n);
|
3194
|
+
VpSetInf(y, (is_even(vexp) ? 1 : -1) * VpGetSign(x));
|
3003
3195
|
return VpCheckGetValue(y);
|
3004
|
-
|
3005
|
-
|
3006
|
-
return VpCheckGetValue(
|
3007
|
-
|
3008
|
-
|
3009
|
-
return VpCheckGetValue(
|
3010
|
-
|
3011
|
-
|
3196
|
+
}
|
3197
|
+
else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
|
3198
|
+
return VpCheckGetValue(NewZeroWrapLimited(-1, n));
|
3199
|
+
}
|
3200
|
+
else {
|
3201
|
+
return VpCheckGetValue(NewZeroWrapLimited(1, n));
|
3202
|
+
}
|
3203
|
+
}
|
3012
3204
|
}
|
3013
3205
|
|
3014
3206
|
int_exp = FIX2LONG(vexp);
|
@@ -3017,15 +3209,15 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
3017
3209
|
if (ma == 0) ma = 1;
|
3018
3210
|
|
3019
3211
|
if (VpIsDef(x)) {
|
3020
|
-
|
3021
|
-
GUARD_OBJ(y,
|
3212
|
+
mp = x->Prec * (VpBaseFig() + 1);
|
3213
|
+
GUARD_OBJ(y, NewZeroWrapLimited(1, mp * (ma + 1)));
|
3022
3214
|
}
|
3023
3215
|
else {
|
3024
|
-
GUARD_OBJ(y,
|
3216
|
+
GUARD_OBJ(y, NewZeroWrapLimited(1, 1));
|
3025
3217
|
}
|
3026
3218
|
VpPowerByInt(y, x, int_exp);
|
3027
3219
|
if (!NIL_P(prec) && VpIsDef(y)) {
|
3028
|
-
|
3220
|
+
VpMidRound(y, VpGetRoundMode(), n);
|
3029
3221
|
}
|
3030
3222
|
return VpCheckGetValue(y);
|
3031
3223
|
}
|
@@ -3114,7 +3306,7 @@ rb_uint64_convert_to_BigDecimal(uint64_t uval, RB_UNUSED_VAR(size_t digs), int r
|
|
3114
3306
|
|
3115
3307
|
Real *vp;
|
3116
3308
|
if (uval == 0) {
|
3117
|
-
vp =
|
3309
|
+
vp = rbd_allocate_struct(1);
|
3118
3310
|
vp->MaxPrec = 1;
|
3119
3311
|
vp->Prec = 1;
|
3120
3312
|
vp->exponent = 1;
|
@@ -3122,7 +3314,7 @@ rb_uint64_convert_to_BigDecimal(uint64_t uval, RB_UNUSED_VAR(size_t digs), int r
|
|
3122
3314
|
vp->frac[0] = 0;
|
3123
3315
|
}
|
3124
3316
|
else if (uval < BASE) {
|
3125
|
-
vp =
|
3317
|
+
vp = rbd_allocate_struct(1);
|
3126
3318
|
vp->MaxPrec = 1;
|
3127
3319
|
vp->Prec = 1;
|
3128
3320
|
vp->exponent = 1;
|
@@ -3148,7 +3340,7 @@ rb_uint64_convert_to_BigDecimal(uint64_t uval, RB_UNUSED_VAR(size_t digs), int r
|
|
3148
3340
|
}
|
3149
3341
|
|
3150
3342
|
const size_t exp = len + ntz;
|
3151
|
-
vp =
|
3343
|
+
vp = rbd_allocate_struct(len);
|
3152
3344
|
vp->MaxPrec = len;
|
3153
3345
|
vp->Prec = len;
|
3154
3346
|
vp->exponent = exp;
|
@@ -3281,7 +3473,7 @@ rb_float_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
|
|
3281
3473
|
|
3282
3474
|
VALUE inum;
|
3283
3475
|
size_t RB_UNUSED_VAR(prec) = 0;
|
3284
|
-
|
3476
|
+
SIGNED_VALUE exp = 0;
|
3285
3477
|
if (decpt > 0) {
|
3286
3478
|
if (decpt < len10) {
|
3287
3479
|
/*
|
@@ -3493,12 +3685,15 @@ rb_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
|
|
3493
3685
|
* BigDecimal(value, exception: true) -> bigdecimal
|
3494
3686
|
* BigDecimal(value, ndigits, exception: true) -> bigdecimal
|
3495
3687
|
*
|
3496
|
-
*
|
3497
|
-
*
|
3688
|
+
* Returns the \BigDecimal converted from +value+
|
3689
|
+
* with a precision of +ndigits+ decimal digits.
|
3690
|
+
*
|
3691
|
+
* When +ndigits+ is less than the number of significant digits
|
3692
|
+
* in the value, the result is rounded to that number of digits,
|
3693
|
+
* according to the current rounding mode; see BigDecimal.mode.
|
3498
3694
|
*
|
3499
|
-
*
|
3500
|
-
*
|
3501
|
-
* according to the current rounding mode; see BigDecimal.mode.
|
3695
|
+
* When +ndigits+ is 0, the number of digits to correctly represent a float number
|
3696
|
+
* is determined automatically.
|
3502
3697
|
*
|
3503
3698
|
* Returns +value+ converted to a \BigDecimal, depending on the type of +value+:
|
3504
3699
|
*
|
@@ -3606,8 +3801,10 @@ BigDecimal_limit(int argc, VALUE *argv, VALUE self)
|
|
3606
3801
|
|
3607
3802
|
/* Returns the sign of the value.
|
3608
3803
|
*
|
3609
|
-
* Returns a positive value if > 0, a negative value if < 0
|
3610
|
-
*
|
3804
|
+
* Returns a positive value if > 0, a negative value if < 0.
|
3805
|
+
* It behaves the same with zeros -
|
3806
|
+
* it returns a positive value for a positive zero (BigDecimal('0')) and
|
3807
|
+
* a negative value for a negative zero (BigDecimal('-0')).
|
3611
3808
|
*
|
3612
3809
|
* The specific value returned indicates the type and sign of the BigDecimal,
|
3613
3810
|
* as follows:
|
@@ -3771,18 +3968,16 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
|
|
3771
3968
|
return VpCheckGetValue(GetVpValueWithPrec(INT2FIX(0), prec, 1));
|
3772
3969
|
}
|
3773
3970
|
else {
|
3774
|
-
Real* vy;
|
3775
|
-
vy = VpCreateRbObject(prec, "#0", true);
|
3971
|
+
Real* vy = NewZeroWrapNolimit(1, prec);
|
3776
3972
|
VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
|
3777
3973
|
RB_GC_GUARD(vy->obj);
|
3778
3974
|
return VpCheckGetValue(vy);
|
3779
3975
|
}
|
3780
3976
|
}
|
3781
3977
|
else if (nan) {
|
3782
|
-
|
3783
|
-
vy
|
3784
|
-
|
3785
|
-
RB_GC_GUARD(vy->obj);
|
3978
|
+
Real* vy = NewZeroWrapNolimit(1, prec);
|
3979
|
+
VpSetNaN(vy);
|
3980
|
+
RB_GC_GUARD(vy->obj);
|
3786
3981
|
return VpCheckGetValue(vy);
|
3787
3982
|
}
|
3788
3983
|
else if (vx == NULL) {
|
@@ -3800,7 +3995,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
|
|
3800
3995
|
VpSetSign(vx, 1);
|
3801
3996
|
}
|
3802
3997
|
|
3803
|
-
one = VpCheckGetValue(
|
3998
|
+
one = VpCheckGetValue(NewOneWrapLimited(1, 1));
|
3804
3999
|
y = one;
|
3805
4000
|
d = y;
|
3806
4001
|
i = 1;
|
@@ -3927,15 +4122,13 @@ get_vp_value:
|
|
3927
4122
|
break;
|
3928
4123
|
}
|
3929
4124
|
if (infinite && !negative) {
|
3930
|
-
|
3931
|
-
vy = VpCreateRbObject(prec, "#0", true);
|
4125
|
+
Real *vy = NewZeroWrapNolimit(1, prec);
|
3932
4126
|
RB_GC_GUARD(vy->obj);
|
3933
4127
|
VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
|
3934
4128
|
return VpCheckGetValue(vy);
|
3935
4129
|
}
|
3936
4130
|
else if (nan) {
|
3937
|
-
Real* vy;
|
3938
|
-
vy = VpCreateRbObject(prec, "#0", true);
|
4131
|
+
Real* vy = NewZeroWrapNolimit(1, prec);
|
3939
4132
|
RB_GC_GUARD(vy->obj);
|
3940
4133
|
VpSetNaN(vy);
|
3941
4134
|
return VpCheckGetValue(vy);
|
@@ -3949,11 +4142,11 @@ get_vp_value:
|
|
3949
4142
|
}
|
3950
4143
|
x = VpCheckGetValue(vx);
|
3951
4144
|
|
3952
|
-
|
3953
|
-
|
4145
|
+
one = VpCheckGetValue(NewOneWrapLimited(1, 1));
|
4146
|
+
two = VpCheckGetValue(VpCreateRbObject(1, "2", true));
|
3954
4147
|
|
3955
4148
|
n = prec + BIGDECIMAL_DOUBLE_FIGURES;
|
3956
|
-
|
4149
|
+
vn = SSIZET2NUM(n);
|
3957
4150
|
expo = VpExponent10(vx);
|
3958
4151
|
if (expo < 0 || expo >= 3) {
|
3959
4152
|
char buf[DECIMAL_SIZE_OF_BITS(SIZEOF_VALUE * CHAR_BIT) + 4];
|
@@ -3965,9 +4158,9 @@ get_vp_value:
|
|
3965
4158
|
}
|
3966
4159
|
w = BigDecimal_sub(x, one);
|
3967
4160
|
x = BigDecimal_div2(w, BigDecimal_add(x, one), vn);
|
3968
|
-
|
3969
|
-
|
3970
|
-
|
4161
|
+
x2 = BigDecimal_mult2(x, x, vn);
|
4162
|
+
y = x;
|
4163
|
+
d = y;
|
3971
4164
|
i = 1;
|
3972
4165
|
while (!VpIsZero((Real*)DATA_PTR(d))) {
|
3973
4166
|
SIGNED_VALUE const ey = VpExponent10(DATA_PTR(y));
|
@@ -3995,6 +4188,13 @@ get_vp_value:
|
|
3995
4188
|
y = BigDecimal_add(y, dy);
|
3996
4189
|
}
|
3997
4190
|
|
4191
|
+
RB_GC_GUARD(one);
|
4192
|
+
RB_GC_GUARD(two);
|
4193
|
+
RB_GC_GUARD(vn);
|
4194
|
+
RB_GC_GUARD(x2);
|
4195
|
+
RB_GC_GUARD(y);
|
4196
|
+
RB_GC_GUARD(d);
|
4197
|
+
|
3998
4198
|
return y;
|
3999
4199
|
}
|
4000
4200
|
|
@@ -4211,13 +4411,10 @@ Init_bigdecimal(void)
|
|
4211
4411
|
|
4212
4412
|
/* Constants definition */
|
4213
4413
|
|
4214
|
-
#ifndef RUBY_BIGDECIMAL_VERSION
|
4215
|
-
# error RUBY_BIGDECIMAL_VERSION is not defined
|
4216
|
-
#endif
|
4217
4414
|
/*
|
4218
4415
|
* The version of bigdecimal library
|
4219
4416
|
*/
|
4220
|
-
rb_define_const(rb_cBigDecimal, "VERSION", rb_str_new2(
|
4417
|
+
rb_define_const(rb_cBigDecimal, "VERSION", rb_str_new2(BIGDECIMAL_VERSION));
|
4221
4418
|
|
4222
4419
|
/*
|
4223
4420
|
* Base value used in internal calculations. On a 32 bit system, BASE
|
@@ -4414,20 +4611,31 @@ Init_bigdecimal(void)
|
|
4414
4611
|
rb_define_singleton_method(rb_mBigMath, "exp", BigMath_s_exp, 2);
|
4415
4612
|
rb_define_singleton_method(rb_mBigMath, "log", BigMath_s_log, 2);
|
4416
4613
|
|
4417
|
-
|
4418
|
-
|
4419
|
-
|
4420
|
-
|
4421
|
-
|
4422
|
-
|
4423
|
-
|
4424
|
-
|
4425
|
-
|
4426
|
-
|
4427
|
-
|
4614
|
+
#define ROUNDING_MODE(i, name, value) \
|
4615
|
+
id_##name = rb_intern_const(#name); \
|
4616
|
+
rbd_rounding_modes[i].id = id_##name; \
|
4617
|
+
rbd_rounding_modes[i].mode = value;
|
4618
|
+
|
4619
|
+
ROUNDING_MODE(0, up, RBD_ROUND_UP);
|
4620
|
+
ROUNDING_MODE(1, down, RBD_ROUND_DOWN);
|
4621
|
+
ROUNDING_MODE(2, half_up, RBD_ROUND_HALF_UP);
|
4622
|
+
ROUNDING_MODE(3, half_down, RBD_ROUND_HALF_DOWN);
|
4623
|
+
ROUNDING_MODE(4, ceil, RBD_ROUND_CEIL);
|
4624
|
+
ROUNDING_MODE(5, floor, RBD_ROUND_FLOOR);
|
4625
|
+
ROUNDING_MODE(6, half_even, RBD_ROUND_HALF_EVEN);
|
4626
|
+
|
4627
|
+
ROUNDING_MODE(7, default, RBD_ROUND_DEFAULT);
|
4628
|
+
ROUNDING_MODE(8, truncate, RBD_ROUND_TRUNCATE);
|
4629
|
+
ROUNDING_MODE(9, banker, RBD_ROUND_BANKER);
|
4630
|
+
ROUNDING_MODE(10, ceiling, RBD_ROUND_CEILING);
|
4631
|
+
|
4632
|
+
#undef ROUNDING_MODE
|
4633
|
+
|
4428
4634
|
id_to_r = rb_intern_const("to_r");
|
4429
4635
|
id_eq = rb_intern_const("==");
|
4430
4636
|
id_half = rb_intern_const("half");
|
4637
|
+
|
4638
|
+
(void)VPrint; /* suppress unused warning */
|
4431
4639
|
}
|
4432
4640
|
|
4433
4641
|
/*
|
@@ -4447,7 +4655,7 @@ static int gfCheckVal = 1; /* Value checking flag in VpNmlz() */
|
|
4447
4655
|
#endif /* BIGDECIMAL_DEBUG */
|
4448
4656
|
|
4449
4657
|
static Real *VpConstOne; /* constant 1.0 */
|
4450
|
-
static Real *
|
4658
|
+
static Real *VpConstPt5; /* constant 0.5 */
|
4451
4659
|
#define maxnr 100UL /* Maximum iterations for calculating sqrt. */
|
4452
4660
|
/* used in VpSqrt() */
|
4453
4661
|
|
@@ -4478,42 +4686,6 @@ static int VpRdup(Real *m, size_t ind_m);
|
|
4478
4686
|
static int gnAlloc = 0; /* Memory allocation counter */
|
4479
4687
|
#endif /* BIGDECIMAL_DEBUG */
|
4480
4688
|
|
4481
|
-
VP_EXPORT void *
|
4482
|
-
VpMemAlloc(size_t mb)
|
4483
|
-
{
|
4484
|
-
void *p = xmalloc(mb);
|
4485
|
-
memset(p, 0, mb);
|
4486
|
-
#ifdef BIGDECIMAL_DEBUG
|
4487
|
-
gnAlloc++; /* Count allocation call */
|
4488
|
-
#endif /* BIGDECIMAL_DEBUG */
|
4489
|
-
return p;
|
4490
|
-
}
|
4491
|
-
|
4492
|
-
VP_EXPORT void *
|
4493
|
-
VpMemRealloc(void *ptr, size_t mb)
|
4494
|
-
{
|
4495
|
-
return xrealloc(ptr, mb);
|
4496
|
-
}
|
4497
|
-
|
4498
|
-
VP_EXPORT void
|
4499
|
-
VpFree(Real *pv)
|
4500
|
-
{
|
4501
|
-
if (pv != NULL) {
|
4502
|
-
xfree(pv);
|
4503
|
-
#ifdef BIGDECIMAL_DEBUG
|
4504
|
-
gnAlloc--; /* Decrement allocation count */
|
4505
|
-
if (gnAlloc == 0) {
|
4506
|
-
printf(" *************** All memories allocated freed ****************\n");
|
4507
|
-
/*getchar();*/
|
4508
|
-
}
|
4509
|
-
if (gnAlloc < 0) {
|
4510
|
-
printf(" ??????????? Too many memory free calls(%d) ?????????????\n", gnAlloc);
|
4511
|
-
/*getchar();*/
|
4512
|
-
}
|
4513
|
-
#endif /* BIGDECIMAL_DEBUG */
|
4514
|
-
}
|
4515
|
-
}
|
4516
|
-
|
4517
4689
|
/*
|
4518
4690
|
* EXCEPTION Handling.
|
4519
4691
|
*/
|
@@ -4902,9 +5074,13 @@ VpInit(DECDIG BaseVal)
|
|
4902
5074
|
/* Setup +/- Inf NaN -0 */
|
4903
5075
|
VpGetDoubleNegZero();
|
4904
5076
|
|
4905
|
-
/*
|
4906
|
-
VpConstOne =
|
4907
|
-
|
5077
|
+
/* Const 1.0 */
|
5078
|
+
VpConstOne = NewOneNolimit(1, 1);
|
5079
|
+
|
5080
|
+
/* Const 0.5 */
|
5081
|
+
VpConstPt5 = NewOneNolimit(1, 1);
|
5082
|
+
VpConstPt5->exponent = 0;
|
5083
|
+
VpConstPt5->frac[0] = 5*BASE1;
|
4908
5084
|
|
4909
5085
|
#ifdef BIGDECIMAL_DEBUG
|
4910
5086
|
gnAlloc = 0;
|
@@ -4993,7 +5169,7 @@ bigdecimal_parse_special_string(const char *str)
|
|
4993
5169
|
p = str + table[i].len;
|
4994
5170
|
while (*p && ISSPACE(*p)) ++p;
|
4995
5171
|
if (*p == '\0') {
|
4996
|
-
Real *vp =
|
5172
|
+
Real *vp = rbd_allocate_struct(1);
|
4997
5173
|
vp->MaxPrec = 1;
|
4998
5174
|
switch (table[i].sign) {
|
4999
5175
|
default:
|
@@ -5017,11 +5193,11 @@ bigdecimal_parse_special_string(const char *str)
|
|
5017
5193
|
/*
|
5018
5194
|
* Allocates variable.
|
5019
5195
|
* [Input]
|
5020
|
-
* mx ...
|
5021
|
-
*
|
5022
|
-
* szVal ... value assigned(char). If szVal==NULL,then zero is assumed.
|
5023
|
-
*
|
5024
|
-
*
|
5196
|
+
* mx ... The number of decimal digits to be allocated, if zero then mx is determined by szVal.
|
5197
|
+
* The mx will be the number of significant digits can to be stored.
|
5198
|
+
* szVal ... The value assigned(char). If szVal==NULL, then zero is assumed.
|
5199
|
+
* If szVal[0]=='#' then MaxPrec is not affected by the precision limit
|
5200
|
+
* so that the full precision specified by szVal is allocated.
|
5025
5201
|
*
|
5026
5202
|
* [Returns]
|
5027
5203
|
* Pointer to the newly allocated variable, or
|
@@ -5032,48 +5208,40 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
|
|
5032
5208
|
{
|
5033
5209
|
const char *orig_szVal = szVal;
|
5034
5210
|
size_t i, j, ni, ipf, nf, ipe, ne, dot_seen, exp_seen, nalloc;
|
5211
|
+
size_t len;
|
5035
5212
|
char v, *psz;
|
5036
5213
|
int sign=1;
|
5037
5214
|
Real *vp = NULL;
|
5038
|
-
size_t mf = VpGetPrecLimit();
|
5039
5215
|
VALUE buf;
|
5040
5216
|
|
5041
|
-
|
5042
|
-
if (mx == 0) ++mx;
|
5043
|
-
|
5044
|
-
if (szVal) {
|
5045
|
-
/* Skipping leading spaces */
|
5046
|
-
while (ISSPACE(*szVal)) szVal++;
|
5047
|
-
|
5048
|
-
/* Processing the leading one `#` */
|
5049
|
-
if (*szVal != '#') {
|
5050
|
-
if (mf) {
|
5051
|
-
mf = (mf + BASE_FIG - 1) / BASE_FIG + 2; /* Needs 1 more for div */
|
5052
|
-
if (mx > mf) {
|
5053
|
-
mx = mf;
|
5054
|
-
}
|
5055
|
-
}
|
5056
|
-
}
|
5057
|
-
else {
|
5058
|
-
++szVal;
|
5059
|
-
}
|
5060
|
-
}
|
5061
|
-
else {
|
5217
|
+
if (szVal == NULL) {
|
5062
5218
|
return_zero:
|
5063
5219
|
/* necessary to be able to store */
|
5064
5220
|
/* at least mx digits. */
|
5065
5221
|
/* szVal==NULL ==> allocate zero value. */
|
5066
|
-
vp =
|
5067
|
-
vp->MaxPrec = mx;
|
5222
|
+
vp = rbd_allocate_struct(mx);
|
5223
|
+
vp->MaxPrec = rbd_calculate_internal_digits(mx, false); /* Must false */
|
5068
5224
|
VpSetZero(vp, 1); /* initialize vp to zero. */
|
5069
5225
|
return vp;
|
5070
5226
|
}
|
5071
5227
|
|
5228
|
+
/* Skipping leading spaces */
|
5229
|
+
while (ISSPACE(*szVal)) szVal++;
|
5230
|
+
|
5072
5231
|
/* Check on Inf & NaN */
|
5073
5232
|
if ((vp = bigdecimal_parse_special_string(szVal)) != NULL) {
|
5074
5233
|
return vp;
|
5075
5234
|
}
|
5076
5235
|
|
5236
|
+
/* Processing the leading one `#` */
|
5237
|
+
if (*szVal != '#') {
|
5238
|
+
len = rbd_calculate_internal_digits(mx, true);
|
5239
|
+
}
|
5240
|
+
else {
|
5241
|
+
len = rbd_calculate_internal_digits(mx, false);
|
5242
|
+
++szVal;
|
5243
|
+
}
|
5244
|
+
|
5077
5245
|
/* Scanning digits */
|
5078
5246
|
|
5079
5247
|
/* A buffer for keeping scanned digits */
|
@@ -5235,11 +5403,11 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
|
|
5235
5403
|
|
5236
5404
|
nalloc = (ni + nf + BASE_FIG - 1) / BASE_FIG + 1; /* set effective allocation */
|
5237
5405
|
/* units for szVal[] */
|
5238
|
-
if (
|
5239
|
-
nalloc = Max(nalloc,
|
5240
|
-
|
5241
|
-
vp =
|
5242
|
-
vp->MaxPrec =
|
5406
|
+
if (len == 0) len = 1;
|
5407
|
+
nalloc = Max(nalloc, len);
|
5408
|
+
len = nalloc;
|
5409
|
+
vp = rbd_allocate_struct(len);
|
5410
|
+
vp->MaxPrec = len; /* set max precision */
|
5243
5411
|
VpSetZero(vp, sign);
|
5244
5412
|
VpCtoV(vp, psz, ni, psz + ipf, nf, psz + ipe, ne);
|
5245
5413
|
rb_str_resize(buf, 0);
|
@@ -5804,7 +5972,7 @@ VpMult(Real *c, Real *a, Real *b)
|
|
5804
5972
|
|
5805
5973
|
if (MxIndC < MxIndAB) { /* The Max. prec. of c < Prec(a)+Prec(b) */
|
5806
5974
|
w = c;
|
5807
|
-
|
5975
|
+
c = NewZeroNolimit(1, (size_t)((MxIndAB + 1) * BASE_FIG));
|
5808
5976
|
MxIndC = MxIndAB;
|
5809
5977
|
}
|
5810
5978
|
|
@@ -5812,8 +5980,8 @@ VpMult(Real *c, Real *a, Real *b)
|
|
5812
5980
|
|
5813
5981
|
c->exponent = a->exponent; /* set exponent */
|
5814
5982
|
if (!AddExponent(c, b->exponent)) {
|
5815
|
-
|
5816
|
-
|
5983
|
+
if (w) rbd_free_struct(c);
|
5984
|
+
return 0;
|
5817
5985
|
}
|
5818
5986
|
VpSetSign(c, VpGetSign(a) * VpGetSign(b)); /* set sign */
|
5819
5987
|
carry = 0;
|
@@ -5863,10 +6031,10 @@ VpMult(Real *c, Real *a, Real *b)
|
|
5863
6031
|
}
|
5864
6032
|
}
|
5865
6033
|
if (w != NULL) { /* free work variable */
|
5866
|
-
|
5867
|
-
|
5868
|
-
|
5869
|
-
|
6034
|
+
VpNmlz(c);
|
6035
|
+
VpAsgn(w, c, 1);
|
6036
|
+
rbd_free_struct(c);
|
6037
|
+
c = w;
|
5870
6038
|
}
|
5871
6039
|
else {
|
5872
6040
|
VpLimitRound(c,0);
|
@@ -5931,18 +6099,17 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
|
|
5931
6099
|
word_c = c->MaxPrec;
|
5932
6100
|
word_r = r->MaxPrec;
|
5933
6101
|
|
5934
|
-
ind_c = 0;
|
5935
|
-
ind_r = 1;
|
5936
|
-
|
5937
6102
|
if (word_a >= word_r) goto space_error;
|
5938
6103
|
|
6104
|
+
ind_r = 1;
|
5939
6105
|
r->frac[0] = 0;
|
5940
6106
|
while (ind_r <= word_a) {
|
5941
6107
|
r->frac[ind_r] = a->frac[ind_r - 1];
|
5942
6108
|
++ind_r;
|
5943
6109
|
}
|
5944
|
-
|
5945
6110
|
while (ind_r < word_r) r->frac[ind_r++] = 0;
|
6111
|
+
|
6112
|
+
ind_c = 0;
|
5946
6113
|
while (ind_c < word_c) c->frac[ind_c++] = 0;
|
5947
6114
|
|
5948
6115
|
/* initial procedure */
|
@@ -6236,7 +6403,6 @@ Exit:
|
|
6236
6403
|
* Note: % must not appear more than once
|
6237
6404
|
* a ... VP variable to be printed
|
6238
6405
|
*/
|
6239
|
-
#ifdef BIGDECIMAL_ENABLE_VPRINT
|
6240
6406
|
static int
|
6241
6407
|
VPrint(FILE *fp, const char *cntl_chr, Real *a)
|
6242
6408
|
{
|
@@ -6249,95 +6415,94 @@ VPrint(FILE *fp, const char *cntl_chr, Real *a)
|
|
6249
6415
|
/* nc : number of characters printed */
|
6250
6416
|
ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
|
6251
6417
|
while (*(cntl_chr + j)) {
|
6252
|
-
|
6253
|
-
|
6254
|
-
|
6255
|
-
|
6256
|
-
|
6257
|
-
|
6258
|
-
|
6259
|
-
|
6260
|
-
|
6261
|
-
|
6262
|
-
|
6263
|
-
|
6264
|
-
|
6265
|
-
|
6266
|
-
|
6267
|
-
|
6268
|
-
|
6269
|
-
|
6270
|
-
|
6271
|
-
|
6272
|
-
|
6273
|
-
|
6274
|
-
|
6418
|
+
if (*(cntl_chr + j) == '%' && *(cntl_chr + j + 1) != '%') {
|
6419
|
+
nc = 0;
|
6420
|
+
if (VpIsNaN(a)) {
|
6421
|
+
fprintf(fp, SZ_NaN);
|
6422
|
+
nc += 8;
|
6423
|
+
}
|
6424
|
+
else if (VpIsPosInf(a)) {
|
6425
|
+
fprintf(fp, SZ_INF);
|
6426
|
+
nc += 8;
|
6427
|
+
}
|
6428
|
+
else if (VpIsNegInf(a)) {
|
6429
|
+
fprintf(fp, SZ_NINF);
|
6430
|
+
nc += 9;
|
6431
|
+
}
|
6432
|
+
else if (!VpIsZero(a)) {
|
6433
|
+
if (BIGDECIMAL_NEGATIVE_P(a)) {
|
6434
|
+
fprintf(fp, "-");
|
6435
|
+
++nc;
|
6436
|
+
}
|
6437
|
+
nc += fprintf(fp, "0.");
|
6438
|
+
switch (*(cntl_chr + j + 1)) {
|
6439
|
+
default:
|
6440
|
+
break;
|
6275
6441
|
|
6276
|
-
|
6277
|
-
|
6278
|
-
|
6279
|
-
|
6280
|
-
|
6281
|
-
|
6282
|
-
|
6283
|
-
|
6284
|
-
|
6285
|
-
|
6286
|
-
|
6287
|
-
|
6288
|
-
|
6289
|
-
|
6290
|
-
|
6291
|
-
|
6292
|
-
|
6293
|
-
|
6294
|
-
|
6295
|
-
|
6296
|
-
|
6297
|
-
|
6298
|
-
|
6299
|
-
|
6300
|
-
|
6301
|
-
|
6302
|
-
|
6303
|
-
|
6304
|
-
|
6305
|
-
|
6306
|
-
|
6307
|
-
|
6308
|
-
|
6309
|
-
|
6310
|
-
|
6311
|
-
|
6312
|
-
|
6313
|
-
|
6314
|
-
|
6315
|
-
|
6316
|
-
|
6317
|
-
|
6318
|
-
|
6319
|
-
|
6320
|
-
|
6321
|
-
|
6322
|
-
|
6323
|
-
|
6324
|
-
|
6325
|
-
|
6326
|
-
|
6327
|
-
|
6328
|
-
|
6329
|
-
|
6330
|
-
|
6331
|
-
|
6332
|
-
|
6333
|
-
|
6334
|
-
|
6335
|
-
|
6442
|
+
case '0': case 'z':
|
6443
|
+
ZeroSup = 0;
|
6444
|
+
++j;
|
6445
|
+
sep = cntl_chr[j] == 'z' ? BIGDECIMAL_COMPONENT_FIGURES : 10;
|
6446
|
+
break;
|
6447
|
+
}
|
6448
|
+
for (i = 0; i < a->Prec; ++i) {
|
6449
|
+
m = BASE1;
|
6450
|
+
e = a->frac[i];
|
6451
|
+
while (m) {
|
6452
|
+
nn = e / m;
|
6453
|
+
if (!ZeroSup || nn) {
|
6454
|
+
nc += fprintf(fp, "%lu", (unsigned long)nn); /* The leading zero(s) */
|
6455
|
+
/* as 0.00xx will not */
|
6456
|
+
/* be printed. */
|
6457
|
+
++nd;
|
6458
|
+
ZeroSup = 0; /* Set to print succeeding zeros */
|
6459
|
+
}
|
6460
|
+
if (nd >= sep) { /* print ' ' after every 10 digits */
|
6461
|
+
nd = 0;
|
6462
|
+
nc += fprintf(fp, " ");
|
6463
|
+
}
|
6464
|
+
e = e - nn * m;
|
6465
|
+
m /= 10;
|
6466
|
+
}
|
6467
|
+
}
|
6468
|
+
nc += fprintf(fp, "E%"PRIdSIZE, VpExponent10(a));
|
6469
|
+
nc += fprintf(fp, " (%"PRIdVALUE", %"PRIuSIZE", %"PRIuSIZE")", a->exponent, a->Prec, a->MaxPrec);
|
6470
|
+
}
|
6471
|
+
else {
|
6472
|
+
nc += fprintf(fp, "0.0");
|
6473
|
+
}
|
6474
|
+
}
|
6475
|
+
else {
|
6476
|
+
++nc;
|
6477
|
+
if (*(cntl_chr + j) == '\\') {
|
6478
|
+
switch (*(cntl_chr + j + 1)) {
|
6479
|
+
case 'n':
|
6480
|
+
fprintf(fp, "\n");
|
6481
|
+
++j;
|
6482
|
+
break;
|
6483
|
+
case 't':
|
6484
|
+
fprintf(fp, "\t");
|
6485
|
+
++j;
|
6486
|
+
break;
|
6487
|
+
case 'b':
|
6488
|
+
fprintf(fp, "\n");
|
6489
|
+
++j;
|
6490
|
+
break;
|
6491
|
+
default:
|
6492
|
+
fprintf(fp, "%c", *(cntl_chr + j));
|
6493
|
+
break;
|
6494
|
+
}
|
6495
|
+
}
|
6496
|
+
else {
|
6497
|
+
fprintf(fp, "%c", *(cntl_chr + j));
|
6498
|
+
if (*(cntl_chr + j) == '%') ++j;
|
6499
|
+
}
|
6500
|
+
}
|
6501
|
+
j++;
|
6336
6502
|
}
|
6337
6503
|
|
6338
6504
|
return (int)nc;
|
6339
6505
|
}
|
6340
|
-
#endif
|
6341
6506
|
|
6342
6507
|
static void
|
6343
6508
|
VpFormatSt(char *psz, size_t fFmt)
|
@@ -6382,188 +6547,254 @@ VpExponent10(Real *a)
|
|
6382
6547
|
}
|
6383
6548
|
|
6384
6549
|
VP_EXPORT void
|
6385
|
-
VpSzMantissa(Real *a,char *
|
6550
|
+
VpSzMantissa(Real *a, char *buf, size_t buflen)
|
6386
6551
|
{
|
6387
6552
|
size_t i, n, ZeroSup;
|
6388
6553
|
DECDIG_DBL m, e, nn;
|
6389
6554
|
|
6390
6555
|
if (VpIsNaN(a)) {
|
6391
|
-
|
6392
|
-
|
6556
|
+
snprintf(buf, buflen, SZ_NaN);
|
6557
|
+
return;
|
6393
6558
|
}
|
6394
6559
|
if (VpIsPosInf(a)) {
|
6395
|
-
|
6560
|
+
snprintf(buf, buflen, SZ_INF);
|
6396
6561
|
return;
|
6397
6562
|
}
|
6398
6563
|
if (VpIsNegInf(a)) {
|
6399
|
-
|
6564
|
+
snprintf(buf, buflen, SZ_NINF);
|
6400
6565
|
return;
|
6401
6566
|
}
|
6402
6567
|
|
6403
6568
|
ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
|
6404
6569
|
if (!VpIsZero(a)) {
|
6405
|
-
|
6406
|
-
|
6407
|
-
|
6408
|
-
|
6409
|
-
|
6410
|
-
|
6411
|
-
|
6412
|
-
|
6413
|
-
|
6414
|
-
|
6415
|
-
|
6416
|
-
|
6417
|
-
|
6418
|
-
|
6419
|
-
|
6420
|
-
|
6421
|
-
|
6422
|
-
|
6423
|
-
|
6570
|
+
if (BIGDECIMAL_NEGATIVE_P(a)) *buf++ = '-';
|
6571
|
+
n = a->Prec;
|
6572
|
+
for (i = 0; i < n; ++i) {
|
6573
|
+
m = BASE1;
|
6574
|
+
e = a->frac[i];
|
6575
|
+
while (m) {
|
6576
|
+
nn = e / m;
|
6577
|
+
if (!ZeroSup || nn) {
|
6578
|
+
snprintf(buf, buflen, "%lu", (unsigned long)nn); /* The leading zero(s) */
|
6579
|
+
buf += strlen(buf);
|
6580
|
+
/* as 0.00xx will be ignored. */
|
6581
|
+
ZeroSup = 0; /* Set to print succeeding zeros */
|
6582
|
+
}
|
6583
|
+
e = e - nn * m;
|
6584
|
+
m /= 10;
|
6585
|
+
}
|
6586
|
+
}
|
6587
|
+
*buf = 0;
|
6588
|
+
while (buf[-1] == '0') *(--buf) = 0;
|
6424
6589
|
}
|
6425
6590
|
else {
|
6426
|
-
if (VpIsPosZero(a))
|
6427
|
-
else
|
6591
|
+
if (VpIsPosZero(a)) snprintf(buf, buflen, "0");
|
6592
|
+
else snprintf(buf, buflen, "-0");
|
6428
6593
|
}
|
6429
6594
|
}
|
6430
6595
|
|
6431
6596
|
VP_EXPORT int
|
6432
|
-
VpToSpecialString(Real *a,char *
|
6597
|
+
VpToSpecialString(Real *a, char *buf, size_t buflen, int fPlus)
|
6433
6598
|
/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
|
6434
6599
|
{
|
6435
6600
|
if (VpIsNaN(a)) {
|
6436
|
-
|
6437
|
-
|
6601
|
+
snprintf(buf, buflen, SZ_NaN);
|
6602
|
+
return 1;
|
6438
6603
|
}
|
6439
6604
|
|
6440
6605
|
if (VpIsPosInf(a)) {
|
6441
|
-
|
6442
|
-
|
6443
|
-
|
6444
|
-
|
6445
|
-
|
6446
|
-
|
6447
|
-
|
6448
|
-
|
6606
|
+
if (fPlus == 1) {
|
6607
|
+
*buf++ = ' ';
|
6608
|
+
}
|
6609
|
+
else if (fPlus == 2) {
|
6610
|
+
*buf++ = '+';
|
6611
|
+
}
|
6612
|
+
snprintf(buf, buflen, SZ_INF);
|
6613
|
+
return 1;
|
6449
6614
|
}
|
6450
6615
|
if (VpIsNegInf(a)) {
|
6451
|
-
|
6452
|
-
|
6616
|
+
snprintf(buf, buflen, SZ_NINF);
|
6617
|
+
return 1;
|
6453
6618
|
}
|
6454
6619
|
if (VpIsZero(a)) {
|
6455
|
-
|
6456
|
-
|
6457
|
-
|
6458
|
-
|
6459
|
-
|
6460
|
-
|
6461
|
-
|
6620
|
+
if (VpIsPosZero(a)) {
|
6621
|
+
if (fPlus == 1) snprintf(buf, buflen, " 0.0");
|
6622
|
+
else if (fPlus == 2) snprintf(buf, buflen, "+0.0");
|
6623
|
+
else snprintf(buf, buflen, "0.0");
|
6624
|
+
}
|
6625
|
+
else snprintf(buf, buflen, "-0.0");
|
6626
|
+
return 1;
|
6462
6627
|
}
|
6463
6628
|
return 0;
|
6464
6629
|
}
|
6465
6630
|
|
6466
6631
|
VP_EXPORT void
|
6467
|
-
VpToString(Real *a, char *
|
6632
|
+
VpToString(Real *a, char *buf, size_t buflen, size_t fFmt, int fPlus)
|
6468
6633
|
/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
|
6469
6634
|
{
|
6470
6635
|
size_t i, n, ZeroSup;
|
6471
6636
|
DECDIG shift, m, e, nn;
|
6472
|
-
char *
|
6637
|
+
char *p = buf;
|
6638
|
+
size_t plen = buflen;
|
6473
6639
|
ssize_t ex;
|
6474
6640
|
|
6475
|
-
if (VpToSpecialString(a,
|
6641
|
+
if (VpToSpecialString(a, buf, buflen, fPlus)) return;
|
6476
6642
|
|
6477
6643
|
ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
|
6478
6644
|
|
6479
|
-
|
6480
|
-
|
6481
|
-
|
6645
|
+
#define ADVANCE(n) do { \
|
6646
|
+
if (plen < n) goto overflow; \
|
6647
|
+
p += n; \
|
6648
|
+
plen -= n; \
|
6649
|
+
} while (0)
|
6650
|
+
|
6651
|
+
if (BIGDECIMAL_NEGATIVE_P(a)) {
|
6652
|
+
*p = '-';
|
6653
|
+
ADVANCE(1);
|
6654
|
+
}
|
6655
|
+
else if (fPlus == 1) {
|
6656
|
+
*p = ' ';
|
6657
|
+
ADVANCE(1);
|
6658
|
+
}
|
6659
|
+
else if (fPlus == 2) {
|
6660
|
+
*p = '+';
|
6661
|
+
ADVANCE(1);
|
6662
|
+
}
|
6663
|
+
|
6664
|
+
*p = '0'; ADVANCE(1);
|
6665
|
+
*p = '.'; ADVANCE(1);
|
6482
6666
|
|
6483
|
-
*psz++ = '0';
|
6484
|
-
*psz++ = '.';
|
6485
6667
|
n = a->Prec;
|
6486
6668
|
for (i = 0; i < n; ++i) {
|
6487
|
-
|
6488
|
-
|
6489
|
-
|
6490
|
-
|
6491
|
-
|
6492
|
-
|
6493
|
-
|
6494
|
-
|
6495
|
-
|
6496
|
-
|
6497
|
-
|
6498
|
-
|
6499
|
-
|
6669
|
+
m = BASE1;
|
6670
|
+
e = a->frac[i];
|
6671
|
+
while (m) {
|
6672
|
+
nn = e / m;
|
6673
|
+
if (!ZeroSup || nn) {
|
6674
|
+
/* The reading zero(s) */
|
6675
|
+
size_t n = (size_t)snprintf(p, plen, "%lu", (unsigned long)nn);
|
6676
|
+
if (n > plen) goto overflow;
|
6677
|
+
ADVANCE(n);
|
6678
|
+
/* as 0.00xx will be ignored. */
|
6679
|
+
ZeroSup = 0; /* Set to print succeeding zeros */
|
6680
|
+
}
|
6681
|
+
e = e - nn * m;
|
6682
|
+
m /= 10;
|
6683
|
+
}
|
6500
6684
|
}
|
6685
|
+
|
6501
6686
|
ex = a->exponent * (ssize_t)BASE_FIG;
|
6502
6687
|
shift = BASE1;
|
6503
6688
|
while (a->frac[0] / shift == 0) {
|
6504
|
-
|
6505
|
-
|
6689
|
+
--ex;
|
6690
|
+
shift /= 10;
|
6506
6691
|
}
|
6507
|
-
while (
|
6508
|
-
|
6692
|
+
while (p - 1 > buf && p[-1] == '0') {
|
6693
|
+
*(--p) = '\0';
|
6694
|
+
++plen;
|
6509
6695
|
}
|
6510
|
-
|
6511
|
-
if (fFmt) VpFormatSt(
|
6696
|
+
snprintf(p, plen, "e%"PRIdSIZE, ex);
|
6697
|
+
if (fFmt) VpFormatSt(buf, fFmt);
|
6698
|
+
|
6699
|
+
overflow:
|
6700
|
+
return;
|
6701
|
+
#undef ADVANCE
|
6512
6702
|
}
|
6513
6703
|
|
6514
6704
|
VP_EXPORT void
|
6515
|
-
VpToFString(Real *a, char *
|
6705
|
+
VpToFString(Real *a, char *buf, size_t buflen, size_t fFmt, int fPlus)
|
6516
6706
|
/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
|
6517
6707
|
{
|
6518
6708
|
size_t i, n;
|
6519
6709
|
DECDIG m, e, nn;
|
6520
|
-
char *
|
6710
|
+
char *p = buf;
|
6711
|
+
size_t plen = buflen;
|
6521
6712
|
ssize_t ex;
|
6522
6713
|
|
6523
|
-
if (VpToSpecialString(a,
|
6714
|
+
if (VpToSpecialString(a, buf, buflen, fPlus)) return;
|
6715
|
+
|
6716
|
+
#define ADVANCE(n) do { \
|
6717
|
+
if (plen < n) goto overflow; \
|
6718
|
+
p += n; \
|
6719
|
+
plen -= n; \
|
6720
|
+
} while (0)
|
6524
6721
|
|
6525
|
-
|
6526
|
-
|
6527
|
-
|
6722
|
+
|
6723
|
+
if (BIGDECIMAL_NEGATIVE_P(a)) {
|
6724
|
+
*p = '-';
|
6725
|
+
ADVANCE(1);
|
6726
|
+
}
|
6727
|
+
else if (fPlus == 1) {
|
6728
|
+
*p = ' ';
|
6729
|
+
ADVANCE(1);
|
6730
|
+
}
|
6731
|
+
else if (fPlus == 2) {
|
6732
|
+
*p = '+';
|
6733
|
+
ADVANCE(1);
|
6734
|
+
}
|
6528
6735
|
|
6529
6736
|
n = a->Prec;
|
6530
6737
|
ex = a->exponent;
|
6531
6738
|
if (ex <= 0) {
|
6532
|
-
|
6533
|
-
|
6534
|
-
|
6535
|
-
|
6536
|
-
|
6537
|
-
|
6739
|
+
*p = '0'; ADVANCE(1);
|
6740
|
+
*p = '.'; ADVANCE(1);
|
6741
|
+
while (ex < 0) {
|
6742
|
+
for (i=0; i < BASE_FIG; ++i) {
|
6743
|
+
*p = '0'; ADVANCE(1);
|
6744
|
+
}
|
6745
|
+
++ex;
|
6746
|
+
}
|
6747
|
+
ex = -1;
|
6538
6748
|
}
|
6539
6749
|
|
6540
6750
|
for (i = 0; i < n; ++i) {
|
6541
|
-
|
6542
|
-
|
6543
|
-
|
6544
|
-
|
6545
|
-
|
6546
|
-
|
6547
|
-
|
6548
|
-
|
6549
|
-
|
6550
|
-
|
6551
|
-
|
6552
|
-
|
6553
|
-
|
6554
|
-
|
6555
|
-
|
6556
|
-
|
6751
|
+
--ex;
|
6752
|
+
if (i == 0 && ex >= 0) {
|
6753
|
+
size_t n = snprintf(p, plen, "%lu", (unsigned long)a->frac[i]);
|
6754
|
+
if (n > plen) goto overflow;
|
6755
|
+
ADVANCE(n);
|
6756
|
+
}
|
6757
|
+
else {
|
6758
|
+
m = BASE1;
|
6759
|
+
e = a->frac[i];
|
6760
|
+
while (m) {
|
6761
|
+
nn = e / m;
|
6762
|
+
*p = (char)(nn + '0');
|
6763
|
+
ADVANCE(1);
|
6764
|
+
e = e - nn * m;
|
6765
|
+
m /= 10;
|
6766
|
+
}
|
6767
|
+
}
|
6768
|
+
if (ex == 0) {
|
6769
|
+
*p = '.';
|
6770
|
+
ADVANCE(1);
|
6771
|
+
}
|
6557
6772
|
}
|
6558
6773
|
while (--ex>=0) {
|
6559
|
-
|
6560
|
-
|
6561
|
-
|
6774
|
+
m = BASE;
|
6775
|
+
while (m /= 10) {
|
6776
|
+
*p = '0';
|
6777
|
+
ADVANCE(1);
|
6778
|
+
}
|
6779
|
+
if (ex == 0) {
|
6780
|
+
*p = '.';
|
6781
|
+
ADVANCE(1);
|
6782
|
+
}
|
6783
|
+
}
|
6784
|
+
|
6785
|
+
*p = '\0';
|
6786
|
+
while (p - 1 > buf && p[-1] == '0') {
|
6787
|
+
*(--p) = '\0';
|
6788
|
+
++plen;
|
6562
6789
|
}
|
6563
|
-
|
6564
|
-
|
6565
|
-
|
6566
|
-
if (fFmt) VpFormatSt(
|
6790
|
+
if (p - 1 > buf && p[-1] == '.') {
|
6791
|
+
snprintf(p, plen, "0");
|
6792
|
+
}
|
6793
|
+
if (fFmt) VpFormatSt(buf, fFmt);
|
6794
|
+
|
6795
|
+
overflow:
|
6796
|
+
return;
|
6797
|
+
#undef ADVANCE
|
6567
6798
|
}
|
6568
6799
|
|
6569
6800
|
/*
|
@@ -6972,8 +7203,9 @@ VpSqrt(Real *y, Real *x)
|
|
6972
7203
|
if (x->MaxPrec > (size_t)n) n = (ssize_t)x->MaxPrec;
|
6973
7204
|
|
6974
7205
|
/* allocate temporally variables */
|
6975
|
-
|
6976
|
-
|
7206
|
+
/* TODO: reconsider MaxPrec of f and r */
|
7207
|
+
f = NewOneNolimit(1, y->MaxPrec * (BASE_FIG + 2));
|
7208
|
+
r = NewOneNolimit(1, (n + n) * (BASE_FIG + 2));
|
6977
7209
|
|
6978
7210
|
nr = 0;
|
6979
7211
|
y_prec = y->MaxPrec;
|
@@ -6998,16 +7230,21 @@ VpSqrt(Real *y, Real *x)
|
|
6998
7230
|
f->MaxPrec = y->MaxPrec + 1;
|
6999
7231
|
n = (SIGNED_VALUE)(y_prec * BASE_FIG);
|
7000
7232
|
if (n < (SIGNED_VALUE)maxnr) n = (SIGNED_VALUE)maxnr;
|
7233
|
+
|
7234
|
+
/*
|
7235
|
+
* Perform: y_{n+1} = (y_n - x/y_n) / 2
|
7236
|
+
*/
|
7001
7237
|
do {
|
7002
|
-
|
7003
|
-
|
7004
|
-
|
7005
|
-
|
7006
|
-
|
7007
|
-
|
7008
|
-
|
7009
|
-
|
7010
|
-
|
7238
|
+
y->MaxPrec *= 2;
|
7239
|
+
if (y->MaxPrec > y_prec) y->MaxPrec = y_prec;
|
7240
|
+
f->MaxPrec = y->MaxPrec;
|
7241
|
+
VpDivd(f, r, x, y); /* f = x/y */
|
7242
|
+
VpAddSub(r, f, y, -1); /* r = f - y */
|
7243
|
+
VpMult(f, VpConstPt5, r); /* f = 0.5*r */
|
7244
|
+
if (VpIsZero(f))
|
7245
|
+
goto converge;
|
7246
|
+
VpAddSub(r, f, y, 1); /* r = y + f */
|
7247
|
+
VpAsgn(y, r, 1); /* y = r */
|
7011
7248
|
} while (++nr < n);
|
7012
7249
|
|
7013
7250
|
#ifdef BIGDECIMAL_DEBUG
|
@@ -7032,8 +7269,8 @@ converge:
|
|
7032
7269
|
y->MaxPrec = y_prec;
|
7033
7270
|
|
7034
7271
|
Exit:
|
7035
|
-
|
7036
|
-
|
7272
|
+
rbd_free_struct(f);
|
7273
|
+
rbd_free_struct(r);
|
7037
7274
|
return 1;
|
7038
7275
|
}
|
7039
7276
|
|
@@ -7424,9 +7661,10 @@ VpPowerByInt(Real *y, Real *x, SIGNED_VALUE n)
|
|
7424
7661
|
}
|
7425
7662
|
|
7426
7663
|
/* Allocate working variables */
|
7664
|
+
/* TODO: reconsider MaxPrec of w1 and w2 */
|
7665
|
+
w1 = NewZeroNolimit(1, (y->MaxPrec + 2) * BASE_FIG);
|
7666
|
+
w2 = NewZeroNolimit(1, (w1->MaxPrec * 2 + 1) * BASE_FIG);
|
7427
7667
|
|
7428
|
-
w1 = VpAlloc((y->MaxPrec + 2) * BASE_FIG, "#0", 1, 1);
|
7429
|
-
w2 = VpAlloc((w1->MaxPrec * 2 + 1) * BASE_FIG, "#0", 1, 1);
|
7430
7668
|
/* calculation start */
|
7431
7669
|
|
7432
7670
|
VpAsgn(y, x, 1);
|
@@ -7455,8 +7693,8 @@ Exit:
|
|
7455
7693
|
printf(" n=%"PRIdVALUE"\n", n);
|
7456
7694
|
}
|
7457
7695
|
#endif /* BIGDECIMAL_DEBUG */
|
7458
|
-
|
7459
|
-
|
7696
|
+
rbd_free_struct(w2);
|
7697
|
+
rbd_free_struct(w1);
|
7460
7698
|
return 1;
|
7461
7699
|
}
|
7462
7700
|
|