numpy  2.0.0
src/umath/test_rational.c.src File Reference
#include <Python.h>
#include <structmember.h>
#include <numpy/arrayobject.h>
#include <numpy/ufuncobject.h>
#include <numpy/npy_3kcompat.h>
#include <math.h>

Data Structures

struct  rational
struct  PyRational
struct  align_test

Defines

#define NPY_NO_DEPRECATED_API   NPY_API_VERSION
#define AS_RATIONAL(dst, object)
#define OP(py, op)   case py: result = rational_##op(x,y); break;
#define RATIONAL_BINOP_2(name, exp)
#define RATIONAL_BINOP(name)   RATIONAL_BINOP_2(name,rational_##name(x,y))
#define RATIONAL_UNOP(name, type, exp, convert)
#define FIND_EXTREME(name, op)
#define DEFINE_CAST(From, To, statement)
#define DEFINE_INT_CAST(bits)
#define BINARY_UFUNC(name, intype0, intype1, outtype, exp)
#define RATIONAL_BINARY_UFUNC(name, type, exp)   BINARY_UFUNC(rational_ufunc_##name,rational,rational,type,exp)
#define UNARY_UFUNC(name, type, exp)
#define RETVAL
#define REGISTER_CAST(From, To, from_descr, to_typenum, safe)
#define REGISTER_INT_CASTS(bits)
#define REGISTER_UFUNC(name,...)
#define REGISTER_UFUNC_BINARY_RATIONAL(name)   REGISTER_UFUNC(name, {npy_rational, npy_rational, npy_rational})
#define REGISTER_UFUNC_BINARY_COMPARE(name)   REGISTER_UFUNC(name, {npy_rational, npy_rational, NPY_BOOL})
#define REGISTER_UFUNC_UNARY(name)   REGISTER_UFUNC(name, {npy_rational, npy_rational})
#define NEW_UNARY_UFUNC(name, type, doc)
#define GCD_LCM_UFUNC(name, type, doc)

Functions

static void set_overflow (void)
static void set_zero_divide (void)
static NPY_INLINE npy_int32 safe_neg (npy_int32 x)
static NPY_INLINE npy_int32 safe_abs32 (npy_int32 x)
static NPY_INLINE npy_int64 safe_abs64 (npy_int64 x)
static NPY_INLINE npy_int64 gcd (npy_int64 x, npy_int64 y)
static NPY_INLINE npy_int64 lcm (npy_int64 x, npy_int64 y)
static NPY_INLINE rational make_rational_int (npy_int64 n)
static rational make_rational_slow (npy_int64 n_, npy_int64 d_)
static NPY_INLINE npy_int32 d (rational r)
static rational make_rational_fast (npy_int64 n_, npy_int64 d_)
static NPY_INLINE rational rational_negative (rational r)
static NPY_INLINE rational rational_add (rational x, rational y)
static NPY_INLINE rational rational_subtract (rational x, rational y)
static NPY_INLINE rational rational_multiply (rational x, rational y)
static NPY_INLINE rational rational_divide (rational x, rational y)
static NPY_INLINE npy_int64 rational_floor (rational x)
static NPY_INLINE npy_int64 rational_ceil (rational x)
static NPY_INLINE rational rational_remainder (rational x, rational y)
static NPY_INLINE rational rational_abs (rational x)
static NPY_INLINE npy_int64 rational_rint (rational x)
static NPY_INLINE int rational_sign (rational x)
static NPY_INLINE rational rational_inverse (rational x)
static NPY_INLINE int rational_eq (rational x, rational y)
static NPY_INLINE int rational_ne (rational x, rational y)
static NPY_INLINE int rational_lt (rational x, rational y)
static NPY_INLINE int rational_gt (rational x, rational y)
static NPY_INLINE int rational_le (rational x, rational y)
static NPY_INLINE int rational_ge (rational x, rational y)
static NPY_INLINE npy_int32 rational_int (rational x)
static NPY_INLINE double rational_double (rational x)
static NPY_INLINE int rational_nonzero (rational x)
static int scan_rational (const char **s, rational *x)
static NPY_INLINE int PyRational_Check (PyObject *object)
static PyObject * PyRational_FromRational (rational x)
static PyObject * pyrational_new (PyTypeObject *type, PyObject *args, PyObject *kwds)
static PyObject * pyrational_richcompare (PyObject *a, PyObject *b, int op)
static PyObject * pyrational_repr (PyObject *self)
static PyObject * pyrational_str (PyObject *self)
static npy_hash_t pyrational_hash (PyObject *self)
 RATIONAL_BINOP_2 (floor_divide, make_rational_int(rational_floor(rational_divide(x, y)))) static PyObject *pyrational_positive(PyObject *self)
static int pyrational_nonzero (PyObject *self)
static PyObject * pyrational_n (PyObject *self, void *closure)
static PyObject * pyrational_d (PyObject *self, void *closure)
static PyObject * npyrational_getitem (void *data, void *arr)
static int npyrational_setitem (PyObject *item, void *data, void *arr)
static NPY_INLINE void byteswap (npy_int32 *x)
static void npyrational_copyswapn (void *dst_, npy_intp dstride, void *src_, npy_intp sstride, npy_intp n, int swap, void *arr)
static void npyrational_copyswap (void *dst, void *src, int swap, void *arr)
static int npyrational_compare (const void *d0, const void *d1, void *arr)
static void npyrational_dot (void *ip0_, npy_intp is0, void *ip1_, npy_intp is1, void *op, npy_intp n, void *arr)
static npy_bool npyrational_nonzero (void *data, void *arr)
static int npyrational_fill (void *data_, npy_intp length, void *arr)
static int npyrational_fillwithscalar (void *buffer_, npy_intp length, void *value, void *arr)
 RATIONAL_BINARY_UFUNC (floor_divide, rational, make_rational_int(rational_floor(rational_divide(x, y)))) PyUFuncGenericFunction rational_ufunc_true_divide
 UNARY_UFUNC (floor, rational, make_rational_int(rational_floor(x))) UNARY_UFUNC(ceil
 make_rational_int (rational_ceil(x))) UNARY_UFUNC(trunc
 make_rational_int (x.n/d(x))) UNARY_UFUNC(rint
 make_rational_int (rational_rint(x))) UNARY_UFUNC(sign
 make_rational_int (rational_sign(x))) static NPY_INLINE void rational_matrix_multiply(char **args
PyMODINIT_FUNC inittest_rational (void)

Variables

static PyTypeObject PyRational_Type
static PyNumberMethods pyrational_as_number
static PyGetSetDef pyrational_getset []
static PyArray_ArrFuncs npyrational_arrfuncs
PyArray_Descr npyrational_descr
 rational
npy_intpdimensions

Define Documentation

#define AS_RATIONAL (   dst,
  object 
)
Returns Py_NotImplemented on most conversion failures, or raises an overflow error for too long ints
#define BINARY_UFUNC (   name,
  intype0,
  intype1,
  outtype,
  exp 
)
Value:
void name(char** args, npy_intp* dimensions, \
              npy_intp* steps, void* data) { \
        npy_intp is0 = steps[0], is1 = steps[1], \
            os = steps[2], n = *dimensions; \
        char *i0 = args[0], *i1 = args[1], *o = args[2]; \
        int k; \
        for (k = 0; k < n; k++) { \
            intype0 x = *(intype0*)i0; \
            intype1 y = *(intype1*)i1; \
            *(outtype*)o = exp; \
            i0 += is0; i1 += is1; o += os; \
        } \
    }
#define DEFINE_CAST (   From,
  To,
  statement 
)
Value:
static void \
    npycast_##From##_##To(void* from_, void* to_, npy_intp n, \
                          void* fromarr, void* toarr) { \
        const From* from = (From*)from_; \
        To* to = (To*)to_; \
        npy_intp i; \
        for (i = 0; i < n; i++) { \
            From x = from[i]; \
            statement \
            to[i] = y; \
        } \
    }
#define DEFINE_INT_CAST (   bits)
Value:
DEFINE_CAST(npy_int##bits,rational,rational y = make_rational_int(x);) \
    DEFINE_CAST(rational,npy_int##bits,npy_int32 z = rational_int(x); \
                npy_int##bits y = z; if (y != z) set_overflow();)
#define FIND_EXTREME (   name,
  op 
)
Value:
static int \
    npyrational_##name(void* data_, npy_intp n, \
            npy_intp* max_ind, void* arr) { \
        const rational* data; \
        npy_intp best_i; \
        rational best_r; \
        npy_intp i; \
        if (!n) { \
            return 0; \
        } \
        data = (rational*)data_; \
        best_i = 0; \
        best_r = data[0]; \
        for (i = 1; i < n; i++) { \
            if (rational_##op(data[i],best_r)) { \
                best_i = i; \
                best_r = data[i]; \
            } \
        } \
        *max_ind = best_i; \
        return 0; \
    }
#define GCD_LCM_UFUNC (   name,
  type,
  doc 
)
Value:
{ \
        static const PyUFuncGenericFunction func[1] = {name##_ufunc}; \
        static const char types[3] = {type,type,type}; \
        static void* data[1] = {0}; \
        PyObject* ufunc = PyUFunc_FromFuncAndData( \
            (PyUFuncGenericFunction*)func, data,(char*)types, \
            1,2,1,PyUFunc_One,(char*)#name,(char*)doc,0); \
        if (!ufunc) { \
            goto fail; \
        } \
        PyModule_AddObject(m,#name,(PyObject*)ufunc); \
    }
#define NEW_UNARY_UFUNC (   name,
  type,
  doc 
)
Value:
{ \
        int types[2] = {npy_rational,type}; \
        PyObject* ufunc = PyUFunc_FromFuncAndData(0,0,0,0,1,1, \
            PyUFunc_None,(char*)#name,(char*)doc,0); \
        if (!ufunc) { \
            goto fail; \
        } \
        if (PyUFunc_RegisterLoopForType((PyUFuncObject*)ufunc, \
                npy_rational,rational_ufunc_##name,types,0)<0) { \
            goto fail; \
        } \
        PyModule_AddObject(m,#name,(PyObject*)ufunc); \
    }
#define NPY_NO_DEPRECATED_API   NPY_API_VERSION
#define OP (   py,
  op 
)    case py: result = rational_##op(x,y); break;
#define RATIONAL_BINARY_UFUNC (   name,
  type,
  exp 
)    BINARY_UFUNC(rational_ufunc_##name,rational,rational,type,exp)
#define RATIONAL_BINOP (   name)    RATIONAL_BINOP_2(name,rational_##name(x,y))
#define RATIONAL_BINOP_2 (   name,
  exp 
)
Value:
static PyObject* \
    pyrational_##name(PyObject* a, PyObject* b) { \
        rational x, y, z; \
        AS_RATIONAL(x,a); \
        AS_RATIONAL(y,b); \
        z = exp; \
        if (PyErr_Occurred()) { \
            return 0; \
        } \
        return PyRational_FromRational(z); \
    }
#define RATIONAL_UNOP (   name,
  type,
  exp,
  convert 
)
Value:
static PyObject* \
    pyrational_##name(PyObject* self) { \
        rational x = ((PyRational*)self)->r; \
        type y = exp; \
        if (PyErr_Occurred()) { \
            return 0; \
        } \
        return convert(y); \
    }

Referenced by pyrational_repr().

#define REGISTER_CAST (   From,
  To,
  from_descr,
  to_typenum,
  safe 
)
Value:
{ \
            PyArray_Descr* from_descr_##From##_##To = (from_descr); \
            if (PyArray_RegisterCastFunc(from_descr_##From##_##To, \
                                         (to_typenum), \
                                         npycast_##From##_##To) < 0) { \
                goto fail; \
            } \
            if (safe && PyArray_RegisterCanCast(from_descr_##From##_##To, \
                                                (to_typenum), \
                                                NPY_NOSCALAR) < 0) { \
                goto fail; \
            } \
        }
#define REGISTER_INT_CASTS (   bits)
Value:
REGISTER_CAST(npy_int##bits, rational, \
                      PyArray_DescrFromType(NPY_INT##bits), npy_rational, 1) \
        REGISTER_CAST(rational, npy_int##bits, &npyrational_descr, \
                      NPY_INT##bits, 0)

Referenced by npyrational_fill().

#define REGISTER_UFUNC (   name,
  ... 
)
Value:
{ \
        PyUFuncObject* ufunc = \
            (PyUFuncObject*)PyObject_GetAttrString(numpy, #name); \
        int _types[] = __VA_ARGS__; \
        if (!ufunc) { \
            goto fail; \
        } \
        if (sizeof(_types)/sizeof(int)!=ufunc->nargs) { \
            PyErr_Format(PyExc_AssertionError, \
                         "ufunc %s takes %d arguments, our loop takes %lu", \
                         #name, ufunc->nargs, (unsigned long) \
                         (sizeof(_types)/sizeof(int))); \
            Py_DECREF(ufunc); \
            goto fail; \
        } \
        if (PyUFunc_RegisterLoopForType((PyUFuncObject*)ufunc, npy_rational, \
                rational_ufunc_##name, _types, 0) < 0) { \
            Py_DECREF(ufunc); \
            goto fail; \
        } \
        Py_DECREF(ufunc); \
    }
#define REGISTER_UFUNC_BINARY_COMPARE (   name)    REGISTER_UFUNC(name, {npy_rational, npy_rational, NPY_BOOL})
#define REGISTER_UFUNC_BINARY_RATIONAL (   name)    REGISTER_UFUNC(name, {npy_rational, npy_rational, npy_rational})
#define REGISTER_UFUNC_UNARY (   name)    REGISTER_UFUNC(name, {npy_rational, npy_rational})
#define RETVAL
#define UNARY_UFUNC (   name,
  type,
  exp 
)
Value:
void rational_ufunc_##name(char** args, npy_intp* dimensions, \
                               npy_intp* steps, void* data) { \
        npy_intp is = steps[0], os = steps[1], n = *dimensions; \
        char *i = args[0], *o = args[1]; \
        int k; \
        for (k = 0; k < n; k++) { \
            rational x = *(rational*)i; \
            *(type*)o = exp; \
            i += is; o += os; \
        } \
    }

Function Documentation

static NPY_INLINE void byteswap ( npy_int32 *  x) [static]

References dimensions, and rational_add().

static NPY_INLINE npy_int64 gcd ( npy_int64  x,
npy_int64  y 
) [static]

References lcm(), safe_abs64(), and set_overflow().

PyMODINIT_FUNC inittest_rational ( void  )
Can't set this until we import numpy
Initialize rational type object
Initialize rational descriptor
Left undefined: scanfunc, fromstr, sort, argsort
Support dtype(rational) syntax
Register casts to and from rational
Register ufuncs
Binary
Comparisons
Unary
Create module
Add rational type
Create matrix multiply generalized ufunc
Create test ufunc with built in input types and rational output type
Create test ufunc with rational types using RegisterLoopForDescr
Create numerator and denominator ufuncs
Create gcd and lcm ufuncs
static NPY_INLINE npy_int64 lcm ( npy_int64  x,
npy_int64  y 
) [static]

Referenced by gcd().

static rational make_rational_fast ( npy_int64  n_,
npy_int64  d_ 
) [static]
Assumes d_ > 0

Docutils System Messages

System Message: ERROR/3 (<string>, line 1); backlink Unknown target name: "d".
static NPY_INLINE rational make_rational_int ( npy_int64  n) [static]

References d(), rational::n, and safe_neg().

Referenced by rational_ne(), and rational_subtract().

make_rational_int ( x.n/  dx)
static rational make_rational_slow ( npy_int64  n_,
npy_int64  d_ 
) [static]

References rational::dmm.

static int npyrational_compare ( const void *  d0,
const void *  d1,
void *  arr 
) [static]
static void npyrational_copyswap ( void *  dst,
void *  src,
int  swap,
void *  arr 
) [static]
static void npyrational_copyswapn ( void *  dst_,
npy_intp  dstride,
void *  src_,
npy_intp  sstride,
npy_intp  n,
int  swap,
void *  arr 
) [static]
static void npyrational_dot ( void *  ip0_,
npy_intp  is0,
void *  ip1_,
npy_intp  is1,
void *  op,
npy_intp  n,
void *  arr 
) [static]
static int npyrational_fill ( void *  data_,
npy_intp  length,
void *  arr 
) [static]

References REGISTER_INT_CASTS.

static int npyrational_fillwithscalar ( void *  buffer_,
npy_intp  length,
void *  value,
void *  arr 
) [static]
static PyObject* npyrational_getitem ( void *  data,
void *  arr 
) [static]
NumPy support
static npy_bool npyrational_nonzero ( void *  data,
void *  arr 
) [static]
static int npyrational_setitem ( PyObject *  item,
void *  data,
void *  arr 
) [static]
static NPY_INLINE int PyRational_Check ( PyObject *  object) [static]
static PyObject* pyrational_d ( PyObject *  self,
void *  closure 
) [static]
static PyObject* PyRational_FromRational ( rational  x) [static]
static npy_hash_t pyrational_hash ( PyObject *  self) [static]
Use a fairly weak hash as Python expects
Never return the special error value -1
static PyObject* pyrational_n ( PyObject *  self,
void *  closure 
) [static]
static PyObject* pyrational_new ( PyTypeObject *  type,
PyObject *  args,
PyObject *  kwds 
) [static]
Check that we had an exact integer
static int pyrational_nonzero ( PyObject *  self) [static]

References rational::n.

static PyObject* pyrational_repr ( PyObject *  self) [static]

References RATIONAL_UNOP.

static PyObject* pyrational_richcompare ( PyObject *  a,
PyObject *  b,
int  op 
) [static]
static PyObject* pyrational_str ( PyObject *  self) [static]
static NPY_INLINE rational rational_abs ( rational  x) [static]
static NPY_INLINE rational rational_add ( rational  x,
rational  y 
) [static]
Note that the numerator computation can never overflow int128_t, since each term is strictly under 2**128/4 (since d > 0).

Referenced by byteswap().

static NPY_INLINE npy_int64 rational_ceil ( rational  x) [static]
static NPY_INLINE rational rational_divide ( rational  x,
rational  y 
) [static]

Referenced by rational_subtract().

static NPY_INLINE double rational_double ( rational  x) [static]

References PyRational::r.

static NPY_INLINE int rational_eq ( rational  x,
rational  y 
) [static]
Since we enforce d > 0, and store fractions in reduced form, equality is easy.
static NPY_INLINE npy_int64 rational_floor ( rational  x) [static]
Always round down
This can be done without casting up to 64 bits, but it requires working out all the sign cases

References rational::n.

Referenced by rational_subtract().

static NPY_INLINE int rational_ge ( rational  x,
rational  y 
) [static]
static NPY_INLINE int rational_gt ( rational  x,
rational  y 
) [static]
static NPY_INLINE npy_int32 rational_int ( rational  x) [static]
static NPY_INLINE rational rational_inverse ( rational  x) [static]

References rational_lt().

static NPY_INLINE int rational_le ( rational  x,
rational  y 
) [static]
static NPY_INLINE int rational_lt ( rational  x,
rational  y 
) [static]

Referenced by rational_inverse(), and rational_sign().

static NPY_INLINE rational rational_multiply ( rational  x,
rational  y 
) [static]
We're safe from overflow as with +

Referenced by rational_subtract().

static NPY_INLINE int rational_ne ( rational  x,
rational  y 
) [static]

References make_rational_int().

References d(), and rational::n.

static NPY_INLINE int rational_nonzero ( rational  x) [static]
static NPY_INLINE rational rational_remainder ( rational  x,
rational  y 
) [static]
static NPY_INLINE npy_int64 rational_rint ( rational  x) [static]
Round towards nearest integer, moving exact half integers towards zero
static NPY_INLINE int rational_sign ( rational  x) [static]

References rational_lt().

static NPY_INLINE rational rational_subtract ( rational  x,
rational  y 
) [static]
We're safe from overflow as with +

References make_rational_int(), rational_divide(), rational_floor(), and rational_multiply().

static NPY_INLINE npy_int32 safe_abs32 ( npy_int32  x) [static]

References set_overflow().

static NPY_INLINE npy_int64 safe_abs64 ( npy_int64  x) [static]

Referenced by gcd().

static NPY_INLINE npy_int32 safe_neg ( npy_int32  x) [static]
Integer arithmetic utilities

Referenced by make_rational_int().

static int scan_rational ( const char **  s,
rational x 
) [static]
static void set_overflow ( void  ) [static]
Relevant arithmetic exceptions
Uncomment the following line to work around a bug in numpy
#define ACQUIRE_GIL

Referenced by gcd(), and safe_abs32().

static void set_zero_divide ( void  ) [static]

Variable Documentation

Initial value:
 {
    PyObject_HEAD_INIT(0)
    &PyRational_Type,       
    'V',                    
    'r',                    
    '=',                    
    
    NPY_NEEDS_PYAPI | NPY_USE_GETITEM | NPY_USE_SETITEM, 
    0,                      
    sizeof(rational),       
    offsetof(align_test,r), 
    0,                      
    0,                      
    0,                      
    &npyrational_arrfuncs,  
}
PyNumberMethods pyrational_as_number [static]
PyGetSetDef pyrational_getset[] [static]
Initial value:
 {
    {(char*)"n",pyrational_n,0,(char*)"numerator",0},
    {(char*)"d",pyrational_d,0,(char*)"denominator",0},
    {0} 
}
static PyTypeObject PyRational_Type [static]