aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Objects/longobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/longobject.c')
-rw-r--r--Objects/longobject.c54
1 files changed, 45 insertions, 9 deletions
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 2b533312fee..59b10355ad9 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -10,6 +10,7 @@
#include "pycore_long.h" // _Py_SmallInts
#include "pycore_object.h" // _PyObject_Init()
#include "pycore_runtime.h" // _PY_NSMALLPOSINTS
+#include "pycore_stackref.h"
#include "pycore_structseq.h" // _PyStructSequence_FiniBuiltin()
#include "pycore_unicodeobject.h" // _PyUnicode_Equal()
@@ -316,6 +317,33 @@ _PyLong_FromSTwoDigits(stwodigits x)
return (PyLongObject*)_PyLong_FromLarge(x);
}
+/* Create a new medium int object from a medium int.
+ * Do not raise. Return NULL if not medium or can't allocate. */
+static inline _PyStackRef
+medium_from_stwodigits(stwodigits x)
+{
+ if (IS_SMALL_INT(x)) {
+ return PyStackRef_FromPyObjectBorrow(get_small_int((sdigit)x));
+ }
+ assert(x != 0);
+ if(!is_medium_int(x)) {
+ return PyStackRef_NULL;
+ }
+ PyLongObject *v = (PyLongObject *)_Py_FREELIST_POP(PyLongObject, ints);
+ if (v == NULL) {
+ v = PyObject_Malloc(sizeof(PyLongObject));
+ if (v == NULL) {
+ return PyStackRef_NULL;
+ }
+ _PyObject_Init((PyObject*)v, &PyLong_Type);
+ }
+ digit abs_x = x < 0 ? -x : x;
+ _PyLong_SetSignAndDigitCount(v, x<0?-1:1, 1);
+ v->long_value.ob_digit[0] = abs_x;
+ return PyStackRef_FromPyObjectStealMortal((PyObject *)v);
+}
+
+
/* If a freshly-allocated int is already shared, it must
be a small integer, so negating it must go to PyLong_FromLong */
Py_LOCAL_INLINE(void)
@@ -3771,10 +3799,12 @@ long_add(PyLongObject *a, PyLongObject *b)
return z;
}
-PyObject *
-_PyLong_Add(PyLongObject *a, PyLongObject *b)
+_PyStackRef
+_PyCompactLong_Add(PyLongObject *a, PyLongObject *b)
{
- return (PyObject*)long_add(a, b);
+ assert(_PyLong_BothAreCompact(a, b));
+ stwodigits v = medium_value(a) + medium_value(b);
+ return medium_from_stwodigits(v);
}
static PyObject *
@@ -3814,10 +3844,12 @@ long_sub(PyLongObject *a, PyLongObject *b)
return z;
}
-PyObject *
-_PyLong_Subtract(PyLongObject *a, PyLongObject *b)
+_PyStackRef
+_PyCompactLong_Subtract(PyLongObject *a, PyLongObject *b)
{
- return (PyObject*)long_sub(a, b);
+ assert(_PyLong_BothAreCompact(a, b));
+ stwodigits v = medium_value(a) - medium_value(b);
+ return medium_from_stwodigits(v);
}
static PyObject *
@@ -4261,10 +4293,14 @@ long_mul(PyLongObject *a, PyLongObject *b)
return z;
}
-PyObject *
-_PyLong_Multiply(PyLongObject *a, PyLongObject *b)
+/* This function returns NULL if the result is not compact,
+ * or if it fails to allocate, but never raises */
+_PyStackRef
+_PyCompactLong_Multiply(PyLongObject *a, PyLongObject *b)
{
- return (PyObject*)long_mul(a, b);
+ assert(_PyLong_BothAreCompact(a, b));
+ stwodigits v = medium_value(a) * medium_value(b);
+ return medium_from_stwodigits(v);
}
static PyObject *