bigdecimal 3.1.2 → 3.1.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|