@@ -2208,6 +2208,14 @@ PyDecType_FromLongExact(PyTypeObject *type, const PyObject *pylong,
22082208 return dec ;
22092209}
22102210
2211+ /* External C-API functions */
2212+ static binaryfunc _py_long_multiply ;
2213+ static binaryfunc _py_long_floor_divide ;
2214+ static ternaryfunc _py_long_power ;
2215+ static unaryfunc _py_float_abs ;
2216+ static PyCFunction _py_long_bit_length ;
2217+ static PyCFunction _py_float_as_integer_ratio ;
2218+
22112219/* Return a PyDecObject or a subtype from a PyFloatObject.
22122220 Conversion is exact. */
22132221static PyObject *
@@ -2258,21 +2266,21 @@ PyDecType_FromFloatExact(PyTypeObject *type, PyObject *v,
22582266 }
22592267
22602268 /* absolute value of the float */
2261- tmp = PyObject_CallMethod ( v , "__abs__" , NULL );
2269+ tmp = _py_float_abs ( v );
22622270 if (tmp == NULL ) {
22632271 return NULL ;
22642272 }
22652273
22662274 /* float as integer ratio: numerator/denominator */
2267- n_d = PyObject_CallMethod (tmp , "as_integer_ratio" , NULL );
2275+ n_d = _py_float_as_integer_ratio (tmp , NULL );
22682276 Py_DECREF (tmp );
22692277 if (n_d == NULL ) {
22702278 return NULL ;
22712279 }
22722280 n = PyTuple_GET_ITEM (n_d , 0 );
22732281 d = PyTuple_GET_ITEM (n_d , 1 );
22742282
2275- tmp = PyObject_CallMethod ( d , "bit_length" , NULL );
2283+ tmp = _py_long_bit_length ( d , NULL );
22762284 if (tmp == NULL ) {
22772285 Py_DECREF (n_d );
22782286 return NULL ;
@@ -5511,6 +5519,32 @@ static struct int_constmap int_constants [] = {
55115519#define CHECK_PTR (expr ) \
55125520 do { if ((expr) == NULL) goto error; } while (0)
55135521
5522+
5523+ static PyCFunction
5524+ cfunc_noargs (PyTypeObject * t , const char * name )
5525+ {
5526+ struct PyMethodDef * m ;
5527+
5528+ if (t -> tp_methods == NULL ) {
5529+ goto error ;
5530+ }
5531+
5532+ for (m = t -> tp_methods ; m -> ml_name != NULL ; m ++ ) {
5533+ if (strcmp (name , m -> ml_name ) == 0 ) {
5534+ if (!(m -> ml_flags & METH_NOARGS )) {
5535+ goto error ;
5536+ }
5537+ return m -> ml_meth ;
5538+ }
5539+ }
5540+
5541+ error :
5542+ PyErr_Format (PyExc_RuntimeError ,
5543+ "internal error: could not find method %s" , name );
5544+ return NULL ;
5545+ }
5546+
5547+
55145548PyMODINIT_FUNC
55155549PyInit__decimal (void )
55165550{
@@ -5535,6 +5569,16 @@ PyInit__decimal(void)
55355569 mpd_setminalloc (_Py_DEC_MINALLOC );
55365570
55375571
5572+ /* Init external C-API functions */
5573+ _py_long_multiply = PyLong_Type .tp_as_number -> nb_multiply ;
5574+ _py_long_floor_divide = PyLong_Type .tp_as_number -> nb_floor_divide ;
5575+ _py_long_power = PyLong_Type .tp_as_number -> nb_power ;
5576+ _py_float_abs = PyFloat_Type .tp_as_number -> nb_absolute ;
5577+ ASSIGN_PTR (_py_float_as_integer_ratio , cfunc_noargs (& PyFloat_Type ,
5578+ "as_integer_ratio" ));
5579+ ASSIGN_PTR (_py_long_bit_length , cfunc_noargs (& PyLong_Type , "bit_length" ));
5580+
5581+
55385582 /* Init types */
55395583 PyDec_Type .tp_base = & PyBaseObject_Type ;
55405584 PyDecContext_Type .tp_base = & PyBaseObject_Type ;
0 commit comments