@@ -2207,6 +2207,14 @@ PyDecType_FromLongExact(PyTypeObject *type, const PyObject *pylong,
22072207 return dec ;
22082208}
22092209
2210+ /* External C-API functions */
2211+ static binaryfunc _py_long_multiply ;
2212+ static binaryfunc _py_long_floor_divide ;
2213+ static ternaryfunc _py_long_power ;
2214+ static unaryfunc _py_float_abs ;
2215+ static PyCFunction _py_long_bit_length ;
2216+ static PyCFunction _py_float_as_integer_ratio ;
2217+
22102218/* Return a PyDecObject or a subtype from a PyFloatObject.
22112219 Conversion is exact. */
22122220static PyObject *
@@ -2257,21 +2265,21 @@ PyDecType_FromFloatExact(PyTypeObject *type, PyObject *v,
22572265 }
22582266
22592267 /* absolute value of the float */
2260- tmp = PyObject_CallMethod ( v , "__abs__" , NULL );
2268+ tmp = _py_float_abs ( v );
22612269 if (tmp == NULL ) {
22622270 return NULL ;
22632271 }
22642272
22652273 /* float as integer ratio: numerator/denominator */
2266- n_d = PyObject_CallMethod (tmp , "as_integer_ratio" , NULL );
2274+ n_d = _py_float_as_integer_ratio (tmp , NULL );
22672275 Py_DECREF (tmp );
22682276 if (n_d == NULL ) {
22692277 return NULL ;
22702278 }
22712279 n = PyTuple_GET_ITEM (n_d , 0 );
22722280 d = PyTuple_GET_ITEM (n_d , 1 );
22732281
2274- tmp = PyObject_CallMethod ( d , "bit_length" , NULL );
2282+ tmp = _py_long_bit_length ( d , NULL );
22752283 if (tmp == NULL ) {
22762284 Py_DECREF (n_d );
22772285 return NULL ;
@@ -3397,7 +3405,6 @@ dec_as_integer_ratio(PyObject *self, PyObject *args UNUSED)
33973405 mpd_ssize_t exp ;
33983406 PyObject * context ;
33993407 uint32_t status = 0 ;
3400- PyNumberMethods * long_methods = PyLong_Type .tp_as_number ;
34013408
34023409 if (mpd_isspecial (MPD (self ))) {
34033410 if (mpd_isnan (MPD (self ))) {
@@ -3444,14 +3451,14 @@ dec_as_integer_ratio(PyObject *self, PyObject *args UNUSED)
34443451 goto error ;
34453452 }
34463453
3447- Py_SETREF (exponent , long_methods -> nb_power (tmp , exponent , Py_None ));
3454+ Py_SETREF (exponent , _py_long_power (tmp , exponent , Py_None ));
34483455 Py_DECREF (tmp );
34493456 if (exponent == NULL ) {
34503457 goto error ;
34513458 }
34523459
34533460 if (exp >= 0 ) {
3454- Py_SETREF (numerator , long_methods -> nb_multiply (numerator , exponent ));
3461+ Py_SETREF (numerator , _py_long_multiply (numerator , exponent ));
34553462 if (numerator == NULL ) {
34563463 goto error ;
34573464 }
@@ -3467,8 +3474,8 @@ dec_as_integer_ratio(PyObject *self, PyObject *args UNUSED)
34673474 if (tmp == NULL ) {
34683475 goto error ;
34693476 }
3470- Py_SETREF (numerator , long_methods -> nb_floor_divide (numerator , tmp ));
3471- Py_SETREF (denominator , long_methods -> nb_floor_divide (denominator , tmp ));
3477+ Py_SETREF (numerator , _py_long_floor_divide (numerator , tmp ));
3478+ Py_SETREF (denominator , _py_long_floor_divide (denominator , tmp ));
34723479 Py_DECREF (tmp );
34733480 if (numerator == NULL || denominator == NULL ) {
34743481 goto error ;
@@ -5611,6 +5618,32 @@ static struct int_constmap int_constants [] = {
56115618#define CHECK_PTR (expr ) \
56125619 do { if ((expr) == NULL) goto error; } while (0)
56135620
5621+
5622+ static PyCFunction
5623+ cfunc_noargs (PyTypeObject * t , const char * name )
5624+ {
5625+ struct PyMethodDef * m ;
5626+
5627+ if (t -> tp_methods == NULL ) {
5628+ goto error ;
5629+ }
5630+
5631+ for (m = t -> tp_methods ; m -> ml_name != NULL ; m ++ ) {
5632+ if (strcmp (name , m -> ml_name ) == 0 ) {
5633+ if (!(m -> ml_flags & METH_NOARGS )) {
5634+ goto error ;
5635+ }
5636+ return m -> ml_meth ;
5637+ }
5638+ }
5639+
5640+ error :
5641+ PyErr_Format (PyExc_RuntimeError ,
5642+ "internal error: could not find method %s" , name );
5643+ return NULL ;
5644+ }
5645+
5646+
56145647PyMODINIT_FUNC
56155648PyInit__decimal (void )
56165649{
@@ -5635,6 +5668,16 @@ PyInit__decimal(void)
56355668 mpd_setminalloc (_Py_DEC_MINALLOC );
56365669
56375670
5671+ /* Init external C-API functions */
5672+ _py_long_multiply = PyLong_Type .tp_as_number -> nb_multiply ;
5673+ _py_long_floor_divide = PyLong_Type .tp_as_number -> nb_floor_divide ;
5674+ _py_long_power = PyLong_Type .tp_as_number -> nb_power ;
5675+ _py_float_abs = PyFloat_Type .tp_as_number -> nb_absolute ;
5676+ ASSIGN_PTR (_py_float_as_integer_ratio , cfunc_noargs (& PyFloat_Type ,
5677+ "as_integer_ratio" ));
5678+ ASSIGN_PTR (_py_long_bit_length , cfunc_noargs (& PyLong_Type , "bit_length" ));
5679+
5680+
56385681 /* Init types */
56395682 PyDec_Type .tp_base = & PyBaseObject_Type ;
56405683 PyDecContext_Type .tp_base = & PyBaseObject_Type ;
0 commit comments