bigdecimal 3.1.1 → 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
  }
@@ -1618,7 +1810,7 @@ BigDecimal_divide(VALUE self, VALUE r, Real **c, Real **res, Real **div)
1618
1810
  /* For c = self.div(r): with round operation */
1619
1811
  {
1620
1812
  ENTER(5);
1621
- Real *a, *b, *d;
1813
+ Real *a, *b;
1622
1814
  ssize_t a_prec, b_prec;
1623
1815
  size_t mx;
1624
1816
 
@@ -1647,18 +1839,16 @@ BigDecimal_divide(VALUE self, VALUE r, Real **c, Real **res, Real **div)
1647
1839
  SAVE(b);
1648
1840
  *div = b;
1649
1841
 
1650
- mx = (a->Prec > b->Prec) ? a->Prec : b->Prec;
1651
- mx *= BASE_FIG;
1652
-
1653
1842
  BigDecimal_count_precision_and_scale(self, &a_prec, NULL);
1654
1843
  BigDecimal_count_precision_and_scale(rr, &b_prec, NULL);
1655
1844
  mx = (a_prec > b_prec) ? a_prec : b_prec;
1845
+ mx *= 2;
1656
1846
 
1657
1847
  if (2*BIGDECIMAL_DOUBLE_FIGURES > mx)
1658
1848
  mx = 2*BIGDECIMAL_DOUBLE_FIGURES;
1659
1849
 
1660
- GUARD_OBJ((*c), VpCreateRbObject(mx + 2*BASE_FIG, "#0", true));
1661
- GUARD_OBJ((*res), VpCreateRbObject(mx*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));
1662
1852
  VpDivd(*c, *res, a, b);
1663
1853
 
1664
1854
  return Qnil;
@@ -1723,7 +1913,7 @@ BigDecimal_quo(int argc, VALUE *argv, VALUE self)
1723
1913
 
1724
1914
  argc = rb_scan_args(argc, argv, "11", &value, &digits);
1725
1915
  if (argc > 1) {
1726
- n = GetPrecisionInt(digits);
1916
+ n = check_int_precision(digits);
1727
1917
  }
1728
1918
 
1729
1919
  if (n > 0) {
@@ -1808,15 +1998,17 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
1808
1998
  BigDecimal_count_precision_and_scale(rr, &b_prec, NULL);
1809
1999
 
1810
2000
  mx = (a_prec > b_prec) ? a_prec : b_prec;
2001
+ mx *= 2;
2002
+
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.
3498
3681
  *
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.
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.
3685
+ *
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);
@@ -5931,18 +6086,17 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
5931
6086
  word_c = c->MaxPrec;
5932
6087
  word_r = r->MaxPrec;
5933
6088
 
5934
- ind_c = 0;
5935
- ind_r = 1;
5936
-
5937
6089
  if (word_a >= word_r) goto space_error;
5938
6090
 
6091
+ ind_r = 1;
5939
6092
  r->frac[0] = 0;
5940
6093
  while (ind_r <= word_a) {
5941
6094
  r->frac[ind_r] = a->frac[ind_r - 1];
5942
6095
  ++ind_r;
5943
6096
  }
5944
-
5945
6097
  while (ind_r < word_r) r->frac[ind_r++] = 0;
6098
+
6099
+ ind_c = 0;
5946
6100
  while (ind_c < word_c) c->frac[ind_c++] = 0;
5947
6101
 
5948
6102
  /* initial procedure */
@@ -6236,7 +6390,6 @@ Exit:
6236
6390
  * Note: % must not appear more than once
6237
6391
  * a ... VP variable to be printed
6238
6392
  */
6239
- #ifdef BIGDECIMAL_ENABLE_VPRINT
6240
6393
  static int
6241
6394
  VPrint(FILE *fp, const char *cntl_chr, Real *a)
6242
6395
  {
@@ -6249,95 +6402,94 @@ VPrint(FILE *fp, const char *cntl_chr, Real *a)
6249
6402
  /* nc : number of characters printed */
6250
6403
  ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
6251
6404
  while (*(cntl_chr + j)) {
6252
- if (*(cntl_chr + j) == '%' && *(cntl_chr + j + 1) != '%') {
6253
- nc = 0;
6254
- if (VpIsNaN(a)) {
6255
- fprintf(fp, SZ_NaN);
6256
- nc += 8;
6257
- }
6258
- else if (VpIsPosInf(a)) {
6259
- fprintf(fp, SZ_INF);
6260
- nc += 8;
6261
- }
6262
- else if (VpIsNegInf(a)) {
6263
- fprintf(fp, SZ_NINF);
6264
- nc += 9;
6265
- }
6266
- else if (!VpIsZero(a)) {
6267
- if (BIGDECIMAL_NEGATIVE_P(a)) {
6268
- fprintf(fp, "-");
6269
- ++nc;
6270
- }
6271
- nc += fprintf(fp, "0.");
6272
- switch (*(cntl_chr + j + 1)) {
6273
- default:
6274
- 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;
6275
6428
 
6276
- case '0': case 'z':
6277
- ZeroSup = 0;
6278
- ++j;
6279
- sep = cntl_chr[j] == 'z' ? BIGDECIMAL_COMPONENT_FIGURES : 10;
6280
- break;
6281
- }
6282
- for (i = 0; i < a->Prec; ++i) {
6283
- m = BASE1;
6284
- e = a->frac[i];
6285
- while (m) {
6286
- nn = e / m;
6287
- if (!ZeroSup || nn) {
6288
- nc += fprintf(fp, "%lu", (unsigned long)nn); /* The leading zero(s) */
6289
- /* as 0.00xx will not */
6290
- /* be printed. */
6291
- ++nd;
6292
- ZeroSup = 0; /* Set to print succeeding zeros */
6293
- }
6294
- if (nd >= sep) { /* print ' ' after every 10 digits */
6295
- nd = 0;
6296
- nc += fprintf(fp, " ");
6297
- }
6298
- e = e - nn * m;
6299
- m /= 10;
6300
- }
6301
- }
6302
- nc += fprintf(fp, "E%"PRIdSIZE, VpExponent10(a));
6303
- nc += fprintf(fp, " (%"PRIdVALUE", %lu, %lu)", a->exponent, a->Prec, a->MaxPrec);
6304
- }
6305
- else {
6306
- nc += fprintf(fp, "0.0");
6307
- }
6308
- }
6309
- else {
6310
- ++nc;
6311
- if (*(cntl_chr + j) == '\\') {
6312
- switch (*(cntl_chr + j + 1)) {
6313
- case 'n':
6314
- fprintf(fp, "\n");
6315
- ++j;
6316
- break;
6317
- case 't':
6318
- fprintf(fp, "\t");
6319
- ++j;
6320
- break;
6321
- case 'b':
6322
- fprintf(fp, "\n");
6323
- ++j;
6324
- break;
6325
- default:
6326
- fprintf(fp, "%c", *(cntl_chr + j));
6327
- break;
6328
- }
6329
- }
6330
- else {
6331
- fprintf(fp, "%c", *(cntl_chr + j));
6332
- if (*(cntl_chr + j) == '%') ++j;
6333
- }
6334
- }
6335
- 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++;
6336
6489
  }
6337
6490
 
6338
6491
  return (int)nc;
6339
6492
  }
6340
- #endif
6341
6493
 
6342
6494
  static void
6343
6495
  VpFormatSt(char *psz, size_t fFmt)
@@ -6382,188 +6534,254 @@ VpExponent10(Real *a)
6382
6534
  }
6383
6535
 
6384
6536
  VP_EXPORT void
6385
- VpSzMantissa(Real *a,char *psz)
6537
+ VpSzMantissa(Real *a, char *buf, size_t buflen)
6386
6538
  {
6387
6539
  size_t i, n, ZeroSup;
6388
6540
  DECDIG_DBL m, e, nn;
6389
6541
 
6390
6542
  if (VpIsNaN(a)) {
6391
- sprintf(psz, SZ_NaN);
6392
- return;
6543
+ snprintf(buf, buflen, SZ_NaN);
6544
+ return;
6393
6545
  }
6394
6546
  if (VpIsPosInf(a)) {
6395
- sprintf(psz, SZ_INF);
6547
+ snprintf(buf, buflen, SZ_INF);
6396
6548
  return;
6397
6549
  }
6398
6550
  if (VpIsNegInf(a)) {
6399
- sprintf(psz, SZ_NINF);
6551
+ snprintf(buf, buflen, SZ_NINF);
6400
6552
  return;
6401
6553
  }
6402
6554
 
6403
6555
  ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
6404
6556
  if (!VpIsZero(a)) {
6405
- if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
6406
- n = a->Prec;
6407
- for (i = 0; i < n; ++i) {
6408
- m = BASE1;
6409
- e = a->frac[i];
6410
- while (m) {
6411
- nn = e / m;
6412
- if (!ZeroSup || nn) {
6413
- sprintf(psz, "%lu", (unsigned long)nn); /* The leading zero(s) */
6414
- psz += strlen(psz);
6415
- /* as 0.00xx will be ignored. */
6416
- ZeroSup = 0; /* Set to print succeeding zeros */
6417
- }
6418
- e = e - nn * m;
6419
- m /= 10;
6420
- }
6421
- }
6422
- *psz = 0;
6423
- 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;
6424
6576
  }
6425
6577
  else {
6426
- if (VpIsPosZero(a)) sprintf(psz, "0");
6427
- else sprintf(psz, "-0");
6578
+ if (VpIsPosZero(a)) snprintf(buf, buflen, "0");
6579
+ else snprintf(buf, buflen, "-0");
6428
6580
  }
6429
6581
  }
6430
6582
 
6431
6583
  VP_EXPORT int
6432
- VpToSpecialString(Real *a,char *psz,int fPlus)
6584
+ VpToSpecialString(Real *a, char *buf, size_t buflen, int fPlus)
6433
6585
  /* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
6434
6586
  {
6435
6587
  if (VpIsNaN(a)) {
6436
- sprintf(psz,SZ_NaN);
6437
- return 1;
6588
+ snprintf(buf, buflen, SZ_NaN);
6589
+ return 1;
6438
6590
  }
6439
6591
 
6440
6592
  if (VpIsPosInf(a)) {
6441
- if (fPlus == 1) {
6442
- *psz++ = ' ';
6443
- }
6444
- else if (fPlus == 2) {
6445
- *psz++ = '+';
6446
- }
6447
- sprintf(psz, SZ_INF);
6448
- 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;
6449
6601
  }
6450
6602
  if (VpIsNegInf(a)) {
6451
- sprintf(psz, SZ_NINF);
6452
- return 1;
6603
+ snprintf(buf, buflen, SZ_NINF);
6604
+ return 1;
6453
6605
  }
6454
6606
  if (VpIsZero(a)) {
6455
- if (VpIsPosZero(a)) {
6456
- if (fPlus == 1) sprintf(psz, " 0.0");
6457
- else if (fPlus == 2) sprintf(psz, "+0.0");
6458
- else sprintf(psz, "0.0");
6459
- }
6460
- else sprintf(psz, "-0.0");
6461
- 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;
6462
6614
  }
6463
6615
  return 0;
6464
6616
  }
6465
6617
 
6466
6618
  VP_EXPORT void
6467
- VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
6619
+ VpToString(Real *a, char *buf, size_t buflen, size_t fFmt, int fPlus)
6468
6620
  /* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
6469
6621
  {
6470
6622
  size_t i, n, ZeroSup;
6471
6623
  DECDIG shift, m, e, nn;
6472
- char *pszSav = psz;
6624
+ char *p = buf;
6625
+ size_t plen = buflen;
6473
6626
  ssize_t ex;
6474
6627
 
6475
- if (VpToSpecialString(a, psz, fPlus)) return;
6628
+ if (VpToSpecialString(a, buf, buflen, fPlus)) return;
6476
6629
 
6477
6630
  ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
6478
6631
 
6479
- if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
6480
- else if (fPlus == 1) *psz++ = ' ';
6481
- 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);
6482
6653
 
6483
- *psz++ = '0';
6484
- *psz++ = '.';
6485
6654
  n = a->Prec;
6486
6655
  for (i = 0; i < n; ++i) {
6487
- m = BASE1;
6488
- e = a->frac[i];
6489
- while (m) {
6490
- nn = e / m;
6491
- if (!ZeroSup || nn) {
6492
- sprintf(psz, "%lu", (unsigned long)nn); /* The reading zero(s) */
6493
- psz += strlen(psz);
6494
- /* as 0.00xx will be ignored. */
6495
- ZeroSup = 0; /* Set to print succeeding zeros */
6496
- }
6497
- e = e - nn * m;
6498
- m /= 10;
6499
- }
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
+ }
6500
6671
  }
6672
+
6501
6673
  ex = a->exponent * (ssize_t)BASE_FIG;
6502
6674
  shift = BASE1;
6503
6675
  while (a->frac[0] / shift == 0) {
6504
- --ex;
6505
- shift /= 10;
6676
+ --ex;
6677
+ shift /= 10;
6506
6678
  }
6507
- while (psz[-1] == '0') {
6508
- *(--psz) = 0;
6679
+ while (p - 1 > buf && p[-1] == '0') {
6680
+ *(--p) = '\0';
6681
+ ++plen;
6509
6682
  }
6510
- sprintf(psz, "e%"PRIdSIZE, ex);
6511
- 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
6512
6689
  }
6513
6690
 
6514
6691
  VP_EXPORT void
6515
- VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
6692
+ VpToFString(Real *a, char *buf, size_t buflen, size_t fFmt, int fPlus)
6516
6693
  /* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
6517
6694
  {
6518
6695
  size_t i, n;
6519
6696
  DECDIG m, e, nn;
6520
- char *pszSav = psz;
6697
+ char *p = buf;
6698
+ size_t plen = buflen;
6521
6699
  ssize_t ex;
6522
6700
 
6523
- if (VpToSpecialString(a, psz, fPlus)) return;
6701
+ if (VpToSpecialString(a, buf, buflen, fPlus)) return;
6702
+
6703
+ #define ADVANCE(n) do { \
6704
+ if (plen < n) goto overflow; \
6705
+ p += n; \
6706
+ plen -= n; \
6707
+ } while (0)
6524
6708
 
6525
- if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
6526
- else if (fPlus == 1) *psz++ = ' ';
6527
- else if (fPlus == 2) *psz++ = '+';
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
+ }
6528
6722
 
6529
6723
  n = a->Prec;
6530
6724
  ex = a->exponent;
6531
6725
  if (ex <= 0) {
6532
- *psz++ = '0';*psz++ = '.';
6533
- while (ex < 0) {
6534
- for (i=0; i < BASE_FIG; ++i) *psz++ = '0';
6535
- ++ex;
6536
- }
6537
- 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;
6538
6735
  }
6539
6736
 
6540
6737
  for (i = 0; i < n; ++i) {
6541
- --ex;
6542
- if (i == 0 && ex >= 0) {
6543
- sprintf(psz, "%lu", (unsigned long)a->frac[i]);
6544
- psz += strlen(psz);
6545
- }
6546
- else {
6547
- m = BASE1;
6548
- e = a->frac[i];
6549
- while (m) {
6550
- nn = e / m;
6551
- *psz++ = (char)(nn + '0');
6552
- e = e - nn * m;
6553
- m /= 10;
6554
- }
6555
- }
6556
- 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
+ }
6557
6759
  }
6558
6760
  while (--ex>=0) {
6559
- m = BASE;
6560
- while (m /= 10) *psz++ = '0';
6561
- 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;
6562
6776
  }
6563
- *psz = 0;
6564
- while (psz[-1] == '0') *(--psz) = 0;
6565
- if (psz[-1] == '.') sprintf(psz, "0");
6566
- if (fFmt) VpFormatSt(pszSav, fFmt);
6777
+ if (p - 1 > buf && p[-1] == '.') {
6778
+ snprintf(p, plen, "0");
6779
+ }
6780
+ if (fFmt) VpFormatSt(buf, fFmt);
6781
+
6782
+ overflow:
6783
+ return;
6784
+ #undef ADVANCE
6567
6785
  }
6568
6786
 
6569
6787
  /*
@@ -6972,8 +7190,9 @@ VpSqrt(Real *y, Real *x)
6972
7190
  if (x->MaxPrec > (size_t)n) n = (ssize_t)x->MaxPrec;
6973
7191
 
6974
7192
  /* allocate temporally variables */
6975
- f = VpAlloc(y->MaxPrec * (BASE_FIG + 2), "#1", 1, 1);
6976
- 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));
6977
7196
 
6978
7197
  nr = 0;
6979
7198
  y_prec = y->MaxPrec;
@@ -6998,16 +7217,21 @@ VpSqrt(Real *y, Real *x)
6998
7217
  f->MaxPrec = y->MaxPrec + 1;
6999
7218
  n = (SIGNED_VALUE)(y_prec * BASE_FIG);
7000
7219
  if (n < (SIGNED_VALUE)maxnr) n = (SIGNED_VALUE)maxnr;
7220
+
7221
+ /*
7222
+ * Perform: y_{n+1} = (y_n - x/y_n) / 2
7223
+ */
7001
7224
  do {
7002
- y->MaxPrec *= 2;
7003
- if (y->MaxPrec > y_prec) y->MaxPrec = y_prec;
7004
- f->MaxPrec = y->MaxPrec;
7005
- VpDivd(f, r, x, y); /* f = x/y */
7006
- VpAddSub(r, f, y, -1); /* r = f - y */
7007
- VpMult(f, VpPt5, r); /* f = 0.5*r */
7008
- if (VpIsZero(f)) goto converge;
7009
- VpAddSub(r, f, y, 1); /* r = y + f */
7010
- 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 */
7011
7235
  } while (++nr < n);
7012
7236
 
7013
7237
  #ifdef BIGDECIMAL_DEBUG
@@ -7032,8 +7256,8 @@ converge:
7032
7256
  y->MaxPrec = y_prec;
7033
7257
 
7034
7258
  Exit:
7035
- VpFree(f);
7036
- VpFree(r);
7259
+ rbd_free_struct(f);
7260
+ rbd_free_struct(r);
7037
7261
  return 1;
7038
7262
  }
7039
7263
 
@@ -7424,9 +7648,10 @@ VpPowerByInt(Real *y, Real *x, SIGNED_VALUE n)
7424
7648
  }
7425
7649
 
7426
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);
7427
7654
 
7428
- w1 = VpAlloc((y->MaxPrec + 2) * BASE_FIG, "#0", 1, 1);
7429
- w2 = VpAlloc((w1->MaxPrec * 2 + 1) * BASE_FIG, "#0", 1, 1);
7430
7655
  /* calculation start */
7431
7656
 
7432
7657
  VpAsgn(y, x, 1);
@@ -7455,8 +7680,8 @@ Exit:
7455
7680
  printf(" n=%"PRIdVALUE"\n", n);
7456
7681
  }
7457
7682
  #endif /* BIGDECIMAL_DEBUG */
7458
- VpFree(w2);
7459
- VpFree(w1);
7683
+ rbd_free_struct(w2);
7684
+ rbd_free_struct(w1);
7460
7685
  return 1;
7461
7686
  }
7462
7687