bigdecimal 3.1.2 → 3.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bigdecimal.gemspec +2 -2
- data/ext/bigdecimal/bigdecimal.c +802 -576
- data/ext/bigdecimal/bigdecimal.h +32 -16
- data/ext/bigdecimal/extconf.rb +0 -4
- data/ext/bigdecimal/missing.h +6 -45
- data/lib/bigdecimal/jacobian.rb +3 -3
- data/lib/bigdecimal/util.rb +5 -1
- metadata +7 -6
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
|
|
@@ -61,6 +59,13 @@ static ID id_to_r;
|
|
61
59
|
static ID id_eq;
|
62
60
|
static ID id_half;
|
63
61
|
|
62
|
+
#define RBD_NUM_ROUNDING_MODES 11
|
63
|
+
|
64
|
+
static struct {
|
65
|
+
ID id;
|
66
|
+
uint8_t mode;
|
67
|
+
} rbd_rounding_modes[RBD_NUM_ROUNDING_MODES];
|
68
|
+
|
64
69
|
/* MACRO's to guard objects from GC by keeping them in stack */
|
65
70
|
#ifdef RBIMPL_ATTR_MAYBE_UNUSED
|
66
71
|
#define ENTER(n) RBIMPL_ATTR_MAYBE_UNUSED() volatile VALUE vStack[n];int iStack=0
|
@@ -102,9 +107,163 @@ static ID id_half;
|
|
102
107
|
# define RB_OBJ_STRING(obj) StringValueCStr(obj)
|
103
108
|
#endif
|
104
109
|
|
110
|
+
#ifndef MAYBE_UNUSED
|
111
|
+
# define MAYBE_UNUSED(x) x
|
112
|
+
#endif
|
113
|
+
|
105
114
|
#define BIGDECIMAL_POSITIVE_P(bd) ((bd)->sign > 0)
|
106
115
|
#define BIGDECIMAL_NEGATIVE_P(bd) ((bd)->sign < 0)
|
107
116
|
|
117
|
+
/*
|
118
|
+
* ================== Memory allocation ============================
|
119
|
+
*/
|
120
|
+
|
121
|
+
#ifdef BIGDECIMAL_DEBUG
|
122
|
+
static size_t rbd_allocation_count = 0; /* Memory allocation counter */
|
123
|
+
static inline void
|
124
|
+
atomic_allocation_count_inc(void)
|
125
|
+
{
|
126
|
+
RUBY_ATOMIC_SIZE_INC(rbd_allocation_count);
|
127
|
+
}
|
128
|
+
static inline void
|
129
|
+
atomic_allocation_count_dec_nounderflow(void)
|
130
|
+
{
|
131
|
+
if (rbd_allocation_count == 0) return;
|
132
|
+
RUBY_ATOMIC_SIZE_DEC(rbd_allocation_count);
|
133
|
+
}
|
134
|
+
static void
|
135
|
+
check_allocation_count_nonzero(void)
|
136
|
+
{
|
137
|
+
if (rbd_allocation_count != 0) return;
|
138
|
+
rb_bug("[bigdecimal][rbd_free_struct] Too many memory free calls");
|
139
|
+
}
|
140
|
+
#else
|
141
|
+
# define atomic_allocation_count_inc() /* nothing */
|
142
|
+
# define atomic_allocation_count_dec_nounderflow() /* nothing */
|
143
|
+
# define check_allocation_count_nonzero() /* nothing */
|
144
|
+
#endif /* BIGDECIMAL_DEBUG */
|
145
|
+
|
146
|
+
PUREFUNC(static inline size_t rbd_struct_size(size_t const));
|
147
|
+
|
148
|
+
static inline size_t
|
149
|
+
rbd_struct_size(size_t const internal_digits)
|
150
|
+
{
|
151
|
+
size_t const frac_len = (internal_digits == 0) ? 1 : internal_digits;
|
152
|
+
return offsetof(Real, frac) + frac_len * sizeof(DECDIG);
|
153
|
+
}
|
154
|
+
|
155
|
+
static inline Real *
|
156
|
+
rbd_allocate_struct(size_t const internal_digits)
|
157
|
+
{
|
158
|
+
size_t const size = rbd_struct_size(internal_digits);
|
159
|
+
Real *real = ruby_xcalloc(1, size);
|
160
|
+
atomic_allocation_count_inc();
|
161
|
+
real->MaxPrec = internal_digits;
|
162
|
+
return real;
|
163
|
+
}
|
164
|
+
|
165
|
+
static size_t
|
166
|
+
rbd_calculate_internal_digits(size_t const digits, bool limit_precision)
|
167
|
+
{
|
168
|
+
size_t const len = roomof(digits, BASE_FIG);
|
169
|
+
if (limit_precision) {
|
170
|
+
size_t const prec_limit = VpGetPrecLimit();
|
171
|
+
if (prec_limit > 0) {
|
172
|
+
/* NOTE: 2 more digits for rounding and division */
|
173
|
+
size_t const max_len = roomof(prec_limit, BASE_FIG) + 2;
|
174
|
+
if (len > max_len)
|
175
|
+
return max_len;
|
176
|
+
}
|
177
|
+
}
|
178
|
+
|
179
|
+
return len;
|
180
|
+
}
|
181
|
+
|
182
|
+
static inline Real *
|
183
|
+
rbd_allocate_struct_decimal_digits(size_t const decimal_digits, bool limit_precision)
|
184
|
+
{
|
185
|
+
size_t const internal_digits = rbd_calculate_internal_digits(decimal_digits, limit_precision);
|
186
|
+
return rbd_allocate_struct(internal_digits);
|
187
|
+
}
|
188
|
+
|
189
|
+
static VALUE BigDecimal_wrap_struct(VALUE obj, Real *vp);
|
190
|
+
|
191
|
+
static Real *
|
192
|
+
rbd_reallocate_struct(Real *real, size_t const internal_digits)
|
193
|
+
{
|
194
|
+
size_t const size = rbd_struct_size(internal_digits);
|
195
|
+
VALUE obj = real ? real->obj : 0;
|
196
|
+
Real *new_real = (Real *)ruby_xrealloc(real, size);
|
197
|
+
new_real->MaxPrec = internal_digits;
|
198
|
+
if (obj) {
|
199
|
+
new_real->obj = 0;
|
200
|
+
BigDecimal_wrap_struct(obj, new_real);
|
201
|
+
}
|
202
|
+
return new_real;
|
203
|
+
}
|
204
|
+
|
205
|
+
static void
|
206
|
+
rbd_free_struct(Real *real)
|
207
|
+
{
|
208
|
+
if (real != NULL) {
|
209
|
+
check_allocation_count_nonzero();
|
210
|
+
ruby_xfree(real);
|
211
|
+
atomic_allocation_count_dec_nounderflow();
|
212
|
+
}
|
213
|
+
}
|
214
|
+
|
215
|
+
#define NewZero rbd_allocate_struct_zero
|
216
|
+
static Real *
|
217
|
+
rbd_allocate_struct_zero(int sign, size_t const digits, bool limit_precision)
|
218
|
+
{
|
219
|
+
Real *real = rbd_allocate_struct_decimal_digits(digits, limit_precision);
|
220
|
+
VpSetZero(real, sign);
|
221
|
+
return real;
|
222
|
+
}
|
223
|
+
|
224
|
+
MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_limited(int sign, size_t const digits));
|
225
|
+
#define NewZeroLimited rbd_allocate_struct_zero_limited
|
226
|
+
static inline Real *
|
227
|
+
rbd_allocate_struct_zero_limited(int sign, size_t const digits)
|
228
|
+
{
|
229
|
+
return rbd_allocate_struct_zero(sign, digits, true);
|
230
|
+
}
|
231
|
+
|
232
|
+
MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_nolimit(int sign, size_t const digits));
|
233
|
+
#define NewZeroNolimit rbd_allocate_struct_zero_nolimit
|
234
|
+
static inline Real *
|
235
|
+
rbd_allocate_struct_zero_nolimit(int sign, size_t const digits)
|
236
|
+
{
|
237
|
+
return rbd_allocate_struct_zero(sign, digits, false);
|
238
|
+
}
|
239
|
+
|
240
|
+
#define NewOne rbd_allocate_struct_one
|
241
|
+
static Real *
|
242
|
+
rbd_allocate_struct_one(int sign, size_t const digits, bool limit_precision)
|
243
|
+
{
|
244
|
+
Real *real = rbd_allocate_struct_decimal_digits(digits, limit_precision);
|
245
|
+
VpSetOne(real);
|
246
|
+
if (sign < 0)
|
247
|
+
VpSetSign(real, VP_SIGN_NEGATIVE_FINITE);
|
248
|
+
return real;
|
249
|
+
}
|
250
|
+
|
251
|
+
MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_limited(int sign, size_t const digits));
|
252
|
+
#define NewOneLimited rbd_allocate_struct_one_limited
|
253
|
+
static inline Real *
|
254
|
+
rbd_allocate_struct_one_limited(int sign, size_t const digits)
|
255
|
+
{
|
256
|
+
return rbd_allocate_struct_one(sign, digits, true);
|
257
|
+
}
|
258
|
+
|
259
|
+
MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_nolimit(int sign, size_t const digits));
|
260
|
+
#define NewOneNolimit rbd_allocate_struct_one_nolimit
|
261
|
+
static inline Real *
|
262
|
+
rbd_allocate_struct_one_nolimit(int sign, size_t const digits)
|
263
|
+
{
|
264
|
+
return rbd_allocate_struct_one(sign, digits, false);
|
265
|
+
}
|
266
|
+
|
108
267
|
/*
|
109
268
|
* ================== Ruby Interface part ==========================
|
110
269
|
*/
|
@@ -120,10 +279,7 @@ static VALUE VpCheckGetValue(Real *p);
|
|
120
279
|
static void VpInternalRound(Real *c, size_t ixDigit, DECDIG vPrev, DECDIG v);
|
121
280
|
static int VpLimitRound(Real *c, size_t ixDigit);
|
122
281
|
static Real *VpCopy(Real *pv, Real const* const x);
|
123
|
-
|
124
|
-
#ifdef BIGDECIMAL_ENABLE_VPRINT
|
125
282
|
static int VPrint(FILE *fp,const char *cntl_chr,Real *a);
|
126
|
-
#endif
|
127
283
|
|
128
284
|
/*
|
129
285
|
* **** BigDecimal part ****
|
@@ -138,7 +294,7 @@ static VALUE BigDecimal_negative_zero(void);
|
|
138
294
|
static void
|
139
295
|
BigDecimal_delete(void *pv)
|
140
296
|
{
|
141
|
-
|
297
|
+
rbd_free_struct(pv);
|
142
298
|
}
|
143
299
|
|
144
300
|
static size_t
|
@@ -161,6 +317,60 @@ static const rb_data_type_t BigDecimal_data_type = {
|
|
161
317
|
#endif
|
162
318
|
};
|
163
319
|
|
320
|
+
static Real *
|
321
|
+
rbd_allocate_struct_zero_wrap_klass(VALUE klass, int sign, size_t const digits, bool limit_precision)
|
322
|
+
{
|
323
|
+
Real *real = rbd_allocate_struct_zero(sign, digits, limit_precision);
|
324
|
+
if (real != NULL) {
|
325
|
+
VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
|
326
|
+
BigDecimal_wrap_struct(obj, real);
|
327
|
+
}
|
328
|
+
return real;
|
329
|
+
}
|
330
|
+
|
331
|
+
MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_limited_wrap(int sign, size_t const digits));
|
332
|
+
#define NewZeroWrapLimited rbd_allocate_struct_zero_limited_wrap
|
333
|
+
static inline Real *
|
334
|
+
rbd_allocate_struct_zero_limited_wrap(int sign, size_t const digits)
|
335
|
+
{
|
336
|
+
return rbd_allocate_struct_zero_wrap_klass(rb_cBigDecimal, sign, digits, true);
|
337
|
+
}
|
338
|
+
|
339
|
+
MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_nolimit_wrap(int sign, size_t const digits));
|
340
|
+
#define NewZeroWrapNolimit rbd_allocate_struct_zero_nolimit_wrap
|
341
|
+
static inline Real *
|
342
|
+
rbd_allocate_struct_zero_nolimit_wrap(int sign, size_t const digits)
|
343
|
+
{
|
344
|
+
return rbd_allocate_struct_zero_wrap_klass(rb_cBigDecimal, sign, digits, false);
|
345
|
+
}
|
346
|
+
|
347
|
+
static Real *
|
348
|
+
rbd_allocate_struct_one_wrap_klass(VALUE klass, int sign, size_t const digits, bool limit_precision)
|
349
|
+
{
|
350
|
+
Real *real = rbd_allocate_struct_one(sign, digits, limit_precision);
|
351
|
+
if (real != NULL) {
|
352
|
+
VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
|
353
|
+
BigDecimal_wrap_struct(obj, real);
|
354
|
+
}
|
355
|
+
return real;
|
356
|
+
}
|
357
|
+
|
358
|
+
MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_limited_wrap(int sign, size_t const digits));
|
359
|
+
#define NewOneWrapLimited rbd_allocate_struct_one_limited_wrap
|
360
|
+
static inline Real *
|
361
|
+
rbd_allocate_struct_one_limited_wrap(int sign, size_t const digits)
|
362
|
+
{
|
363
|
+
return rbd_allocate_struct_one_wrap_klass(rb_cBigDecimal, sign, digits, true);
|
364
|
+
}
|
365
|
+
|
366
|
+
MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_nolimit_wrap(int sign, size_t const digits));
|
367
|
+
#define NewOneWrapNolimit rbd_allocate_struct_one_nolimit_wrap
|
368
|
+
static inline Real *
|
369
|
+
rbd_allocate_struct_one_nolimit_wrap(int sign, size_t const digits)
|
370
|
+
{
|
371
|
+
return rbd_allocate_struct_one_wrap_klass(rb_cBigDecimal, sign, digits, false);
|
372
|
+
}
|
373
|
+
|
164
374
|
static inline int
|
165
375
|
is_kind_of_BigDecimal(VALUE const v)
|
166
376
|
{
|
@@ -214,7 +424,7 @@ GetVpValueWithPrec(VALUE v, long prec, int must)
|
|
214
424
|
|
215
425
|
case T_FIXNUM: {
|
216
426
|
char szD[128];
|
217
|
-
|
427
|
+
snprintf(szD, 128, "%ld", FIX2LONG(v));
|
218
428
|
v = rb_cstr_convert_to_BigDecimal(szD, VpBaseFig() * 2 + 1, must);
|
219
429
|
break;
|
220
430
|
}
|
@@ -249,7 +459,7 @@ SomeOneMayDoIt:
|
|
249
459
|
return NULL; /* NULL means to coerce */
|
250
460
|
}
|
251
461
|
|
252
|
-
static Real*
|
462
|
+
static inline Real*
|
253
463
|
GetVpValue(VALUE v, int must)
|
254
464
|
{
|
255
465
|
return GetVpValueWithPrec(v, -1, must);
|
@@ -264,7 +474,7 @@ GetVpValue(VALUE v, int must)
|
|
264
474
|
* BigDecimal.double_fig # => 16
|
265
475
|
*
|
266
476
|
*/
|
267
|
-
static VALUE
|
477
|
+
static inline VALUE
|
268
478
|
BigDecimal_double_fig(VALUE self)
|
269
479
|
{
|
270
480
|
return INT2FIX(VpDblFig());
|
@@ -486,15 +696,15 @@ BigDecimal_precision_scale(VALUE self)
|
|
486
696
|
*
|
487
697
|
* Returns the number of decimal significant digits in +self+.
|
488
698
|
*
|
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").
|
699
|
+
* BigDecimal("0").n_significant_digits # => 0
|
700
|
+
* BigDecimal("1").n_significant_digits # => 1
|
701
|
+
* BigDecimal("1.1").n_significant_digits # => 2
|
702
|
+
* BigDecimal("3.1415").n_significant_digits # => 5
|
703
|
+
* BigDecimal("-1e20").n_significant_digits # => 1
|
704
|
+
* BigDecimal("1e-20").n_significant_digits # => 1
|
705
|
+
* BigDecimal("Infinity").n_significant_digits # => 0
|
706
|
+
* BigDecimal("-Infinity").n_significant_digits # => 0
|
707
|
+
* BigDecimal("NaN").n_significant_digits # => 0
|
498
708
|
*/
|
499
709
|
static VALUE
|
500
710
|
BigDecimal_n_significant_digits(VALUE self)
|
@@ -573,13 +783,15 @@ BigDecimal_dump(int argc, VALUE *argv, VALUE self)
|
|
573
783
|
char *psz;
|
574
784
|
VALUE dummy;
|
575
785
|
volatile VALUE dump;
|
786
|
+
size_t len;
|
576
787
|
|
577
788
|
rb_scan_args(argc, argv, "01", &dummy);
|
578
789
|
GUARD_OBJ(vp,GetVpValue(self, 1));
|
579
790
|
dump = rb_str_new(0, VpNumOfChars(vp, "E")+50);
|
580
791
|
psz = RSTRING_PTR(dump);
|
581
|
-
|
582
|
-
|
792
|
+
snprintf(psz, RSTRING_LEN(dump), "%"PRIuSIZE":", VpMaxPrec(vp)*VpBaseFig());
|
793
|
+
len = strlen(psz);
|
794
|
+
VpToString(vp, psz+len, RSTRING_LEN(dump)-len, 0, 0);
|
583
795
|
rb_str_resize(dump, strlen(psz));
|
584
796
|
return dump;
|
585
797
|
}
|
@@ -623,18 +835,19 @@ check_rounding_mode_option(VALUE const opts)
|
|
623
835
|
assert(RB_TYPE_P(opts, T_HASH));
|
624
836
|
|
625
837
|
if (NIL_P(opts))
|
626
|
-
goto
|
838
|
+
goto no_opt;
|
627
839
|
|
628
840
|
mode = rb_hash_lookup2(opts, ID2SYM(id_half), Qundef);
|
629
841
|
if (mode == Qundef || NIL_P(mode))
|
630
|
-
goto
|
842
|
+
goto no_opt;
|
631
843
|
|
632
844
|
if (SYMBOL_P(mode))
|
633
845
|
mode = rb_sym2str(mode);
|
634
846
|
else if (!RB_TYPE_P(mode, T_STRING)) {
|
635
|
-
|
636
|
-
|
637
|
-
|
847
|
+
VALUE str_mode = rb_check_string_type(mode);
|
848
|
+
if (NIL_P(str_mode))
|
849
|
+
goto invalid;
|
850
|
+
mode = str_mode;
|
638
851
|
}
|
639
852
|
s = RSTRING_PTR(mode);
|
640
853
|
l = RSTRING_LEN(mode);
|
@@ -652,13 +865,11 @@ check_rounding_mode_option(VALUE const opts)
|
|
652
865
|
default:
|
653
866
|
break;
|
654
867
|
}
|
868
|
+
|
655
869
|
invalid:
|
656
|
-
|
657
|
-
rb_raise(rb_eArgError, "invalid rounding mode: nil");
|
658
|
-
else
|
659
|
-
rb_raise(rb_eArgError, "invalid rounding mode: %"PRIsVALUE, mode);
|
870
|
+
rb_raise(rb_eArgError, "invalid rounding mode (%"PRIsVALUE")", mode);
|
660
871
|
|
661
|
-
|
872
|
+
no_opt:
|
662
873
|
return VpGetRoundMode();
|
663
874
|
}
|
664
875
|
|
@@ -667,34 +878,23 @@ check_rounding_mode(VALUE const v)
|
|
667
878
|
{
|
668
879
|
unsigned short sw;
|
669
880
|
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;
|
881
|
+
if (RB_TYPE_P(v, T_SYMBOL)) {
|
882
|
+
int i;
|
883
|
+
id = SYM2ID(v);
|
884
|
+
for (i = 0; i < RBD_NUM_ROUNDING_MODES; ++i) {
|
885
|
+
if (rbd_rounding_modes[i].id == id) {
|
886
|
+
return rbd_rounding_modes[i].mode;
|
887
|
+
}
|
888
|
+
}
|
889
|
+
rb_raise(rb_eArgError, "invalid rounding mode (%"PRIsVALUE")", v);
|
691
890
|
}
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
891
|
+
else {
|
892
|
+
sw = NUM2USHORT(v);
|
893
|
+
if (!VpIsRoundMode(sw)) {
|
894
|
+
rb_raise(rb_eArgError, "invalid rounding mode (%"PRIsVALUE")", v);
|
895
|
+
}
|
896
|
+
return sw;
|
696
897
|
}
|
697
|
-
return sw;
|
698
898
|
}
|
699
899
|
|
700
900
|
/* call-seq:
|
@@ -933,11 +1133,17 @@ GetAddSubPrec(Real *a, Real *b)
|
|
933
1133
|
return mx;
|
934
1134
|
}
|
935
1135
|
|
936
|
-
static SIGNED_VALUE
|
937
|
-
|
1136
|
+
static inline SIGNED_VALUE
|
1137
|
+
check_int_precision(VALUE v)
|
938
1138
|
{
|
939
1139
|
SIGNED_VALUE n;
|
940
|
-
|
1140
|
+
#if SIZEOF_VALUE <= SIZEOF_LONG
|
1141
|
+
n = (SIGNED_VALUE)NUM2LONG(v);
|
1142
|
+
#elif SIZEOF_VALUE <= SIZEOF_LONG_LONG
|
1143
|
+
n = (SIGNED_VALUE)NUM2LL(v);
|
1144
|
+
#else
|
1145
|
+
# error SIZEOF_VALUE is too large
|
1146
|
+
#endif
|
941
1147
|
if (n < 0) {
|
942
1148
|
rb_raise(rb_eArgError, "negative precision");
|
943
1149
|
}
|
@@ -979,26 +1185,12 @@ VpCreateRbObject(size_t mx, const char *str, bool raise_exception)
|
|
979
1185
|
return VpNewRbClass(mx, str, rb_cBigDecimal, true, raise_exception);
|
980
1186
|
}
|
981
1187
|
|
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
1188
|
static Real *
|
997
1189
|
VpCopy(Real *pv, Real const* const x)
|
998
1190
|
{
|
999
1191
|
assert(x != NULL);
|
1000
1192
|
|
1001
|
-
pv =
|
1193
|
+
pv = rbd_reallocate_struct(pv, x->MaxPrec);
|
1002
1194
|
pv->MaxPrec = x->MaxPrec;
|
1003
1195
|
pv->Prec = x->Prec;
|
1004
1196
|
pv->exponent = x->exponent;
|
@@ -1119,7 +1311,7 @@ BigDecimal_to_f(VALUE self)
|
|
1119
1311
|
|
1120
1312
|
str = rb_str_new(0, VpNumOfChars(p, "E"));
|
1121
1313
|
buf = RSTRING_PTR(str);
|
1122
|
-
VpToString(p, buf, 0, 0);
|
1314
|
+
VpToString(p, buf, RSTRING_LEN(str), 0, 0);
|
1123
1315
|
errno = 0;
|
1124
1316
|
d = strtod(buf, 0);
|
1125
1317
|
if (errno == ERANGE) {
|
@@ -1276,17 +1468,17 @@ BigDecimal_add(VALUE self, VALUE r)
|
|
1276
1468
|
|
1277
1469
|
mx = GetAddSubPrec(a, b);
|
1278
1470
|
if (mx == (size_t)-1L) {
|
1279
|
-
GUARD_OBJ(c,
|
1280
|
-
|
1471
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, VpBaseFig() + 1));
|
1472
|
+
VpAddSub(c, a, b, 1);
|
1281
1473
|
}
|
1282
1474
|
else {
|
1283
|
-
GUARD_OBJ(c,
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1475
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx * (VpBaseFig() + 1)));
|
1476
|
+
if (!mx) {
|
1477
|
+
VpSetInf(c, VpGetSign(a));
|
1478
|
+
}
|
1479
|
+
else {
|
1480
|
+
VpAddSub(c, a, b, 1);
|
1481
|
+
}
|
1290
1482
|
}
|
1291
1483
|
return VpCheckGetValue(c);
|
1292
1484
|
}
|
@@ -1331,17 +1523,17 @@ BigDecimal_sub(VALUE self, VALUE r)
|
|
1331
1523
|
|
1332
1524
|
mx = GetAddSubPrec(a,b);
|
1333
1525
|
if (mx == (size_t)-1L) {
|
1334
|
-
GUARD_OBJ(c,
|
1335
|
-
|
1526
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, VpBaseFig() + 1));
|
1527
|
+
VpAddSub(c, a, b, -1);
|
1336
1528
|
}
|
1337
1529
|
else {
|
1338
|
-
GUARD_OBJ(c,
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1344
|
-
|
1530
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx *(VpBaseFig() + 1)));
|
1531
|
+
if (!mx) {
|
1532
|
+
VpSetInf(c,VpGetSign(a));
|
1533
|
+
}
|
1534
|
+
else {
|
1535
|
+
VpAddSub(c, a, b, -1);
|
1536
|
+
}
|
1345
1537
|
}
|
1346
1538
|
return VpCheckGetValue(c);
|
1347
1539
|
}
|
@@ -1581,7 +1773,7 @@ BigDecimal_neg(VALUE self)
|
|
1581
1773
|
ENTER(5);
|
1582
1774
|
Real *c, *a;
|
1583
1775
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1584
|
-
GUARD_OBJ(c,
|
1776
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, a->Prec *(VpBaseFig() + 1)));
|
1585
1777
|
VpAsgn(c, a, -1);
|
1586
1778
|
return VpCheckGetValue(c);
|
1587
1779
|
}
|
@@ -1608,7 +1800,7 @@ BigDecimal_mult(VALUE self, VALUE r)
|
|
1608
1800
|
SAVE(b);
|
1609
1801
|
|
1610
1802
|
mx = a->Prec + b->Prec;
|
1611
|
-
GUARD_OBJ(c,
|
1803
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx * (VpBaseFig() + 1)));
|
1612
1804
|
VpMult(c, a, b);
|
1613
1805
|
return VpCheckGetValue(c);
|
1614
1806
|
}
|
@@ -1655,8 +1847,8 @@ BigDecimal_divide(VALUE self, VALUE r, Real **c, Real **res, Real **div)
|
|
1655
1847
|
if (2*BIGDECIMAL_DOUBLE_FIGURES > mx)
|
1656
1848
|
mx = 2*BIGDECIMAL_DOUBLE_FIGURES;
|
1657
1849
|
|
1658
|
-
GUARD_OBJ((*c),
|
1659
|
-
GUARD_OBJ((*res),
|
1850
|
+
GUARD_OBJ((*c), NewZeroWrapNolimit(1, mx + 2*BASE_FIG));
|
1851
|
+
GUARD_OBJ((*res), NewZeroWrapNolimit(1, (mx + 1)*2 + 2*BASE_FIG));
|
1660
1852
|
VpDivd(*c, *res, a, b);
|
1661
1853
|
|
1662
1854
|
return Qnil;
|
@@ -1721,7 +1913,7 @@ BigDecimal_quo(int argc, VALUE *argv, VALUE self)
|
|
1721
1913
|
|
1722
1914
|
argc = rb_scan_args(argc, argv, "11", &value, &digits);
|
1723
1915
|
if (argc > 1) {
|
1724
|
-
n =
|
1916
|
+
n = check_int_precision(digits);
|
1725
1917
|
}
|
1726
1918
|
|
1727
1919
|
if (n > 0) {
|
@@ -1811,12 +2003,12 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
|
|
1811
2003
|
if (2*BIGDECIMAL_DOUBLE_FIGURES > mx)
|
1812
2004
|
mx = 2*BIGDECIMAL_DOUBLE_FIGURES;
|
1813
2005
|
|
1814
|
-
GUARD_OBJ(c,
|
1815
|
-
GUARD_OBJ(res,
|
2006
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx + 2*BASE_FIG));
|
2007
|
+
GUARD_OBJ(res, NewZeroWrapNolimit(1, mx*2 + 2*BASE_FIG));
|
1816
2008
|
VpDivd(c, res, a, b);
|
1817
2009
|
|
1818
2010
|
mx = c->Prec * BASE_FIG;
|
1819
|
-
GUARD_OBJ(d,
|
2011
|
+
GUARD_OBJ(d, NewZeroWrapLimited(1, mx));
|
1820
2012
|
VpActiveRound(d, c, VP_ROUND_DOWN, 0);
|
1821
2013
|
|
1822
2014
|
VpMult(res, d, b);
|
@@ -1824,10 +2016,10 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
|
|
1824
2016
|
|
1825
2017
|
if (!VpIsZero(c) && (VpGetSign(a) * VpGetSign(b) < 0)) {
|
1826
2018
|
/* result adjustment for negative case */
|
1827
|
-
res =
|
2019
|
+
res = rbd_reallocate_struct(res, d->MaxPrec);
|
1828
2020
|
res->MaxPrec = d->MaxPrec;
|
1829
2021
|
VpAddSub(res, d, VpOne(), -1);
|
1830
|
-
GUARD_OBJ(d,
|
2022
|
+
GUARD_OBJ(d, NewZeroWrapLimited(1, GetAddSubPrec(c, b) * 2*BASE_FIG));
|
1831
2023
|
VpAddSub(d, c, b, 1);
|
1832
2024
|
*div = res;
|
1833
2025
|
*mod = d;
|
@@ -1891,17 +2083,17 @@ BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
|
|
1891
2083
|
SAVE(b);
|
1892
2084
|
|
1893
2085
|
mx = (a->MaxPrec + b->MaxPrec) *VpBaseFig();
|
1894
|
-
GUARD_OBJ(c,
|
1895
|
-
GUARD_OBJ(res,
|
1896
|
-
GUARD_OBJ(rr,
|
1897
|
-
GUARD_OBJ(ff,
|
2086
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
|
2087
|
+
GUARD_OBJ(res, NewZeroWrapNolimit(1, (mx+1) * 2 + (VpBaseFig() + 1)));
|
2088
|
+
GUARD_OBJ(rr, NewZeroWrapNolimit(1, (mx+1) * 2 + (VpBaseFig() + 1)));
|
2089
|
+
GUARD_OBJ(ff, NewZeroWrapNolimit(1, (mx+1) * 2 + (VpBaseFig() + 1)));
|
1898
2090
|
|
1899
2091
|
VpDivd(c, res, a, b);
|
1900
2092
|
|
1901
2093
|
mx = c->Prec *(VpBaseFig() + 1);
|
1902
2094
|
|
1903
|
-
GUARD_OBJ(d,
|
1904
|
-
GUARD_OBJ(f,
|
2095
|
+
GUARD_OBJ(d, NewZeroWrapLimited(1, mx));
|
2096
|
+
GUARD_OBJ(f, NewZeroWrapLimited(1, mx));
|
1905
2097
|
|
1906
2098
|
VpActiveRound(d, c, VP_ROUND_DOWN, 0); /* 0: round off */
|
1907
2099
|
|
@@ -1986,7 +2178,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
|
1986
2178
|
}
|
1987
2179
|
|
1988
2180
|
/* div in BigDecimal sense */
|
1989
|
-
ix =
|
2181
|
+
ix = check_int_precision(n);
|
1990
2182
|
if (ix == 0) {
|
1991
2183
|
return BigDecimal_div(self, b);
|
1992
2184
|
}
|
@@ -1997,7 +2189,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
|
1997
2189
|
size_t b_prec = ix;
|
1998
2190
|
size_t pl = VpSetPrecLimit(0);
|
1999
2191
|
|
2000
|
-
GUARD_OBJ(cv,
|
2192
|
+
GUARD_OBJ(cv, NewZeroWrapLimited(1, mx + VpBaseFig()));
|
2001
2193
|
GUARD_OBJ(av, GetVpValue(self, 1));
|
2002
2194
|
/* TODO: I want to refactor this precision control for a float value later
|
2003
2195
|
* by introducing an implicit conversion function instead of
|
@@ -2008,7 +2200,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
|
2008
2200
|
GUARD_OBJ(bv, GetVpValueWithPrec(b, b_prec, 1));
|
2009
2201
|
mx = av->Prec + bv->Prec + 2;
|
2010
2202
|
if (mx <= cv->MaxPrec) mx = cv->MaxPrec + 1;
|
2011
|
-
GUARD_OBJ(res,
|
2203
|
+
GUARD_OBJ(res, NewZeroWrapNolimit(1, (mx * 2 + 2)*VpBaseFig()));
|
2012
2204
|
VpDivd(cv, res, av, bv);
|
2013
2205
|
VpSetPrecLimit(pl);
|
2014
2206
|
VpLeftRound(cv, VpGetRoundMode(), ix);
|
@@ -2091,7 +2283,7 @@ BigDecimal_add2(VALUE self, VALUE b, VALUE n)
|
|
2091
2283
|
{
|
2092
2284
|
ENTER(2);
|
2093
2285
|
Real *cv;
|
2094
|
-
SIGNED_VALUE mx =
|
2286
|
+
SIGNED_VALUE mx = check_int_precision(n);
|
2095
2287
|
if (mx == 0) return BigDecimal_add(self, b);
|
2096
2288
|
else {
|
2097
2289
|
size_t pl = VpSetPrecLimit(0);
|
@@ -2121,7 +2313,7 @@ BigDecimal_sub2(VALUE self, VALUE b, VALUE n)
|
|
2121
2313
|
{
|
2122
2314
|
ENTER(2);
|
2123
2315
|
Real *cv;
|
2124
|
-
SIGNED_VALUE mx =
|
2316
|
+
SIGNED_VALUE mx = check_int_precision(n);
|
2125
2317
|
if (mx == 0) return BigDecimal_sub(self, b);
|
2126
2318
|
else {
|
2127
2319
|
size_t pl = VpSetPrecLimit(0);
|
@@ -2164,7 +2356,7 @@ BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
|
|
2164
2356
|
{
|
2165
2357
|
ENTER(2);
|
2166
2358
|
Real *cv;
|
2167
|
-
SIGNED_VALUE mx =
|
2359
|
+
SIGNED_VALUE mx = check_int_precision(n);
|
2168
2360
|
if (mx == 0) return BigDecimal_mult(self, b);
|
2169
2361
|
else {
|
2170
2362
|
size_t pl = VpSetPrecLimit(0);
|
@@ -2196,7 +2388,7 @@ BigDecimal_abs(VALUE self)
|
|
2196
2388
|
|
2197
2389
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
2198
2390
|
mx = a->Prec *(VpBaseFig() + 1);
|
2199
|
-
GUARD_OBJ(c,
|
2391
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
|
2200
2392
|
VpAsgn(c, a, 1);
|
2201
2393
|
VpChangeSign(c, 1);
|
2202
2394
|
return VpCheckGetValue(c);
|
@@ -2219,9 +2411,10 @@ BigDecimal_sqrt(VALUE self, VALUE nFig)
|
|
2219
2411
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
2220
2412
|
mx = a->Prec * (VpBaseFig() + 1);
|
2221
2413
|
|
2222
|
-
n =
|
2414
|
+
n = check_int_precision(nFig);
|
2415
|
+
n += VpDblFig() + VpBaseFig();
|
2223
2416
|
if (mx <= n) mx = n;
|
2224
|
-
GUARD_OBJ(c,
|
2417
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
|
2225
2418
|
VpSqrt(c, a);
|
2226
2419
|
return VpCheckGetValue(c);
|
2227
2420
|
}
|
@@ -2237,7 +2430,7 @@ BigDecimal_fix(VALUE self)
|
|
2237
2430
|
|
2238
2431
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
2239
2432
|
mx = a->Prec *(VpBaseFig() + 1);
|
2240
|
-
GUARD_OBJ(c,
|
2433
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
|
2241
2434
|
VpActiveRound(c, a, VP_ROUND_DOWN, 0); /* 0: round off */
|
2242
2435
|
return VpCheckGetValue(c);
|
2243
2436
|
}
|
@@ -2310,7 +2503,7 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
|
|
2310
2503
|
pl = VpSetPrecLimit(0);
|
2311
2504
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
2312
2505
|
mx = a->Prec * (VpBaseFig() + 1);
|
2313
|
-
GUARD_OBJ(c,
|
2506
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
|
2314
2507
|
VpSetPrecLimit(pl);
|
2315
2508
|
VpActiveRound(c, a, sw, iLoc);
|
2316
2509
|
if (round_to_int) {
|
@@ -2356,7 +2549,7 @@ BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
|
|
2356
2549
|
|
2357
2550
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
2358
2551
|
mx = a->Prec * (VpBaseFig() + 1);
|
2359
|
-
GUARD_OBJ(c,
|
2552
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
|
2360
2553
|
VpSetPrecLimit(pl);
|
2361
2554
|
VpActiveRound(c, a, VP_ROUND_DOWN, iLoc); /* 0: truncate */
|
2362
2555
|
if (argc == 0) {
|
@@ -2376,7 +2569,7 @@ BigDecimal_frac(VALUE self)
|
|
2376
2569
|
|
2377
2570
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
2378
2571
|
mx = a->Prec * (VpBaseFig() + 1);
|
2379
|
-
GUARD_OBJ(c,
|
2572
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
|
2380
2573
|
VpFrac(c, a);
|
2381
2574
|
return VpCheckGetValue(c);
|
2382
2575
|
}
|
@@ -2416,7 +2609,7 @@ BigDecimal_floor(int argc, VALUE *argv, VALUE self)
|
|
2416
2609
|
|
2417
2610
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
2418
2611
|
mx = a->Prec * (VpBaseFig() + 1);
|
2419
|
-
GUARD_OBJ(c,
|
2612
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
|
2420
2613
|
VpSetPrecLimit(pl);
|
2421
2614
|
VpActiveRound(c, a, VP_ROUND_FLOOR, iLoc);
|
2422
2615
|
#ifdef BIGDECIMAL_DEBUG
|
@@ -2462,7 +2655,7 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
|
|
2462
2655
|
|
2463
2656
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
2464
2657
|
mx = a->Prec * (VpBaseFig() + 1);
|
2465
|
-
GUARD_OBJ(c,
|
2658
|
+
GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
|
2466
2659
|
VpSetPrecLimit(pl);
|
2467
2660
|
VpActiveRound(c, a, VP_ROUND_CEIL, iLoc);
|
2468
2661
|
if (argc == 0) {
|
@@ -2566,10 +2759,10 @@ BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
|
|
2566
2759
|
psz = RSTRING_PTR(str);
|
2567
2760
|
|
2568
2761
|
if (fmt) {
|
2569
|
-
VpToFString(vp, psz, mc, fPlus);
|
2762
|
+
VpToFString(vp, psz, RSTRING_LEN(str), mc, fPlus);
|
2570
2763
|
}
|
2571
2764
|
else {
|
2572
|
-
VpToString (vp, psz, mc, fPlus);
|
2765
|
+
VpToString (vp, psz, RSTRING_LEN(str), mc, fPlus);
|
2573
2766
|
}
|
2574
2767
|
rb_str_resize(str, strlen(psz));
|
2575
2768
|
return str;
|
@@ -2611,7 +2804,7 @@ BigDecimal_split(VALUE self)
|
|
2611
2804
|
GUARD_OBJ(vp, GetVpValue(self, 1));
|
2612
2805
|
str = rb_str_new(0, VpNumOfChars(vp, "E"));
|
2613
2806
|
psz1 = RSTRING_PTR(str);
|
2614
|
-
VpSzMantissa(vp, psz1);
|
2807
|
+
VpSzMantissa(vp, psz1, RSTRING_LEN(str));
|
2615
2808
|
s = 1;
|
2616
2809
|
if(psz1[0] == '-') {
|
2617
2810
|
size_t len = strlen(psz1 + 1);
|
@@ -2660,7 +2853,7 @@ BigDecimal_inspect(VALUE self)
|
|
2660
2853
|
nc = VpNumOfChars(vp, "E");
|
2661
2854
|
|
2662
2855
|
str = rb_str_new(0, nc);
|
2663
|
-
VpToString(vp, RSTRING_PTR(str), 0, 0);
|
2856
|
+
VpToString(vp, RSTRING_PTR(str), RSTRING_LEN(str), 0, 0);
|
2664
2857
|
rb_str_resize(str, strlen(RSTRING_PTR(str)));
|
2665
2858
|
return str;
|
2666
2859
|
}
|
@@ -2770,7 +2963,7 @@ bigdecimal_power_by_bigdecimal(Real const* x, Real const* exp, ssize_t const n)
|
|
2770
2963
|
volatile VALUE obj = exp->obj;
|
2771
2964
|
|
2772
2965
|
if (VpIsZero(exp)) {
|
2773
|
-
return VpCheckGetValue(
|
2966
|
+
return VpCheckGetValue(NewOneWrapLimited(1, n));
|
2774
2967
|
}
|
2775
2968
|
|
2776
2969
|
log_x = BigMath_log(x->obj, SSIZET2NUM(n+1));
|
@@ -2808,9 +3001,9 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2808
3001
|
n = NIL_P(prec) ? (ssize_t)(x->Prec*VpBaseFig()) : NUM2SSIZET(prec);
|
2809
3002
|
|
2810
3003
|
if (VpIsNaN(x)) {
|
2811
|
-
y =
|
2812
|
-
|
2813
|
-
|
3004
|
+
y = NewZeroWrapLimited(1, n);
|
3005
|
+
VpSetNaN(y);
|
3006
|
+
RB_GC_GUARD(y->obj);
|
2814
3007
|
return VpCheckGetValue(y);
|
2815
3008
|
}
|
2816
3009
|
|
@@ -2879,136 +3072,126 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2879
3072
|
}
|
2880
3073
|
|
2881
3074
|
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
|
-
|
3075
|
+
if (is_negative(vexp)) {
|
3076
|
+
y = NewZeroWrapNolimit(1, n);
|
3077
|
+
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
3078
|
+
if (is_integer(vexp)) {
|
3079
|
+
if (is_even(vexp)) {
|
3080
|
+
/* (-0) ** (-even_integer) -> Infinity */
|
3081
|
+
VpSetPosInf(y);
|
3082
|
+
}
|
3083
|
+
else {
|
3084
|
+
/* (-0) ** (-odd_integer) -> -Infinity */
|
3085
|
+
VpSetNegInf(y);
|
3086
|
+
}
|
3087
|
+
}
|
3088
|
+
else {
|
3089
|
+
/* (-0) ** (-non_integer) -> Infinity */
|
3090
|
+
VpSetPosInf(y);
|
3091
|
+
}
|
3092
|
+
}
|
3093
|
+
else {
|
3094
|
+
/* (+0) ** (-num) -> Infinity */
|
3095
|
+
VpSetPosInf(y);
|
3096
|
+
}
|
3097
|
+
RB_GC_GUARD(y->obj);
|
2905
3098
|
return VpCheckGetValue(y);
|
2906
|
-
|
2907
|
-
|
2908
|
-
return VpCheckGetValue(
|
2909
|
-
|
2910
|
-
|
2911
|
-
return VpCheckGetValue(
|
2912
|
-
|
3099
|
+
}
|
3100
|
+
else if (is_zero(vexp)) {
|
3101
|
+
return VpCheckGetValue(NewOneWrapLimited(1, n));
|
3102
|
+
}
|
3103
|
+
else {
|
3104
|
+
return VpCheckGetValue(NewZeroWrapLimited(1, n));
|
3105
|
+
}
|
2913
3106
|
}
|
2914
3107
|
|
2915
3108
|
if (is_zero(vexp)) {
|
2916
|
-
return VpCheckGetValue(
|
3109
|
+
return VpCheckGetValue(NewOneWrapLimited(1, n));
|
2917
3110
|
}
|
2918
3111
|
else if (is_one(vexp)) {
|
2919
|
-
|
3112
|
+
return self;
|
2920
3113
|
}
|
2921
3114
|
|
2922
3115
|
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
|
-
|
3116
|
+
if (is_negative(vexp)) {
|
3117
|
+
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
3118
|
+
if (is_integer(vexp)) {
|
3119
|
+
if (is_even(vexp)) {
|
3120
|
+
/* (-Infinity) ** (-even_integer) -> +0 */
|
3121
|
+
return VpCheckGetValue(NewZeroWrapLimited(1, n));
|
3122
|
+
}
|
3123
|
+
else {
|
3124
|
+
/* (-Infinity) ** (-odd_integer) -> -0 */
|
3125
|
+
return VpCheckGetValue(NewZeroWrapLimited(-1, n));
|
3126
|
+
}
|
3127
|
+
}
|
3128
|
+
else {
|
3129
|
+
/* (-Infinity) ** (-non_integer) -> -0 */
|
3130
|
+
return VpCheckGetValue(NewZeroWrapLimited(-1, n));
|
3131
|
+
}
|
3132
|
+
}
|
3133
|
+
else {
|
3134
|
+
return VpCheckGetValue(NewZeroWrapLimited(1, n));
|
3135
|
+
}
|
3136
|
+
}
|
3137
|
+
else {
|
3138
|
+
y = NewZeroWrapLimited(1, n);
|
3139
|
+
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
3140
|
+
if (is_integer(vexp)) {
|
3141
|
+
if (is_even(vexp)) {
|
3142
|
+
VpSetPosInf(y);
|
3143
|
+
}
|
3144
|
+
else {
|
3145
|
+
VpSetNegInf(y);
|
3146
|
+
}
|
3147
|
+
}
|
3148
|
+
else {
|
3149
|
+
/* TODO: support complex */
|
3150
|
+
rb_raise(rb_eMathDomainError,
|
3151
|
+
"a non-integral exponent for a negative base");
|
3152
|
+
}
|
3153
|
+
}
|
3154
|
+
else {
|
3155
|
+
VpSetPosInf(y);
|
3156
|
+
}
|
2964
3157
|
return VpCheckGetValue(y);
|
2965
|
-
|
3158
|
+
}
|
2966
3159
|
}
|
2967
3160
|
|
2968
3161
|
if (exp != NULL) {
|
2969
|
-
|
3162
|
+
return bigdecimal_power_by_bigdecimal(x, exp, n);
|
2970
3163
|
}
|
2971
3164
|
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
|
-
}
|
3165
|
+
VALUE abs_value = BigDecimal_abs(self);
|
3166
|
+
if (is_one(abs_value)) {
|
3167
|
+
return VpCheckGetValue(NewOneWrapLimited(1, n));
|
3168
|
+
}
|
3169
|
+
else if (RTEST(rb_funcall(abs_value, '<', 1, INT2FIX(1)))) {
|
3170
|
+
if (is_negative(vexp)) {
|
3171
|
+
y = NewZeroWrapLimited(1, n);
|
3172
|
+
VpSetInf(y, (is_even(vexp) ? 1 : -1) * VpGetSign(x));
|
2985
3173
|
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
|
-
}
|
3174
|
+
}
|
3175
|
+
else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
|
3176
|
+
return VpCheckGetValue(NewZeroWrapLimited(-1, n));
|
3177
|
+
}
|
3178
|
+
else {
|
3179
|
+
return VpCheckGetValue(NewZeroWrapLimited(1, n));
|
3180
|
+
}
|
3181
|
+
}
|
3182
|
+
else {
|
3183
|
+
if (is_positive(vexp)) {
|
3184
|
+
y = NewZeroWrapLimited(1, n);
|
3185
|
+
VpSetInf(y, (is_even(vexp) ? 1 : -1) * VpGetSign(x));
|
3003
3186
|
return VpCheckGetValue(y);
|
3004
|
-
|
3005
|
-
|
3006
|
-
return VpCheckGetValue(
|
3007
|
-
|
3008
|
-
|
3009
|
-
return VpCheckGetValue(
|
3010
|
-
|
3011
|
-
|
3187
|
+
}
|
3188
|
+
else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
|
3189
|
+
return VpCheckGetValue(NewZeroWrapLimited(-1, n));
|
3190
|
+
}
|
3191
|
+
else {
|
3192
|
+
return VpCheckGetValue(NewZeroWrapLimited(1, n));
|
3193
|
+
}
|
3194
|
+
}
|
3012
3195
|
}
|
3013
3196
|
|
3014
3197
|
int_exp = FIX2LONG(vexp);
|
@@ -3017,15 +3200,15 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
3017
3200
|
if (ma == 0) ma = 1;
|
3018
3201
|
|
3019
3202
|
if (VpIsDef(x)) {
|
3020
|
-
|
3021
|
-
GUARD_OBJ(y,
|
3203
|
+
mp = x->Prec * (VpBaseFig() + 1);
|
3204
|
+
GUARD_OBJ(y, NewZeroWrapLimited(1, mp * (ma + 1)));
|
3022
3205
|
}
|
3023
3206
|
else {
|
3024
|
-
GUARD_OBJ(y,
|
3207
|
+
GUARD_OBJ(y, NewZeroWrapLimited(1, 1));
|
3025
3208
|
}
|
3026
3209
|
VpPowerByInt(y, x, int_exp);
|
3027
3210
|
if (!NIL_P(prec) && VpIsDef(y)) {
|
3028
|
-
|
3211
|
+
VpMidRound(y, VpGetRoundMode(), n);
|
3029
3212
|
}
|
3030
3213
|
return VpCheckGetValue(y);
|
3031
3214
|
}
|
@@ -3114,7 +3297,7 @@ rb_uint64_convert_to_BigDecimal(uint64_t uval, RB_UNUSED_VAR(size_t digs), int r
|
|
3114
3297
|
|
3115
3298
|
Real *vp;
|
3116
3299
|
if (uval == 0) {
|
3117
|
-
vp =
|
3300
|
+
vp = rbd_allocate_struct(1);
|
3118
3301
|
vp->MaxPrec = 1;
|
3119
3302
|
vp->Prec = 1;
|
3120
3303
|
vp->exponent = 1;
|
@@ -3122,7 +3305,7 @@ rb_uint64_convert_to_BigDecimal(uint64_t uval, RB_UNUSED_VAR(size_t digs), int r
|
|
3122
3305
|
vp->frac[0] = 0;
|
3123
3306
|
}
|
3124
3307
|
else if (uval < BASE) {
|
3125
|
-
vp =
|
3308
|
+
vp = rbd_allocate_struct(1);
|
3126
3309
|
vp->MaxPrec = 1;
|
3127
3310
|
vp->Prec = 1;
|
3128
3311
|
vp->exponent = 1;
|
@@ -3148,7 +3331,7 @@ rb_uint64_convert_to_BigDecimal(uint64_t uval, RB_UNUSED_VAR(size_t digs), int r
|
|
3148
3331
|
}
|
3149
3332
|
|
3150
3333
|
const size_t exp = len + ntz;
|
3151
|
-
vp =
|
3334
|
+
vp = rbd_allocate_struct(len);
|
3152
3335
|
vp->MaxPrec = len;
|
3153
3336
|
vp->Prec = len;
|
3154
3337
|
vp->exponent = exp;
|
@@ -3281,7 +3464,7 @@ rb_float_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
|
|
3281
3464
|
|
3282
3465
|
VALUE inum;
|
3283
3466
|
size_t RB_UNUSED_VAR(prec) = 0;
|
3284
|
-
|
3467
|
+
SIGNED_VALUE exp = 0;
|
3285
3468
|
if (decpt > 0) {
|
3286
3469
|
if (decpt < len10) {
|
3287
3470
|
/*
|
@@ -3493,12 +3676,15 @@ rb_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
|
|
3493
3676
|
* BigDecimal(value, exception: true) -> bigdecimal
|
3494
3677
|
* BigDecimal(value, ndigits, exception: true) -> bigdecimal
|
3495
3678
|
*
|
3496
|
-
*
|
3497
|
-
*
|
3679
|
+
* Returns the \BigDecimal converted from +value+
|
3680
|
+
* with a precision of +ndigits+ decimal digits.
|
3681
|
+
*
|
3682
|
+
* When +ndigits+ is less than the number of significant digits
|
3683
|
+
* in the value, the result is rounded to that number of digits,
|
3684
|
+
* according to the current rounding mode; see BigDecimal.mode.
|
3498
3685
|
*
|
3499
|
-
*
|
3500
|
-
*
|
3501
|
-
* according to the current rounding mode; see BigDecimal.mode.
|
3686
|
+
* When +ndigits+ is 0, the number of digits to correctly represent a float number
|
3687
|
+
* is determined automatically.
|
3502
3688
|
*
|
3503
3689
|
* Returns +value+ converted to a \BigDecimal, depending on the type of +value+:
|
3504
3690
|
*
|
@@ -3606,8 +3792,10 @@ BigDecimal_limit(int argc, VALUE *argv, VALUE self)
|
|
3606
3792
|
|
3607
3793
|
/* Returns the sign of the value.
|
3608
3794
|
*
|
3609
|
-
* Returns a positive value if > 0, a negative value if < 0
|
3610
|
-
*
|
3795
|
+
* Returns a positive value if > 0, a negative value if < 0.
|
3796
|
+
* It behaves the same with zeros -
|
3797
|
+
* it returns a positive value for a positive zero (BigDecimal('0')) and
|
3798
|
+
* a negative value for a negative zero (BigDecimal('-0')).
|
3611
3799
|
*
|
3612
3800
|
* The specific value returned indicates the type and sign of the BigDecimal,
|
3613
3801
|
* as follows:
|
@@ -3771,18 +3959,16 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
|
|
3771
3959
|
return VpCheckGetValue(GetVpValueWithPrec(INT2FIX(0), prec, 1));
|
3772
3960
|
}
|
3773
3961
|
else {
|
3774
|
-
Real* vy;
|
3775
|
-
vy = VpCreateRbObject(prec, "#0", true);
|
3962
|
+
Real* vy = NewZeroWrapNolimit(1, prec);
|
3776
3963
|
VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
|
3777
3964
|
RB_GC_GUARD(vy->obj);
|
3778
3965
|
return VpCheckGetValue(vy);
|
3779
3966
|
}
|
3780
3967
|
}
|
3781
3968
|
else if (nan) {
|
3782
|
-
|
3783
|
-
vy
|
3784
|
-
|
3785
|
-
RB_GC_GUARD(vy->obj);
|
3969
|
+
Real* vy = NewZeroWrapNolimit(1, prec);
|
3970
|
+
VpSetNaN(vy);
|
3971
|
+
RB_GC_GUARD(vy->obj);
|
3786
3972
|
return VpCheckGetValue(vy);
|
3787
3973
|
}
|
3788
3974
|
else if (vx == NULL) {
|
@@ -3800,7 +3986,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
|
|
3800
3986
|
VpSetSign(vx, 1);
|
3801
3987
|
}
|
3802
3988
|
|
3803
|
-
one = VpCheckGetValue(
|
3989
|
+
one = VpCheckGetValue(NewOneWrapLimited(1, 1));
|
3804
3990
|
y = one;
|
3805
3991
|
d = y;
|
3806
3992
|
i = 1;
|
@@ -3927,15 +4113,13 @@ get_vp_value:
|
|
3927
4113
|
break;
|
3928
4114
|
}
|
3929
4115
|
if (infinite && !negative) {
|
3930
|
-
|
3931
|
-
vy = VpCreateRbObject(prec, "#0", true);
|
4116
|
+
Real *vy = NewZeroWrapNolimit(1, prec);
|
3932
4117
|
RB_GC_GUARD(vy->obj);
|
3933
4118
|
VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
|
3934
4119
|
return VpCheckGetValue(vy);
|
3935
4120
|
}
|
3936
4121
|
else if (nan) {
|
3937
|
-
Real* vy;
|
3938
|
-
vy = VpCreateRbObject(prec, "#0", true);
|
4122
|
+
Real* vy = NewZeroWrapNolimit(1, prec);
|
3939
4123
|
RB_GC_GUARD(vy->obj);
|
3940
4124
|
VpSetNaN(vy);
|
3941
4125
|
return VpCheckGetValue(vy);
|
@@ -3949,7 +4133,7 @@ get_vp_value:
|
|
3949
4133
|
}
|
3950
4134
|
x = VpCheckGetValue(vx);
|
3951
4135
|
|
3952
|
-
RB_GC_GUARD(one) = VpCheckGetValue(
|
4136
|
+
RB_GC_GUARD(one) = VpCheckGetValue(NewOneWrapLimited(1, 1));
|
3953
4137
|
RB_GC_GUARD(two) = VpCheckGetValue(VpCreateRbObject(1, "2", true));
|
3954
4138
|
|
3955
4139
|
n = prec + BIGDECIMAL_DOUBLE_FIGURES;
|
@@ -4414,20 +4598,31 @@ Init_bigdecimal(void)
|
|
4414
4598
|
rb_define_singleton_method(rb_mBigMath, "exp", BigMath_s_exp, 2);
|
4415
4599
|
rb_define_singleton_method(rb_mBigMath, "log", BigMath_s_log, 2);
|
4416
4600
|
|
4417
|
-
|
4418
|
-
|
4419
|
-
|
4420
|
-
|
4421
|
-
|
4422
|
-
|
4423
|
-
|
4424
|
-
|
4425
|
-
|
4426
|
-
|
4427
|
-
|
4601
|
+
#define ROUNDING_MODE(i, name, value) \
|
4602
|
+
id_##name = rb_intern_const(#name); \
|
4603
|
+
rbd_rounding_modes[i].id = id_##name; \
|
4604
|
+
rbd_rounding_modes[i].mode = value;
|
4605
|
+
|
4606
|
+
ROUNDING_MODE(0, up, RBD_ROUND_UP);
|
4607
|
+
ROUNDING_MODE(1, down, RBD_ROUND_DOWN);
|
4608
|
+
ROUNDING_MODE(2, half_up, RBD_ROUND_HALF_UP);
|
4609
|
+
ROUNDING_MODE(3, half_down, RBD_ROUND_HALF_DOWN);
|
4610
|
+
ROUNDING_MODE(4, ceil, RBD_ROUND_CEIL);
|
4611
|
+
ROUNDING_MODE(5, floor, RBD_ROUND_FLOOR);
|
4612
|
+
ROUNDING_MODE(6, half_even, RBD_ROUND_HALF_EVEN);
|
4613
|
+
|
4614
|
+
ROUNDING_MODE(7, default, RBD_ROUND_DEFAULT);
|
4615
|
+
ROUNDING_MODE(8, truncate, RBD_ROUND_TRUNCATE);
|
4616
|
+
ROUNDING_MODE(9, banker, RBD_ROUND_BANKER);
|
4617
|
+
ROUNDING_MODE(10, ceiling, RBD_ROUND_CEILING);
|
4618
|
+
|
4619
|
+
#undef ROUNDING_MODE
|
4620
|
+
|
4428
4621
|
id_to_r = rb_intern_const("to_r");
|
4429
4622
|
id_eq = rb_intern_const("==");
|
4430
4623
|
id_half = rb_intern_const("half");
|
4624
|
+
|
4625
|
+
(void)VPrint; /* suppress unused warning */
|
4431
4626
|
}
|
4432
4627
|
|
4433
4628
|
/*
|
@@ -4447,7 +4642,7 @@ static int gfCheckVal = 1; /* Value checking flag in VpNmlz() */
|
|
4447
4642
|
#endif /* BIGDECIMAL_DEBUG */
|
4448
4643
|
|
4449
4644
|
static Real *VpConstOne; /* constant 1.0 */
|
4450
|
-
static Real *
|
4645
|
+
static Real *VpConstPt5; /* constant 0.5 */
|
4451
4646
|
#define maxnr 100UL /* Maximum iterations for calculating sqrt. */
|
4452
4647
|
/* used in VpSqrt() */
|
4453
4648
|
|
@@ -4478,42 +4673,6 @@ static int VpRdup(Real *m, size_t ind_m);
|
|
4478
4673
|
static int gnAlloc = 0; /* Memory allocation counter */
|
4479
4674
|
#endif /* BIGDECIMAL_DEBUG */
|
4480
4675
|
|
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
4676
|
/*
|
4518
4677
|
* EXCEPTION Handling.
|
4519
4678
|
*/
|
@@ -4902,9 +5061,13 @@ VpInit(DECDIG BaseVal)
|
|
4902
5061
|
/* Setup +/- Inf NaN -0 */
|
4903
5062
|
VpGetDoubleNegZero();
|
4904
5063
|
|
4905
|
-
/*
|
4906
|
-
VpConstOne =
|
4907
|
-
|
5064
|
+
/* Const 1.0 */
|
5065
|
+
VpConstOne = NewOneNolimit(1, 1);
|
5066
|
+
|
5067
|
+
/* Const 0.5 */
|
5068
|
+
VpConstPt5 = NewOneNolimit(1, 1);
|
5069
|
+
VpConstPt5->exponent = 0;
|
5070
|
+
VpConstPt5->frac[0] = 5*BASE1;
|
4908
5071
|
|
4909
5072
|
#ifdef BIGDECIMAL_DEBUG
|
4910
5073
|
gnAlloc = 0;
|
@@ -4993,7 +5156,7 @@ bigdecimal_parse_special_string(const char *str)
|
|
4993
5156
|
p = str + table[i].len;
|
4994
5157
|
while (*p && ISSPACE(*p)) ++p;
|
4995
5158
|
if (*p == '\0') {
|
4996
|
-
Real *vp =
|
5159
|
+
Real *vp = rbd_allocate_struct(1);
|
4997
5160
|
vp->MaxPrec = 1;
|
4998
5161
|
switch (table[i].sign) {
|
4999
5162
|
default:
|
@@ -5017,11 +5180,11 @@ bigdecimal_parse_special_string(const char *str)
|
|
5017
5180
|
/*
|
5018
5181
|
* Allocates variable.
|
5019
5182
|
* [Input]
|
5020
|
-
* mx ...
|
5021
|
-
*
|
5022
|
-
* szVal ... value assigned(char). If szVal==NULL,then zero is assumed.
|
5023
|
-
*
|
5024
|
-
*
|
5183
|
+
* mx ... The number of decimal digits to be allocated, if zero then mx is determined by szVal.
|
5184
|
+
* The mx will be the number of significant digits can to be stored.
|
5185
|
+
* szVal ... The value assigned(char). If szVal==NULL, then zero is assumed.
|
5186
|
+
* If szVal[0]=='#' then MaxPrec is not affected by the precision limit
|
5187
|
+
* so that the full precision specified by szVal is allocated.
|
5025
5188
|
*
|
5026
5189
|
* [Returns]
|
5027
5190
|
* Pointer to the newly allocated variable, or
|
@@ -5032,48 +5195,40 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
|
|
5032
5195
|
{
|
5033
5196
|
const char *orig_szVal = szVal;
|
5034
5197
|
size_t i, j, ni, ipf, nf, ipe, ne, dot_seen, exp_seen, nalloc;
|
5198
|
+
size_t len;
|
5035
5199
|
char v, *psz;
|
5036
5200
|
int sign=1;
|
5037
5201
|
Real *vp = NULL;
|
5038
|
-
size_t mf = VpGetPrecLimit();
|
5039
5202
|
VALUE buf;
|
5040
5203
|
|
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 {
|
5204
|
+
if (szVal == NULL) {
|
5062
5205
|
return_zero:
|
5063
5206
|
/* necessary to be able to store */
|
5064
5207
|
/* at least mx digits. */
|
5065
5208
|
/* szVal==NULL ==> allocate zero value. */
|
5066
|
-
vp =
|
5067
|
-
vp->MaxPrec = mx;
|
5209
|
+
vp = rbd_allocate_struct(mx);
|
5210
|
+
vp->MaxPrec = rbd_calculate_internal_digits(mx, false); /* Must false */
|
5068
5211
|
VpSetZero(vp, 1); /* initialize vp to zero. */
|
5069
5212
|
return vp;
|
5070
5213
|
}
|
5071
5214
|
|
5215
|
+
/* Skipping leading spaces */
|
5216
|
+
while (ISSPACE(*szVal)) szVal++;
|
5217
|
+
|
5072
5218
|
/* Check on Inf & NaN */
|
5073
5219
|
if ((vp = bigdecimal_parse_special_string(szVal)) != NULL) {
|
5074
5220
|
return vp;
|
5075
5221
|
}
|
5076
5222
|
|
5223
|
+
/* Processing the leading one `#` */
|
5224
|
+
if (*szVal != '#') {
|
5225
|
+
len = rbd_calculate_internal_digits(mx, true);
|
5226
|
+
}
|
5227
|
+
else {
|
5228
|
+
len = rbd_calculate_internal_digits(mx, false);
|
5229
|
+
++szVal;
|
5230
|
+
}
|
5231
|
+
|
5077
5232
|
/* Scanning digits */
|
5078
5233
|
|
5079
5234
|
/* A buffer for keeping scanned digits */
|
@@ -5235,11 +5390,11 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
|
|
5235
5390
|
|
5236
5391
|
nalloc = (ni + nf + BASE_FIG - 1) / BASE_FIG + 1; /* set effective allocation */
|
5237
5392
|
/* units for szVal[] */
|
5238
|
-
if (
|
5239
|
-
nalloc = Max(nalloc,
|
5240
|
-
|
5241
|
-
vp =
|
5242
|
-
vp->MaxPrec =
|
5393
|
+
if (len == 0) len = 1;
|
5394
|
+
nalloc = Max(nalloc, len);
|
5395
|
+
len = nalloc;
|
5396
|
+
vp = rbd_allocate_struct(len);
|
5397
|
+
vp->MaxPrec = len; /* set max precision */
|
5243
5398
|
VpSetZero(vp, sign);
|
5244
5399
|
VpCtoV(vp, psz, ni, psz + ipf, nf, psz + ipe, ne);
|
5245
5400
|
rb_str_resize(buf, 0);
|
@@ -5804,7 +5959,7 @@ VpMult(Real *c, Real *a, Real *b)
|
|
5804
5959
|
|
5805
5960
|
if (MxIndC < MxIndAB) { /* The Max. prec. of c < Prec(a)+Prec(b) */
|
5806
5961
|
w = c;
|
5807
|
-
|
5962
|
+
c = NewZeroNolimit(1, (size_t)((MxIndAB + 1) * BASE_FIG));
|
5808
5963
|
MxIndC = MxIndAB;
|
5809
5964
|
}
|
5810
5965
|
|
@@ -5812,8 +5967,8 @@ VpMult(Real *c, Real *a, Real *b)
|
|
5812
5967
|
|
5813
5968
|
c->exponent = a->exponent; /* set exponent */
|
5814
5969
|
if (!AddExponent(c, b->exponent)) {
|
5815
|
-
|
5816
|
-
|
5970
|
+
if (w) rbd_free_struct(c);
|
5971
|
+
return 0;
|
5817
5972
|
}
|
5818
5973
|
VpSetSign(c, VpGetSign(a) * VpGetSign(b)); /* set sign */
|
5819
5974
|
carry = 0;
|
@@ -5863,10 +6018,10 @@ VpMult(Real *c, Real *a, Real *b)
|
|
5863
6018
|
}
|
5864
6019
|
}
|
5865
6020
|
if (w != NULL) { /* free work variable */
|
5866
|
-
|
5867
|
-
|
5868
|
-
|
5869
|
-
|
6021
|
+
VpNmlz(c);
|
6022
|
+
VpAsgn(w, c, 1);
|
6023
|
+
rbd_free_struct(c);
|
6024
|
+
c = w;
|
5870
6025
|
}
|
5871
6026
|
else {
|
5872
6027
|
VpLimitRound(c,0);
|
@@ -6235,7 +6390,6 @@ Exit:
|
|
6235
6390
|
* Note: % must not appear more than once
|
6236
6391
|
* a ... VP variable to be printed
|
6237
6392
|
*/
|
6238
|
-
#ifdef BIGDECIMAL_ENABLE_VPRINT
|
6239
6393
|
static int
|
6240
6394
|
VPrint(FILE *fp, const char *cntl_chr, Real *a)
|
6241
6395
|
{
|
@@ -6248,95 +6402,94 @@ VPrint(FILE *fp, const char *cntl_chr, Real *a)
|
|
6248
6402
|
/* nc : number of characters printed */
|
6249
6403
|
ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
|
6250
6404
|
while (*(cntl_chr + j)) {
|
6251
|
-
|
6252
|
-
|
6253
|
-
|
6254
|
-
|
6255
|
-
|
6256
|
-
|
6257
|
-
|
6258
|
-
|
6259
|
-
|
6260
|
-
|
6261
|
-
|
6262
|
-
|
6263
|
-
|
6264
|
-
|
6265
|
-
|
6266
|
-
|
6267
|
-
|
6268
|
-
|
6269
|
-
|
6270
|
-
|
6271
|
-
|
6272
|
-
|
6273
|
-
|
6405
|
+
if (*(cntl_chr + j) == '%' && *(cntl_chr + j + 1) != '%') {
|
6406
|
+
nc = 0;
|
6407
|
+
if (VpIsNaN(a)) {
|
6408
|
+
fprintf(fp, SZ_NaN);
|
6409
|
+
nc += 8;
|
6410
|
+
}
|
6411
|
+
else if (VpIsPosInf(a)) {
|
6412
|
+
fprintf(fp, SZ_INF);
|
6413
|
+
nc += 8;
|
6414
|
+
}
|
6415
|
+
else if (VpIsNegInf(a)) {
|
6416
|
+
fprintf(fp, SZ_NINF);
|
6417
|
+
nc += 9;
|
6418
|
+
}
|
6419
|
+
else if (!VpIsZero(a)) {
|
6420
|
+
if (BIGDECIMAL_NEGATIVE_P(a)) {
|
6421
|
+
fprintf(fp, "-");
|
6422
|
+
++nc;
|
6423
|
+
}
|
6424
|
+
nc += fprintf(fp, "0.");
|
6425
|
+
switch (*(cntl_chr + j + 1)) {
|
6426
|
+
default:
|
6427
|
+
break;
|
6274
6428
|
|
6275
|
-
|
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
|
-
|
6429
|
+
case '0': case 'z':
|
6430
|
+
ZeroSup = 0;
|
6431
|
+
++j;
|
6432
|
+
sep = cntl_chr[j] == 'z' ? BIGDECIMAL_COMPONENT_FIGURES : 10;
|
6433
|
+
break;
|
6434
|
+
}
|
6435
|
+
for (i = 0; i < a->Prec; ++i) {
|
6436
|
+
m = BASE1;
|
6437
|
+
e = a->frac[i];
|
6438
|
+
while (m) {
|
6439
|
+
nn = e / m;
|
6440
|
+
if (!ZeroSup || nn) {
|
6441
|
+
nc += fprintf(fp, "%lu", (unsigned long)nn); /* The leading zero(s) */
|
6442
|
+
/* as 0.00xx will not */
|
6443
|
+
/* be printed. */
|
6444
|
+
++nd;
|
6445
|
+
ZeroSup = 0; /* Set to print succeeding zeros */
|
6446
|
+
}
|
6447
|
+
if (nd >= sep) { /* print ' ' after every 10 digits */
|
6448
|
+
nd = 0;
|
6449
|
+
nc += fprintf(fp, " ");
|
6450
|
+
}
|
6451
|
+
e = e - nn * m;
|
6452
|
+
m /= 10;
|
6453
|
+
}
|
6454
|
+
}
|
6455
|
+
nc += fprintf(fp, "E%"PRIdSIZE, VpExponent10(a));
|
6456
|
+
nc += fprintf(fp, " (%"PRIdVALUE", %lu, %lu)", a->exponent, a->Prec, a->MaxPrec);
|
6457
|
+
}
|
6458
|
+
else {
|
6459
|
+
nc += fprintf(fp, "0.0");
|
6460
|
+
}
|
6461
|
+
}
|
6462
|
+
else {
|
6463
|
+
++nc;
|
6464
|
+
if (*(cntl_chr + j) == '\\') {
|
6465
|
+
switch (*(cntl_chr + j + 1)) {
|
6466
|
+
case 'n':
|
6467
|
+
fprintf(fp, "\n");
|
6468
|
+
++j;
|
6469
|
+
break;
|
6470
|
+
case 't':
|
6471
|
+
fprintf(fp, "\t");
|
6472
|
+
++j;
|
6473
|
+
break;
|
6474
|
+
case 'b':
|
6475
|
+
fprintf(fp, "\n");
|
6476
|
+
++j;
|
6477
|
+
break;
|
6478
|
+
default:
|
6479
|
+
fprintf(fp, "%c", *(cntl_chr + j));
|
6480
|
+
break;
|
6481
|
+
}
|
6482
|
+
}
|
6483
|
+
else {
|
6484
|
+
fprintf(fp, "%c", *(cntl_chr + j));
|
6485
|
+
if (*(cntl_chr + j) == '%') ++j;
|
6486
|
+
}
|
6487
|
+
}
|
6488
|
+
j++;
|
6335
6489
|
}
|
6336
6490
|
|
6337
6491
|
return (int)nc;
|
6338
6492
|
}
|
6339
|
-
#endif
|
6340
6493
|
|
6341
6494
|
static void
|
6342
6495
|
VpFormatSt(char *psz, size_t fFmt)
|
@@ -6381,188 +6534,254 @@ VpExponent10(Real *a)
|
|
6381
6534
|
}
|
6382
6535
|
|
6383
6536
|
VP_EXPORT void
|
6384
|
-
VpSzMantissa(Real *a,char *
|
6537
|
+
VpSzMantissa(Real *a, char *buf, size_t buflen)
|
6385
6538
|
{
|
6386
6539
|
size_t i, n, ZeroSup;
|
6387
6540
|
DECDIG_DBL m, e, nn;
|
6388
6541
|
|
6389
6542
|
if (VpIsNaN(a)) {
|
6390
|
-
|
6391
|
-
|
6543
|
+
snprintf(buf, buflen, SZ_NaN);
|
6544
|
+
return;
|
6392
6545
|
}
|
6393
6546
|
if (VpIsPosInf(a)) {
|
6394
|
-
|
6547
|
+
snprintf(buf, buflen, SZ_INF);
|
6395
6548
|
return;
|
6396
6549
|
}
|
6397
6550
|
if (VpIsNegInf(a)) {
|
6398
|
-
|
6551
|
+
snprintf(buf, buflen, SZ_NINF);
|
6399
6552
|
return;
|
6400
6553
|
}
|
6401
6554
|
|
6402
6555
|
ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
|
6403
6556
|
if (!VpIsZero(a)) {
|
6404
|
-
|
6405
|
-
|
6406
|
-
|
6407
|
-
|
6408
|
-
|
6409
|
-
|
6410
|
-
|
6411
|
-
|
6412
|
-
|
6413
|
-
|
6414
|
-
|
6415
|
-
|
6416
|
-
|
6417
|
-
|
6418
|
-
|
6419
|
-
|
6420
|
-
|
6421
|
-
|
6422
|
-
|
6557
|
+
if (BIGDECIMAL_NEGATIVE_P(a)) *buf++ = '-';
|
6558
|
+
n = a->Prec;
|
6559
|
+
for (i = 0; i < n; ++i) {
|
6560
|
+
m = BASE1;
|
6561
|
+
e = a->frac[i];
|
6562
|
+
while (m) {
|
6563
|
+
nn = e / m;
|
6564
|
+
if (!ZeroSup || nn) {
|
6565
|
+
snprintf(buf, buflen, "%lu", (unsigned long)nn); /* The leading zero(s) */
|
6566
|
+
buf += strlen(buf);
|
6567
|
+
/* as 0.00xx will be ignored. */
|
6568
|
+
ZeroSup = 0; /* Set to print succeeding zeros */
|
6569
|
+
}
|
6570
|
+
e = e - nn * m;
|
6571
|
+
m /= 10;
|
6572
|
+
}
|
6573
|
+
}
|
6574
|
+
*buf = 0;
|
6575
|
+
while (buf[-1] == '0') *(--buf) = 0;
|
6423
6576
|
}
|
6424
6577
|
else {
|
6425
|
-
if (VpIsPosZero(a))
|
6426
|
-
else
|
6578
|
+
if (VpIsPosZero(a)) snprintf(buf, buflen, "0");
|
6579
|
+
else snprintf(buf, buflen, "-0");
|
6427
6580
|
}
|
6428
6581
|
}
|
6429
6582
|
|
6430
6583
|
VP_EXPORT int
|
6431
|
-
VpToSpecialString(Real *a,char *
|
6584
|
+
VpToSpecialString(Real *a, char *buf, size_t buflen, int fPlus)
|
6432
6585
|
/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
|
6433
6586
|
{
|
6434
6587
|
if (VpIsNaN(a)) {
|
6435
|
-
|
6436
|
-
|
6588
|
+
snprintf(buf, buflen, SZ_NaN);
|
6589
|
+
return 1;
|
6437
6590
|
}
|
6438
6591
|
|
6439
6592
|
if (VpIsPosInf(a)) {
|
6440
|
-
|
6441
|
-
|
6442
|
-
|
6443
|
-
|
6444
|
-
|
6445
|
-
|
6446
|
-
|
6447
|
-
|
6593
|
+
if (fPlus == 1) {
|
6594
|
+
*buf++ = ' ';
|
6595
|
+
}
|
6596
|
+
else if (fPlus == 2) {
|
6597
|
+
*buf++ = '+';
|
6598
|
+
}
|
6599
|
+
snprintf(buf, buflen, SZ_INF);
|
6600
|
+
return 1;
|
6448
6601
|
}
|
6449
6602
|
if (VpIsNegInf(a)) {
|
6450
|
-
|
6451
|
-
|
6603
|
+
snprintf(buf, buflen, SZ_NINF);
|
6604
|
+
return 1;
|
6452
6605
|
}
|
6453
6606
|
if (VpIsZero(a)) {
|
6454
|
-
|
6455
|
-
|
6456
|
-
|
6457
|
-
|
6458
|
-
|
6459
|
-
|
6460
|
-
|
6607
|
+
if (VpIsPosZero(a)) {
|
6608
|
+
if (fPlus == 1) snprintf(buf, buflen, " 0.0");
|
6609
|
+
else if (fPlus == 2) snprintf(buf, buflen, "+0.0");
|
6610
|
+
else snprintf(buf, buflen, "0.0");
|
6611
|
+
}
|
6612
|
+
else snprintf(buf, buflen, "-0.0");
|
6613
|
+
return 1;
|
6461
6614
|
}
|
6462
6615
|
return 0;
|
6463
6616
|
}
|
6464
6617
|
|
6465
6618
|
VP_EXPORT void
|
6466
|
-
VpToString(Real *a, char *
|
6619
|
+
VpToString(Real *a, char *buf, size_t buflen, size_t fFmt, int fPlus)
|
6467
6620
|
/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
|
6468
6621
|
{
|
6469
6622
|
size_t i, n, ZeroSup;
|
6470
6623
|
DECDIG shift, m, e, nn;
|
6471
|
-
char *
|
6624
|
+
char *p = buf;
|
6625
|
+
size_t plen = buflen;
|
6472
6626
|
ssize_t ex;
|
6473
6627
|
|
6474
|
-
if (VpToSpecialString(a,
|
6628
|
+
if (VpToSpecialString(a, buf, buflen, fPlus)) return;
|
6475
6629
|
|
6476
6630
|
ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
|
6477
6631
|
|
6478
|
-
|
6479
|
-
|
6480
|
-
|
6632
|
+
#define ADVANCE(n) do { \
|
6633
|
+
if (plen < n) goto overflow; \
|
6634
|
+
p += n; \
|
6635
|
+
plen -= n; \
|
6636
|
+
} while (0)
|
6637
|
+
|
6638
|
+
if (BIGDECIMAL_NEGATIVE_P(a)) {
|
6639
|
+
*p = '-';
|
6640
|
+
ADVANCE(1);
|
6641
|
+
}
|
6642
|
+
else if (fPlus == 1) {
|
6643
|
+
*p = ' ';
|
6644
|
+
ADVANCE(1);
|
6645
|
+
}
|
6646
|
+
else if (fPlus == 2) {
|
6647
|
+
*p = '+';
|
6648
|
+
ADVANCE(1);
|
6649
|
+
}
|
6650
|
+
|
6651
|
+
*p = '0'; ADVANCE(1);
|
6652
|
+
*p = '.'; ADVANCE(1);
|
6481
6653
|
|
6482
|
-
*psz++ = '0';
|
6483
|
-
*psz++ = '.';
|
6484
6654
|
n = a->Prec;
|
6485
6655
|
for (i = 0; i < n; ++i) {
|
6486
|
-
|
6487
|
-
|
6488
|
-
|
6489
|
-
|
6490
|
-
|
6491
|
-
|
6492
|
-
|
6493
|
-
|
6494
|
-
|
6495
|
-
|
6496
|
-
|
6497
|
-
|
6498
|
-
|
6656
|
+
m = BASE1;
|
6657
|
+
e = a->frac[i];
|
6658
|
+
while (m) {
|
6659
|
+
nn = e / m;
|
6660
|
+
if (!ZeroSup || nn) {
|
6661
|
+
/* The reading zero(s) */
|
6662
|
+
size_t n = (size_t)snprintf(p, plen, "%lu", (unsigned long)nn);
|
6663
|
+
if (n > plen) goto overflow;
|
6664
|
+
ADVANCE(n);
|
6665
|
+
/* as 0.00xx will be ignored. */
|
6666
|
+
ZeroSup = 0; /* Set to print succeeding zeros */
|
6667
|
+
}
|
6668
|
+
e = e - nn * m;
|
6669
|
+
m /= 10;
|
6670
|
+
}
|
6499
6671
|
}
|
6672
|
+
|
6500
6673
|
ex = a->exponent * (ssize_t)BASE_FIG;
|
6501
6674
|
shift = BASE1;
|
6502
6675
|
while (a->frac[0] / shift == 0) {
|
6503
|
-
|
6504
|
-
|
6676
|
+
--ex;
|
6677
|
+
shift /= 10;
|
6505
6678
|
}
|
6506
|
-
while (
|
6507
|
-
|
6679
|
+
while (p - 1 > buf && p[-1] == '0') {
|
6680
|
+
*(--p) = '\0';
|
6681
|
+
++plen;
|
6508
6682
|
}
|
6509
|
-
|
6510
|
-
if (fFmt) VpFormatSt(
|
6683
|
+
snprintf(p, plen, "e%"PRIdSIZE, ex);
|
6684
|
+
if (fFmt) VpFormatSt(buf, fFmt);
|
6685
|
+
|
6686
|
+
overflow:
|
6687
|
+
return;
|
6688
|
+
#undef ADVANCE
|
6511
6689
|
}
|
6512
6690
|
|
6513
6691
|
VP_EXPORT void
|
6514
|
-
VpToFString(Real *a, char *
|
6692
|
+
VpToFString(Real *a, char *buf, size_t buflen, size_t fFmt, int fPlus)
|
6515
6693
|
/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
|
6516
6694
|
{
|
6517
6695
|
size_t i, n;
|
6518
6696
|
DECDIG m, e, nn;
|
6519
|
-
char *
|
6697
|
+
char *p = buf;
|
6698
|
+
size_t plen = buflen;
|
6520
6699
|
ssize_t ex;
|
6521
6700
|
|
6522
|
-
if (VpToSpecialString(a,
|
6701
|
+
if (VpToSpecialString(a, buf, buflen, fPlus)) return;
|
6523
6702
|
|
6524
|
-
|
6525
|
-
|
6526
|
-
|
6703
|
+
#define ADVANCE(n) do { \
|
6704
|
+
if (plen < n) goto overflow; \
|
6705
|
+
p += n; \
|
6706
|
+
plen -= n; \
|
6707
|
+
} while (0)
|
6708
|
+
|
6709
|
+
|
6710
|
+
if (BIGDECIMAL_NEGATIVE_P(a)) {
|
6711
|
+
*p = '-';
|
6712
|
+
ADVANCE(1);
|
6713
|
+
}
|
6714
|
+
else if (fPlus == 1) {
|
6715
|
+
*p = ' ';
|
6716
|
+
ADVANCE(1);
|
6717
|
+
}
|
6718
|
+
else if (fPlus == 2) {
|
6719
|
+
*p = '+';
|
6720
|
+
ADVANCE(1);
|
6721
|
+
}
|
6527
6722
|
|
6528
6723
|
n = a->Prec;
|
6529
6724
|
ex = a->exponent;
|
6530
6725
|
if (ex <= 0) {
|
6531
|
-
|
6532
|
-
|
6533
|
-
|
6534
|
-
|
6535
|
-
|
6536
|
-
|
6726
|
+
*p = '0'; ADVANCE(1);
|
6727
|
+
*p = '.'; ADVANCE(1);
|
6728
|
+
while (ex < 0) {
|
6729
|
+
for (i=0; i < BASE_FIG; ++i) {
|
6730
|
+
*p = '0'; ADVANCE(1);
|
6731
|
+
}
|
6732
|
+
++ex;
|
6733
|
+
}
|
6734
|
+
ex = -1;
|
6537
6735
|
}
|
6538
6736
|
|
6539
6737
|
for (i = 0; i < n; ++i) {
|
6540
|
-
|
6541
|
-
|
6542
|
-
|
6543
|
-
|
6544
|
-
|
6545
|
-
|
6546
|
-
|
6547
|
-
|
6548
|
-
|
6549
|
-
|
6550
|
-
|
6551
|
-
|
6552
|
-
|
6553
|
-
|
6554
|
-
|
6555
|
-
|
6738
|
+
--ex;
|
6739
|
+
if (i == 0 && ex >= 0) {
|
6740
|
+
size_t n = snprintf(p, plen, "%lu", (unsigned long)a->frac[i]);
|
6741
|
+
if (n > plen) goto overflow;
|
6742
|
+
ADVANCE(n);
|
6743
|
+
}
|
6744
|
+
else {
|
6745
|
+
m = BASE1;
|
6746
|
+
e = a->frac[i];
|
6747
|
+
while (m) {
|
6748
|
+
nn = e / m;
|
6749
|
+
*p = (char)(nn + '0');
|
6750
|
+
ADVANCE(1);
|
6751
|
+
e = e - nn * m;
|
6752
|
+
m /= 10;
|
6753
|
+
}
|
6754
|
+
}
|
6755
|
+
if (ex == 0) {
|
6756
|
+
*p = '.';
|
6757
|
+
ADVANCE(1);
|
6758
|
+
}
|
6556
6759
|
}
|
6557
6760
|
while (--ex>=0) {
|
6558
|
-
|
6559
|
-
|
6560
|
-
|
6761
|
+
m = BASE;
|
6762
|
+
while (m /= 10) {
|
6763
|
+
*p = '0';
|
6764
|
+
ADVANCE(1);
|
6765
|
+
}
|
6766
|
+
if (ex == 0) {
|
6767
|
+
*p = '.';
|
6768
|
+
ADVANCE(1);
|
6769
|
+
}
|
6770
|
+
}
|
6771
|
+
|
6772
|
+
*p = '\0';
|
6773
|
+
while (p - 1 > buf && p[-1] == '0') {
|
6774
|
+
*(--p) = '\0';
|
6775
|
+
++plen;
|
6776
|
+
}
|
6777
|
+
if (p - 1 > buf && p[-1] == '.') {
|
6778
|
+
snprintf(p, plen, "0");
|
6561
6779
|
}
|
6562
|
-
|
6563
|
-
|
6564
|
-
|
6565
|
-
|
6780
|
+
if (fFmt) VpFormatSt(buf, fFmt);
|
6781
|
+
|
6782
|
+
overflow:
|
6783
|
+
return;
|
6784
|
+
#undef ADVANCE
|
6566
6785
|
}
|
6567
6786
|
|
6568
6787
|
/*
|
@@ -6971,8 +7190,9 @@ VpSqrt(Real *y, Real *x)
|
|
6971
7190
|
if (x->MaxPrec > (size_t)n) n = (ssize_t)x->MaxPrec;
|
6972
7191
|
|
6973
7192
|
/* allocate temporally variables */
|
6974
|
-
|
6975
|
-
|
7193
|
+
/* TODO: reconsider MaxPrec of f and r */
|
7194
|
+
f = NewOneNolimit(1, y->MaxPrec * (BASE_FIG + 2));
|
7195
|
+
r = NewOneNolimit(1, (n + n) * (BASE_FIG + 2));
|
6976
7196
|
|
6977
7197
|
nr = 0;
|
6978
7198
|
y_prec = y->MaxPrec;
|
@@ -6997,16 +7217,21 @@ VpSqrt(Real *y, Real *x)
|
|
6997
7217
|
f->MaxPrec = y->MaxPrec + 1;
|
6998
7218
|
n = (SIGNED_VALUE)(y_prec * BASE_FIG);
|
6999
7219
|
if (n < (SIGNED_VALUE)maxnr) n = (SIGNED_VALUE)maxnr;
|
7220
|
+
|
7221
|
+
/*
|
7222
|
+
* Perform: y_{n+1} = (y_n - x/y_n) / 2
|
7223
|
+
*/
|
7000
7224
|
do {
|
7001
|
-
|
7002
|
-
|
7003
|
-
|
7004
|
-
|
7005
|
-
|
7006
|
-
|
7007
|
-
|
7008
|
-
|
7009
|
-
|
7225
|
+
y->MaxPrec *= 2;
|
7226
|
+
if (y->MaxPrec > y_prec) y->MaxPrec = y_prec;
|
7227
|
+
f->MaxPrec = y->MaxPrec;
|
7228
|
+
VpDivd(f, r, x, y); /* f = x/y */
|
7229
|
+
VpAddSub(r, f, y, -1); /* r = f - y */
|
7230
|
+
VpMult(f, VpConstPt5, r); /* f = 0.5*r */
|
7231
|
+
if (VpIsZero(f))
|
7232
|
+
goto converge;
|
7233
|
+
VpAddSub(r, f, y, 1); /* r = y + f */
|
7234
|
+
VpAsgn(y, r, 1); /* y = r */
|
7010
7235
|
} while (++nr < n);
|
7011
7236
|
|
7012
7237
|
#ifdef BIGDECIMAL_DEBUG
|
@@ -7031,8 +7256,8 @@ converge:
|
|
7031
7256
|
y->MaxPrec = y_prec;
|
7032
7257
|
|
7033
7258
|
Exit:
|
7034
|
-
|
7035
|
-
|
7259
|
+
rbd_free_struct(f);
|
7260
|
+
rbd_free_struct(r);
|
7036
7261
|
return 1;
|
7037
7262
|
}
|
7038
7263
|
|
@@ -7423,9 +7648,10 @@ VpPowerByInt(Real *y, Real *x, SIGNED_VALUE n)
|
|
7423
7648
|
}
|
7424
7649
|
|
7425
7650
|
/* Allocate working variables */
|
7651
|
+
/* TODO: reconsider MaxPrec of w1 and w2 */
|
7652
|
+
w1 = NewZeroNolimit(1, (y->MaxPrec + 2) * BASE_FIG);
|
7653
|
+
w2 = NewZeroNolimit(1, (w1->MaxPrec * 2 + 1) * BASE_FIG);
|
7426
7654
|
|
7427
|
-
w1 = VpAlloc((y->MaxPrec + 2) * BASE_FIG, "#0", 1, 1);
|
7428
|
-
w2 = VpAlloc((w1->MaxPrec * 2 + 1) * BASE_FIG, "#0", 1, 1);
|
7429
7655
|
/* calculation start */
|
7430
7656
|
|
7431
7657
|
VpAsgn(y, x, 1);
|
@@ -7454,8 +7680,8 @@ Exit:
|
|
7454
7680
|
printf(" n=%"PRIdVALUE"\n", n);
|
7455
7681
|
}
|
7456
7682
|
#endif /* BIGDECIMAL_DEBUG */
|
7457
|
-
|
7458
|
-
|
7683
|
+
rbd_free_struct(w2);
|
7684
|
+
rbd_free_struct(w1);
|
7459
7685
|
return 1;
|
7460
7686
|
}
|
7461
7687
|
|