summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--ext/bigdecimal/bigdecimal.c17
-rw-r--r--test/bigdecimal/test_bigdecimal.rb14
3 files changed, 35 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index 918a1b0488..f8cee58788 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+Sun Jul 10 22:50:00 2011 Kenta Murata <mrkn@mrkn.jp>
+
+ * ext/bigdecimal/bigdecimal.c (rmpd_power_by_big_decimal): fix
+ precision treatment errors.
+
+ * test/bigdecimal/test_bigdecimal.rb: add tests for the above change.
+ fix precision treatment errors.
+
+ * ext/bigdecimal/bigdecimal.c (BigDecimal_power): precision argument
+ should be optional for its compatibility.
+
Sun Jul 10 22:38:09 2011 Nobuyoshi Nakada <nobu@ruby-lang.org>
* parse.y (var_ref): distinguish vcall from local variable
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index 15d2c2c0f7..0997dd6ad2 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -1932,15 +1932,15 @@ is_even(VALUE x)
static VALUE
rmpd_power_by_big_decimal(Real const* x, Real const* exp, ssize_t const n)
{
- VALUE log_x, multiplied, y;
+ VALUE log_x, multiplied, y, vn;
if (VpIsZero(exp)) {
return ToValue(VpCreateRbObject(n, "1"));
}
- log_x = BigMath_log(x->obj, n);
- multiplied = BigDecimal_mult2(exp->obj, log_x, SSIZET2NUM(n));
- y = BigMath_exp(multiplied, n);
+ log_x = BigMath_log(x->obj, SSIZET2NUM(n+1));
+ multiplied = BigDecimal_mult2(exp->obj, log_x, SSIZET2NUM(n+1));
+ y = BigMath_exp(multiplied, SSIZET2NUM(n));
return y;
}
@@ -1954,15 +1954,18 @@ rmpd_power_by_big_decimal(Real const* x, Real const* exp, ssize_t const n)
* Also available as the operator **
*/
static VALUE
-BigDecimal_power(VALUE self, VALUE vexp, VALUE prec)
+BigDecimal_power(int argc, VALUE*argv, VALUE self)
{
ENTER(5);
+ VALUE vexp, prec;
Real* exp = NULL;
Real *x, *y;
ssize_t mp, ma, n;
SIGNED_VALUE int_exp;
double d;
+ rb_scan_args(argc, argv, "11", &vexp, &prec);
+
GUARD_OBJ(x, GetVpValue(self, 1));
n = NIL_P(prec) ? (ssize_t)(x->Prec*VpBaseFig()) : NUM2SSIZET(prec);
@@ -2179,7 +2182,7 @@ retry:
static VALUE
BigDecimal_power_op(VALUE self, VALUE exp)
{
- return BigDecimal_power(self, exp, Qnil);
+ return BigDecimal_power(1, &exp, self);
}
/* call-seq:
@@ -2910,7 +2913,7 @@ Init_bigdecimal(void)
rb_define_method(rb_cBigDecimal, "frac", BigDecimal_frac, 0);
rb_define_method(rb_cBigDecimal, "floor", BigDecimal_floor, -1);
rb_define_method(rb_cBigDecimal, "ceil", BigDecimal_ceil, -1);
- rb_define_method(rb_cBigDecimal, "power", BigDecimal_power, 2);
+ rb_define_method(rb_cBigDecimal, "power", BigDecimal_power, -1);
rb_define_method(rb_cBigDecimal, "**", BigDecimal_power_op, 1);
rb_define_method(rb_cBigDecimal, "<=>", BigDecimal_comp, 1);
rb_define_method(rb_cBigDecimal, "==", BigDecimal_eq, 1);
diff --git a/test/bigdecimal/test_bigdecimal.rb b/test/bigdecimal/test_bigdecimal.rb
index 9bd068bfe5..96211a09c7 100644
--- a/test/bigdecimal/test_bigdecimal.rb
+++ b/test/bigdecimal/test_bigdecimal.rb
@@ -964,6 +964,20 @@ class TestBigDecimal < Test::Unit::TestCase
end
end
+ def test_power_without_prec
+ pi = BigDecimal("3.14159265358979323846264338327950288419716939937511")
+ e = BigDecimal("2.71828182845904523536028747135266249775724709369996")
+ pow = BigDecimal("22.4591577183610454734271522045437350275893151339967843873233068")
+ assert_equal(pow, pi.power(e))
+ end
+
+ def test_power_with_prec
+ pi = BigDecimal("3.14159265358979323846264338327950288419716939937511")
+ e = BigDecimal("2.71828182845904523536028747135266249775724709369996")
+ pow = BigDecimal("22.459157718361045473")
+ assert_equal(pow, pi.power(e, 20))
+ end
+
def test_limit
BigDecimal.limit(1)
x = BigDecimal.new("3")