diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cd6f20b..5bee326 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: ruby-versions: uses: ruby/actions/.github/workflows/ruby_versions.yml@master with: - engine: cruby + engine: cruby-truffleruby min_version: 2.5 versions: '["debug"]' @@ -35,6 +35,7 @@ jobs: - { os: windows-latest , ruby: mingw } - { os: windows-latest , ruby: mswin } exclude: + - { os: macos-latest , ruby: "2.5" } - { os: macos-arm-oss , ruby: "2.5" } - { os: windows-latest , ruby: debug } - { os: windows-latest , ruby: truffleruby } diff --git a/CHANGES.md b/CHANGES.md index 2123976..299819c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,20 @@ # CHANGES +## 3.1.8 + +* Add missing documents [GH-277] + + **@nobu** + +* Fix memory leak in VpAlloc [GH-294] [GH-290] + + Reoprted by **@MaxLap** + +## 3.1.7 + +* Only consists of CI settings and test changes. + This release is needed for developing Ruby to run `make test-bundled-gems` with the released version of bigdecimal. + ## 3.1.6 * Add LICENSE file to gem files [GH-282] diff --git a/bigdecimal.gemspec b/bigdecimal.gemspec index 6942383..b6ef8fd 100644 --- a/bigdecimal.gemspec +++ b/bigdecimal.gemspec @@ -52,4 +52,6 @@ Gem::Specification.new do |s| end s.required_ruby_version = Gem::Requirement.new(">= 2.5.0") + + s.metadata["changelog_uri"] = s.homepage + "/blob/master/CHANGES.md" end diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c index 3e14364..aa2bf21 100644 --- a/ext/bigdecimal/bigdecimal.c +++ b/ext/bigdecimal/bigdecimal.c @@ -31,7 +31,7 @@ #include "bits.h" #include "static_assert.h" -#define BIGDECIMAL_VERSION "3.1.7" +#define BIGDECIMAL_VERSION "3.1.8" /* #define ENABLE_NUMERIC_STRING */ @@ -1780,6 +1780,17 @@ BigDecimal_neg(VALUE self) return VpCheckGetValue(c); } +/* + * call-seq: + * a * b -> bigdecimal + * + * Multiply by the specified value. + * + * The result precision will be the precision of the sum of each precision. + * + * See BigDecimal#mult. + */ + static VALUE BigDecimal_mult(VALUE self, VALUE r) { @@ -3257,10 +3268,11 @@ BigDecimal_initialize_copy(VALUE self, VALUE other) return self; } +/* :nodoc: */ static VALUE BigDecimal_clone(VALUE self) { - return self; + return self; } #ifdef HAVE_RB_OPTS_EXCEPTION_P @@ -3758,6 +3770,12 @@ f_BigDecimal(int argc, VALUE *argv, VALUE self) return rb_convert_to_BigDecimal(val, digs, exception); } +/* call-seq: + * BigDecimal.interpret_loosely(string) -> bigdecimal + * + * Returns the +BigDecimal+ converted loosely from +string+. + */ + static VALUE BigDecimal_s_interpret_loosely(VALUE klass, VALUE str) { @@ -4238,6 +4256,17 @@ BigDecimal_negative_zero(void) return BIGDECIMAL_NEGATIVE_ZERO; } +static inline VALUE +BigDecimal_literal(const char *str) +{ + VALUE arg = rb_str_new_cstr(str); + VALUE val = f_BigDecimal(1, &arg, rb_cBigDecimal); + rb_gc_register_mark_object(val); + return val; +} + +#define BIGDECIMAL_LITERAL(var, val) (BIGDECIMAL_ ## var = BigDecimal_literal(#val)) + /* Document-class: BigDecimal * BigDecimal provides arbitrary-precision floating point decimal arithmetic. * @@ -4394,7 +4423,6 @@ Init_bigdecimal(void) #ifdef HAVE_RB_EXT_RACTOR_SAFE rb_ext_ractor_safe(true); #endif - VALUE arg; id_BigDecimal_exception_mode = rb_intern_const("BigDecimal.exception_mode"); id_BigDecimal_rounding_mode = rb_intern_const("BigDecimal.rounding_mode"); @@ -4532,33 +4560,19 @@ Init_bigdecimal(void) rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_INFINITE", INT2FIX(VP_SIGN_NEGATIVE_INFINITE)); /* Positive zero value. */ - arg = rb_str_new2("+0"); - BIGDECIMAL_POSITIVE_ZERO = f_BigDecimal(1, &arg, rb_cBigDecimal); - rb_gc_register_mark_object(BIGDECIMAL_POSITIVE_ZERO); + BIGDECIMAL_LITERAL(POSITIVE_ZERO, +0); /* Negative zero value. */ - arg = rb_str_new2("-0"); - BIGDECIMAL_NEGATIVE_ZERO = f_BigDecimal(1, &arg, rb_cBigDecimal); - rb_gc_register_mark_object(BIGDECIMAL_NEGATIVE_ZERO); + BIGDECIMAL_LITERAL(NEGATIVE_ZERO, -0); - /* Positive infinity value. */ - arg = rb_str_new2("+Infinity"); - BIGDECIMAL_POSITIVE_INFINITY = f_BigDecimal(1, &arg, rb_cBigDecimal); - rb_gc_register_mark_object(BIGDECIMAL_POSITIVE_INFINITY); + /* Positive infinity[rdoc-ref:BigDecimal@Infinity] value. */ + rb_define_const(rb_cBigDecimal, "INFINITY", BIGDECIMAL_LITERAL(POSITIVE_INFINITY, +Infinity)); /* Negative infinity value. */ - arg = rb_str_new2("-Infinity"); - BIGDECIMAL_NEGATIVE_INFINITY = f_BigDecimal(1, &arg, rb_cBigDecimal); - rb_gc_register_mark_object(BIGDECIMAL_NEGATIVE_INFINITY); + BIGDECIMAL_LITERAL(NEGATIVE_INFINITY, -Infinity); - /* 'Not a Number' value. */ - arg = rb_str_new2("NaN"); - BIGDECIMAL_NAN = f_BigDecimal(1, &arg, rb_cBigDecimal); - rb_gc_register_mark_object(BIGDECIMAL_NAN); - - /* Special value constants */ - rb_define_const(rb_cBigDecimal, "INFINITY", BIGDECIMAL_POSITIVE_INFINITY); - rb_define_const(rb_cBigDecimal, "NAN", BIGDECIMAL_NAN); + /* '{Not a Number}[rdoc-ref:BigDecimal@Not+a+Number]' value. */ + rb_define_const(rb_cBigDecimal, "NAN", BIGDECIMAL_LITERAL(NAN, NaN)); /* instance methods */ rb_define_method(rb_cBigDecimal, "precs", BigDecimal_prec, 0); @@ -5203,6 +5217,48 @@ bigdecimal_parse_special_string(const char *str) return NULL; } +struct VpCtoV_args { + Real *a; + const char *int_chr; + size_t ni; + const char *frac; + size_t nf; + const char *exp_chr; + size_t ne; +}; + +static VALUE +call_VpCtoV(VALUE arg) +{ + struct VpCtoV_args *x = (struct VpCtoV_args *)arg; + return (VALUE)VpCtoV(x->a, x->int_chr, x->ni, x->frac, x->nf, x->exp_chr, x->ne); +} + +static int +protected_VpCtoV(Real *a, const char *int_chr, size_t ni, const char *frac, size_t nf, const char *exp_chr, size_t ne, int free_on_error) +{ + struct VpCtoV_args args; + int state = 0; + + args.a = a; + args.int_chr = int_chr; + args.ni = ni; + args.frac = frac; + args.nf = nf; + args.exp_chr = exp_chr; + args.ne = ne; + + VALUE result = rb_protect(call_VpCtoV, (VALUE)&args, &state); + if (state) { + if (free_on_error) { + rbd_free_struct(a); + } + rb_jump_tag(state); + } + + return (int)result; +} + /* * Allocates variable. * [Input] @@ -5422,7 +5478,7 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc) vp = rbd_allocate_struct(len); vp->MaxPrec = len; /* set max precision */ VpSetZero(vp, sign); - VpCtoV(vp, psz, ni, psz + ipf, nf, psz + ipe, ne); + protected_VpCtoV(vp, psz, ni, psz + ipf, nf, psz + ipe, ne, true); rb_str_resize(buf, 0); return vp; }