summaryrefslogtreecommitdiff
path: root/ext/bigdecimal/bigdecimal.c
diff options
context:
space:
mode:
authormrkn <mrkn@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-07-26 15:40:23 +0000
committermrkn <mrkn@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-07-26 15:40:23 +0000
commita238140726b6ce044e89b80b465a9ce0deda8757 (patch)
tree19e355148157e4916cd989199378fdfa2949bcaa /ext/bigdecimal/bigdecimal.c
parent710dc1afc0ffe7ec031a54e6794af142a35b773c (diff)
* 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] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@32674 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/bigdecimal/bigdecimal.c')
-rw-r--r--ext/bigdecimal/bigdecimal.c40
1 files changed, 38 insertions, 2 deletions
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index 0997dd6..b336045 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: