[Python-checkins] r46163 - sandbox/trunk/decimal-c/_decimal.c
georg.brandl
python-checkins at python.org
Wed May 24 13:42:02 CEST 2006
Author: georg.brandl
Date: Wed May 24 13:42:02 2006
New Revision: 46163
Modified:
sandbox/trunk/decimal-c/_decimal.c
Log:
Adding some nb_ methods.
Modified: sandbox/trunk/decimal-c/_decimal.c
==============================================================================
--- sandbox/trunk/decimal-c/_decimal.c (original)
+++ sandbox/trunk/decimal-c/_decimal.c Wed May 24 13:42:02 2006
@@ -624,10 +624,10 @@
if (!new) return NULL;
}
- expdiff = prec - new->ob_size;
+ expdiff = new->ob_size - prec;
if (expdiff == 0)
return new;
- else if (expdiff > 0) {
+ else if (expdiff < 0) {
/* we need to extend precision */
new2 = _NEW_decimalobj(prec, new->sign, new->exp - expdiff);
if (!new2) {
@@ -901,20 +901,20 @@
returns NotImplemented or raises an exception, depending
on the raise argument.
*/
-static decimalobject *
+static PyObject *
_convert_to_decimal(PyTypeObject *type, PyObject *thing,
contextobject *ctx, int raise)
{
if (PyDecimal_Check(thing)) {
Py_INCREF(thing);
- return (decimalobject *)thing;
+ return thing;
} else if (PyInt_Check(thing)) {
long val = PyInt_AsLong(thing);
if (val == -1 && PyErr_Occurred())
return NULL;
- return (decimalobject *)decimal_from_long(type, val);
+ return decimal_from_long(type, val);
} else if (PyLong_Check(thing)) {
- return _decimal_from_pylong(type, thing, ctx);
+ return (PyObject *)_decimal_from_pylong(type, thing, ctx);
}
/* failed to convert */
if (raise) {
@@ -1248,24 +1248,36 @@
PyDoc_STR("Floating point class for decimal arithmetic.");
-#define DECIMAL_SPECIAL_FUNC(func) \
- static PyObject * \
- func (decimalobject *self, decimalobject *other) { \
- contextobject *ctx = getcontext(); \
- if (!ctx) return NULL; \
- return (PyObject *)_do_##func(self, other, ctx); \
+#define DECIMAL_SPECIAL_2FUNC(func) \
+ static PyObject * \
+ func (PyObject *self, PyObject *other) { \
+ decimalobject *res; \
+ contextobject *ctx = getcontext(); \
+ if (!ctx) return NULL; \
+ other = _convert_to_decimal(self->ob_type, other, ctx, 0); \
+ if (other == NULL || other == Py_NotImplemented) return other; \
+ res = _do_##func((decimalobject *)self, \
+ (decimalobject *)other, ctx); \
+ Py_DECREF(other); \
+ }
+
+#define DECIMAL_SPECIAL_1FUNC(func) \
+ static PyObject * \
+ func (PyObject *self) { \
+ contextobject *ctx = getcontext(); \
+ if (!ctx) return NULL; \
+ return (PyObject *)_do_##func((decimalobject *)self, ctx); \
}
-static PyObject *
+
+
+static decimalobject *
_do_decimal_add(decimalobject *self, decimalobject *other,
contextobject *ctx)
{
- other = _convert_to_decimal(self->ob_type, other, ctx, 0);
- if (other == Py_NotImplemented) return other;
-
/* XXX */
}
-DECIMAL_SPECIAL_FUNC(decimal_add)
+DECIMAL_SPECIAL_2FUNC(decimal_add)
static decimalobject *
_do_decimal_subtract(decimalobject *self, decimalobject *other,
@@ -1273,19 +1285,13 @@
{
decimalobject *copy, *res;
- other = _convert_to_decimal(self->ob_type, other, ctx, 0);
- if (other == Py_NotImplemented) return other;
-
if (ISSPECIAL(self) || ISSPECIAL(other)) {
decimalobject *nan;
- if (_check_nans(self, other, ctx, &nan) != 0) {
- Py_DECREF(other);
+ if (_check_nans(self, other, ctx, &nan) != 0)
return nan;
- }
}
copy = _decimal_get_copy(other);
- Py_DECREF(other);
if (!copy)
return NULL;
/* flip sign */
@@ -1298,52 +1304,180 @@
Py_DECREF(copy);
return res;
}
-DECIMAL_SPECIAL_FUNC(decimal_subtract)
+DECIMAL_SPECIAL_2FUNC(decimal_subtract)
STUB(multiply)
STUB(divide)
STUB(remainder)
STUB(divmod)
STUB(power)
-STUB1(negative)
-STUB1(positive)
-STUB1(absolute)
-STUB1(invert)
+static decimalobject *
+_do_decimal_negative(decimalobject *self, contextobject *ctx)
+{
+ int sign = 0;
+ decimalobject *tmp, *res;
+
+ if (ISSPECIAL(self)) {
+ decimalobject *nan;
+ if (_check_nans(self, NULL, ctx, &nan) != 0)
+ return nan;
+ }
+ if (! decimal_nonzero(self))
+ /* - '0' => '0', not '-0' */
+ sign = 0;
+ else if (self->sign & 1)
+ sign--;
+ else
+ sign++;
+
+ res = _decimal_get_copy(self);
+ if (!res) return NULL;
+ res->sign = sign;
+ if (ctx->rounding_dec == ALWAYS_ROUND) {
+ tmp = _decimal_fix(res, ctx);
+ Py_DECREF(res);
+ if (!tmp)
+ return NULL;
+ return tmp;
+ } else {
+ return res;
+ }
+}
+DECIMAL_SPECIAL_1FUNC(decimal_negative)
+
+
+static decimalobject *
+_do_decimal_positive(decimalobject *self, contextobject *ctx)
+{
+ decimalobject *res, *tmp;
+ char sign = self->sign;
+
+ if (ISSPECIAL(self)) {
+ decimalobject *nan;
+ if (_check_nans(self, NULL, ctx, &nan) != 0)
+ return nan;
+ }
+
+ if (! decimal_nonzero(self))
+ /* + '-0' => '0' */
+ sign = 0;
+
+ res = _decimal_get_copy(self);
+ if (!res) return NULL;
+ res->sign = sign;
+ if (ctx->rounding_dec == ALWAYS_ROUND) {
+ tmp = _decimal_fix(res, ctx);
+ Py_DECREF(res);
+ if (!tmp)
+ return NULL;
+ return tmp;
+ } else {
+ return res;
+ }
+}
+DECIMAL_SPECIAL_1FUNC(decimal_positive)
+
+
+static decimalobject *
+_do_decimal_absolute(decimalobject *self, contextobject *ctx, int round)
+{
+ contextobject *ctx2 = NULL;
+ decimalobject *ans;
+
+ if (ISSPECIAL(self)) {
+ decimalobject *nan;
+ if (_check_nans(self, NULL, ctx, &nan) != 0)
+ return nan;
+ }
+
+ if (!round) {
+ ctx2 = context_copy(ctx);
+ if (!ctx2) return NULL;
+ ctx2->rounding_dec = NEVER_ROUND;
+ }
+
+ if (self->sign & 1)
+ ans = _do_decimal_negative(self, ctx2);
+ else
+ ans = _do_decimal_positive(self, ctx2);
+ Py_XDECREF(ctx2);
+ return ans;
+}
static PyObject *
+decimal_absolute(PyObject *self)
+{
+ contextobject *ctx = getcontext();
+ if (!ctx) return NULL;
+ return (PyObject *)_do_decimal_absolute((decimalobject *)self, ctx, 1);
+}
+
+
+static PyObject *
+decimal_long(decimalobject *self)
+{
+ long i, max;
+ char *buf;
+ PyObject *res;
+
+ max = self->ob_size + self->exp;
+
+ buf = PyMem_MALLOC(max + 2); /* with sign */
+ if (!buf) return NULL;
+ buf[0] = (self->sign & 1 ? '-' : '+');
+ for (i = 0; i < max; i++) {
+ if (i < self->ob_size)
+ buf[i+1] = self->digits[i] + 48;
+ else
+ buf[i+1] = '0';
+ }
+ buf[max+1] = 0;
+ res = PyLong_FromString(buf, NULL, 10);
+ PyMem_FREE(buf);
+ return res;
+}
+
+/* Convert to int, truncating. */
+static PyObject *
decimal_int(decimalobject *self)
{
- if (ISSPECIAL(self))
+ long res = 0;
+ long i, max;
+
+ if (ISSPECIAL(self)) {
if (GETNAN(self)) {
contextobject *ctx;
ctx = getcontext();
if (!ctx) return NULL;
- return handle_InvalidContext(self->ob_type, ctx, NULL);
+ return (PyObject *)handle_InvalidContext(self->ob_type, ctx, NULL);
} else if (ISINF(self)) {
PyErr_SetString(PyExc_OverflowError, "Cannot convert infinity to long");
return NULL;
}
+ }
-}
-
+ /* try converting to int, if it's too big, convert to long */
+ max = self->ob_size + self->exp;
-static PyObject *
-decimal_long(decimalobject *self)
-{
- PyObject *tmp, *res;
- tmp = decimal_int(self);
- if (PyInt_Check(tmp)) {
- res = PyLong_FromLong(PyInt_AsLong(tmp));
- Py_DECREF(tmp);
- return res;
- } else {
- /* it's already a long */
- assert(PyLong_Check(tmp));
- return tmp;
+#if SIZEOF_LONG == 4
+ if (max > 9) return decimal_long(self);
+#elif SIZEOF_LONG == 8
+ if (max > 18) return decimal_long(self);
+#else
+#error "Decimal currently assumes that SIZEOF_LONG is 4 or 8, please adapt this"
+#endif
+
+ for (i = 0; i < max; i++) {
+ if (i < self->ob_size)
+ res = res * 10 + self->digits[i];
+ else
+ res *= 10;
}
+ if (self->sign & 1) res = -res;
+ return PyInt_FromLong(res);
}
-
+
static PyObject *
decimal_float(decimalobject *self)
{
@@ -1366,7 +1500,7 @@
if (ISSPECIAL(self))
return 1;
for (i = 0; i < self->ob_size; i++)
- if (i != 0) return 1;
+ if (self->digits[i] != 0) return 1;
return 0;
}
@@ -1381,17 +1515,17 @@
decimal_negative, /* nb_negative */
decimal_positive, /* nb_positive */
decimal_absolute, /* nb_absolute */
- decimal_nonzero, /* nb_nonzero */
- decimal_invert, /* nb_invert */
+ (inquiry)decimal_nonzero, /* nb_nonzero */
+ 0, /* nb_invert */
0, /* nb_lshift */
0, /* nb_rshift */
0, /* nb_and */
0, /* nb_xor */
0, /* nb_or */
0, /* nb_coerce */
- decimal_int, /* nb_int */
- decimal_long, /* nb_long */
- decimal_float, /* nb_float */
+ (unaryfunc)decimal_int, /* nb_int */
+ (unaryfunc)decimal_long, /* nb_long */
+ (unaryfunc)decimal_float, /* nb_float */
0, /* nb_oct */
0, /* nb_hex */
0, /* nb_inplace_add */
@@ -2195,8 +2329,8 @@
{
static char *kwlist[] = {"num", 0};
PyObject *thing = NULL;
- PyObject *nargs, *nkwds;
- PyObject *res, *fixed;
+ PyObject *nargs, *nkwds, *res;
+ decimalobject *fixed;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &thing))
return NULL;
@@ -2224,7 +2358,7 @@
Py_DECREF(nargs);
}
- fixed = _decimal_fix(res, self);
+ fixed = _decimal_fix((decimalobject *)res, self);
Py_DECREF(res);
return fixed;
}
@@ -2794,20 +2928,20 @@
ctx = getcontext();
if (!ctx) return;
- PyDecimal_NaN = PyDecimal_FromString("nan", 3, ctx);
+ PyDecimal_NaN = (decimalobject *)PyDecimal_FromString("nan", 3, ctx);
if (!PyDecimal_NaN)
return;
- if (PyModule_AddObject(m, "NaN", PyDecimal_NaN) < 0)
+ if (PyModule_AddObject(m, "NaN", (PyObject *)PyDecimal_NaN) < 0)
return;
- PyDecimal_Inf = PyDecimal_FromString("inf", 3, ctx);
+ PyDecimal_Inf = (decimalobject *)PyDecimal_FromString("inf", 3, ctx);
if (!PyDecimal_Inf)
return;
- if (PyModule_AddObject(m, "Inf", PyDecimal_Inf) < 0)
+ if (PyModule_AddObject(m, "Inf", (PyObject *)PyDecimal_Inf) < 0)
return;
- PyDecimal_NegInf = PyDecimal_FromString("-inf", 4, ctx);
+ PyDecimal_NegInf = (decimalobject *)PyDecimal_FromString("-inf", 4, ctx);
if (!PyDecimal_NegInf)
return;
- if (PyModule_AddObject(m, "negInf", PyDecimal_NegInf) < 0)
+ if (PyModule_AddObject(m, "negInf", (PyObject *)PyDecimal_NegInf) < 0)
return;
ADD_CONST(m, ROUND_DOWN);
More information about the Python-checkins
mailing list