aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--ext/bigdecimal/bigdecimal.c40
-rw-r--r--test/bigdecimal/test_bigdecimal.rb26
3 files changed, 73 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index ebf7fd32a5..fff25a47fb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Wed Jul 27 00:27:00 2011 Kenta Murata <mrkn@mrkn.jp>
+
+ * bigdecimal/bigdecimal.c (VpDup) a new function for duplicating
+ a BigDecimal.
+
+ * bigdecimal/bigdecimal.c (BigDecimal_new): support generating a new
+ BigDecimal from another BigDecimal using BigDecimal global function
+ or constructor. [ruby-dev:44245]
+
Tue Jul 26 23:33:24 2011 Igor Zubkov <igor.zubkov@gmail.com>
* array.c: Fix typo. https://github.com/ruby/ruby/pull/36
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index 0997dd6ad2..b3360451a9 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -19,6 +19,11 @@
#endif
#include "bigdecimal.h"
+#ifndef BIGDECIMAL_DEBUG
+# define NDEBUG
+#endif
+#include <assert.h>
+
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
@@ -125,6 +130,7 @@ static unsigned short VpGetException(void);
static void VpSetException(unsigned short f);
static void VpInternalRound(Real *c, size_t ixDigit, BDIGIT vPrev, BDIGIT v);
static int VpLimitRound(Real *c, size_t ixDigit);
+static Real *VpDup(Real const* const x);
/*
* **** BigDecimal part ****
@@ -530,6 +536,27 @@ VpCreateRbObject(size_t mx, const char *str)
return pv;
}
+static Real *
+VpDup(Real const* const x)
+{
+ Real *pv;
+
+ assert(x != NULL);
+
+ pv = VpMemAlloc(sizeof(Real) + x->MaxPrec * sizeof(BDIGIT));
+ pv->MaxPrec = x->MaxPrec;
+ pv->Prec = x->Prec;
+ pv->exponent = x->exponent;
+ pv->sign = x->sign;
+ pv->flag = x->flag;
+ MEMCPY(pv->frac, x->frac, BDIGIT, pv->MaxPrec);
+
+ pv->obj = TypedData_Wrap_Struct(
+ rb_obj_class(x->obj), &BigDecimal_data_type, pv);
+
+ return pv;
+}
+
/* Returns True if the value is Not a Number */
static VALUE
BigDecimal_IsNaN(VALUE self)
@@ -2190,8 +2217,10 @@ BigDecimal_power_op(VALUE self, VALUE exp)
*
* Create a new BigDecimal object.
*
- * initial:: The initial value, as a String. Spaces are ignored, unrecognized
- * characters terminate the value.
+ * initial:: The initial value, as an Integer, a Float, a Rational,
+ * a BigDecimal, or a String.
+ * If it is a String, spaces are ignored and unrecognized characters
+ * terminate the value.
*
* digits:: The number of significant digits, as a Fixnum. If omitted or 0,
* the number of significant digits is determined from the initial
@@ -2217,6 +2246,13 @@ BigDecimal_new(int argc, VALUE *argv, VALUE self)
}
switch (TYPE(iniValue)) {
+ case T_DATA:
+ if (is_kind_of_BigDecimal(iniValue)) {
+ pv = VpDup(DATA_PTR(iniValue));
+ return ToValue(pv);
+ }
+ break;
+
case T_FIXNUM:
/* fall through */
case T_BIGNUM:
diff --git a/test/bigdecimal/test_bigdecimal.rb b/test/bigdecimal/test_bigdecimal.rb
index 96211a09c7..e34cbc59c5 100644
--- a/test/bigdecimal/test_bigdecimal.rb
+++ b/test/bigdecimal/test_bigdecimal.rb
@@ -74,6 +74,19 @@ class TestBigDecimal < Test::Unit::TestCase
assert_nothing_raised { BigDecimal(0.1, Float::DIG + 1) }
end
+ def test_global_new_with_big_decimal
+ assert_equal(BigDecimal(1), BigDecimal(BigDecimal(1)))
+ assert_equal(BigDecimal('+0'), BigDecimal(BigDecimal('+0')))
+ assert_equal(BigDecimal('-0'), BigDecimal(BigDecimal('-0')))
+ BigDecimal.save_exception_mode do
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+ assert_positive_infinite(BigDecimal(BigDecimal('Infinity')))
+ assert_negative_infinite(BigDecimal(BigDecimal('-Infinity')))
+ assert_nan(BigDecimal(BigDecimal('NaN')))
+ end
+ end
+
def test_new
assert_equal(1, BigDecimal.new("1"))
assert_equal(1, BigDecimal.new("1", 1))
@@ -111,6 +124,19 @@ class TestBigDecimal < Test::Unit::TestCase
assert_nothing_raised { BigDecimal.new(0.1, Float::DIG + 1) }
end
+ def test_new_with_big_decimal
+ assert_equal(BigDecimal(1), BigDecimal.new(BigDecimal(1)))
+ assert_equal(BigDecimal('+0'), BigDecimal.new(BigDecimal('+0')))
+ assert_equal(BigDecimal('-0'), BigDecimal.new(BigDecimal('-0')))
+ BigDecimal.save_exception_mode do
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+ assert_positive_infinite(BigDecimal.new(BigDecimal('Infinity')))
+ assert_negative_infinite(BigDecimal.new(BigDecimal('-Infinity')))
+ assert_nan(BigDecimal(BigDecimal.new('NaN')))
+ end
+ end
+
def _test_mode(type)
BigDecimal.mode(type, true)
assert_raise(FloatDomainError) { yield }