numpy  2.0.0
src/multiarray/number.c File Reference
#include <Python.h>
#include "structmember.h"
#include "numpy/arrayobject.h"
#include "npy_config.h"
#include "npy_pycompat.h"
#include "npy_import.h"
#include "common.h"
#include "number.h"

Defines

#define PY_SSIZE_T_CLEAN
#define NPY_NO_DEPRECATED_API   NPY_API_VERSION
#define _MULTIARRAYMODULE
#define SET(op)
#define GET(op)
#define SAME_SLOTS(m1, m2, slot_name)
#define GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, left_name, right_name, inplace, slot_name)

Functions

NPY_NO_EXPORT int PyArray_SetNumericOps (PyObject *dict)
static int has_ufunc_attr (PyObject *obj)
NPY_NO_EXPORT int needs_right_binop_forward (PyObject *self, PyObject *other, const char *right_name, int inplace_op)
NPY_NO_EXPORT PyObject * PyArray_GetNumericOps (void)
static PyObject * _get_keywords (int rtype, PyArrayObject *out)
NPY_NO_EXPORT PyObject * PyArray_GenericReduceFunction (PyArrayObject *m1, PyObject *op, int axis, int rtype, PyArrayObject *out)
NPY_NO_EXPORT PyObject * PyArray_GenericAccumulateFunction (PyArrayObject *m1, PyObject *op, int axis, int rtype, PyArrayObject *out)
NPY_NO_EXPORT PyObject * PyArray_GenericBinaryFunction (PyArrayObject *m1, PyObject *m2, PyObject *op)
NPY_NO_EXPORT PyObject * PyArray_GenericUnaryFunction (PyArrayObject *m1, PyObject *op)
static PyObject * PyArray_GenericInplaceBinaryFunction (PyArrayObject *m1, PyObject *m2, PyObject *op)
static PyObject * PyArray_GenericInplaceUnaryFunction (PyArrayObject *m1, PyObject *op)
static PyObject * array_add (PyArrayObject *m1, PyObject *m2)
static PyObject * array_subtract (PyArrayObject *m1, PyObject *m2)
static PyObject * array_multiply (PyArrayObject *m1, PyObject *m2)
static PyObject * array_divide (PyArrayObject *m1, PyObject *m2)
static PyObject * array_remainder (PyArrayObject *m1, PyObject *m2)
static NPY_SCALARKIND is_scalar_with_conversion (PyObject *o2, double *out_exponent)
static PyObject * fast_scalar_power (PyArrayObject *a1, PyObject *o2, int inplace)
static PyObject * array_power (PyArrayObject *a1, PyObject *o2, PyObject *NPY_UNUSED(modulo))
static PyObject * array_negative (PyArrayObject *m1)
static PyObject * array_absolute (PyArrayObject *m1)
static PyObject * array_invert (PyArrayObject *m1)
static PyObject * array_left_shift (PyArrayObject *m1, PyObject *m2)
static PyObject * array_right_shift (PyArrayObject *m1, PyObject *m2)
static PyObject * array_bitwise_and (PyArrayObject *m1, PyObject *m2)
static PyObject * array_bitwise_or (PyArrayObject *m1, PyObject *m2)
static PyObject * array_bitwise_xor (PyArrayObject *m1, PyObject *m2)
static PyObject * array_inplace_add (PyArrayObject *m1, PyObject *m2)
static PyObject * array_inplace_subtract (PyArrayObject *m1, PyObject *m2)
static PyObject * array_inplace_multiply (PyArrayObject *m1, PyObject *m2)
static PyObject * array_inplace_divide (PyArrayObject *m1, PyObject *m2)
static PyObject * array_inplace_remainder (PyArrayObject *m1, PyObject *m2)
static PyObject * array_inplace_power (PyArrayObject *a1, PyObject *o2, PyObject *NPY_UNUSED(modulo))
static PyObject * array_inplace_left_shift (PyArrayObject *m1, PyObject *m2)
static PyObject * array_inplace_right_shift (PyArrayObject *m1, PyObject *m2)
static PyObject * array_inplace_bitwise_and (PyArrayObject *m1, PyObject *m2)
static PyObject * array_inplace_bitwise_or (PyArrayObject *m1, PyObject *m2)
static PyObject * array_inplace_bitwise_xor (PyArrayObject *m1, PyObject *m2)
static PyObject * array_floor_divide (PyArrayObject *m1, PyObject *m2)
static PyObject * array_true_divide (PyArrayObject *m1, PyObject *m2)
static PyObject * array_inplace_floor_divide (PyArrayObject *m1, PyObject *m2)
static PyObject * array_inplace_true_divide (PyArrayObject *m1, PyObject *m2)
static int _array_nonzero (PyArrayObject *mp)
static PyObject * array_divmod (PyArrayObject *op1, PyObject *op2)
NPY_NO_EXPORT PyObject * array_int (PyArrayObject *v)
static PyObject * array_float (PyArrayObject *v)
static PyObject * array_long (PyArrayObject *v)
static PyObject * array_oct (PyArrayObject *v)
static PyObject * array_hex (PyArrayObject *v)
static PyObject * _array_copy_nice (PyArrayObject *self)
static PyObject * array_index (PyArrayObject *v)

Variables

NPY_NO_EXPORT NumericOps n_ops
NPY_NO_EXPORT PyNumberMethods array_as_number

Define Documentation

#define GET (   op)
Value:
if (n_ops.op &&                                         \
                    (PyDict_SetItemString(dict, #op, n_ops.op)==-1))    \
        goto fail;
FIXME - macro contains goto
#define GIVE_UP_IF_HAS_RIGHT_BINOP (   m1,
  m2,
  left_name,
  right_name,
  inplace,
  slot_name 
)
Value:
do {                                                                          \
        if (needs_right_binop_forward((PyObject *)m1, m2, right_name, inplace) && \
                (inplace || !SAME_SLOTS(m1, m2, slot_name))) {                    \
            Py_INCREF(Py_NotImplemented);                                         \
            return Py_NotImplemented;                                             \
        }                                                                         \
    } while (0)

Referenced by array_bitwise_and(), array_bitwise_or(), array_bitwise_xor(), array_inplace_add(), array_inplace_bitwise_and(), array_inplace_multiply(), array_inplace_subtract(), array_invert(), array_left_shift(), array_negative(), PyArray_GenericInplaceUnaryFunction(), and PyArray_GenericUnaryFunction().

#define NPY_NO_DEPRECATED_API   NPY_API_VERSION
#include <stdio.h>
#define SAME_SLOTS (   m1,
  m2,
  slot_name 
)
Value:
(Py_TYPE(m1)->tp_as_number != NULL && Py_TYPE(m2)->tp_as_number != NULL && \
     Py_TYPE(m1)->tp_as_number->slot_name == Py_TYPE(m2)->tp_as_number->slot_name)
In pure-Python, SAME_SLOTS can be replaced by
getattr(m1, op_name) is getattr(m2, op_name)
#define SET (   op)
Value:
temp = PyDict_GetItemString(dict, #op); \
    if (temp != NULL) { \
        if (!(PyCallable_Check(temp))) { \
            return -1; \
        } \
        Py_INCREF(temp); \
        Py_XDECREF(n_ops.op); \
        n_ops.op = temp; \
    }
Dictionary can contain any of the numeric operations, by name. Those not present will not be changed
FIXME - macro contains a return

Function Documentation

static PyObject* _array_copy_nice ( PyArrayObject self) [static]
static int _array_nonzero ( PyArrayObject mp) [static]
static PyObject* _get_keywords ( int  rtype,
PyArrayObject out 
) [static]
static PyObject* array_absolute ( PyArrayObject m1) [static]
static PyObject* array_add ( PyArrayObject m1,
PyObject *  m2 
) [static]

References npy_cache_import().

static PyObject* array_bitwise_and ( PyArrayObject m1,
PyObject *  m2 
) [static]
static PyObject* array_bitwise_or ( PyArrayObject m1,
PyObject *  m2 
) [static]
static PyObject* array_bitwise_xor ( PyArrayObject m1,
PyObject *  m2 
) [static]
static PyObject* array_divide ( PyArrayObject m1,
PyObject *  m2 
) [static]
static PyObject* array_divmod ( PyArrayObject op1,
PyObject *  op2 
) [static]
static PyObject* array_float ( PyArrayObject v) [static]
If we still got an array which can hold references, stop because it could point back at 'v'.
static PyObject* array_floor_divide ( PyArrayObject m1,
PyObject *  m2 
) [static]
static PyObject* array_hex ( PyArrayObject v) [static]
If we still got an array which can hold references, stop because it could point back at 'v'.
static PyObject* array_index ( PyArrayObject v) [static]
static PyObject* array_inplace_add ( PyArrayObject m1,
PyObject *  m2 
) [static]
static PyObject* array_inplace_bitwise_and ( PyArrayObject m1,
PyObject *  m2 
) [static]
static PyObject* array_inplace_bitwise_or ( PyArrayObject m1,
PyObject *  m2 
) [static]
static PyObject* array_inplace_bitwise_xor ( PyArrayObject m1,
PyObject *  m2 
) [static]
static PyObject* array_inplace_divide ( PyArrayObject m1,
PyObject *  m2 
) [static]
static PyObject* array_inplace_floor_divide ( PyArrayObject m1,
PyObject *  m2 
) [static]
static PyObject* array_inplace_left_shift ( PyArrayObject m1,
PyObject *  m2 
) [static]
static PyObject* array_inplace_multiply ( PyArrayObject m1,
PyObject *  m2 
) [static]
static PyObject* array_inplace_power ( PyArrayObject a1,
PyObject *  o2,
PyObject *  NPY_UNUSEDmodulo 
) [static]
modulo is ignored!
static PyObject* array_inplace_remainder ( PyArrayObject m1,
PyObject *  m2 
) [static]
static PyObject* array_inplace_right_shift ( PyArrayObject m1,
PyObject *  m2 
) [static]
static PyObject* array_inplace_true_divide ( PyArrayObject m1,
PyObject *  m2 
) [static]
If we still got an array which can hold references, stop because it could point back at 'v'.
static PyObject* array_left_shift ( PyArrayObject m1,
PyObject *  m2 
) [static]
static PyObject* array_long ( PyArrayObject v) [static]
If we still got an array which can hold references, stop because it could point back at 'v'.
static PyObject* array_multiply ( PyArrayObject m1,
PyObject *  m2 
) [static]
static PyObject* array_negative ( PyArrayObject m1) [static]
static PyObject* array_oct ( PyArrayObject v) [static]
If we still got an array which can hold references, stop because it could point back at 'v'.
static PyObject* array_power ( PyArrayObject a1,
PyObject *  o2,
PyObject *  NPY_UNUSEDmodulo 
) [static]
modulo is ignored!
static PyObject* array_right_shift ( PyArrayObject m1,
PyObject *  m2 
) [static]
static PyObject* array_subtract ( PyArrayObject m1,
PyObject *  m2 
) [static]
static PyObject* array_true_divide ( PyArrayObject m1,
PyObject *  m2 
) [static]

References PyArray_SIZE.

static PyObject* fast_scalar_power ( PyArrayObject a1,
PyObject *  o2,
int  inplace 
) [static]
optimize float array or complex array to a scalar power

<

NPY_NOSCALAR is not scalar
we have to do this one special, as the
"copy" method of array objects isn't set up early enough to be added by PyArray_SetNumericOps.
Because this is called with all arrays, we need to
change the output if the kind of the scalar is different than that of the input and inplace is not on --- (thus, the input should be up-cast)
We only special-case the FLOAT_SCALAR and integer types

References NPY_DOUBLE, PyArray_CastToType(), PyArray_DescrFromType(), and PyArray_ISFORTRAN.

Referenced by array_left_shift().

static int has_ufunc_attr ( PyObject *  obj) [static]
attribute check is expensive for scalar operations, avoid if possible

References PyArray_Check, PyArray_CheckAnyScalar, and PyArray_CheckExact.

static NPY_SCALARKIND is_scalar_with_conversion ( PyObject *  o2,
double *  out_exponent 
) [static]
Determine if object is a scalar and if so, convert the object
to a double and place it in the out_exponent argument and return the "scalar kind" as a result. If the object is not a scalar (or if there are other error conditions) return NPY_NOSCALAR, and out_exponent is undefined.

<

ISFLOAT

<

IsScalar(o2, Floating)
NPY_NO_EXPORT int needs_right_binop_forward ( PyObject *  self,
PyObject *  other,
const char *  right_name,
int  inplace_op 
)
Check whether the operation needs to be forwarded to the right-hand binary operation.
This is the case when all of the following conditions apply:

  1. the other object defines __numpy_ufunc__
  2. the other object defines the right-hand operation __r*__
  3. Python hasn't already called the right-hand operation [occurs if the other object is a strict subclass provided the operation is not in-place]
An additional check is made in GIVE_UP_IF_HAS_RIGHT_BINOP macro below:

  1. other.__class__.__r*__ is not self.__class__.__r*__

    This is needed, because CPython does not call __rmul__ if the tp_number slots of the two objects are the same.

This always prioritizes the __r*__ routines over __numpy_ufunc__, independent of whether the other object is an ndarray subclass or not.
Quick cases
Bail out if Python would already have called the right-hand operation.
NPY_NO_EXPORT PyObject* PyArray_GenericAccumulateFunction ( PyArrayObject m1,
PyObject *  op,
int  axis,
int  rtype,
PyArrayObject out 
)

Referenced by PyArray_Prod(), and PyArray_Sum().

NPY_NO_EXPORT PyObject* PyArray_GenericBinaryFunction ( PyArrayObject m1,
PyObject *  m2,
PyObject *  op 
)
Catch priority inversion and punt, but only if it's guaranteed that we were called through m1 and the other guy is not an array at all. Note that some arrays need to pass through here even with priorities inverted, for example: float(17) * np.matrix(...)
See also:

System Message: WARNING/2 (<string>, line 12) Definition list ends without a blank line; unexpected unindent.
which should possibly be updated when this is.

Referenced by array_inplace_multiply(), PyArray_GenericInplaceUnaryFunction(), and PyArray_GenericUnaryFunction().

NPY_NO_EXPORT PyObject* PyArray_GenericReduceFunction ( PyArrayObject m1,
PyObject *  op,
int  axis,
int  rtype,
PyArrayObject out 
)
NPY_NO_EXPORT PyObject* PyArray_GetNumericOps ( void  )
Get dictionary showing number functions that all arrays will use
NPY_NO_EXPORT int PyArray_SetNumericOps ( PyObject *  dict)
Set internal structure with number functions that all arrays will use

Variable Documentation

NPY_NO_EXPORT PyNumberMethods array_as_number

*********** Implement Number Protocol ************************

System Message: WARNING/2 (<string>, line 1)
Title overline too short.

   Implement Number Protocol ****************************
 
NB: static objects initialized to zero

Referenced by array_bitwise_and(), array_bitwise_or(), array_bitwise_xor(), array_inplace_add(), array_inplace_multiply(), array_inplace_subtract(), array_invert(), PyArray_GenericInplaceUnaryFunction(), PyArray_GenericUnaryFunction(), PyArray_Max(), PyArray_Mean(), PyArray_Prod(), PyArray_Ptp(), and PyArray_Sum().