bigdecimal 1.4.4 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 87db143e2139576067ccfd911dde4e081aad19bc0faa08ca6b74a34c430e82de
4
- data.tar.gz: 54bde88f847fae9e241ec3817e96f45d21a8831b5827f76a0b25915b576d0900
3
+ metadata.gz: ef063cb7c648ba239e4179669ed4d410d9d160e293377ce4b1bdb73ec68366cb
4
+ data.tar.gz: d0e2d57a69c624ba2ef446c52fc19f889721809e7f6933ed8f0db684e3f9c1a2
5
5
  SHA512:
6
- metadata.gz: 360aa77ae2daadf7ff173669e115b76038b17f233694b316b17a159bec27be4eb1c57adee88350e3e3bde27097257b6d3526e057a28f5a4e457864cceb3aec5a
7
- data.tar.gz: 4cbb886e60336b3741f5f1cef0a29877384f1e51b49aee13a18d1afd4f4cea3b86a826cb1ee2923f23684a148334c9ec0a09bef620b29eb62283baa299b45366
6
+ metadata.gz: a7fa4a273ccddcdc65fd477b8ff59abde5951966b45ea43b78b257eb69e10a3dece8f62cb37d34b68f02201fcf0e2e2d471b835660ddb4bab9a1e1bc74d7c22b
7
+ data.tar.gz: 3a2de54bf09de5ffc15f31227a1458ad670ddccefa716e48c06ca4f98709d4de068f72be0be603c9e5bf60191b91a54f1e13ef617bdde833e98740c6ad34faf9
data/bigdecimal.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  # coding: utf-8
2
2
 
3
- bigdecimal_version = '1.4.4'
3
+ bigdecimal_version = '2.0.3'
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "bigdecimal"
@@ -11,7 +11,7 @@ Gem::Specification.new do |s|
11
11
  s.summary = "Arbitrary-precision decimal floating-point number library."
12
12
  s.description = "This library provides arbitrary-precision decimal floating-point number class."
13
13
  s.homepage = "https://github.com/ruby/bigdecimal"
14
- s.license = "ruby"
14
+ s.license = "Ruby"
15
15
 
16
16
  s.require_paths = %w[lib]
17
17
  s.extensions = %w[ext/bigdecimal/extconf.rb]
@@ -30,11 +30,10 @@ Gem::Specification.new do |s|
30
30
  sample/pi.rb
31
31
  ]
32
32
 
33
- s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze)
33
+ s.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
34
34
 
35
- s.add_development_dependency "rake", "~> 10.0"
35
+ s.add_development_dependency "rake", ">= 12.3.3"
36
36
  s.add_development_dependency "rake-compiler", ">= 0.9"
37
- s.add_development_dependency "rake-compiler-dock", ">= 0.6.1"
38
37
  s.add_development_dependency "minitest", "< 5.0.0"
39
38
  s.add_development_dependency "pry"
40
39
  end
@@ -14,6 +14,7 @@
14
14
  #include "ruby/util.h"
15
15
 
16
16
  #ifndef BIGDECIMAL_DEBUG
17
+ # undef NDEBUG
17
18
  # define NDEBUG
18
19
  #endif
19
20
  #include <assert.h>
@@ -24,7 +25,6 @@
24
25
  #include <string.h>
25
26
  #include <errno.h>
26
27
  #include <math.h>
27
- #include "math.h"
28
28
 
29
29
  #ifdef HAVE_IEEEFP_H
30
30
  #include <ieeefp.h>
@@ -77,7 +77,7 @@ static ID id_half;
77
77
  #define BASE1 (BASE/10)
78
78
 
79
79
  #ifndef DBLE_FIG
80
- #define DBLE_FIG (DBL_DIG+1) /* figure of double */
80
+ #define DBLE_FIG rmpd_double_figures() /* figure of double */
81
81
  #endif
82
82
 
83
83
  #ifndef RRATIONAL_ZERO_P
@@ -127,6 +127,30 @@ rb_rational_den(VALUE rat)
127
127
  }
128
128
  #endif
129
129
 
130
+ #ifndef HAVE_RB_COMPLEX_REAL
131
+ static inline VALUE
132
+ rb_complex_real(VALUE cmp)
133
+ {
134
+ #ifdef HAVE_TYPE_STRUCT_RCOMPLEX
135
+ return RCOMPLEX(cmp)->real;
136
+ #else
137
+ return rb_funcall(cmp, rb_intern("real"), 0);
138
+ #endif
139
+ }
140
+ #endif
141
+
142
+ #ifndef HAVE_RB_COMPLEX_IMAG
143
+ static inline VALUE
144
+ rb_complex_imag(VALUE cmp)
145
+ {
146
+ #ifdef HAVE_TYPE_STRUCT_RCOMPLEX
147
+ return RCOMPLEX(cmp)->imag;
148
+ #else
149
+ return rb_funcall(cmp, rb_intern("imag"), 0);
150
+ #endif
151
+ }
152
+ #endif
153
+
130
154
  #define BIGDECIMAL_POSITIVE_P(bd) ((bd)->sign > 0)
131
155
  #define BIGDECIMAL_NEGATIVE_P(bd) ((bd)->sign < 0)
132
156
 
@@ -228,7 +252,7 @@ again:
228
252
  switch(TYPE(v)) {
229
253
  case T_FLOAT:
230
254
  if (prec < 0) goto unable_to_coerce_without_prec;
231
- if (prec > DBL_DIG+1) goto SomeOneMayDoIt;
255
+ if (prec > (long)DBLE_FIG) goto SomeOneMayDoIt;
232
256
  d = RFLOAT_VALUE(v);
233
257
  if (!isfinite(d)) {
234
258
  pv = VpCreateRbObject(1, NULL);
@@ -276,7 +300,6 @@ again:
276
300
  #ifdef ENABLE_NUMERIC_STRING
277
301
  case T_STRING:
278
302
  StringValueCStr(v);
279
- rb_check_safe_obj(v);
280
303
  return VpCreateRbObject(RSTRING_LEN(v) + VpBaseFig() + 1,
281
304
  RSTRING_PTR(v));
282
305
  #endif /* ENABLE_NUMERIC_STRING */
@@ -327,11 +350,13 @@ BigDecimal_double_fig(VALUE self)
327
350
  /* call-seq:
328
351
  * big_decimal.precs -> array
329
352
  *
330
- * Returns an Array of two Integer values.
353
+ * Returns an Array of two Integer values that represent platform-dependent
354
+ * internal storage properties.
331
355
  *
332
- * The first value is the current number of significant digits in the
333
- * BigDecimal. The second value is the maximum number of significant digits
334
- * for the BigDecimal.
356
+ * This method is deprecated and will be removed in the future.
357
+ * Instead, use BigDecimal#n_significant_digits for obtaining the number of
358
+ * significant digits in scientific notation, and BigDecimal#precision for
359
+ * obtaining the number of digits in decimal notation.
335
360
  *
336
361
  * BigDecimal('5').precs #=> [9, 18]
337
362
  */
@@ -343,12 +368,109 @@ BigDecimal_prec(VALUE self)
343
368
  Real *p;
344
369
  VALUE obj;
345
370
 
371
+ rb_category_warn(RB_WARN_CATEGORY_DEPRECATED,
372
+ "BigDecimal#precs is deprecated and will be removed in the future; "
373
+ "use BigDecimal#precision instead.");
374
+
346
375
  GUARD_OBJ(p, GetVpValue(self, 1));
347
- obj = rb_assoc_new(INT2NUM(p->Prec*VpBaseFig()),
348
- INT2NUM(p->MaxPrec*VpBaseFig()));
376
+ obj = rb_assoc_new(SIZET2NUM(p->Prec*VpBaseFig()),
377
+ SIZET2NUM(p->MaxPrec*VpBaseFig()));
349
378
  return obj;
350
379
  }
351
380
 
381
+ /*
382
+ * call-seq:
383
+ * big_decimal.precision -> intreger
384
+ *
385
+ * Returns the number of decimal digits in this number.
386
+ *
387
+ * Example:
388
+ *
389
+ * BigDecimal("0").precision # => 0
390
+ * BigDecimal("1").precision # => 1
391
+ * BigDecimal("-1e20").precision # => 21
392
+ * BigDecimal("1e-20").precision # => 20
393
+ * BigDecimal("Infinity").precision # => 0
394
+ * BigDecimal("-Infinity").precision # => 0
395
+ * BigDecimal("NaN").precision # => 0
396
+ */
397
+ static VALUE
398
+ BigDecimal_precision(VALUE self)
399
+ {
400
+ ENTER(1);
401
+
402
+ Real *p;
403
+ GUARD_OBJ(p, GetVpValue(self, 1));
404
+
405
+ /*
406
+ * The most significant digit is frac[0], and the least significant digit is frac[Prec-1].
407
+ * When the exponent is zero, the decimal point is located just before frac[0].
408
+ * When the exponent is negative, the decimal point moves to leftward.
409
+ * Conversely, when the exponent is positive, the decimal point moves to rightward.
410
+ *
411
+ * | frac[0] frac[1] frac[2] . frac[3] frac[4] ... frac[Prec-1]
412
+ * |------------------------> exponent == 3
413
+ */
414
+
415
+ ssize_t ex = p->exponent;
416
+ ssize_t precision;
417
+ if (ex < 0) {
418
+ precision = (-ex + 1) * BASE_FIG; /* 1 is for p->frac[0] */
419
+ ex = 0;
420
+ }
421
+ else if (p->Prec > 0) {
422
+ BDIGIT x = p->frac[0];
423
+ for (precision = 0; x > 0; x /= 10) {
424
+ ++precision;
425
+ }
426
+ }
427
+
428
+ if (ex > (ssize_t)p->Prec) {
429
+ precision += (ex - 1) * BASE_FIG;
430
+ }
431
+ else if (p->Prec > 0) {
432
+ ssize_t n = (ssize_t)p->Prec - 1;
433
+ while (n > 0 && p->frac[n] == 0) --n;
434
+
435
+ precision += n * BASE_FIG;
436
+
437
+ if (ex < (ssize_t)p->Prec) {
438
+ BDIGIT x = p->frac[n];
439
+ for (; x > 0 && x % 10 == 0; x /= 10) {
440
+ --precision;
441
+ }
442
+ }
443
+ }
444
+
445
+ return SSIZET2NUM(precision);
446
+ }
447
+
448
+ static VALUE
449
+ BigDecimal_n_significant_digits(VALUE self)
450
+ {
451
+ ENTER(1);
452
+
453
+ Real *p;
454
+ GUARD_OBJ(p, GetVpValue(self, 1));
455
+
456
+ ssize_t n = p->Prec;
457
+ while (n > 0 && p->frac[n-1] == 0) --n;
458
+ if (n <= 0) {
459
+ return INT2FIX(0);
460
+ }
461
+
462
+ int nlz, ntz;
463
+
464
+ BDIGIT x = p->frac[0];
465
+ for (nlz = BASE_FIG; x > 0; x /= 10) --nlz;
466
+
467
+ x = p->frac[n-1];
468
+ for (ntz = 0; x > 0 && x % 10 == 0; x /= 10) ++ntz;
469
+
470
+ ssize_t n_digits = BASE_FIG * n - nlz - ntz;
471
+ return SSIZET2NUM(n_digits);
472
+ }
473
+
352
474
  /*
353
475
  * call-seq: hash
354
476
  *
@@ -418,7 +540,6 @@ BigDecimal_load(VALUE self, VALUE str)
418
540
  unsigned long m=0;
419
541
 
420
542
  pch = (unsigned char *)StringValueCStr(str);
421
- rb_check_safe_obj(str);
422
543
  /* First get max prec */
423
544
  while((*pch) != (unsigned char)'\0' && (ch = *pch++) != (unsigned char)':') {
424
545
  if(!ISDIGIT(ch)) {
@@ -877,7 +998,7 @@ BigDecimal_coerce(VALUE self, VALUE other)
877
998
  Real *b;
878
999
 
879
1000
  if (RB_TYPE_P(other, T_FLOAT)) {
880
- GUARD_OBJ(b, GetVpValueWithPrec(other, DBL_DIG+1, 1));
1001
+ GUARD_OBJ(b, GetVpValueWithPrec(other, DBLE_FIG, 1));
881
1002
  obj = rb_assoc_new(ToValue(b), self);
882
1003
  }
883
1004
  else {
@@ -935,7 +1056,7 @@ BigDecimal_add(VALUE self, VALUE r)
935
1056
 
936
1057
  GUARD_OBJ(a, GetVpValue(self, 1));
937
1058
  if (RB_TYPE_P(r, T_FLOAT)) {
938
- b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
1059
+ b = GetVpValueWithPrec(r, DBLE_FIG, 1);
939
1060
  }
940
1061
  else if (RB_TYPE_P(r, T_RATIONAL)) {
941
1062
  b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
@@ -993,7 +1114,7 @@ BigDecimal_sub(VALUE self, VALUE r)
993
1114
 
994
1115
  GUARD_OBJ(a, GetVpValue(self,1));
995
1116
  if (RB_TYPE_P(r, T_FLOAT)) {
996
- b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
1117
+ b = GetVpValueWithPrec(r, DBLE_FIG, 1);
997
1118
  }
998
1119
  else if (RB_TYPE_P(r, T_RATIONAL)) {
999
1120
  b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
@@ -1043,7 +1164,7 @@ BigDecimalCmp(VALUE self, VALUE r,char op)
1043
1164
  break;
1044
1165
 
1045
1166
  case T_FLOAT:
1046
- GUARD_OBJ(b, GetVpValueWithPrec(r, DBL_DIG+1, 0));
1167
+ GUARD_OBJ(b, GetVpValueWithPrec(r, DBLE_FIG, 0));
1047
1168
  break;
1048
1169
 
1049
1170
  case T_RATIONAL:
@@ -1256,7 +1377,7 @@ BigDecimal_mult(VALUE self, VALUE r)
1256
1377
 
1257
1378
  GUARD_OBJ(a, GetVpValue(self, 1));
1258
1379
  if (RB_TYPE_P(r, T_FLOAT)) {
1259
- b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
1380
+ b = GetVpValueWithPrec(r, DBLE_FIG, 1);
1260
1381
  }
1261
1382
  else if (RB_TYPE_P(r, T_RATIONAL)) {
1262
1383
  b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
@@ -1284,7 +1405,7 @@ BigDecimal_divide(Real **c, Real **res, Real **div, VALUE self, VALUE r)
1284
1405
 
1285
1406
  GUARD_OBJ(a, GetVpValue(self, 1));
1286
1407
  if (RB_TYPE_P(r, T_FLOAT)) {
1287
- b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
1408
+ b = GetVpValueWithPrec(r, DBLE_FIG, 1);
1288
1409
  }
1289
1410
  else if (RB_TYPE_P(r, T_RATIONAL)) {
1290
1411
  b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
@@ -1350,7 +1471,7 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
1350
1471
 
1351
1472
  GUARD_OBJ(a, GetVpValue(self, 1));
1352
1473
  if (RB_TYPE_P(r, T_FLOAT)) {
1353
- b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
1474
+ b = GetVpValueWithPrec(r, DBLE_FIG, 1);
1354
1475
  }
1355
1476
  else if (RB_TYPE_P(r, T_RATIONAL)) {
1356
1477
  b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
@@ -1451,7 +1572,7 @@ BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
1451
1572
 
1452
1573
  GUARD_OBJ(a, GetVpValue(self, 1));
1453
1574
  if (RB_TYPE_P(r, T_FLOAT)) {
1454
- b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
1575
+ b = GetVpValueWithPrec(r, DBLE_FIG, 1);
1455
1576
  }
1456
1577
  else if (RB_TYPE_P(r, T_RATIONAL)) {
1457
1578
  b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
@@ -1756,20 +1877,23 @@ BigDecimal_fix(VALUE self)
1756
1877
  * round(n, mode)
1757
1878
  *
1758
1879
  * Round to the nearest integer (by default), returning the result as a
1759
- * BigDecimal.
1880
+ * BigDecimal if n is specified, or as an Integer if it isn't.
1760
1881
  *
1761
1882
  * BigDecimal('3.14159').round #=> 3
1762
1883
  * BigDecimal('8.7').round #=> 9
1763
1884
  * BigDecimal('-9.9').round #=> -10
1764
1885
  *
1886
+ * BigDecimal('3.14159').round(2).class.name #=> "BigDecimal"
1887
+ * BigDecimal('3.14159').round.class.name #=> "Integer"
1888
+ *
1765
1889
  * If n is specified and positive, the fractional part of the result has no
1766
1890
  * more than that many digits.
1767
1891
  *
1768
1892
  * If n is specified and negative, at least that many digits to the left of the
1769
- * decimal point will be 0 in the result.
1893
+ * decimal point will be 0 in the result, and return value will be an Integer.
1770
1894
  *
1771
1895
  * BigDecimal('3.14159').round(3) #=> 3.142
1772
- * BigDecimal('13345.234').round(-2) #=> 13300.0
1896
+ * BigDecimal('13345.234').round(-2) #=> 13300
1773
1897
  *
1774
1898
  * The value of the optional mode argument can be used to determine how
1775
1899
  * rounding is performed; see BigDecimal.mode.
@@ -1782,6 +1906,7 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
1782
1906
  int iLoc = 0;
1783
1907
  VALUE vLoc;
1784
1908
  VALUE vRound;
1909
+ int round_to_int = 0;
1785
1910
  size_t mx, pl;
1786
1911
 
1787
1912
  unsigned short sw = VpGetRoundMode();
@@ -1789,6 +1914,7 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
1789
1914
  switch (rb_scan_args(argc, argv, "02", &vLoc, &vRound)) {
1790
1915
  case 0:
1791
1916
  iLoc = 0;
1917
+ round_to_int = 1;
1792
1918
  break;
1793
1919
  case 1:
1794
1920
  if (RB_TYPE_P(vLoc, T_HASH)) {
@@ -1796,6 +1922,7 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
1796
1922
  }
1797
1923
  else {
1798
1924
  iLoc = NUM2INT(vLoc);
1925
+ if (iLoc < 1) round_to_int = 1;
1799
1926
  }
1800
1927
  break;
1801
1928
  case 2:
@@ -1817,7 +1944,7 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
1817
1944
  GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
1818
1945
  VpSetPrecLimit(pl);
1819
1946
  VpActiveRound(c, a, sw, iLoc);
1820
- if (argc == 0) {
1947
+ if (round_to_int) {
1821
1948
  return BigDecimal_to_i(ToValue(c));
1822
1949
  }
1823
1950
  return ToValue(c);
@@ -2027,7 +2154,6 @@ BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
2027
2154
  if (rb_scan_args(argc, argv, "01", &f) == 1) {
2028
2155
  if (RB_TYPE_P(f, T_STRING)) {
2029
2156
  psz = StringValueCStr(f);
2030
- rb_check_safe_obj(f);
2031
2157
  if (*psz == ' ') {
2032
2158
  fPlus = 1;
2033
2159
  psz++;
@@ -2067,7 +2193,7 @@ BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
2067
2193
  nc += (nc + mc - 1) / mc + 1;
2068
2194
  }
2069
2195
 
2070
- str = rb_str_new(0, nc);
2196
+ str = rb_usascii_str_new(0, nc);
2071
2197
  psz = RSTRING_PTR(str);
2072
2198
 
2073
2199
  if (fmt) {
@@ -2132,7 +2258,7 @@ BigDecimal_split(VALUE self)
2132
2258
  rb_ary_push(obj, str);
2133
2259
  rb_str_resize(str, strlen(psz1));
2134
2260
  rb_ary_push(obj, INT2FIX(10));
2135
- rb_ary_push(obj, INT2NUM(e));
2261
+ rb_ary_push(obj, SSIZET2NUM(e));
2136
2262
  return obj;
2137
2263
  }
2138
2264
 
@@ -2145,7 +2271,7 @@ static VALUE
2145
2271
  BigDecimal_exponent(VALUE self)
2146
2272
  {
2147
2273
  ssize_t e = VpExponent10(GetVpValue(self, 1));
2148
- return INT2NUM(e);
2274
+ return SSIZET2NUM(e);
2149
2275
  }
2150
2276
 
2151
2277
  /* Returns a string representation of self.
@@ -2338,7 +2464,10 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2338
2464
  }
2339
2465
  goto retry;
2340
2466
  }
2341
- exp = GetVpValueWithPrec(vexp, DBL_DIG+1, 1);
2467
+ if (NIL_P(prec)) {
2468
+ n += DBLE_FIG;
2469
+ }
2470
+ exp = GetVpValueWithPrec(vexp, DBLE_FIG, 1);
2342
2471
  break;
2343
2472
 
2344
2473
  case T_RATIONAL:
@@ -2353,6 +2482,9 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2353
2482
  goto retry;
2354
2483
  }
2355
2484
  exp = GetVpValueWithPrec(vexp, n, 1);
2485
+ if (NIL_P(prec)) {
2486
+ n += n;
2487
+ }
2356
2488
  break;
2357
2489
 
2358
2490
  case T_DATA:
@@ -2363,6 +2495,10 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2363
2495
  vexp = BigDecimal_to_i(vexp);
2364
2496
  goto retry;
2365
2497
  }
2498
+ if (NIL_P(prec)) {
2499
+ GUARD_OBJ(y, GetVpValue(vexp, 1));
2500
+ n += y->Prec*VpBaseFig();
2501
+ }
2366
2502
  exp = DATA_PTR(vexp);
2367
2503
  break;
2368
2504
  }
@@ -2560,6 +2696,10 @@ BigDecimal_clone(VALUE self)
2560
2696
  return self;
2561
2697
  }
2562
2698
 
2699
+ #ifdef HAVE_RB_OPTS_EXCEPTION_P
2700
+ int rb_opts_exception_p(VALUE opts, int default_value);
2701
+ #define opts_exception_p(opts) rb_opts_exception_p((opts), 1)
2702
+ #else
2563
2703
  static int
2564
2704
  opts_exception_p(VALUE opts)
2565
2705
  {
@@ -2568,12 +2708,20 @@ opts_exception_p(VALUE opts)
2568
2708
  if (!kwds[0]) {
2569
2709
  kwds[0] = rb_intern_const("exception");
2570
2710
  }
2571
- rb_get_kwargs(opts, kwds, 0, 1, &exception);
2711
+ if (!rb_get_kwargs(opts, kwds, 0, 1, &exception)) return 1;
2712
+ switch (exception) {
2713
+ case Qtrue: case Qfalse:
2714
+ break;
2715
+ default:
2716
+ rb_raise(rb_eArgError, "true or false is expected as exception: %+"PRIsVALUE,
2717
+ exception);
2718
+ }
2572
2719
  return exception != Qfalse;
2573
2720
  }
2721
+ #endif
2574
2722
 
2575
2723
  static Real *
2576
- VpNewVarArgs(int argc, VALUE *argv)
2724
+ VpNewVarArg(int argc, VALUE *argv)
2577
2725
  {
2578
2726
  size_t mf;
2579
2727
  VALUE opts = Qnil;
@@ -2616,6 +2764,7 @@ VpNewVarArgs(int argc, VALUE *argv)
2616
2764
  }
2617
2765
  }
2618
2766
 
2767
+ retry:
2619
2768
  switch (TYPE(iniValue)) {
2620
2769
  case T_DATA:
2621
2770
  if (is_kind_of_BigDecimal(iniValue)) {
@@ -2635,7 +2784,7 @@ VpNewVarArgs(int argc, VALUE *argv)
2635
2784
  VpDtoV(pv, d);
2636
2785
  return pv;
2637
2786
  }
2638
- if (mf > DBL_DIG+1) {
2787
+ if (mf > DBLE_FIG) {
2639
2788
  if (!exc) {
2640
2789
  return NULL;
2641
2790
  }
@@ -2653,6 +2802,18 @@ VpNewVarArgs(int argc, VALUE *argv)
2653
2802
  }
2654
2803
  return GetVpValueWithPrec(iniValue, mf, 1);
2655
2804
 
2805
+ case T_COMPLEX:
2806
+ {
2807
+ VALUE im;
2808
+ im = rb_complex_imag(iniValue);
2809
+ if (!is_zero(im)) {
2810
+ rb_raise(rb_eArgError,
2811
+ "Unable to make a BigDecimal from non-zero imaginary number");
2812
+ }
2813
+ iniValue = rb_complex_real(iniValue);
2814
+ goto retry;
2815
+ }
2816
+
2656
2817
  case T_STRING:
2657
2818
  /* fall through */
2658
2819
  default:
@@ -2667,23 +2828,6 @@ VpNewVarArgs(int argc, VALUE *argv)
2667
2828
  return VpAlloc(mf, RSTRING_PTR(iniValue), 1, exc);
2668
2829
  }
2669
2830
 
2670
- static VALUE
2671
- BigDecimal_new(int argc, VALUE *argv, VALUE klass)
2672
- {
2673
- ENTER(1);
2674
- Real *pv;
2675
- VALUE obj;
2676
-
2677
- obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
2678
- pv = VpNewVarArgs(argc, argv);
2679
- if (pv == NULL) return Qnil;
2680
- SAVE(pv);
2681
- if (ToValue(pv)) pv = VpCopy(NULL, pv);
2682
- RTYPEDDATA_DATA(obj) = pv;
2683
- RB_OBJ_FREEZE(obj);
2684
- return pv->obj = obj;
2685
- }
2686
-
2687
2831
  /* call-seq:
2688
2832
  * BigDecimal(initial, digits, exception: true)
2689
2833
  *
@@ -2723,28 +2867,35 @@ BigDecimal_new(int argc, VALUE *argv, VALUE klass)
2723
2867
  static VALUE
2724
2868
  f_BigDecimal(int argc, VALUE *argv, VALUE self)
2725
2869
  {
2726
- return BigDecimal_new(argc, argv, rb_cBigDecimal);
2870
+ ENTER(1);
2871
+ Real *pv;
2872
+ VALUE obj;
2873
+
2874
+ if (argc > 0 && CLASS_OF(argv[0]) == rb_cBigDecimal) {
2875
+ if (argc == 1 || (argc == 2 && RB_TYPE_P(argv[1], T_HASH))) return argv[0];
2876
+ }
2877
+ obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0);
2878
+ pv = VpNewVarArg(argc, argv);
2879
+ if (pv == NULL) return Qnil;
2880
+ SAVE(pv);
2881
+ if (ToValue(pv)) pv = VpCopy(NULL, pv);
2882
+ RTYPEDDATA_DATA(obj) = pv;
2883
+ RB_OBJ_FREEZE(obj);
2884
+ return pv->obj = obj;
2727
2885
  }
2728
2886
 
2729
2887
  static VALUE
2730
2888
  BigDecimal_s_interpret_loosely(VALUE klass, VALUE str)
2731
2889
  {
2732
- ENTER(1);
2733
- char const *c_str;
2734
- Real *pv;
2735
-
2736
- c_str = StringValueCStr(str);
2737
- GUARD_OBJ(pv, VpAlloc(0, c_str, 0, 1));
2738
- pv->obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, pv);
2739
- RB_OBJ_FREEZE(pv->obj);
2740
- return pv->obj;
2741
- }
2890
+ ENTER(1);
2891
+ char const *c_str;
2892
+ Real *pv;
2742
2893
 
2743
- /* DEPRECATED: BigDecimal.new() */
2744
- static VALUE
2745
- BigDecimal_s_new(int argc, VALUE *argv, VALUE klass)
2746
- {
2747
- return BigDecimal_new(argc, argv, klass);
2894
+ c_str = StringValueCStr(str);
2895
+ GUARD_OBJ(pv, VpAlloc(0, c_str, 0, 1));
2896
+ pv->obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, pv);
2897
+ RB_OBJ_FREEZE(pv->obj);
2898
+ return pv->obj;
2748
2899
  }
2749
2900
 
2750
2901
  /* call-seq:
@@ -2763,7 +2914,7 @@ static VALUE
2763
2914
  BigDecimal_limit(int argc, VALUE *argv, VALUE self)
2764
2915
  {
2765
2916
  VALUE nFig;
2766
- VALUE nCur = INT2NUM(VpGetPrecLimit());
2917
+ VALUE nCur = SIZET2NUM(VpGetPrecLimit());
2767
2918
 
2768
2919
  if (rb_scan_args(argc, argv, "01", &nFig) == 1) {
2769
2920
  int nf;
@@ -2928,7 +3079,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
2928
3079
  infinite = isinf(flo);
2929
3080
  nan = isnan(flo);
2930
3081
  if (!infinite && !nan) {
2931
- vx = GetVpValueWithPrec(x, DBL_DIG+1, 0);
3082
+ vx = GetVpValueWithPrec(x, DBLE_FIG, 0);
2932
3083
  }
2933
3084
  break;
2934
3085
 
@@ -2966,6 +3117,10 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
2966
3117
  n = prec + rmpd_double_figures();
2967
3118
  negative = BIGDECIMAL_NEGATIVE_P(vx);
2968
3119
  if (negative) {
3120
+ VALUE x_zero = INT2NUM(1);
3121
+ VALUE x_copy = f_BigDecimal(1, &x_zero, klass);
3122
+ x = BigDecimal_initialize_copy(x_copy, x);
3123
+ vx = DATA_PTR(x);
2969
3124
  VpSetSign(vx, 1);
2970
3125
  }
2971
3126
 
@@ -3077,7 +3232,7 @@ get_vp_value:
3077
3232
  infinite = isinf(flo);
3078
3233
  nan = isnan(flo);
3079
3234
  if (!zero && !negative && !infinite && !nan) {
3080
- vx = GetVpValueWithPrec(x, DBL_DIG+1, 1);
3235
+ vx = GetVpValueWithPrec(x, DBLE_FIG, 1);
3081
3236
  }
3082
3237
  break;
3083
3238
 
@@ -3311,9 +3466,9 @@ Init_bigdecimal(void)
3311
3466
  rb_define_global_function("BigDecimal", f_BigDecimal, -1);
3312
3467
 
3313
3468
  /* Class methods */
3314
- rb_undef_method(CLASS_OF(rb_cBigDecimal), "allocate");
3469
+ rb_undef_alloc_func(rb_cBigDecimal);
3470
+ rb_undef_method(CLASS_OF(rb_cBigDecimal), "new");
3315
3471
  rb_define_singleton_method(rb_cBigDecimal, "interpret_loosely", BigDecimal_s_interpret_loosely, 1);
3316
- rb_define_singleton_method(rb_cBigDecimal, "new", BigDecimal_s_new, -1);
3317
3472
  rb_define_singleton_method(rb_cBigDecimal, "mode", BigDecimal_mode, -1);
3318
3473
  rb_define_singleton_method(rb_cBigDecimal, "limit", BigDecimal_limit, -1);
3319
3474
  rb_define_singleton_method(rb_cBigDecimal, "double_fig", BigDecimal_double_fig, 0);
@@ -3444,8 +3599,9 @@ Init_bigdecimal(void)
3444
3599
 
3445
3600
 
3446
3601
  /* instance methods */
3447
- rb_define_method(rb_cBigDecimal, "initialize_copy", BigDecimal_initialize_copy, 1);
3448
3602
  rb_define_method(rb_cBigDecimal, "precs", BigDecimal_prec, 0);
3603
+ rb_define_method(rb_cBigDecimal, "precision", BigDecimal_precision, 0);
3604
+ rb_define_method(rb_cBigDecimal, "n_significant_digits", BigDecimal_n_significant_digits, 0);
3449
3605
 
3450
3606
  rb_define_method(rb_cBigDecimal, "add", BigDecimal_add2, 2);
3451
3607
  rb_define_method(rb_cBigDecimal, "sub", BigDecimal_sub2, 2);
@@ -3968,7 +4124,7 @@ VpNumOfChars(Real *vp,const char *pszFmt)
3968
4124
  * by one BDIGIT word in the computer used.
3969
4125
  *
3970
4126
  * [Returns]
3971
- * 1+DBL_DIG ... OK
4127
+ * DBLE_FIG ... OK
3972
4128
  */
3973
4129
  VP_EXPORT size_t
3974
4130
  VpInit(BDIGIT BaseVal)
@@ -4138,7 +4294,7 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
4138
4294
  /* at least mx digits. */
4139
4295
  /* szVal==NULL ==> allocate zero value. */
4140
4296
  vp = VpAllocReal(mx);
4141
- /* xmalloc() alway returns(or throw interruption) */
4297
+ /* xmalloc() always returns(or throw interruption) */
4142
4298
  vp->MaxPrec = mx; /* set max precision */
4143
4299
  VpSetZero(vp, 1); /* initialize vp to zero. */
4144
4300
  return vp;
@@ -4314,7 +4470,7 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
4314
4470
  nalloc = Max(nalloc, mx);
4315
4471
  mx = nalloc;
4316
4472
  vp = VpAllocReal(mx);
4317
- /* xmalloc() alway returns(or throw interruption) */
4473
+ /* xmalloc() always returns(or throw interruption) */
4318
4474
  vp->MaxPrec = mx; /* set max precision */
4319
4475
  VpSetZero(vp, sign);
4320
4476
  VpCtoV(vp, psz, ni, psz + ipf, nf, psz + ipe, ne);
@@ -159,6 +159,10 @@ rb_sym2str(VALUE sym)
159
159
  # define vabs llabs
160
160
  #endif
161
161
 
162
+ #if !defined(HAVE_RB_CATEGORY_WARN) || !defined(HAVE_CONST_RB_WARN_CATEGORY_DEPRECATED)
163
+ # define rb_category_warn(category, ...) rb_warn(__VA_ARGS__)
164
+ #endif
165
+
162
166
  extern VALUE rb_cBigDecimal;
163
167
 
164
168
  #if 0 || SIZEOF_BDIGITS >= 16
@@ -36,8 +36,14 @@ have_func("isfinite", "math.h")
36
36
  have_type("struct RRational", "ruby.h")
37
37
  have_func("rb_rational_num", "ruby.h")
38
38
  have_func("rb_rational_den", "ruby.h")
39
+ have_type("struct RComplex", "ruby.h")
40
+ have_func("rb_complex_real", "ruby.h")
41
+ have_func("rb_complex_imag", "ruby.h")
39
42
  have_func("rb_array_const_ptr", "ruby.h")
40
43
  have_func("rb_sym2str", "ruby.h")
44
+ have_func("rb_opts_exception_p", "ruby.h")
45
+ have_func("rb_category_warn", "ruby.h")
46
+ have_const("RB_WARN_CATEGORY_DEPRECATED", "ruby.h")
41
47
 
42
48
  if File.file?(File.expand_path('../lib/bigdecimal.rb', __FILE__))
43
49
  bigdecimal_rb = "$(srcdir)/lib/bigdecimal.rb"
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: false
2
- #
2
+
3
+ require 'bigdecimal'
4
+
3
5
  # require 'bigdecimal/jacobian'
4
6
  #
5
7
  # Provides methods to compute the Jacobian matrix of a set of equations at a
@@ -21,9 +23,6 @@
21
23
  #
22
24
  # fx is f.values(x).
23
25
  #
24
-
25
- require 'bigdecimal'
26
-
27
26
  module Jacobian
28
27
  module_function
29
28
 
@@ -43,7 +43,7 @@ class Float < Numeric
43
43
  #
44
44
  # See also BigDecimal::new.
45
45
  #
46
- def to_d(precision=Float::DIG)
46
+ def to_d(precision=Float::DIG+1)
47
47
  BigDecimal(self, precision)
48
48
  end
49
49
  end
@@ -131,6 +131,39 @@ class Rational < Numeric
131
131
  end
132
132
 
133
133
 
134
+ class Complex < Numeric
135
+ # call-seq:
136
+ # cmp.to_d -> bigdecimal
137
+ # cmp.to_d(precision) -> bigdecimal
138
+ #
139
+ # Returns the value as a BigDecimal.
140
+ #
141
+ # The +precision+ parameter is required for a rational complex number.
142
+ # This parameter is used to determine the number of significant digits
143
+ # for the result.
144
+ #
145
+ # require 'bigdecimal'
146
+ # require 'bigdecimal/util'
147
+ #
148
+ # Complex(0.1234567, 0).to_d(4) # => 0.1235e0
149
+ # Complex(Rational(22, 7), 0).to_d(3) # => 0.314e1
150
+ #
151
+ # See also BigDecimal::new.
152
+ #
153
+ def to_d(*args)
154
+ BigDecimal(self) unless self.imag.zero? # to raise eerror
155
+
156
+ if args.length == 0
157
+ case self.real
158
+ when Rational
159
+ BigDecimal(self.real) # to raise error
160
+ end
161
+ end
162
+ self.real.to_d(*args)
163
+ end
164
+ end
165
+
166
+
134
167
  class NilClass
135
168
  # call-seq:
136
169
  # nil.to_d -> bigdecimal
data/lib/bigdecimal.rb CHANGED
@@ -1,22 +1 @@
1
- begin
2
- require "#{RUBY_VERSION[/\d+\.\d+/]}/bigdecimal.so"
3
- rescue LoadError
4
- require 'bigdecimal.so'
5
- end
6
-
7
- class BigDecimal
8
- module Deprecation
9
- def new(*args, **kwargs)
10
- warn "BigDecimal.new is deprecated; use BigDecimal() method instead.", uplevel: 1
11
- super
12
- end
13
- end
14
-
15
- class << self
16
- prepend Deprecation
17
-
18
- def inherited(subclass)
19
- warn "subclassing BigDecimal will be disallowed after bigdecimal version 2.0", uplevel: 1
20
- end
21
- end
22
- end
1
+ require 'bigdecimal.so'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bigdecimal
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.4
4
+ version: 2.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kenta Murata
@@ -10,22 +10,22 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2019-05-13 00:00:00.000000000 Z
13
+ date: 2020-12-19 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rake
17
17
  requirement: !ruby/object:Gem::Requirement
18
18
  requirements:
19
- - - "~>"
19
+ - - ">="
20
20
  - !ruby/object:Gem::Version
21
- version: '10.0'
21
+ version: 12.3.3
22
22
  type: :development
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
- - - "~>"
26
+ - - ">="
27
27
  - !ruby/object:Gem::Version
28
- version: '10.0'
28
+ version: 12.3.3
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: rake-compiler
31
31
  requirement: !ruby/object:Gem::Requirement
@@ -40,20 +40,6 @@ dependencies:
40
40
  - - ">="
41
41
  - !ruby/object:Gem::Version
42
42
  version: '0.9'
43
- - !ruby/object:Gem::Dependency
44
- name: rake-compiler-dock
45
- requirement: !ruby/object:Gem::Requirement
46
- requirements:
47
- - - ">="
48
- - !ruby/object:Gem::Version
49
- version: 0.6.1
50
- type: :development
51
- prerelease: false
52
- version_requirements: !ruby/object:Gem::Requirement
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- version: 0.6.1
57
43
  - !ruby/object:Gem::Dependency
58
44
  name: minitest
59
45
  requirement: !ruby/object:Gem::Requirement
@@ -106,7 +92,7 @@ files:
106
92
  - sample/pi.rb
107
93
  homepage: https://github.com/ruby/bigdecimal
108
94
  licenses:
109
- - ruby
95
+ - Ruby
110
96
  metadata: {}
111
97
  post_install_message:
112
98
  rdoc_options: []
@@ -116,14 +102,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
116
102
  requirements:
117
103
  - - ">="
118
104
  - !ruby/object:Gem::Version
119
- version: 2.3.0
105
+ version: 2.4.0
120
106
  required_rubygems_version: !ruby/object:Gem::Requirement
121
107
  requirements:
122
108
  - - ">="
123
109
  - !ruby/object:Gem::Version
124
110
  version: '0'
125
111
  requirements: []
126
- rubygems_version: 3.0.3
112
+ rubygems_version: 3.2.2
127
113
  signing_key:
128
114
  specification_version: 4
129
115
  summary: Arbitrary-precision decimal floating-point number library.