bigdecimal 3.1.1 → 3.1.3

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