bigdecimal 3.1.1 → 3.1.4

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
 
@@ -33,6 +31,8 @@
33
31
  #include "bits.h"
34
32
  #include "static_assert.h"
35
33
 
34
+ #define BIGDECIMAL_VERSION "3.1.4"
35
+
36
36
  /* #define ENABLE_NUMERIC_STRING */
37
37
 
38
38
  #define SIGNED_VALUE_MAX INTPTR_MAX
@@ -61,6 +61,13 @@ static ID id_to_r;
61
61
  static ID id_eq;
62
62
  static ID id_half;
63
63
 
64
+ #define RBD_NUM_ROUNDING_MODES 11
65
+
66
+ static struct {
67
+ ID id;
68
+ uint8_t mode;
69
+ } rbd_rounding_modes[RBD_NUM_ROUNDING_MODES];
70
+
64
71
  /* MACRO's to guard objects from GC by keeping them in stack */
65
72
  #ifdef RBIMPL_ATTR_MAYBE_UNUSED
66
73
  #define ENTER(n) RBIMPL_ATTR_MAYBE_UNUSED() volatile VALUE vStack[n];int iStack=0
@@ -102,9 +109,163 @@ static ID id_half;
102
109
  # define RB_OBJ_STRING(obj) StringValueCStr(obj)
103
110
  #endif
104
111
 
112
+ #ifndef MAYBE_UNUSED
113
+ # define MAYBE_UNUSED(x) x
114
+ #endif
115
+
105
116
  #define BIGDECIMAL_POSITIVE_P(bd) ((bd)->sign > 0)
106
117
  #define BIGDECIMAL_NEGATIVE_P(bd) ((bd)->sign < 0)
107
118
 
119
+ /*
120
+ * ================== Memory allocation ============================
121
+ */
122
+
123
+ #ifdef BIGDECIMAL_DEBUG
124
+ static size_t rbd_allocation_count = 0; /* Memory allocation counter */
125
+ static inline void
126
+ atomic_allocation_count_inc(void)
127
+ {
128
+ RUBY_ATOMIC_SIZE_INC(rbd_allocation_count);
129
+ }
130
+ static inline void
131
+ atomic_allocation_count_dec_nounderflow(void)
132
+ {
133
+ if (rbd_allocation_count == 0) return;
134
+ RUBY_ATOMIC_SIZE_DEC(rbd_allocation_count);
135
+ }
136
+ static void
137
+ check_allocation_count_nonzero(void)
138
+ {
139
+ if (rbd_allocation_count != 0) return;
140
+ rb_bug("[bigdecimal][rbd_free_struct] Too many memory free calls");
141
+ }
142
+ #else
143
+ # define atomic_allocation_count_inc() /* nothing */
144
+ # define atomic_allocation_count_dec_nounderflow() /* nothing */
145
+ # define check_allocation_count_nonzero() /* nothing */
146
+ #endif /* BIGDECIMAL_DEBUG */
147
+
148
+ PUREFUNC(static inline size_t rbd_struct_size(size_t const));
149
+
150
+ static inline size_t
151
+ rbd_struct_size(size_t const internal_digits)
152
+ {
153
+ size_t const frac_len = (internal_digits == 0) ? 1 : internal_digits;
154
+ return offsetof(Real, frac) + frac_len * sizeof(DECDIG);
155
+ }
156
+
157
+ static inline Real *
158
+ rbd_allocate_struct(size_t const internal_digits)
159
+ {
160
+ size_t const size = rbd_struct_size(internal_digits);
161
+ Real *real = ruby_xcalloc(1, size);
162
+ atomic_allocation_count_inc();
163
+ real->MaxPrec = internal_digits;
164
+ return real;
165
+ }
166
+
167
+ static size_t
168
+ rbd_calculate_internal_digits(size_t const digits, bool limit_precision)
169
+ {
170
+ size_t const len = roomof(digits, BASE_FIG);
171
+ if (limit_precision) {
172
+ size_t const prec_limit = VpGetPrecLimit();
173
+ if (prec_limit > 0) {
174
+ /* NOTE: 2 more digits for rounding and division */
175
+ size_t const max_len = roomof(prec_limit, BASE_FIG) + 2;
176
+ if (len > max_len)
177
+ return max_len;
178
+ }
179
+ }
180
+
181
+ return len;
182
+ }
183
+
184
+ static inline Real *
185
+ rbd_allocate_struct_decimal_digits(size_t const decimal_digits, bool limit_precision)
186
+ {
187
+ size_t const internal_digits = rbd_calculate_internal_digits(decimal_digits, limit_precision);
188
+ return rbd_allocate_struct(internal_digits);
189
+ }
190
+
191
+ static VALUE BigDecimal_wrap_struct(VALUE obj, Real *vp);
192
+
193
+ static Real *
194
+ rbd_reallocate_struct(Real *real, size_t const internal_digits)
195
+ {
196
+ size_t const size = rbd_struct_size(internal_digits);
197
+ VALUE obj = real ? real->obj : 0;
198
+ Real *new_real = (Real *)ruby_xrealloc(real, size);
199
+ new_real->MaxPrec = internal_digits;
200
+ if (obj) {
201
+ new_real->obj = 0;
202
+ BigDecimal_wrap_struct(obj, new_real);
203
+ }
204
+ return new_real;
205
+ }
206
+
207
+ static void
208
+ rbd_free_struct(Real *real)
209
+ {
210
+ if (real != NULL) {
211
+ check_allocation_count_nonzero();
212
+ ruby_xfree(real);
213
+ atomic_allocation_count_dec_nounderflow();
214
+ }
215
+ }
216
+
217
+ #define NewZero rbd_allocate_struct_zero
218
+ static Real *
219
+ rbd_allocate_struct_zero(int sign, size_t const digits, bool limit_precision)
220
+ {
221
+ Real *real = rbd_allocate_struct_decimal_digits(digits, limit_precision);
222
+ VpSetZero(real, sign);
223
+ return real;
224
+ }
225
+
226
+ MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_limited(int sign, size_t const digits));
227
+ #define NewZeroLimited rbd_allocate_struct_zero_limited
228
+ static inline Real *
229
+ rbd_allocate_struct_zero_limited(int sign, size_t const digits)
230
+ {
231
+ return rbd_allocate_struct_zero(sign, digits, true);
232
+ }
233
+
234
+ MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_nolimit(int sign, size_t const digits));
235
+ #define NewZeroNolimit rbd_allocate_struct_zero_nolimit
236
+ static inline Real *
237
+ rbd_allocate_struct_zero_nolimit(int sign, size_t const digits)
238
+ {
239
+ return rbd_allocate_struct_zero(sign, digits, false);
240
+ }
241
+
242
+ #define NewOne rbd_allocate_struct_one
243
+ static Real *
244
+ rbd_allocate_struct_one(int sign, size_t const digits, bool limit_precision)
245
+ {
246
+ Real *real = rbd_allocate_struct_decimal_digits(digits, limit_precision);
247
+ VpSetOne(real);
248
+ if (sign < 0)
249
+ VpSetSign(real, VP_SIGN_NEGATIVE_FINITE);
250
+ return real;
251
+ }
252
+
253
+ MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_limited(int sign, size_t const digits));
254
+ #define NewOneLimited rbd_allocate_struct_one_limited
255
+ static inline Real *
256
+ rbd_allocate_struct_one_limited(int sign, size_t const digits)
257
+ {
258
+ return rbd_allocate_struct_one(sign, digits, true);
259
+ }
260
+
261
+ MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_nolimit(int sign, size_t const digits));
262
+ #define NewOneNolimit rbd_allocate_struct_one_nolimit
263
+ static inline Real *
264
+ rbd_allocate_struct_one_nolimit(int sign, size_t const digits)
265
+ {
266
+ return rbd_allocate_struct_one(sign, digits, false);
267
+ }
268
+
108
269
  /*
109
270
  * ================== Ruby Interface part ==========================
110
271
  */
@@ -120,10 +281,7 @@ static VALUE VpCheckGetValue(Real *p);
120
281
  static void VpInternalRound(Real *c, size_t ixDigit, DECDIG vPrev, DECDIG v);
121
282
  static int VpLimitRound(Real *c, size_t ixDigit);
122
283
  static Real *VpCopy(Real *pv, Real const* const x);
123
-
124
- #ifdef BIGDECIMAL_ENABLE_VPRINT
125
284
  static int VPrint(FILE *fp,const char *cntl_chr,Real *a);
126
- #endif
127
285
 
128
286
  /*
129
287
  * **** BigDecimal part ****
@@ -138,7 +296,7 @@ static VALUE BigDecimal_negative_zero(void);
138
296
  static void
139
297
  BigDecimal_delete(void *pv)
140
298
  {
141
- VpFree(pv);
299
+ rbd_free_struct(pv);
142
300
  }
143
301
 
144
302
  static size_t
@@ -157,10 +315,64 @@ static const rb_data_type_t BigDecimal_data_type = {
157
315
  "BigDecimal",
158
316
  { 0, BigDecimal_delete, BigDecimal_memsize, },
159
317
  #ifdef RUBY_TYPED_FREE_IMMEDIATELY
160
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE
318
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE | RUBY_TYPED_WB_PROTECTED
161
319
  #endif
162
320
  };
163
321
 
322
+ static Real *
323
+ rbd_allocate_struct_zero_wrap_klass(VALUE klass, int sign, size_t const digits, bool limit_precision)
324
+ {
325
+ Real *real = rbd_allocate_struct_zero(sign, digits, limit_precision);
326
+ if (real != NULL) {
327
+ VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
328
+ BigDecimal_wrap_struct(obj, real);
329
+ }
330
+ return real;
331
+ }
332
+
333
+ MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_limited_wrap(int sign, size_t const digits));
334
+ #define NewZeroWrapLimited rbd_allocate_struct_zero_limited_wrap
335
+ static inline Real *
336
+ rbd_allocate_struct_zero_limited_wrap(int sign, size_t const digits)
337
+ {
338
+ return rbd_allocate_struct_zero_wrap_klass(rb_cBigDecimal, sign, digits, true);
339
+ }
340
+
341
+ MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_nolimit_wrap(int sign, size_t const digits));
342
+ #define NewZeroWrapNolimit rbd_allocate_struct_zero_nolimit_wrap
343
+ static inline Real *
344
+ rbd_allocate_struct_zero_nolimit_wrap(int sign, size_t const digits)
345
+ {
346
+ return rbd_allocate_struct_zero_wrap_klass(rb_cBigDecimal, sign, digits, false);
347
+ }
348
+
349
+ static Real *
350
+ rbd_allocate_struct_one_wrap_klass(VALUE klass, int sign, size_t const digits, bool limit_precision)
351
+ {
352
+ Real *real = rbd_allocate_struct_one(sign, digits, limit_precision);
353
+ if (real != NULL) {
354
+ VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
355
+ BigDecimal_wrap_struct(obj, real);
356
+ }
357
+ return real;
358
+ }
359
+
360
+ MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_limited_wrap(int sign, size_t const digits));
361
+ #define NewOneWrapLimited rbd_allocate_struct_one_limited_wrap
362
+ static inline Real *
363
+ rbd_allocate_struct_one_limited_wrap(int sign, size_t const digits)
364
+ {
365
+ return rbd_allocate_struct_one_wrap_klass(rb_cBigDecimal, sign, digits, true);
366
+ }
367
+
368
+ MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_nolimit_wrap(int sign, size_t const digits));
369
+ #define NewOneWrapNolimit rbd_allocate_struct_one_nolimit_wrap
370
+ static inline Real *
371
+ rbd_allocate_struct_one_nolimit_wrap(int sign, size_t const digits)
372
+ {
373
+ return rbd_allocate_struct_one_wrap_klass(rb_cBigDecimal, sign, digits, false);
374
+ }
375
+
164
376
  static inline int
165
377
  is_kind_of_BigDecimal(VALUE const v)
166
378
  {
@@ -214,7 +426,7 @@ GetVpValueWithPrec(VALUE v, long prec, int must)
214
426
 
215
427
  case T_FIXNUM: {
216
428
  char szD[128];
217
- sprintf(szD, "%ld", FIX2LONG(v));
429
+ snprintf(szD, 128, "%ld", FIX2LONG(v));
218
430
  v = rb_cstr_convert_to_BigDecimal(szD, VpBaseFig() * 2 + 1, must);
219
431
  break;
220
432
  }
@@ -249,7 +461,7 @@ SomeOneMayDoIt:
249
461
  return NULL; /* NULL means to coerce */
250
462
  }
251
463
 
252
- static Real*
464
+ static inline Real*
253
465
  GetVpValue(VALUE v, int must)
254
466
  {
255
467
  return GetVpValueWithPrec(v, -1, must);
@@ -264,7 +476,7 @@ GetVpValue(VALUE v, int must)
264
476
  * BigDecimal.double_fig # => 16
265
477
  *
266
478
  */
267
- static VALUE
479
+ static inline VALUE
268
480
  BigDecimal_double_fig(VALUE self)
269
481
  {
270
482
  return INT2FIX(VpDblFig());
@@ -486,15 +698,15 @@ BigDecimal_precision_scale(VALUE self)
486
698
  *
487
699
  * Returns the number of decimal significant digits in +self+.
488
700
  *
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
701
+ * BigDecimal("0").n_significant_digits # => 0
702
+ * BigDecimal("1").n_significant_digits # => 1
703
+ * BigDecimal("1.1").n_significant_digits # => 2
704
+ * BigDecimal("3.1415").n_significant_digits # => 5
705
+ * BigDecimal("-1e20").n_significant_digits # => 1
706
+ * BigDecimal("1e-20").n_significant_digits # => 1
707
+ * BigDecimal("Infinity").n_significant_digits # => 0
708
+ * BigDecimal("-Infinity").n_significant_digits # => 0
709
+ * BigDecimal("NaN").n_significant_digits # => 0
498
710
  */
499
711
  static VALUE
500
712
  BigDecimal_n_significant_digits(VALUE self)
@@ -573,13 +785,15 @@ BigDecimal_dump(int argc, VALUE *argv, VALUE self)
573
785
  char *psz;
574
786
  VALUE dummy;
575
787
  volatile VALUE dump;
788
+ size_t len;
576
789
 
577
790
  rb_scan_args(argc, argv, "01", &dummy);
578
791
  GUARD_OBJ(vp,GetVpValue(self, 1));
579
792
  dump = rb_str_new(0, VpNumOfChars(vp, "E")+50);
580
793
  psz = RSTRING_PTR(dump);
581
- sprintf(psz, "%"PRIuSIZE":", VpMaxPrec(vp)*VpBaseFig());
582
- VpToString(vp, psz+strlen(psz), 0, 0);
794
+ snprintf(psz, RSTRING_LEN(dump), "%"PRIuSIZE":", VpMaxPrec(vp)*VpBaseFig());
795
+ len = strlen(psz);
796
+ VpToString(vp, psz+len, RSTRING_LEN(dump)-len, 0, 0);
583
797
  rb_str_resize(dump, strlen(psz));
584
798
  return dump;
585
799
  }
@@ -623,18 +837,19 @@ check_rounding_mode_option(VALUE const opts)
623
837
  assert(RB_TYPE_P(opts, T_HASH));
624
838
 
625
839
  if (NIL_P(opts))
626
- goto noopt;
840
+ goto no_opt;
627
841
 
628
842
  mode = rb_hash_lookup2(opts, ID2SYM(id_half), Qundef);
629
843
  if (mode == Qundef || NIL_P(mode))
630
- goto noopt;
844
+ goto no_opt;
631
845
 
632
846
  if (SYMBOL_P(mode))
633
847
  mode = rb_sym2str(mode);
634
848
  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;
849
+ VALUE str_mode = rb_check_string_type(mode);
850
+ if (NIL_P(str_mode))
851
+ goto invalid;
852
+ mode = str_mode;
638
853
  }
639
854
  s = RSTRING_PTR(mode);
640
855
  l = RSTRING_LEN(mode);
@@ -652,13 +867,11 @@ check_rounding_mode_option(VALUE const opts)
652
867
  default:
653
868
  break;
654
869
  }
870
+
655
871
  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);
872
+ rb_raise(rb_eArgError, "invalid rounding mode (%"PRIsVALUE")", mode);
660
873
 
661
- noopt:
874
+ no_opt:
662
875
  return VpGetRoundMode();
663
876
  }
664
877
 
@@ -667,34 +880,23 @@ check_rounding_mode(VALUE const v)
667
880
  {
668
881
  unsigned short sw;
669
882
  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;
883
+ if (RB_TYPE_P(v, T_SYMBOL)) {
884
+ int i;
885
+ id = SYM2ID(v);
886
+ for (i = 0; i < RBD_NUM_ROUNDING_MODES; ++i) {
887
+ if (rbd_rounding_modes[i].id == id) {
888
+ return rbd_rounding_modes[i].mode;
889
+ }
890
+ }
891
+ rb_raise(rb_eArgError, "invalid rounding mode (%"PRIsVALUE")", v);
691
892
  }
692
-
693
- sw = NUM2USHORT(v);
694
- if (!VpIsRoundMode(sw)) {
695
- rb_raise(rb_eArgError, "invalid rounding mode");
893
+ else {
894
+ sw = NUM2USHORT(v);
895
+ if (!VpIsRoundMode(sw)) {
896
+ rb_raise(rb_eArgError, "invalid rounding mode (%"PRIsVALUE")", v);
897
+ }
898
+ return sw;
696
899
  }
697
- return sw;
698
900
  }
699
901
 
700
902
  /* call-seq:
@@ -933,11 +1135,17 @@ GetAddSubPrec(Real *a, Real *b)
933
1135
  return mx;
934
1136
  }
935
1137
 
936
- static SIGNED_VALUE
937
- GetPrecisionInt(VALUE v)
1138
+ static inline SIGNED_VALUE
1139
+ check_int_precision(VALUE v)
938
1140
  {
939
1141
  SIGNED_VALUE n;
940
- n = NUM2INT(v);
1142
+ #if SIZEOF_VALUE <= SIZEOF_LONG
1143
+ n = (SIGNED_VALUE)NUM2LONG(v);
1144
+ #elif SIZEOF_VALUE <= SIZEOF_LONG_LONG
1145
+ n = (SIGNED_VALUE)NUM2LL(v);
1146
+ #else
1147
+ # error SIZEOF_VALUE is too large
1148
+ #endif
941
1149
  if (n < 0) {
942
1150
  rb_raise(rb_eArgError, "negative precision");
943
1151
  }
@@ -979,26 +1187,12 @@ VpCreateRbObject(size_t mx, const char *str, bool raise_exception)
979
1187
  return VpNewRbClass(mx, str, rb_cBigDecimal, true, raise_exception);
980
1188
  }
981
1189
 
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
1190
  static Real *
997
1191
  VpCopy(Real *pv, Real const* const x)
998
1192
  {
999
1193
  assert(x != NULL);
1000
1194
 
1001
- pv = VpReallocReal(pv, x->MaxPrec);
1195
+ pv = rbd_reallocate_struct(pv, x->MaxPrec);
1002
1196
  pv->MaxPrec = x->MaxPrec;
1003
1197
  pv->Prec = x->Prec;
1004
1198
  pv->exponent = x->exponent;
@@ -1119,7 +1313,7 @@ BigDecimal_to_f(VALUE self)
1119
1313
 
1120
1314
  str = rb_str_new(0, VpNumOfChars(p, "E"));
1121
1315
  buf = RSTRING_PTR(str);
1122
- VpToString(p, buf, 0, 0);
1316
+ VpToString(p, buf, RSTRING_LEN(str), 0, 0);
1123
1317
  errno = 0;
1124
1318
  d = strtod(buf, 0);
1125
1319
  if (errno == ERANGE) {
@@ -1276,17 +1470,17 @@ BigDecimal_add(VALUE self, VALUE r)
1276
1470
 
1277
1471
  mx = GetAddSubPrec(a, b);
1278
1472
  if (mx == (size_t)-1L) {
1279
- GUARD_OBJ(c, VpCreateRbObject(VpBaseFig() + 1, "0", true));
1280
- VpAddSub(c, a, b, 1);
1473
+ GUARD_OBJ(c, NewZeroWrapLimited(1, VpBaseFig() + 1));
1474
+ VpAddSub(c, a, b, 1);
1281
1475
  }
1282
1476
  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
- }
1477
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx * (VpBaseFig() + 1)));
1478
+ if (!mx) {
1479
+ VpSetInf(c, VpGetSign(a));
1480
+ }
1481
+ else {
1482
+ VpAddSub(c, a, b, 1);
1483
+ }
1290
1484
  }
1291
1485
  return VpCheckGetValue(c);
1292
1486
  }
@@ -1331,17 +1525,17 @@ BigDecimal_sub(VALUE self, VALUE r)
1331
1525
 
1332
1526
  mx = GetAddSubPrec(a,b);
1333
1527
  if (mx == (size_t)-1L) {
1334
- GUARD_OBJ(c, VpCreateRbObject(VpBaseFig() + 1, "0", true));
1335
- VpAddSub(c, a, b, -1);
1528
+ GUARD_OBJ(c, NewZeroWrapLimited(1, VpBaseFig() + 1));
1529
+ VpAddSub(c, a, b, -1);
1336
1530
  }
1337
1531
  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
- }
1532
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx *(VpBaseFig() + 1)));
1533
+ if (!mx) {
1534
+ VpSetInf(c,VpGetSign(a));
1535
+ }
1536
+ else {
1537
+ VpAddSub(c, a, b, -1);
1538
+ }
1345
1539
  }
1346
1540
  return VpCheckGetValue(c);
1347
1541
  }
@@ -1581,7 +1775,7 @@ BigDecimal_neg(VALUE self)
1581
1775
  ENTER(5);
1582
1776
  Real *c, *a;
1583
1777
  GUARD_OBJ(a, GetVpValue(self, 1));
1584
- GUARD_OBJ(c, VpCreateRbObject(a->Prec *(VpBaseFig() + 1), "0", true));
1778
+ GUARD_OBJ(c, NewZeroWrapLimited(1, a->Prec *(VpBaseFig() + 1)));
1585
1779
  VpAsgn(c, a, -1);
1586
1780
  return VpCheckGetValue(c);
1587
1781
  }
@@ -1608,7 +1802,7 @@ BigDecimal_mult(VALUE self, VALUE r)
1608
1802
  SAVE(b);
1609
1803
 
1610
1804
  mx = a->Prec + b->Prec;
1611
- GUARD_OBJ(c, VpCreateRbObject(mx *(VpBaseFig() + 1), "0", true));
1805
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx * (VpBaseFig() + 1)));
1612
1806
  VpMult(c, a, b);
1613
1807
  return VpCheckGetValue(c);
1614
1808
  }
@@ -1618,7 +1812,7 @@ BigDecimal_divide(VALUE self, VALUE r, Real **c, Real **res, Real **div)
1618
1812
  /* For c = self.div(r): with round operation */
1619
1813
  {
1620
1814
  ENTER(5);
1621
- Real *a, *b, *d;
1815
+ Real *a, *b;
1622
1816
  ssize_t a_prec, b_prec;
1623
1817
  size_t mx;
1624
1818
 
@@ -1647,18 +1841,16 @@ BigDecimal_divide(VALUE self, VALUE r, Real **c, Real **res, Real **div)
1647
1841
  SAVE(b);
1648
1842
  *div = b;
1649
1843
 
1650
- mx = (a->Prec > b->Prec) ? a->Prec : b->Prec;
1651
- mx *= BASE_FIG;
1652
-
1653
1844
  BigDecimal_count_precision_and_scale(self, &a_prec, NULL);
1654
1845
  BigDecimal_count_precision_and_scale(rr, &b_prec, NULL);
1655
1846
  mx = (a_prec > b_prec) ? a_prec : b_prec;
1847
+ mx *= 2;
1656
1848
 
1657
1849
  if (2*BIGDECIMAL_DOUBLE_FIGURES > mx)
1658
1850
  mx = 2*BIGDECIMAL_DOUBLE_FIGURES;
1659
1851
 
1660
- GUARD_OBJ((*c), VpCreateRbObject(mx + 2*BASE_FIG, "#0", true));
1661
- GUARD_OBJ((*res), VpCreateRbObject(mx*2 + 2*BASE_FIG, "#0", true));
1852
+ GUARD_OBJ((*c), NewZeroWrapNolimit(1, mx + 2*BASE_FIG));
1853
+ GUARD_OBJ((*res), NewZeroWrapNolimit(1, (mx + 1)*2 + 2*BASE_FIG));
1662
1854
  VpDivd(*c, *res, a, b);
1663
1855
 
1664
1856
  return Qnil;
@@ -1723,7 +1915,7 @@ BigDecimal_quo(int argc, VALUE *argv, VALUE self)
1723
1915
 
1724
1916
  argc = rb_scan_args(argc, argv, "11", &value, &digits);
1725
1917
  if (argc > 1) {
1726
- n = GetPrecisionInt(digits);
1918
+ n = check_int_precision(digits);
1727
1919
  }
1728
1920
 
1729
1921
  if (n > 0) {
@@ -1808,15 +2000,17 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
1808
2000
  BigDecimal_count_precision_and_scale(rr, &b_prec, NULL);
1809
2001
 
1810
2002
  mx = (a_prec > b_prec) ? a_prec : b_prec;
2003
+ mx *= 2;
2004
+
1811
2005
  if (2*BIGDECIMAL_DOUBLE_FIGURES > mx)
1812
2006
  mx = 2*BIGDECIMAL_DOUBLE_FIGURES;
1813
2007
 
1814
- GUARD_OBJ(c, VpCreateRbObject(mx + 2*BASE_FIG, "0", true));
1815
- GUARD_OBJ(res, VpCreateRbObject(mx*2 + 2*BASE_FIG, "#0", true));
2008
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx + 2*BASE_FIG));
2009
+ GUARD_OBJ(res, NewZeroWrapNolimit(1, mx*2 + 2*BASE_FIG));
1816
2010
  VpDivd(c, res, a, b);
1817
2011
 
1818
2012
  mx = c->Prec * BASE_FIG;
1819
- GUARD_OBJ(d, VpCreateRbObject(mx, "0", true));
2013
+ GUARD_OBJ(d, NewZeroWrapLimited(1, mx));
1820
2014
  VpActiveRound(d, c, VP_ROUND_DOWN, 0);
1821
2015
 
1822
2016
  VpMult(res, d, b);
@@ -1824,10 +2018,10 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
1824
2018
 
1825
2019
  if (!VpIsZero(c) && (VpGetSign(a) * VpGetSign(b) < 0)) {
1826
2020
  /* result adjustment for negative case */
1827
- res = VpReallocReal(res, d->MaxPrec);
2021
+ res = rbd_reallocate_struct(res, d->MaxPrec);
1828
2022
  res->MaxPrec = d->MaxPrec;
1829
2023
  VpAddSub(res, d, VpOne(), -1);
1830
- GUARD_OBJ(d, VpCreateRbObject(GetAddSubPrec(c, b) * 2*BASE_FIG, "0", true));
2024
+ GUARD_OBJ(d, NewZeroWrapLimited(1, GetAddSubPrec(c, b) * 2*BASE_FIG));
1831
2025
  VpAddSub(d, c, b, 1);
1832
2026
  *div = res;
1833
2027
  *mod = d;
@@ -1890,18 +2084,25 @@ BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
1890
2084
  if (!b) return DoSomeOne(self, r, rb_intern("remainder"));
1891
2085
  SAVE(b);
1892
2086
 
2087
+ if (VpIsPosInf(b) || VpIsNegInf(b)) {
2088
+ GUARD_OBJ(*dv, NewZeroWrapLimited(1, 1));
2089
+ VpSetZero(*dv, 1);
2090
+ *rv = a;
2091
+ return Qnil;
2092
+ }
2093
+
1893
2094
  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));
2095
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
2096
+ GUARD_OBJ(res, NewZeroWrapNolimit(1, (mx+1) * 2 + (VpBaseFig() + 1)));
2097
+ GUARD_OBJ(rr, NewZeroWrapNolimit(1, (mx+1) * 2 + (VpBaseFig() + 1)));
2098
+ GUARD_OBJ(ff, NewZeroWrapNolimit(1, (mx+1) * 2 + (VpBaseFig() + 1)));
1898
2099
 
1899
2100
  VpDivd(c, res, a, b);
1900
2101
 
1901
2102
  mx = c->Prec *(VpBaseFig() + 1);
1902
2103
 
1903
- GUARD_OBJ(d, VpCreateRbObject(mx, "0", true));
1904
- GUARD_OBJ(f, VpCreateRbObject(mx, "0", true));
2104
+ GUARD_OBJ(d, NewZeroWrapLimited(1, mx));
2105
+ GUARD_OBJ(f, NewZeroWrapLimited(1, mx));
1905
2106
 
1906
2107
  VpActiveRound(d, c, VP_ROUND_DOWN, 0); /* 0: round off */
1907
2108
 
@@ -1986,7 +2187,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
1986
2187
  }
1987
2188
 
1988
2189
  /* div in BigDecimal sense */
1989
- ix = GetPrecisionInt(n);
2190
+ ix = check_int_precision(n);
1990
2191
  if (ix == 0) {
1991
2192
  return BigDecimal_div(self, b);
1992
2193
  }
@@ -1997,7 +2198,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
1997
2198
  size_t b_prec = ix;
1998
2199
  size_t pl = VpSetPrecLimit(0);
1999
2200
 
2000
- GUARD_OBJ(cv, VpCreateRbObject(mx + VpBaseFig(), "0", true));
2201
+ GUARD_OBJ(cv, NewZeroWrapLimited(1, mx + VpBaseFig()));
2001
2202
  GUARD_OBJ(av, GetVpValue(self, 1));
2002
2203
  /* TODO: I want to refactor this precision control for a float value later
2003
2204
  * by introducing an implicit conversion function instead of
@@ -2008,7 +2209,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
2008
2209
  GUARD_OBJ(bv, GetVpValueWithPrec(b, b_prec, 1));
2009
2210
  mx = av->Prec + bv->Prec + 2;
2010
2211
  if (mx <= cv->MaxPrec) mx = cv->MaxPrec + 1;
2011
- GUARD_OBJ(res, VpCreateRbObject((mx * 2 + 2)*VpBaseFig(), "#0", true));
2212
+ GUARD_OBJ(res, NewZeroWrapNolimit(1, (mx * 2 + 2)*VpBaseFig()));
2012
2213
  VpDivd(cv, res, av, bv);
2013
2214
  VpSetPrecLimit(pl);
2014
2215
  VpLeftRound(cv, VpGetRoundMode(), ix);
@@ -2091,7 +2292,7 @@ BigDecimal_add2(VALUE self, VALUE b, VALUE n)
2091
2292
  {
2092
2293
  ENTER(2);
2093
2294
  Real *cv;
2094
- SIGNED_VALUE mx = GetPrecisionInt(n);
2295
+ SIGNED_VALUE mx = check_int_precision(n);
2095
2296
  if (mx == 0) return BigDecimal_add(self, b);
2096
2297
  else {
2097
2298
  size_t pl = VpSetPrecLimit(0);
@@ -2121,7 +2322,7 @@ BigDecimal_sub2(VALUE self, VALUE b, VALUE n)
2121
2322
  {
2122
2323
  ENTER(2);
2123
2324
  Real *cv;
2124
- SIGNED_VALUE mx = GetPrecisionInt(n);
2325
+ SIGNED_VALUE mx = check_int_precision(n);
2125
2326
  if (mx == 0) return BigDecimal_sub(self, b);
2126
2327
  else {
2127
2328
  size_t pl = VpSetPrecLimit(0);
@@ -2164,7 +2365,7 @@ BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
2164
2365
  {
2165
2366
  ENTER(2);
2166
2367
  Real *cv;
2167
- SIGNED_VALUE mx = GetPrecisionInt(n);
2368
+ SIGNED_VALUE mx = check_int_precision(n);
2168
2369
  if (mx == 0) return BigDecimal_mult(self, b);
2169
2370
  else {
2170
2371
  size_t pl = VpSetPrecLimit(0);
@@ -2196,7 +2397,7 @@ BigDecimal_abs(VALUE self)
2196
2397
 
2197
2398
  GUARD_OBJ(a, GetVpValue(self, 1));
2198
2399
  mx = a->Prec *(VpBaseFig() + 1);
2199
- GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
2400
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
2200
2401
  VpAsgn(c, a, 1);
2201
2402
  VpChangeSign(c, 1);
2202
2403
  return VpCheckGetValue(c);
@@ -2219,9 +2420,10 @@ BigDecimal_sqrt(VALUE self, VALUE nFig)
2219
2420
  GUARD_OBJ(a, GetVpValue(self, 1));
2220
2421
  mx = a->Prec * (VpBaseFig() + 1);
2221
2422
 
2222
- n = GetPrecisionInt(nFig) + VpDblFig() + BASE_FIG;
2423
+ n = check_int_precision(nFig);
2424
+ n += VpDblFig() + VpBaseFig();
2223
2425
  if (mx <= n) mx = n;
2224
- GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
2426
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
2225
2427
  VpSqrt(c, a);
2226
2428
  return VpCheckGetValue(c);
2227
2429
  }
@@ -2237,7 +2439,7 @@ BigDecimal_fix(VALUE self)
2237
2439
 
2238
2440
  GUARD_OBJ(a, GetVpValue(self, 1));
2239
2441
  mx = a->Prec *(VpBaseFig() + 1);
2240
- GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
2442
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
2241
2443
  VpActiveRound(c, a, VP_ROUND_DOWN, 0); /* 0: round off */
2242
2444
  return VpCheckGetValue(c);
2243
2445
  }
@@ -2310,7 +2512,7 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
2310
2512
  pl = VpSetPrecLimit(0);
2311
2513
  GUARD_OBJ(a, GetVpValue(self, 1));
2312
2514
  mx = a->Prec * (VpBaseFig() + 1);
2313
- GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
2515
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
2314
2516
  VpSetPrecLimit(pl);
2315
2517
  VpActiveRound(c, a, sw, iLoc);
2316
2518
  if (round_to_int) {
@@ -2356,7 +2558,7 @@ BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
2356
2558
 
2357
2559
  GUARD_OBJ(a, GetVpValue(self, 1));
2358
2560
  mx = a->Prec * (VpBaseFig() + 1);
2359
- GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
2561
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
2360
2562
  VpSetPrecLimit(pl);
2361
2563
  VpActiveRound(c, a, VP_ROUND_DOWN, iLoc); /* 0: truncate */
2362
2564
  if (argc == 0) {
@@ -2376,7 +2578,7 @@ BigDecimal_frac(VALUE self)
2376
2578
 
2377
2579
  GUARD_OBJ(a, GetVpValue(self, 1));
2378
2580
  mx = a->Prec * (VpBaseFig() + 1);
2379
- GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
2581
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
2380
2582
  VpFrac(c, a);
2381
2583
  return VpCheckGetValue(c);
2382
2584
  }
@@ -2416,7 +2618,7 @@ BigDecimal_floor(int argc, VALUE *argv, VALUE self)
2416
2618
 
2417
2619
  GUARD_OBJ(a, GetVpValue(self, 1));
2418
2620
  mx = a->Prec * (VpBaseFig() + 1);
2419
- GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
2621
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
2420
2622
  VpSetPrecLimit(pl);
2421
2623
  VpActiveRound(c, a, VP_ROUND_FLOOR, iLoc);
2422
2624
  #ifdef BIGDECIMAL_DEBUG
@@ -2462,7 +2664,7 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
2462
2664
 
2463
2665
  GUARD_OBJ(a, GetVpValue(self, 1));
2464
2666
  mx = a->Prec * (VpBaseFig() + 1);
2465
- GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
2667
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
2466
2668
  VpSetPrecLimit(pl);
2467
2669
  VpActiveRound(c, a, VP_ROUND_CEIL, iLoc);
2468
2670
  if (argc == 0) {
@@ -2566,10 +2768,10 @@ BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
2566
2768
  psz = RSTRING_PTR(str);
2567
2769
 
2568
2770
  if (fmt) {
2569
- VpToFString(vp, psz, mc, fPlus);
2771
+ VpToFString(vp, psz, RSTRING_LEN(str), mc, fPlus);
2570
2772
  }
2571
2773
  else {
2572
- VpToString (vp, psz, mc, fPlus);
2774
+ VpToString (vp, psz, RSTRING_LEN(str), mc, fPlus);
2573
2775
  }
2574
2776
  rb_str_resize(str, strlen(psz));
2575
2777
  return str;
@@ -2611,7 +2813,7 @@ BigDecimal_split(VALUE self)
2611
2813
  GUARD_OBJ(vp, GetVpValue(self, 1));
2612
2814
  str = rb_str_new(0, VpNumOfChars(vp, "E"));
2613
2815
  psz1 = RSTRING_PTR(str);
2614
- VpSzMantissa(vp, psz1);
2816
+ VpSzMantissa(vp, psz1, RSTRING_LEN(str));
2615
2817
  s = 1;
2616
2818
  if(psz1[0] == '-') {
2617
2819
  size_t len = strlen(psz1 + 1);
@@ -2660,7 +2862,7 @@ BigDecimal_inspect(VALUE self)
2660
2862
  nc = VpNumOfChars(vp, "E");
2661
2863
 
2662
2864
  str = rb_str_new(0, nc);
2663
- VpToString(vp, RSTRING_PTR(str), 0, 0);
2865
+ VpToString(vp, RSTRING_PTR(str), RSTRING_LEN(str), 0, 0);
2664
2866
  rb_str_resize(str, strlen(RSTRING_PTR(str)));
2665
2867
  return str;
2666
2868
  }
@@ -2770,7 +2972,7 @@ bigdecimal_power_by_bigdecimal(Real const* x, Real const* exp, ssize_t const n)
2770
2972
  volatile VALUE obj = exp->obj;
2771
2973
 
2772
2974
  if (VpIsZero(exp)) {
2773
- return VpCheckGetValue(VpCreateRbObject(n, "1", true));
2975
+ return VpCheckGetValue(NewOneWrapLimited(1, n));
2774
2976
  }
2775
2977
 
2776
2978
  log_x = BigMath_log(x->obj, SSIZET2NUM(n+1));
@@ -2808,9 +3010,9 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2808
3010
  n = NIL_P(prec) ? (ssize_t)(x->Prec*VpBaseFig()) : NUM2SSIZET(prec);
2809
3011
 
2810
3012
  if (VpIsNaN(x)) {
2811
- y = VpCreateRbObject(n, "0", true);
2812
- RB_GC_GUARD(y->obj);
2813
- VpSetNaN(y);
3013
+ y = NewZeroWrapLimited(1, n);
3014
+ VpSetNaN(y);
3015
+ RB_GC_GUARD(y->obj);
2814
3016
  return VpCheckGetValue(y);
2815
3017
  }
2816
3018
 
@@ -2879,136 +3081,126 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2879
3081
  }
2880
3082
 
2881
3083
  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
- }
3084
+ if (is_negative(vexp)) {
3085
+ y = NewZeroWrapNolimit(1, n);
3086
+ if (BIGDECIMAL_NEGATIVE_P(x)) {
3087
+ if (is_integer(vexp)) {
3088
+ if (is_even(vexp)) {
3089
+ /* (-0) ** (-even_integer) -> Infinity */
3090
+ VpSetPosInf(y);
3091
+ }
3092
+ else {
3093
+ /* (-0) ** (-odd_integer) -> -Infinity */
3094
+ VpSetNegInf(y);
3095
+ }
3096
+ }
3097
+ else {
3098
+ /* (-0) ** (-non_integer) -> Infinity */
3099
+ VpSetPosInf(y);
3100
+ }
3101
+ }
3102
+ else {
3103
+ /* (+0) ** (-num) -> Infinity */
3104
+ VpSetPosInf(y);
3105
+ }
3106
+ RB_GC_GUARD(y->obj);
2905
3107
  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
- }
3108
+ }
3109
+ else if (is_zero(vexp)) {
3110
+ return VpCheckGetValue(NewOneWrapLimited(1, n));
3111
+ }
3112
+ else {
3113
+ return VpCheckGetValue(NewZeroWrapLimited(1, n));
3114
+ }
2913
3115
  }
2914
3116
 
2915
3117
  if (is_zero(vexp)) {
2916
- return VpCheckGetValue(VpCreateRbObject(n, "1", true));
3118
+ return VpCheckGetValue(NewOneWrapLimited(1, n));
2917
3119
  }
2918
3120
  else if (is_one(vexp)) {
2919
- return self;
3121
+ return self;
2920
3122
  }
2921
3123
 
2922
3124
  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
- }
3125
+ if (is_negative(vexp)) {
3126
+ if (BIGDECIMAL_NEGATIVE_P(x)) {
3127
+ if (is_integer(vexp)) {
3128
+ if (is_even(vexp)) {
3129
+ /* (-Infinity) ** (-even_integer) -> +0 */
3130
+ return VpCheckGetValue(NewZeroWrapLimited(1, n));
3131
+ }
3132
+ else {
3133
+ /* (-Infinity) ** (-odd_integer) -> -0 */
3134
+ return VpCheckGetValue(NewZeroWrapLimited(-1, n));
3135
+ }
3136
+ }
3137
+ else {
3138
+ /* (-Infinity) ** (-non_integer) -> -0 */
3139
+ return VpCheckGetValue(NewZeroWrapLimited(-1, n));
3140
+ }
3141
+ }
3142
+ else {
3143
+ return VpCheckGetValue(NewZeroWrapLimited(1, n));
3144
+ }
3145
+ }
3146
+ else {
3147
+ y = NewZeroWrapLimited(1, n);
3148
+ if (BIGDECIMAL_NEGATIVE_P(x)) {
3149
+ if (is_integer(vexp)) {
3150
+ if (is_even(vexp)) {
3151
+ VpSetPosInf(y);
3152
+ }
3153
+ else {
3154
+ VpSetNegInf(y);
3155
+ }
3156
+ }
3157
+ else {
3158
+ /* TODO: support complex */
3159
+ rb_raise(rb_eMathDomainError,
3160
+ "a non-integral exponent for a negative base");
3161
+ }
3162
+ }
3163
+ else {
3164
+ VpSetPosInf(y);
3165
+ }
2964
3166
  return VpCheckGetValue(y);
2965
- }
3167
+ }
2966
3168
  }
2967
3169
 
2968
3170
  if (exp != NULL) {
2969
- return bigdecimal_power_by_bigdecimal(x, exp, n);
3171
+ return bigdecimal_power_by_bigdecimal(x, exp, n);
2970
3172
  }
2971
3173
  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
- }
3174
+ VALUE abs_value = BigDecimal_abs(self);
3175
+ if (is_one(abs_value)) {
3176
+ return VpCheckGetValue(NewOneWrapLimited(1, n));
3177
+ }
3178
+ else if (RTEST(rb_funcall(abs_value, '<', 1, INT2FIX(1)))) {
3179
+ if (is_negative(vexp)) {
3180
+ y = NewZeroWrapLimited(1, n);
3181
+ VpSetInf(y, (is_even(vexp) ? 1 : -1) * VpGetSign(x));
2985
3182
  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
- }
3183
+ }
3184
+ else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
3185
+ return VpCheckGetValue(NewZeroWrapLimited(-1, n));
3186
+ }
3187
+ else {
3188
+ return VpCheckGetValue(NewZeroWrapLimited(1, n));
3189
+ }
3190
+ }
3191
+ else {
3192
+ if (is_positive(vexp)) {
3193
+ y = NewZeroWrapLimited(1, n);
3194
+ VpSetInf(y, (is_even(vexp) ? 1 : -1) * VpGetSign(x));
3003
3195
  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
- }
3196
+ }
3197
+ else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
3198
+ return VpCheckGetValue(NewZeroWrapLimited(-1, n));
3199
+ }
3200
+ else {
3201
+ return VpCheckGetValue(NewZeroWrapLimited(1, n));
3202
+ }
3203
+ }
3012
3204
  }
3013
3205
 
3014
3206
  int_exp = FIX2LONG(vexp);
@@ -3017,15 +3209,15 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
3017
3209
  if (ma == 0) ma = 1;
3018
3210
 
3019
3211
  if (VpIsDef(x)) {
3020
- mp = x->Prec * (VpBaseFig() + 1);
3021
- GUARD_OBJ(y, VpCreateRbObject(mp * (ma + 1), "0", true));
3212
+ mp = x->Prec * (VpBaseFig() + 1);
3213
+ GUARD_OBJ(y, NewZeroWrapLimited(1, mp * (ma + 1)));
3022
3214
  }
3023
3215
  else {
3024
- GUARD_OBJ(y, VpCreateRbObject(1, "0", true));
3216
+ GUARD_OBJ(y, NewZeroWrapLimited(1, 1));
3025
3217
  }
3026
3218
  VpPowerByInt(y, x, int_exp);
3027
3219
  if (!NIL_P(prec) && VpIsDef(y)) {
3028
- VpMidRound(y, VpGetRoundMode(), n);
3220
+ VpMidRound(y, VpGetRoundMode(), n);
3029
3221
  }
3030
3222
  return VpCheckGetValue(y);
3031
3223
  }
@@ -3114,7 +3306,7 @@ rb_uint64_convert_to_BigDecimal(uint64_t uval, RB_UNUSED_VAR(size_t digs), int r
3114
3306
 
3115
3307
  Real *vp;
3116
3308
  if (uval == 0) {
3117
- vp = VpAllocReal(1);
3309
+ vp = rbd_allocate_struct(1);
3118
3310
  vp->MaxPrec = 1;
3119
3311
  vp->Prec = 1;
3120
3312
  vp->exponent = 1;
@@ -3122,7 +3314,7 @@ rb_uint64_convert_to_BigDecimal(uint64_t uval, RB_UNUSED_VAR(size_t digs), int r
3122
3314
  vp->frac[0] = 0;
3123
3315
  }
3124
3316
  else if (uval < BASE) {
3125
- vp = VpAllocReal(1);
3317
+ vp = rbd_allocate_struct(1);
3126
3318
  vp->MaxPrec = 1;
3127
3319
  vp->Prec = 1;
3128
3320
  vp->exponent = 1;
@@ -3148,7 +3340,7 @@ rb_uint64_convert_to_BigDecimal(uint64_t uval, RB_UNUSED_VAR(size_t digs), int r
3148
3340
  }
3149
3341
 
3150
3342
  const size_t exp = len + ntz;
3151
- vp = VpAllocReal(len);
3343
+ vp = rbd_allocate_struct(len);
3152
3344
  vp->MaxPrec = len;
3153
3345
  vp->Prec = len;
3154
3346
  vp->exponent = exp;
@@ -3281,7 +3473,7 @@ rb_float_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
3281
3473
 
3282
3474
  VALUE inum;
3283
3475
  size_t RB_UNUSED_VAR(prec) = 0;
3284
- size_t exp = 0;
3476
+ SIGNED_VALUE exp = 0;
3285
3477
  if (decpt > 0) {
3286
3478
  if (decpt < len10) {
3287
3479
  /*
@@ -3493,12 +3685,15 @@ rb_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
3493
3685
  * BigDecimal(value, exception: true) -> bigdecimal
3494
3686
  * BigDecimal(value, ndigits, exception: true) -> bigdecimal
3495
3687
  *
3496
- * Returns the \BigDecimal converted from +value+
3497
- * with a precision of +ndigits+ decimal digits.
3688
+ * Returns the \BigDecimal converted from +value+
3689
+ * with a precision of +ndigits+ decimal digits.
3690
+ *
3691
+ * When +ndigits+ is less than the number of significant digits
3692
+ * in the value, the result is rounded to that number of digits,
3693
+ * according to the current rounding mode; see BigDecimal.mode.
3498
3694
  *
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.
3695
+ * When +ndigits+ is 0, the number of digits to correctly represent a float number
3696
+ * is determined automatically.
3502
3697
  *
3503
3698
  * Returns +value+ converted to a \BigDecimal, depending on the type of +value+:
3504
3699
  *
@@ -3606,8 +3801,10 @@ BigDecimal_limit(int argc, VALUE *argv, VALUE self)
3606
3801
 
3607
3802
  /* Returns the sign of the value.
3608
3803
  *
3609
- * Returns a positive value if > 0, a negative value if < 0, and a
3610
- * zero if == 0.
3804
+ * Returns a positive value if > 0, a negative value if < 0.
3805
+ * It behaves the same with zeros -
3806
+ * it returns a positive value for a positive zero (BigDecimal('0')) and
3807
+ * a negative value for a negative zero (BigDecimal('-0')).
3611
3808
  *
3612
3809
  * The specific value returned indicates the type and sign of the BigDecimal,
3613
3810
  * as follows:
@@ -3771,18 +3968,16 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
3771
3968
  return VpCheckGetValue(GetVpValueWithPrec(INT2FIX(0), prec, 1));
3772
3969
  }
3773
3970
  else {
3774
- Real* vy;
3775
- vy = VpCreateRbObject(prec, "#0", true);
3971
+ Real* vy = NewZeroWrapNolimit(1, prec);
3776
3972
  VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
3777
3973
  RB_GC_GUARD(vy->obj);
3778
3974
  return VpCheckGetValue(vy);
3779
3975
  }
3780
3976
  }
3781
3977
  else if (nan) {
3782
- Real* vy;
3783
- vy = VpCreateRbObject(prec, "#0", true);
3784
- VpSetNaN(vy);
3785
- RB_GC_GUARD(vy->obj);
3978
+ Real* vy = NewZeroWrapNolimit(1, prec);
3979
+ VpSetNaN(vy);
3980
+ RB_GC_GUARD(vy->obj);
3786
3981
  return VpCheckGetValue(vy);
3787
3982
  }
3788
3983
  else if (vx == NULL) {
@@ -3800,7 +3995,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
3800
3995
  VpSetSign(vx, 1);
3801
3996
  }
3802
3997
 
3803
- one = VpCheckGetValue(VpCreateRbObject(1, "1", true));
3998
+ one = VpCheckGetValue(NewOneWrapLimited(1, 1));
3804
3999
  y = one;
3805
4000
  d = y;
3806
4001
  i = 1;
@@ -3927,15 +4122,13 @@ get_vp_value:
3927
4122
  break;
3928
4123
  }
3929
4124
  if (infinite && !negative) {
3930
- Real* vy;
3931
- vy = VpCreateRbObject(prec, "#0", true);
4125
+ Real *vy = NewZeroWrapNolimit(1, prec);
3932
4126
  RB_GC_GUARD(vy->obj);
3933
4127
  VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
3934
4128
  return VpCheckGetValue(vy);
3935
4129
  }
3936
4130
  else if (nan) {
3937
- Real* vy;
3938
- vy = VpCreateRbObject(prec, "#0", true);
4131
+ Real* vy = NewZeroWrapNolimit(1, prec);
3939
4132
  RB_GC_GUARD(vy->obj);
3940
4133
  VpSetNaN(vy);
3941
4134
  return VpCheckGetValue(vy);
@@ -3949,11 +4142,11 @@ get_vp_value:
3949
4142
  }
3950
4143
  x = VpCheckGetValue(vx);
3951
4144
 
3952
- RB_GC_GUARD(one) = VpCheckGetValue(VpCreateRbObject(1, "1", true));
3953
- RB_GC_GUARD(two) = VpCheckGetValue(VpCreateRbObject(1, "2", true));
4145
+ one = VpCheckGetValue(NewOneWrapLimited(1, 1));
4146
+ two = VpCheckGetValue(VpCreateRbObject(1, "2", true));
3954
4147
 
3955
4148
  n = prec + BIGDECIMAL_DOUBLE_FIGURES;
3956
- RB_GC_GUARD(vn) = SSIZET2NUM(n);
4149
+ vn = SSIZET2NUM(n);
3957
4150
  expo = VpExponent10(vx);
3958
4151
  if (expo < 0 || expo >= 3) {
3959
4152
  char buf[DECIMAL_SIZE_OF_BITS(SIZEOF_VALUE * CHAR_BIT) + 4];
@@ -3965,9 +4158,9 @@ get_vp_value:
3965
4158
  }
3966
4159
  w = BigDecimal_sub(x, one);
3967
4160
  x = BigDecimal_div2(w, BigDecimal_add(x, one), vn);
3968
- RB_GC_GUARD(x2) = BigDecimal_mult2(x, x, vn);
3969
- RB_GC_GUARD(y) = x;
3970
- RB_GC_GUARD(d) = y;
4161
+ x2 = BigDecimal_mult2(x, x, vn);
4162
+ y = x;
4163
+ d = y;
3971
4164
  i = 1;
3972
4165
  while (!VpIsZero((Real*)DATA_PTR(d))) {
3973
4166
  SIGNED_VALUE const ey = VpExponent10(DATA_PTR(y));
@@ -3995,6 +4188,13 @@ get_vp_value:
3995
4188
  y = BigDecimal_add(y, dy);
3996
4189
  }
3997
4190
 
4191
+ RB_GC_GUARD(one);
4192
+ RB_GC_GUARD(two);
4193
+ RB_GC_GUARD(vn);
4194
+ RB_GC_GUARD(x2);
4195
+ RB_GC_GUARD(y);
4196
+ RB_GC_GUARD(d);
4197
+
3998
4198
  return y;
3999
4199
  }
4000
4200
 
@@ -4211,13 +4411,10 @@ Init_bigdecimal(void)
4211
4411
 
4212
4412
  /* Constants definition */
4213
4413
 
4214
- #ifndef RUBY_BIGDECIMAL_VERSION
4215
- # error RUBY_BIGDECIMAL_VERSION is not defined
4216
- #endif
4217
4414
  /*
4218
4415
  * The version of bigdecimal library
4219
4416
  */
4220
- rb_define_const(rb_cBigDecimal, "VERSION", rb_str_new2(RUBY_BIGDECIMAL_VERSION));
4417
+ rb_define_const(rb_cBigDecimal, "VERSION", rb_str_new2(BIGDECIMAL_VERSION));
4221
4418
 
4222
4419
  /*
4223
4420
  * Base value used in internal calculations. On a 32 bit system, BASE
@@ -4414,20 +4611,31 @@ Init_bigdecimal(void)
4414
4611
  rb_define_singleton_method(rb_mBigMath, "exp", BigMath_s_exp, 2);
4415
4612
  rb_define_singleton_method(rb_mBigMath, "log", BigMath_s_log, 2);
4416
4613
 
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");
4614
+ #define ROUNDING_MODE(i, name, value) \
4615
+ id_##name = rb_intern_const(#name); \
4616
+ rbd_rounding_modes[i].id = id_##name; \
4617
+ rbd_rounding_modes[i].mode = value;
4618
+
4619
+ ROUNDING_MODE(0, up, RBD_ROUND_UP);
4620
+ ROUNDING_MODE(1, down, RBD_ROUND_DOWN);
4621
+ ROUNDING_MODE(2, half_up, RBD_ROUND_HALF_UP);
4622
+ ROUNDING_MODE(3, half_down, RBD_ROUND_HALF_DOWN);
4623
+ ROUNDING_MODE(4, ceil, RBD_ROUND_CEIL);
4624
+ ROUNDING_MODE(5, floor, RBD_ROUND_FLOOR);
4625
+ ROUNDING_MODE(6, half_even, RBD_ROUND_HALF_EVEN);
4626
+
4627
+ ROUNDING_MODE(7, default, RBD_ROUND_DEFAULT);
4628
+ ROUNDING_MODE(8, truncate, RBD_ROUND_TRUNCATE);
4629
+ ROUNDING_MODE(9, banker, RBD_ROUND_BANKER);
4630
+ ROUNDING_MODE(10, ceiling, RBD_ROUND_CEILING);
4631
+
4632
+ #undef ROUNDING_MODE
4633
+
4428
4634
  id_to_r = rb_intern_const("to_r");
4429
4635
  id_eq = rb_intern_const("==");
4430
4636
  id_half = rb_intern_const("half");
4637
+
4638
+ (void)VPrint; /* suppress unused warning */
4431
4639
  }
4432
4640
 
4433
4641
  /*
@@ -4447,7 +4655,7 @@ static int gfCheckVal = 1; /* Value checking flag in VpNmlz() */
4447
4655
  #endif /* BIGDECIMAL_DEBUG */
4448
4656
 
4449
4657
  static Real *VpConstOne; /* constant 1.0 */
4450
- static Real *VpPt5; /* constant 0.5 */
4658
+ static Real *VpConstPt5; /* constant 0.5 */
4451
4659
  #define maxnr 100UL /* Maximum iterations for calculating sqrt. */
4452
4660
  /* used in VpSqrt() */
4453
4661
 
@@ -4478,42 +4686,6 @@ static int VpRdup(Real *m, size_t ind_m);
4478
4686
  static int gnAlloc = 0; /* Memory allocation counter */
4479
4687
  #endif /* BIGDECIMAL_DEBUG */
4480
4688
 
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
4689
  /*
4518
4690
  * EXCEPTION Handling.
4519
4691
  */
@@ -4902,9 +5074,13 @@ VpInit(DECDIG BaseVal)
4902
5074
  /* Setup +/- Inf NaN -0 */
4903
5075
  VpGetDoubleNegZero();
4904
5076
 
4905
- /* Allocates Vp constants. */
4906
- VpConstOne = VpAlloc(1UL, "1", 1, 1);
4907
- VpPt5 = VpAlloc(1UL, ".5", 1, 1);
5077
+ /* Const 1.0 */
5078
+ VpConstOne = NewOneNolimit(1, 1);
5079
+
5080
+ /* Const 0.5 */
5081
+ VpConstPt5 = NewOneNolimit(1, 1);
5082
+ VpConstPt5->exponent = 0;
5083
+ VpConstPt5->frac[0] = 5*BASE1;
4908
5084
 
4909
5085
  #ifdef BIGDECIMAL_DEBUG
4910
5086
  gnAlloc = 0;
@@ -4993,7 +5169,7 @@ bigdecimal_parse_special_string(const char *str)
4993
5169
  p = str + table[i].len;
4994
5170
  while (*p && ISSPACE(*p)) ++p;
4995
5171
  if (*p == '\0') {
4996
- Real *vp = VpAllocReal(1);
5172
+ Real *vp = rbd_allocate_struct(1);
4997
5173
  vp->MaxPrec = 1;
4998
5174
  switch (table[i].sign) {
4999
5175
  default:
@@ -5017,11 +5193,11 @@ bigdecimal_parse_special_string(const char *str)
5017
5193
  /*
5018
5194
  * Allocates variable.
5019
5195
  * [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.
5196
+ * mx ... The number of decimal digits to be allocated, if zero then mx is determined by szVal.
5197
+ * The mx will be the number of significant digits can to be stored.
5198
+ * szVal ... The value assigned(char). If szVal==NULL, then zero is assumed.
5199
+ * If szVal[0]=='#' then MaxPrec is not affected by the precision limit
5200
+ * so that the full precision specified by szVal is allocated.
5025
5201
  *
5026
5202
  * [Returns]
5027
5203
  * Pointer to the newly allocated variable, or
@@ -5032,48 +5208,40 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
5032
5208
  {
5033
5209
  const char *orig_szVal = szVal;
5034
5210
  size_t i, j, ni, ipf, nf, ipe, ne, dot_seen, exp_seen, nalloc;
5211
+ size_t len;
5035
5212
  char v, *psz;
5036
5213
  int sign=1;
5037
5214
  Real *vp = NULL;
5038
- size_t mf = VpGetPrecLimit();
5039
5215
  VALUE buf;
5040
5216
 
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 {
5217
+ if (szVal == NULL) {
5062
5218
  return_zero:
5063
5219
  /* necessary to be able to store */
5064
5220
  /* at least mx digits. */
5065
5221
  /* szVal==NULL ==> allocate zero value. */
5066
- vp = VpAllocReal(mx);
5067
- vp->MaxPrec = mx; /* set max precision */
5222
+ vp = rbd_allocate_struct(mx);
5223
+ vp->MaxPrec = rbd_calculate_internal_digits(mx, false); /* Must false */
5068
5224
  VpSetZero(vp, 1); /* initialize vp to zero. */
5069
5225
  return vp;
5070
5226
  }
5071
5227
 
5228
+ /* Skipping leading spaces */
5229
+ while (ISSPACE(*szVal)) szVal++;
5230
+
5072
5231
  /* Check on Inf & NaN */
5073
5232
  if ((vp = bigdecimal_parse_special_string(szVal)) != NULL) {
5074
5233
  return vp;
5075
5234
  }
5076
5235
 
5236
+ /* Processing the leading one `#` */
5237
+ if (*szVal != '#') {
5238
+ len = rbd_calculate_internal_digits(mx, true);
5239
+ }
5240
+ else {
5241
+ len = rbd_calculate_internal_digits(mx, false);
5242
+ ++szVal;
5243
+ }
5244
+
5077
5245
  /* Scanning digits */
5078
5246
 
5079
5247
  /* A buffer for keeping scanned digits */
@@ -5235,11 +5403,11 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
5235
5403
 
5236
5404
  nalloc = (ni + nf + BASE_FIG - 1) / BASE_FIG + 1; /* set effective allocation */
5237
5405
  /* 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 */
5406
+ if (len == 0) len = 1;
5407
+ nalloc = Max(nalloc, len);
5408
+ len = nalloc;
5409
+ vp = rbd_allocate_struct(len);
5410
+ vp->MaxPrec = len; /* set max precision */
5243
5411
  VpSetZero(vp, sign);
5244
5412
  VpCtoV(vp, psz, ni, psz + ipf, nf, psz + ipe, ne);
5245
5413
  rb_str_resize(buf, 0);
@@ -5804,7 +5972,7 @@ VpMult(Real *c, Real *a, Real *b)
5804
5972
 
5805
5973
  if (MxIndC < MxIndAB) { /* The Max. prec. of c < Prec(a)+Prec(b) */
5806
5974
  w = c;
5807
- c = VpAlloc((size_t)((MxIndAB + 1) * BASE_FIG), "#0", 1, 1);
5975
+ c = NewZeroNolimit(1, (size_t)((MxIndAB + 1) * BASE_FIG));
5808
5976
  MxIndC = MxIndAB;
5809
5977
  }
5810
5978
 
@@ -5812,8 +5980,8 @@ VpMult(Real *c, Real *a, Real *b)
5812
5980
 
5813
5981
  c->exponent = a->exponent; /* set exponent */
5814
5982
  if (!AddExponent(c, b->exponent)) {
5815
- if (w) VpFree(c);
5816
- return 0;
5983
+ if (w) rbd_free_struct(c);
5984
+ return 0;
5817
5985
  }
5818
5986
  VpSetSign(c, VpGetSign(a) * VpGetSign(b)); /* set sign */
5819
5987
  carry = 0;
@@ -5863,10 +6031,10 @@ VpMult(Real *c, Real *a, Real *b)
5863
6031
  }
5864
6032
  }
5865
6033
  if (w != NULL) { /* free work variable */
5866
- VpNmlz(c);
5867
- VpAsgn(w, c, 1);
5868
- VpFree(c);
5869
- c = w;
6034
+ VpNmlz(c);
6035
+ VpAsgn(w, c, 1);
6036
+ rbd_free_struct(c);
6037
+ c = w;
5870
6038
  }
5871
6039
  else {
5872
6040
  VpLimitRound(c,0);
@@ -5931,18 +6099,17 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
5931
6099
  word_c = c->MaxPrec;
5932
6100
  word_r = r->MaxPrec;
5933
6101
 
5934
- ind_c = 0;
5935
- ind_r = 1;
5936
-
5937
6102
  if (word_a >= word_r) goto space_error;
5938
6103
 
6104
+ ind_r = 1;
5939
6105
  r->frac[0] = 0;
5940
6106
  while (ind_r <= word_a) {
5941
6107
  r->frac[ind_r] = a->frac[ind_r - 1];
5942
6108
  ++ind_r;
5943
6109
  }
5944
-
5945
6110
  while (ind_r < word_r) r->frac[ind_r++] = 0;
6111
+
6112
+ ind_c = 0;
5946
6113
  while (ind_c < word_c) c->frac[ind_c++] = 0;
5947
6114
 
5948
6115
  /* initial procedure */
@@ -6236,7 +6403,6 @@ Exit:
6236
6403
  * Note: % must not appear more than once
6237
6404
  * a ... VP variable to be printed
6238
6405
  */
6239
- #ifdef BIGDECIMAL_ENABLE_VPRINT
6240
6406
  static int
6241
6407
  VPrint(FILE *fp, const char *cntl_chr, Real *a)
6242
6408
  {
@@ -6249,95 +6415,94 @@ VPrint(FILE *fp, const char *cntl_chr, Real *a)
6249
6415
  /* nc : number of characters printed */
6250
6416
  ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
6251
6417
  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;
6418
+ if (*(cntl_chr + j) == '%' && *(cntl_chr + j + 1) != '%') {
6419
+ nc = 0;
6420
+ if (VpIsNaN(a)) {
6421
+ fprintf(fp, SZ_NaN);
6422
+ nc += 8;
6423
+ }
6424
+ else if (VpIsPosInf(a)) {
6425
+ fprintf(fp, SZ_INF);
6426
+ nc += 8;
6427
+ }
6428
+ else if (VpIsNegInf(a)) {
6429
+ fprintf(fp, SZ_NINF);
6430
+ nc += 9;
6431
+ }
6432
+ else if (!VpIsZero(a)) {
6433
+ if (BIGDECIMAL_NEGATIVE_P(a)) {
6434
+ fprintf(fp, "-");
6435
+ ++nc;
6436
+ }
6437
+ nc += fprintf(fp, "0.");
6438
+ switch (*(cntl_chr + j + 1)) {
6439
+ default:
6440
+ break;
6275
6441
 
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++;
6442
+ case '0': case 'z':
6443
+ ZeroSup = 0;
6444
+ ++j;
6445
+ sep = cntl_chr[j] == 'z' ? BIGDECIMAL_COMPONENT_FIGURES : 10;
6446
+ break;
6447
+ }
6448
+ for (i = 0; i < a->Prec; ++i) {
6449
+ m = BASE1;
6450
+ e = a->frac[i];
6451
+ while (m) {
6452
+ nn = e / m;
6453
+ if (!ZeroSup || nn) {
6454
+ nc += fprintf(fp, "%lu", (unsigned long)nn); /* The leading zero(s) */
6455
+ /* as 0.00xx will not */
6456
+ /* be printed. */
6457
+ ++nd;
6458
+ ZeroSup = 0; /* Set to print succeeding zeros */
6459
+ }
6460
+ if (nd >= sep) { /* print ' ' after every 10 digits */
6461
+ nd = 0;
6462
+ nc += fprintf(fp, " ");
6463
+ }
6464
+ e = e - nn * m;
6465
+ m /= 10;
6466
+ }
6467
+ }
6468
+ nc += fprintf(fp, "E%"PRIdSIZE, VpExponent10(a));
6469
+ nc += fprintf(fp, " (%"PRIdVALUE", %"PRIuSIZE", %"PRIuSIZE")", a->exponent, a->Prec, a->MaxPrec);
6470
+ }
6471
+ else {
6472
+ nc += fprintf(fp, "0.0");
6473
+ }
6474
+ }
6475
+ else {
6476
+ ++nc;
6477
+ if (*(cntl_chr + j) == '\\') {
6478
+ switch (*(cntl_chr + j + 1)) {
6479
+ case 'n':
6480
+ fprintf(fp, "\n");
6481
+ ++j;
6482
+ break;
6483
+ case 't':
6484
+ fprintf(fp, "\t");
6485
+ ++j;
6486
+ break;
6487
+ case 'b':
6488
+ fprintf(fp, "\n");
6489
+ ++j;
6490
+ break;
6491
+ default:
6492
+ fprintf(fp, "%c", *(cntl_chr + j));
6493
+ break;
6494
+ }
6495
+ }
6496
+ else {
6497
+ fprintf(fp, "%c", *(cntl_chr + j));
6498
+ if (*(cntl_chr + j) == '%') ++j;
6499
+ }
6500
+ }
6501
+ j++;
6336
6502
  }
6337
6503
 
6338
6504
  return (int)nc;
6339
6505
  }
6340
- #endif
6341
6506
 
6342
6507
  static void
6343
6508
  VpFormatSt(char *psz, size_t fFmt)
@@ -6382,188 +6547,254 @@ VpExponent10(Real *a)
6382
6547
  }
6383
6548
 
6384
6549
  VP_EXPORT void
6385
- VpSzMantissa(Real *a,char *psz)
6550
+ VpSzMantissa(Real *a, char *buf, size_t buflen)
6386
6551
  {
6387
6552
  size_t i, n, ZeroSup;
6388
6553
  DECDIG_DBL m, e, nn;
6389
6554
 
6390
6555
  if (VpIsNaN(a)) {
6391
- sprintf(psz, SZ_NaN);
6392
- return;
6556
+ snprintf(buf, buflen, SZ_NaN);
6557
+ return;
6393
6558
  }
6394
6559
  if (VpIsPosInf(a)) {
6395
- sprintf(psz, SZ_INF);
6560
+ snprintf(buf, buflen, SZ_INF);
6396
6561
  return;
6397
6562
  }
6398
6563
  if (VpIsNegInf(a)) {
6399
- sprintf(psz, SZ_NINF);
6564
+ snprintf(buf, buflen, SZ_NINF);
6400
6565
  return;
6401
6566
  }
6402
6567
 
6403
6568
  ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
6404
6569
  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;
6570
+ if (BIGDECIMAL_NEGATIVE_P(a)) *buf++ = '-';
6571
+ n = a->Prec;
6572
+ for (i = 0; i < n; ++i) {
6573
+ m = BASE1;
6574
+ e = a->frac[i];
6575
+ while (m) {
6576
+ nn = e / m;
6577
+ if (!ZeroSup || nn) {
6578
+ snprintf(buf, buflen, "%lu", (unsigned long)nn); /* The leading zero(s) */
6579
+ buf += strlen(buf);
6580
+ /* as 0.00xx will be ignored. */
6581
+ ZeroSup = 0; /* Set to print succeeding zeros */
6582
+ }
6583
+ e = e - nn * m;
6584
+ m /= 10;
6585
+ }
6586
+ }
6587
+ *buf = 0;
6588
+ while (buf[-1] == '0') *(--buf) = 0;
6424
6589
  }
6425
6590
  else {
6426
- if (VpIsPosZero(a)) sprintf(psz, "0");
6427
- else sprintf(psz, "-0");
6591
+ if (VpIsPosZero(a)) snprintf(buf, buflen, "0");
6592
+ else snprintf(buf, buflen, "-0");
6428
6593
  }
6429
6594
  }
6430
6595
 
6431
6596
  VP_EXPORT int
6432
- VpToSpecialString(Real *a,char *psz,int fPlus)
6597
+ VpToSpecialString(Real *a, char *buf, size_t buflen, int fPlus)
6433
6598
  /* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
6434
6599
  {
6435
6600
  if (VpIsNaN(a)) {
6436
- sprintf(psz,SZ_NaN);
6437
- return 1;
6601
+ snprintf(buf, buflen, SZ_NaN);
6602
+ return 1;
6438
6603
  }
6439
6604
 
6440
6605
  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;
6606
+ if (fPlus == 1) {
6607
+ *buf++ = ' ';
6608
+ }
6609
+ else if (fPlus == 2) {
6610
+ *buf++ = '+';
6611
+ }
6612
+ snprintf(buf, buflen, SZ_INF);
6613
+ return 1;
6449
6614
  }
6450
6615
  if (VpIsNegInf(a)) {
6451
- sprintf(psz, SZ_NINF);
6452
- return 1;
6616
+ snprintf(buf, buflen, SZ_NINF);
6617
+ return 1;
6453
6618
  }
6454
6619
  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;
6620
+ if (VpIsPosZero(a)) {
6621
+ if (fPlus == 1) snprintf(buf, buflen, " 0.0");
6622
+ else if (fPlus == 2) snprintf(buf, buflen, "+0.0");
6623
+ else snprintf(buf, buflen, "0.0");
6624
+ }
6625
+ else snprintf(buf, buflen, "-0.0");
6626
+ return 1;
6462
6627
  }
6463
6628
  return 0;
6464
6629
  }
6465
6630
 
6466
6631
  VP_EXPORT void
6467
- VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
6632
+ VpToString(Real *a, char *buf, size_t buflen, size_t fFmt, int fPlus)
6468
6633
  /* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
6469
6634
  {
6470
6635
  size_t i, n, ZeroSup;
6471
6636
  DECDIG shift, m, e, nn;
6472
- char *pszSav = psz;
6637
+ char *p = buf;
6638
+ size_t plen = buflen;
6473
6639
  ssize_t ex;
6474
6640
 
6475
- if (VpToSpecialString(a, psz, fPlus)) return;
6641
+ if (VpToSpecialString(a, buf, buflen, fPlus)) return;
6476
6642
 
6477
6643
  ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
6478
6644
 
6479
- if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
6480
- else if (fPlus == 1) *psz++ = ' ';
6481
- else if (fPlus == 2) *psz++ = '+';
6645
+ #define ADVANCE(n) do { \
6646
+ if (plen < n) goto overflow; \
6647
+ p += n; \
6648
+ plen -= n; \
6649
+ } while (0)
6650
+
6651
+ if (BIGDECIMAL_NEGATIVE_P(a)) {
6652
+ *p = '-';
6653
+ ADVANCE(1);
6654
+ }
6655
+ else if (fPlus == 1) {
6656
+ *p = ' ';
6657
+ ADVANCE(1);
6658
+ }
6659
+ else if (fPlus == 2) {
6660
+ *p = '+';
6661
+ ADVANCE(1);
6662
+ }
6663
+
6664
+ *p = '0'; ADVANCE(1);
6665
+ *p = '.'; ADVANCE(1);
6482
6666
 
6483
- *psz++ = '0';
6484
- *psz++ = '.';
6485
6667
  n = a->Prec;
6486
6668
  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
- }
6669
+ m = BASE1;
6670
+ e = a->frac[i];
6671
+ while (m) {
6672
+ nn = e / m;
6673
+ if (!ZeroSup || nn) {
6674
+ /* The reading zero(s) */
6675
+ size_t n = (size_t)snprintf(p, plen, "%lu", (unsigned long)nn);
6676
+ if (n > plen) goto overflow;
6677
+ ADVANCE(n);
6678
+ /* as 0.00xx will be ignored. */
6679
+ ZeroSup = 0; /* Set to print succeeding zeros */
6680
+ }
6681
+ e = e - nn * m;
6682
+ m /= 10;
6683
+ }
6500
6684
  }
6685
+
6501
6686
  ex = a->exponent * (ssize_t)BASE_FIG;
6502
6687
  shift = BASE1;
6503
6688
  while (a->frac[0] / shift == 0) {
6504
- --ex;
6505
- shift /= 10;
6689
+ --ex;
6690
+ shift /= 10;
6506
6691
  }
6507
- while (psz[-1] == '0') {
6508
- *(--psz) = 0;
6692
+ while (p - 1 > buf && p[-1] == '0') {
6693
+ *(--p) = '\0';
6694
+ ++plen;
6509
6695
  }
6510
- sprintf(psz, "e%"PRIdSIZE, ex);
6511
- if (fFmt) VpFormatSt(pszSav, fFmt);
6696
+ snprintf(p, plen, "e%"PRIdSIZE, ex);
6697
+ if (fFmt) VpFormatSt(buf, fFmt);
6698
+
6699
+ overflow:
6700
+ return;
6701
+ #undef ADVANCE
6512
6702
  }
6513
6703
 
6514
6704
  VP_EXPORT void
6515
- VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
6705
+ VpToFString(Real *a, char *buf, size_t buflen, size_t fFmt, int fPlus)
6516
6706
  /* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
6517
6707
  {
6518
6708
  size_t i, n;
6519
6709
  DECDIG m, e, nn;
6520
- char *pszSav = psz;
6710
+ char *p = buf;
6711
+ size_t plen = buflen;
6521
6712
  ssize_t ex;
6522
6713
 
6523
- if (VpToSpecialString(a, psz, fPlus)) return;
6714
+ if (VpToSpecialString(a, buf, buflen, fPlus)) return;
6715
+
6716
+ #define ADVANCE(n) do { \
6717
+ if (plen < n) goto overflow; \
6718
+ p += n; \
6719
+ plen -= n; \
6720
+ } while (0)
6524
6721
 
6525
- if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
6526
- else if (fPlus == 1) *psz++ = ' ';
6527
- else if (fPlus == 2) *psz++ = '+';
6722
+
6723
+ if (BIGDECIMAL_NEGATIVE_P(a)) {
6724
+ *p = '-';
6725
+ ADVANCE(1);
6726
+ }
6727
+ else if (fPlus == 1) {
6728
+ *p = ' ';
6729
+ ADVANCE(1);
6730
+ }
6731
+ else if (fPlus == 2) {
6732
+ *p = '+';
6733
+ ADVANCE(1);
6734
+ }
6528
6735
 
6529
6736
  n = a->Prec;
6530
6737
  ex = a->exponent;
6531
6738
  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;
6739
+ *p = '0'; ADVANCE(1);
6740
+ *p = '.'; ADVANCE(1);
6741
+ while (ex < 0) {
6742
+ for (i=0; i < BASE_FIG; ++i) {
6743
+ *p = '0'; ADVANCE(1);
6744
+ }
6745
+ ++ex;
6746
+ }
6747
+ ex = -1;
6538
6748
  }
6539
6749
 
6540
6750
  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++ = '.';
6751
+ --ex;
6752
+ if (i == 0 && ex >= 0) {
6753
+ size_t n = snprintf(p, plen, "%lu", (unsigned long)a->frac[i]);
6754
+ if (n > plen) goto overflow;
6755
+ ADVANCE(n);
6756
+ }
6757
+ else {
6758
+ m = BASE1;
6759
+ e = a->frac[i];
6760
+ while (m) {
6761
+ nn = e / m;
6762
+ *p = (char)(nn + '0');
6763
+ ADVANCE(1);
6764
+ e = e - nn * m;
6765
+ m /= 10;
6766
+ }
6767
+ }
6768
+ if (ex == 0) {
6769
+ *p = '.';
6770
+ ADVANCE(1);
6771
+ }
6557
6772
  }
6558
6773
  while (--ex>=0) {
6559
- m = BASE;
6560
- while (m /= 10) *psz++ = '0';
6561
- if (ex == 0) *psz++ = '.';
6774
+ m = BASE;
6775
+ while (m /= 10) {
6776
+ *p = '0';
6777
+ ADVANCE(1);
6778
+ }
6779
+ if (ex == 0) {
6780
+ *p = '.';
6781
+ ADVANCE(1);
6782
+ }
6783
+ }
6784
+
6785
+ *p = '\0';
6786
+ while (p - 1 > buf && p[-1] == '0') {
6787
+ *(--p) = '\0';
6788
+ ++plen;
6562
6789
  }
6563
- *psz = 0;
6564
- while (psz[-1] == '0') *(--psz) = 0;
6565
- if (psz[-1] == '.') sprintf(psz, "0");
6566
- if (fFmt) VpFormatSt(pszSav, fFmt);
6790
+ if (p - 1 > buf && p[-1] == '.') {
6791
+ snprintf(p, plen, "0");
6792
+ }
6793
+ if (fFmt) VpFormatSt(buf, fFmt);
6794
+
6795
+ overflow:
6796
+ return;
6797
+ #undef ADVANCE
6567
6798
  }
6568
6799
 
6569
6800
  /*
@@ -6972,8 +7203,9 @@ VpSqrt(Real *y, Real *x)
6972
7203
  if (x->MaxPrec > (size_t)n) n = (ssize_t)x->MaxPrec;
6973
7204
 
6974
7205
  /* 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);
7206
+ /* TODO: reconsider MaxPrec of f and r */
7207
+ f = NewOneNolimit(1, y->MaxPrec * (BASE_FIG + 2));
7208
+ r = NewOneNolimit(1, (n + n) * (BASE_FIG + 2));
6977
7209
 
6978
7210
  nr = 0;
6979
7211
  y_prec = y->MaxPrec;
@@ -6998,16 +7230,21 @@ VpSqrt(Real *y, Real *x)
6998
7230
  f->MaxPrec = y->MaxPrec + 1;
6999
7231
  n = (SIGNED_VALUE)(y_prec * BASE_FIG);
7000
7232
  if (n < (SIGNED_VALUE)maxnr) n = (SIGNED_VALUE)maxnr;
7233
+
7234
+ /*
7235
+ * Perform: y_{n+1} = (y_n - x/y_n) / 2
7236
+ */
7001
7237
  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 */
7238
+ y->MaxPrec *= 2;
7239
+ if (y->MaxPrec > y_prec) y->MaxPrec = y_prec;
7240
+ f->MaxPrec = y->MaxPrec;
7241
+ VpDivd(f, r, x, y); /* f = x/y */
7242
+ VpAddSub(r, f, y, -1); /* r = f - y */
7243
+ VpMult(f, VpConstPt5, r); /* f = 0.5*r */
7244
+ if (VpIsZero(f))
7245
+ goto converge;
7246
+ VpAddSub(r, f, y, 1); /* r = y + f */
7247
+ VpAsgn(y, r, 1); /* y = r */
7011
7248
  } while (++nr < n);
7012
7249
 
7013
7250
  #ifdef BIGDECIMAL_DEBUG
@@ -7032,8 +7269,8 @@ converge:
7032
7269
  y->MaxPrec = y_prec;
7033
7270
 
7034
7271
  Exit:
7035
- VpFree(f);
7036
- VpFree(r);
7272
+ rbd_free_struct(f);
7273
+ rbd_free_struct(r);
7037
7274
  return 1;
7038
7275
  }
7039
7276
 
@@ -7424,9 +7661,10 @@ VpPowerByInt(Real *y, Real *x, SIGNED_VALUE n)
7424
7661
  }
7425
7662
 
7426
7663
  /* Allocate working variables */
7664
+ /* TODO: reconsider MaxPrec of w1 and w2 */
7665
+ w1 = NewZeroNolimit(1, (y->MaxPrec + 2) * BASE_FIG);
7666
+ w2 = NewZeroNolimit(1, (w1->MaxPrec * 2 + 1) * BASE_FIG);
7427
7667
 
7428
- w1 = VpAlloc((y->MaxPrec + 2) * BASE_FIG, "#0", 1, 1);
7429
- w2 = VpAlloc((w1->MaxPrec * 2 + 1) * BASE_FIG, "#0", 1, 1);
7430
7668
  /* calculation start */
7431
7669
 
7432
7670
  VpAsgn(y, x, 1);
@@ -7455,8 +7693,8 @@ Exit:
7455
7693
  printf(" n=%"PRIdVALUE"\n", n);
7456
7694
  }
7457
7695
  #endif /* BIGDECIMAL_DEBUG */
7458
- VpFree(w2);
7459
- VpFree(w1);
7696
+ rbd_free_struct(w2);
7697
+ rbd_free_struct(w1);
7460
7698
  return 1;
7461
7699
  }
7462
7700