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.
@@ -7,9 +7,7 @@
7
7
  */
8
8
 
9
9
  /* #define BIGDECIMAL_DEBUG 1 */
10
- #ifdef BIGDECIMAL_DEBUG
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
- VpFree(pv);
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
- sprintf(szD, "%ld", FIX2LONG(v));
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").scale # => 0
490
- * BigDecimal("1").scale # => 1
491
- * BigDecimal("1.1").scale # => 2
492
- * BigDecimal("3.1415").scale # => 5
493
- * BigDecimal("-1e20").precision # => 1
494
- * BigDecimal("1e-20").precision # => 1
495
- * BigDecimal("Infinity").scale # => 0
496
- * BigDecimal("-Infinity").scale # => 0
497
- * BigDecimal("NaN").scale # => 0
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
- sprintf(psz, "%"PRIuSIZE":", VpMaxPrec(vp)*VpBaseFig());
582
- VpToString(vp, psz+strlen(psz), 0, 0);
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 noopt;
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 noopt;
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
- VALUE str_mode = rb_check_string_type(mode);
636
- if (NIL_P(str_mode)) goto invalid;
637
- mode = str_mode;
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
- if (NIL_P(mode))
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
- noopt:
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
- switch (TYPE(v)) {
671
- case T_SYMBOL:
672
- id = SYM2ID(v);
673
- if (id == id_up)
674
- return VP_ROUND_UP;
675
- if (id == id_down || id == id_truncate)
676
- return VP_ROUND_DOWN;
677
- if (id == id_half_up || id == id_default)
678
- return VP_ROUND_HALF_UP;
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
- sw = NUM2USHORT(v);
694
- if (!VpIsRoundMode(sw)) {
695
- rb_raise(rb_eArgError, "invalid rounding mode");
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
- GetPrecisionInt(VALUE v)
1136
+ static inline SIGNED_VALUE
1137
+ check_int_precision(VALUE v)
938
1138
  {
939
1139
  SIGNED_VALUE n;
940
- n = NUM2INT(v);
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 = VpReallocReal(pv, x->MaxPrec);
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, VpCreateRbObject(VpBaseFig() + 1, "0", true));
1280
- VpAddSub(c, a, b, 1);
1471
+ GUARD_OBJ(c, NewZeroWrapLimited(1, VpBaseFig() + 1));
1472
+ VpAddSub(c, a, b, 1);
1281
1473
  }
1282
1474
  else {
1283
- GUARD_OBJ(c, VpCreateRbObject(mx * (VpBaseFig() + 1), "0", true));
1284
- if(!mx) {
1285
- VpSetInf(c, VpGetSign(a));
1286
- }
1287
- else {
1288
- VpAddSub(c, a, b, 1);
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, VpCreateRbObject(VpBaseFig() + 1, "0", true));
1335
- VpAddSub(c, a, b, -1);
1526
+ GUARD_OBJ(c, NewZeroWrapLimited(1, VpBaseFig() + 1));
1527
+ VpAddSub(c, a, b, -1);
1336
1528
  }
1337
1529
  else {
1338
- GUARD_OBJ(c,VpCreateRbObject(mx *(VpBaseFig() + 1), "0", true));
1339
- if (!mx) {
1340
- VpSetInf(c,VpGetSign(a));
1341
- }
1342
- else {
1343
- VpAddSub(c, a, b, -1);
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, VpCreateRbObject(a->Prec *(VpBaseFig() + 1), "0", true));
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, VpCreateRbObject(mx *(VpBaseFig() + 1), "0", true));
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), VpCreateRbObject(mx + 2*BASE_FIG, "#0", true));
1659
- GUARD_OBJ((*res), VpCreateRbObject((mx + 1)*2 + 2*BASE_FIG, "#0", true));
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 = GetPrecisionInt(digits);
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, VpCreateRbObject(mx + 2*BASE_FIG, "0", true));
1815
- GUARD_OBJ(res, VpCreateRbObject(mx*2 + 2*BASE_FIG, "#0", true));
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, VpCreateRbObject(mx, "0", true));
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 = VpReallocReal(res, d->MaxPrec);
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, VpCreateRbObject(GetAddSubPrec(c, b) * 2*BASE_FIG, "0", true));
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, VpCreateRbObject(mx, "0", true));
1895
- GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0", true));
1896
- GUARD_OBJ(rr, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0", true));
1897
- GUARD_OBJ(ff, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0", true));
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, VpCreateRbObject(mx, "0", true));
1904
- GUARD_OBJ(f, VpCreateRbObject(mx, "0", true));
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 = GetPrecisionInt(n);
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, VpCreateRbObject(mx + VpBaseFig(), "0", true));
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, VpCreateRbObject((mx * 2 + 2)*VpBaseFig(), "#0", true));
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 = GetPrecisionInt(n);
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 = GetPrecisionInt(n);
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 = GetPrecisionInt(n);
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, VpCreateRbObject(mx, "0", true));
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 = GetPrecisionInt(nFig) + VpDblFig() + BASE_FIG;
2414
+ n = check_int_precision(nFig);
2415
+ n += VpDblFig() + VpBaseFig();
2223
2416
  if (mx <= n) mx = n;
2224
- GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
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, VpCreateRbObject(mx, "0", true));
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, VpCreateRbObject(mx, "0", true));
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, VpCreateRbObject(mx, "0", true));
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, VpCreateRbObject(mx, "0", true));
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, VpCreateRbObject(mx, "0", true));
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, VpCreateRbObject(mx, "0", true));
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(VpCreateRbObject(n, "1", true));
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 = VpCreateRbObject(n, "0", true);
2812
- RB_GC_GUARD(y->obj);
2813
- VpSetNaN(y);
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
- if (is_negative(vexp)) {
2883
- y = VpCreateRbObject(n, "#0", true);
2884
- RB_GC_GUARD(y->obj);
2885
- if (BIGDECIMAL_NEGATIVE_P(x)) {
2886
- if (is_integer(vexp)) {
2887
- if (is_even(vexp)) {
2888
- /* (-0) ** (-even_integer) -> Infinity */
2889
- VpSetPosInf(y);
2890
- }
2891
- else {
2892
- /* (-0) ** (-odd_integer) -> -Infinity */
2893
- VpSetNegInf(y);
2894
- }
2895
- }
2896
- else {
2897
- /* (-0) ** (-non_integer) -> Infinity */
2898
- VpSetPosInf(y);
2899
- }
2900
- }
2901
- else {
2902
- /* (+0) ** (-num) -> Infinity */
2903
- VpSetPosInf(y);
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
- else if (is_zero(vexp)) {
2908
- return VpCheckGetValue(VpCreateRbObject(n, "1", true));
2909
- }
2910
- else {
2911
- return VpCheckGetValue(VpCreateRbObject(n, "0", true));
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(VpCreateRbObject(n, "1", true));
3109
+ return VpCheckGetValue(NewOneWrapLimited(1, n));
2917
3110
  }
2918
3111
  else if (is_one(vexp)) {
2919
- return self;
3112
+ return self;
2920
3113
  }
2921
3114
 
2922
3115
  if (VpIsInf(x)) {
2923
- if (is_negative(vexp)) {
2924
- if (BIGDECIMAL_NEGATIVE_P(x)) {
2925
- if (is_integer(vexp)) {
2926
- if (is_even(vexp)) {
2927
- /* (-Infinity) ** (-even_integer) -> +0 */
2928
- return VpCheckGetValue(VpCreateRbObject(n, "0", true));
2929
- }
2930
- else {
2931
- /* (-Infinity) ** (-odd_integer) -> -0 */
2932
- return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
2933
- }
2934
- }
2935
- else {
2936
- /* (-Infinity) ** (-non_integer) -> -0 */
2937
- return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
2938
- }
2939
- }
2940
- else {
2941
- return VpCheckGetValue(VpCreateRbObject(n, "0", true));
2942
- }
2943
- }
2944
- else {
2945
- y = VpCreateRbObject(n, "0", true);
2946
- if (BIGDECIMAL_NEGATIVE_P(x)) {
2947
- if (is_integer(vexp)) {
2948
- if (is_even(vexp)) {
2949
- VpSetPosInf(y);
2950
- }
2951
- else {
2952
- VpSetNegInf(y);
2953
- }
2954
- }
2955
- else {
2956
- /* TODO: support complex */
2957
- rb_raise(rb_eMathDomainError,
2958
- "a non-integral exponent for a negative base");
2959
- }
2960
- }
2961
- else {
2962
- VpSetPosInf(y);
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
- return bigdecimal_power_by_bigdecimal(x, exp, n);
3162
+ return bigdecimal_power_by_bigdecimal(x, exp, n);
2970
3163
  }
2971
3164
  else if (RB_TYPE_P(vexp, T_BIGNUM)) {
2972
- VALUE abs_value = BigDecimal_abs(self);
2973
- if (is_one(abs_value)) {
2974
- return VpCheckGetValue(VpCreateRbObject(n, "1", true));
2975
- }
2976
- else if (RTEST(rb_funcall(abs_value, '<', 1, INT2FIX(1)))) {
2977
- if (is_negative(vexp)) {
2978
- y = VpCreateRbObject(n, "0", true);
2979
- if (is_even(vexp)) {
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
- else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
2988
- return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
2989
- }
2990
- else {
2991
- return VpCheckGetValue(VpCreateRbObject(n, "0", true));
2992
- }
2993
- }
2994
- else {
2995
- if (is_positive(vexp)) {
2996
- y = VpCreateRbObject(n, "0", true);
2997
- if (is_even(vexp)) {
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
- else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
3006
- return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
3007
- }
3008
- else {
3009
- return VpCheckGetValue(VpCreateRbObject(n, "0", true));
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
- mp = x->Prec * (VpBaseFig() + 1);
3021
- GUARD_OBJ(y, VpCreateRbObject(mp * (ma + 1), "0", true));
3203
+ mp = x->Prec * (VpBaseFig() + 1);
3204
+ GUARD_OBJ(y, NewZeroWrapLimited(1, mp * (ma + 1)));
3022
3205
  }
3023
3206
  else {
3024
- GUARD_OBJ(y, VpCreateRbObject(1, "0", true));
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
- VpMidRound(y, VpGetRoundMode(), n);
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 = VpAllocReal(1);
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 = VpAllocReal(1);
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 = VpAllocReal(len);
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
- size_t exp = 0;
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
- * Returns the \BigDecimal converted from +value+
3497
- * with a precision of +ndigits+ decimal digits.
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
- * When +ndigits+ is less than the number of significant digits
3500
- * in the value, the result is rounded to that number of digits,
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, and a
3610
- * zero if == 0.
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
- Real* vy;
3783
- vy = VpCreateRbObject(prec, "#0", true);
3784
- VpSetNaN(vy);
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(VpCreateRbObject(1, "1", true));
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
- Real* vy;
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(VpCreateRbObject(1, "1", true));
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
- id_up = rb_intern_const("up");
4418
- id_down = rb_intern_const("down");
4419
- id_truncate = rb_intern_const("truncate");
4420
- id_half_up = rb_intern_const("half_up");
4421
- id_default = rb_intern_const("default");
4422
- id_half_down = rb_intern_const("half_down");
4423
- id_half_even = rb_intern_const("half_even");
4424
- id_banker = rb_intern_const("banker");
4425
- id_ceiling = rb_intern_const("ceiling");
4426
- id_ceil = rb_intern_const("ceil");
4427
- id_floor = rb_intern_const("floor");
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 *VpPt5; /* constant 0.5 */
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
- /* Allocates Vp constants. */
4906
- VpConstOne = VpAlloc(1UL, "1", 1, 1);
4907
- VpPt5 = VpAlloc(1UL, ".5", 1, 1);
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 = VpAllocReal(1);
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 ... allocation unit, if zero then mx is determined by szVal.
5021
- * The mx is the number of effective digits can to be stored.
5022
- * szVal ... value assigned(char). If szVal==NULL,then zero is assumed.
5023
- * If szVal[0]=='#' then Max. Prec. will not be considered(1.1.7),
5024
- * full precision specified by szVal is allocated.
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
- mx = (mx + BASE_FIG - 1) / BASE_FIG; /* Determine allocation unit. */
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 = VpAllocReal(mx);
5067
- vp->MaxPrec = mx; /* set max precision */
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 (mx == 0) mx = 1;
5239
- nalloc = Max(nalloc, mx);
5240
- mx = nalloc;
5241
- vp = VpAllocReal(mx);
5242
- vp->MaxPrec = mx; /* set max precision */
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
- c = VpAlloc((size_t)((MxIndAB + 1) * BASE_FIG), "#0", 1, 1);
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
- if (w) VpFree(c);
5816
- return 0;
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
- VpNmlz(c);
5867
- VpAsgn(w, c, 1);
5868
- VpFree(c);
5869
- c = w;
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
- if (*(cntl_chr + j) == '%' && *(cntl_chr + j + 1) != '%') {
6252
- nc = 0;
6253
- if (VpIsNaN(a)) {
6254
- fprintf(fp, SZ_NaN);
6255
- nc += 8;
6256
- }
6257
- else if (VpIsPosInf(a)) {
6258
- fprintf(fp, SZ_INF);
6259
- nc += 8;
6260
- }
6261
- else if (VpIsNegInf(a)) {
6262
- fprintf(fp, SZ_NINF);
6263
- nc += 9;
6264
- }
6265
- else if (!VpIsZero(a)) {
6266
- if (BIGDECIMAL_NEGATIVE_P(a)) {
6267
- fprintf(fp, "-");
6268
- ++nc;
6269
- }
6270
- nc += fprintf(fp, "0.");
6271
- switch (*(cntl_chr + j + 1)) {
6272
- default:
6273
- break;
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
- case '0': case 'z':
6276
- ZeroSup = 0;
6277
- ++j;
6278
- sep = cntl_chr[j] == 'z' ? BIGDECIMAL_COMPONENT_FIGURES : 10;
6279
- break;
6280
- }
6281
- for (i = 0; i < a->Prec; ++i) {
6282
- m = BASE1;
6283
- e = a->frac[i];
6284
- while (m) {
6285
- nn = e / m;
6286
- if (!ZeroSup || nn) {
6287
- nc += fprintf(fp, "%lu", (unsigned long)nn); /* The leading zero(s) */
6288
- /* as 0.00xx will not */
6289
- /* be printed. */
6290
- ++nd;
6291
- ZeroSup = 0; /* Set to print succeeding zeros */
6292
- }
6293
- if (nd >= sep) { /* print ' ' after every 10 digits */
6294
- nd = 0;
6295
- nc += fprintf(fp, " ");
6296
- }
6297
- e = e - nn * m;
6298
- m /= 10;
6299
- }
6300
- }
6301
- nc += fprintf(fp, "E%"PRIdSIZE, VpExponent10(a));
6302
- nc += fprintf(fp, " (%"PRIdVALUE", %lu, %lu)", a->exponent, a->Prec, a->MaxPrec);
6303
- }
6304
- else {
6305
- nc += fprintf(fp, "0.0");
6306
- }
6307
- }
6308
- else {
6309
- ++nc;
6310
- if (*(cntl_chr + j) == '\\') {
6311
- switch (*(cntl_chr + j + 1)) {
6312
- case 'n':
6313
- fprintf(fp, "\n");
6314
- ++j;
6315
- break;
6316
- case 't':
6317
- fprintf(fp, "\t");
6318
- ++j;
6319
- break;
6320
- case 'b':
6321
- fprintf(fp, "\n");
6322
- ++j;
6323
- break;
6324
- default:
6325
- fprintf(fp, "%c", *(cntl_chr + j));
6326
- break;
6327
- }
6328
- }
6329
- else {
6330
- fprintf(fp, "%c", *(cntl_chr + j));
6331
- if (*(cntl_chr + j) == '%') ++j;
6332
- }
6333
- }
6334
- j++;
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 *psz)
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
- sprintf(psz, SZ_NaN);
6391
- return;
6543
+ snprintf(buf, buflen, SZ_NaN);
6544
+ return;
6392
6545
  }
6393
6546
  if (VpIsPosInf(a)) {
6394
- sprintf(psz, SZ_INF);
6547
+ snprintf(buf, buflen, SZ_INF);
6395
6548
  return;
6396
6549
  }
6397
6550
  if (VpIsNegInf(a)) {
6398
- sprintf(psz, SZ_NINF);
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
- if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
6405
- n = a->Prec;
6406
- for (i = 0; i < n; ++i) {
6407
- m = BASE1;
6408
- e = a->frac[i];
6409
- while (m) {
6410
- nn = e / m;
6411
- if (!ZeroSup || nn) {
6412
- sprintf(psz, "%lu", (unsigned long)nn); /* The leading zero(s) */
6413
- psz += strlen(psz);
6414
- /* as 0.00xx will be ignored. */
6415
- ZeroSup = 0; /* Set to print succeeding zeros */
6416
- }
6417
- e = e - nn * m;
6418
- m /= 10;
6419
- }
6420
- }
6421
- *psz = 0;
6422
- while (psz[-1] == '0') *(--psz) = 0;
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)) sprintf(psz, "0");
6426
- else sprintf(psz, "-0");
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 *psz,int fPlus)
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
- sprintf(psz,SZ_NaN);
6436
- return 1;
6588
+ snprintf(buf, buflen, SZ_NaN);
6589
+ return 1;
6437
6590
  }
6438
6591
 
6439
6592
  if (VpIsPosInf(a)) {
6440
- if (fPlus == 1) {
6441
- *psz++ = ' ';
6442
- }
6443
- else if (fPlus == 2) {
6444
- *psz++ = '+';
6445
- }
6446
- sprintf(psz, SZ_INF);
6447
- return 1;
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
- sprintf(psz, SZ_NINF);
6451
- return 1;
6603
+ snprintf(buf, buflen, SZ_NINF);
6604
+ return 1;
6452
6605
  }
6453
6606
  if (VpIsZero(a)) {
6454
- if (VpIsPosZero(a)) {
6455
- if (fPlus == 1) sprintf(psz, " 0.0");
6456
- else if (fPlus == 2) sprintf(psz, "+0.0");
6457
- else sprintf(psz, "0.0");
6458
- }
6459
- else sprintf(psz, "-0.0");
6460
- return 1;
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 *psz, size_t fFmt, int fPlus)
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 *pszSav = psz;
6624
+ char *p = buf;
6625
+ size_t plen = buflen;
6472
6626
  ssize_t ex;
6473
6627
 
6474
- if (VpToSpecialString(a, psz, fPlus)) return;
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
- if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
6479
- else if (fPlus == 1) *psz++ = ' ';
6480
- else if (fPlus == 2) *psz++ = '+';
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
- m = BASE1;
6487
- e = a->frac[i];
6488
- while (m) {
6489
- nn = e / m;
6490
- if (!ZeroSup || nn) {
6491
- sprintf(psz, "%lu", (unsigned long)nn); /* The reading zero(s) */
6492
- psz += strlen(psz);
6493
- /* as 0.00xx will be ignored. */
6494
- ZeroSup = 0; /* Set to print succeeding zeros */
6495
- }
6496
- e = e - nn * m;
6497
- m /= 10;
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
- --ex;
6504
- shift /= 10;
6676
+ --ex;
6677
+ shift /= 10;
6505
6678
  }
6506
- while (psz[-1] == '0') {
6507
- *(--psz) = 0;
6679
+ while (p - 1 > buf && p[-1] == '0') {
6680
+ *(--p) = '\0';
6681
+ ++plen;
6508
6682
  }
6509
- sprintf(psz, "e%"PRIdSIZE, ex);
6510
- if (fFmt) VpFormatSt(pszSav, fFmt);
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 *psz, size_t fFmt, int fPlus)
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 *pszSav = psz;
6697
+ char *p = buf;
6698
+ size_t plen = buflen;
6520
6699
  ssize_t ex;
6521
6700
 
6522
- if (VpToSpecialString(a, psz, fPlus)) return;
6701
+ if (VpToSpecialString(a, buf, buflen, fPlus)) return;
6523
6702
 
6524
- if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
6525
- else if (fPlus == 1) *psz++ = ' ';
6526
- else if (fPlus == 2) *psz++ = '+';
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
- *psz++ = '0';*psz++ = '.';
6532
- while (ex < 0) {
6533
- for (i=0; i < BASE_FIG; ++i) *psz++ = '0';
6534
- ++ex;
6535
- }
6536
- ex = -1;
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
- --ex;
6541
- if (i == 0 && ex >= 0) {
6542
- sprintf(psz, "%lu", (unsigned long)a->frac[i]);
6543
- psz += strlen(psz);
6544
- }
6545
- else {
6546
- m = BASE1;
6547
- e = a->frac[i];
6548
- while (m) {
6549
- nn = e / m;
6550
- *psz++ = (char)(nn + '0');
6551
- e = e - nn * m;
6552
- m /= 10;
6553
- }
6554
- }
6555
- if (ex == 0) *psz++ = '.';
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
- m = BASE;
6559
- while (m /= 10) *psz++ = '0';
6560
- if (ex == 0) *psz++ = '.';
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
- *psz = 0;
6563
- while (psz[-1] == '0') *(--psz) = 0;
6564
- if (psz[-1] == '.') sprintf(psz, "0");
6565
- if (fFmt) VpFormatSt(pszSav, fFmt);
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
- f = VpAlloc(y->MaxPrec * (BASE_FIG + 2), "#1", 1, 1);
6975
- r = VpAlloc((n + n) * (BASE_FIG + 2), "#1", 1, 1);
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
- y->MaxPrec *= 2;
7002
- if (y->MaxPrec > y_prec) y->MaxPrec = y_prec;
7003
- f->MaxPrec = y->MaxPrec;
7004
- VpDivd(f, r, x, y); /* f = x/y */
7005
- VpAddSub(r, f, y, -1); /* r = f - y */
7006
- VpMult(f, VpPt5, r); /* f = 0.5*r */
7007
- if (VpIsZero(f)) goto converge;
7008
- VpAddSub(r, f, y, 1); /* r = y + f */
7009
- VpAsgn(y, r, 1); /* y = r */
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
- VpFree(f);
7035
- VpFree(r);
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
- VpFree(w2);
7458
- VpFree(w1);
7683
+ rbd_free_struct(w2);
7684
+ rbd_free_struct(w1);
7459
7685
  return 1;
7460
7686
  }
7461
7687