Skip to content

Commit 680d00a

Browse files
committed
Specialize addition for small integer literals
1 parent 3fe7c26 commit 680d00a

File tree

1 file changed

+123
-1
lines changed

1 file changed

+123
-1
lines changed

gmp.c

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,129 @@ to_bool(PyObject *self)
883883
return res; \
884884
}
885885

886-
BINOP(add, PyNumber_Add)
886+
#define CHECK_OPv2(u, a, iu) \
887+
if (MPZ_Check(a)) { \
888+
u = (MPZ_Object *)a; \
889+
Py_INCREF(u); \
890+
} \
891+
else if (PyLong_Check(a)) { \
892+
iu = true; \
893+
} \
894+
else if (Number_Check(a)) { \
895+
goto numbers; \
896+
} \
897+
else { \
898+
goto fallback; \
899+
}
900+
901+
#define BINOPv2(suff, slot) \
902+
static PyObject * \
903+
nb_##suff(PyObject *self, PyObject *other) \
904+
{ \
905+
PyObject *res = NULL; \
906+
MPZ_Object *u = NULL, *v = NULL; \
907+
bool iu = false, iv = false; \
908+
\
909+
CHECK_OPv2(u, self, iu); \
910+
CHECK_OPv2(v, other, iv); \
911+
\
912+
res = (PyObject *)MPZ_new(0); \
913+
if (!res) { \
914+
goto end; \
915+
} \
916+
\
917+
zz_err ret = ZZ_OK; \
918+
\
919+
if (iu) { \
920+
int32_t x; \
921+
\
922+
if (PyLong_AsInt32(self, &x) == 0) { \
923+
ret = zz_i32_##suff(x, &v->z, \
924+
&((MPZ_Object *)res)->z); \
925+
goto done; \
926+
} \
927+
else { \
928+
PyErr_Clear(); \
929+
u = MPZ_from_int(self); \
930+
if (!u) { \
931+
goto end; \
932+
} \
933+
} \
934+
} \
935+
if (iv) { \
936+
int32_t x; \
937+
\
938+
if (PyLong_AsInt32(other, &x) == 0) { \
939+
ret = zz_##suff##_i32(&u->z, x, \
940+
&((MPZ_Object *)res)->z); \
941+
goto done; \
942+
} \
943+
else { \
944+
PyErr_Clear(); \
945+
v = MPZ_from_int(other); \
946+
if (!v) { \
947+
goto end; \
948+
} \
949+
} \
950+
} \
951+
ret = zz_##suff(&u->z, &v->z, &((MPZ_Object *)res)->z); \
952+
done: \
953+
if (ret == ZZ_OK) { \
954+
goto end; \
955+
} \
956+
if (ret == ZZ_VAL) { \
957+
Py_CLEAR(res); \
958+
PyErr_SetString(PyExc_ZeroDivisionError, \
959+
"division by zero"); \
960+
} \
961+
else { \
962+
Py_CLEAR(res); \
963+
PyErr_NoMemory(); \
964+
} \
965+
end: \
966+
Py_XDECREF(u); \
967+
Py_XDECREF(v); \
968+
return res; \
969+
fallback: \
970+
Py_XDECREF(u); \
971+
Py_XDECREF(v); \
972+
Py_RETURN_NOTIMPLEMENTED; \
973+
numbers: \
974+
Py_XDECREF(u); \
975+
Py_XDECREF(v); \
976+
\
977+
PyObject *uf, *vf; \
978+
\
979+
if (Number_Check(self)) { \
980+
uf = self; \
981+
Py_INCREF(uf); \
982+
} \
983+
else { \
984+
uf = to_float(self); \
985+
if (!uf) { \
986+
return NULL; \
987+
} \
988+
} \
989+
if (Number_Check(other)) { \
990+
vf = other; \
991+
Py_INCREF(vf); \
992+
} \
993+
else { \
994+
vf = to_float(other); \
995+
if (!vf) { \
996+
Py_DECREF(uf); \
997+
return NULL; \
998+
} \
999+
} \
1000+
res = slot(uf, vf); \
1001+
Py_DECREF(uf); \
1002+
Py_DECREF(vf); \
1003+
return res; \
1004+
}
1005+
1006+
#define zz_i32_add(x, y, r) zz_add_i32((y), (x), (r))
1007+
1008+
BINOPv2(add, PyNumber_Add)
8871009
BINOP(sub, PyNumber_Subtract)
8881010
BINOP(mul, PyNumber_Multiply)
8891011

0 commit comments

Comments
 (0)