numpy 2.0.0
src/umath/ufunc_type_resolution.c File Reference
#include "Python.h"
#include "npy_config.h"
#include "numpy/npy_3kcompat.h"
#include "numpy/ufuncobject.h"
#include "ufunc_type_resolution.h"

Data Structures

struct  _ufunc_masker_data

Defines

#define _UMATHMODULE
#define NPY_NO_DEPRECATED_API

Functions

static const char * npy_casting_to_string (NPY_CASTING casting)
NPY_NO_EXPORT int PyUFunc_ValidateCasting (PyUFuncObject *ufunc, NPY_CASTING casting, PyArrayObject **operands, PyArray_Descr **dtypes)
static PyArray_Descrensure_dtype_nbo (PyArray_Descr *type)
NPY_NO_EXPORT int PyUFunc_DefaultTypeResolution (PyUFuncObject *ufunc, NPY_CASTING casting, PyArrayObject **operands, PyObject *type_tup, PyArray_Descr **out_dtypes, PyUFuncGenericFunction *out_innerloop, void **out_innerloopdata)
NPY_NO_EXPORT int PyUFunc_SimpleBinaryComparisonTypeResolution (PyUFuncObject *ufunc, NPY_CASTING casting, PyArrayObject **operands, PyObject *type_tup, PyArray_Descr **out_dtypes, PyUFuncGenericFunction *out_innerloop, void **out_innerloopdata)
NPY_NO_EXPORT int PyUFunc_SimpleUnaryOperationTypeResolution (PyUFuncObject *ufunc, NPY_CASTING casting, PyArrayObject **operands, PyObject *type_tup, PyArray_Descr **out_dtypes, PyUFuncGenericFunction *out_innerloop, void **out_innerloopdata)
NPY_NO_EXPORT int PyUFunc_OnesLikeTypeResolution (PyUFuncObject *ufunc, NPY_CASTING NPY_UNUSED(casting), PyArrayObject **operands, PyObject *type_tup, PyArray_Descr **out_dtypes, PyUFuncGenericFunction *out_innerloop, void **out_innerloopdata)
NPY_NO_EXPORT int PyUFunc_SimpleBinaryOperationTypeResolution (PyUFuncObject *ufunc, NPY_CASTING casting, PyArrayObject **operands, PyObject *type_tup, PyArray_Descr **out_dtypes, PyUFuncGenericFunction *out_innerloop, void **out_innerloopdata)
NPY_NO_EXPORT int PyUFunc_AbsoluteTypeResolution (PyUFuncObject *ufunc, NPY_CASTING casting, PyArrayObject **operands, PyObject *type_tup, PyArray_Descr **out_dtypes, PyUFuncGenericFunction *out_innerloop, void **out_innerloopdata)
static PyObject * get_datetime_metacobj_from_dtype (PyArray_Descr *dtype)
static PyArray_Descrtimedelta_dtype_with_copied_meta (PyArray_Descr *dtype)
NPY_NO_EXPORT int PyUFunc_AdditionTypeResolution (PyUFuncObject *ufunc, NPY_CASTING casting, PyArrayObject **operands, PyObject *type_tup, PyArray_Descr **out_dtypes, PyUFuncGenericFunction *out_innerloop, void **out_innerloopdata)
NPY_NO_EXPORT int PyUFunc_SubtractionTypeResolution (PyUFuncObject *ufunc, NPY_CASTING casting, PyArrayObject **operands, PyObject *type_tup, PyArray_Descr **out_dtypes, PyUFuncGenericFunction *out_innerloop, void **out_innerloopdata)
NPY_NO_EXPORT int PyUFunc_MultiplicationTypeResolution (PyUFuncObject *ufunc, NPY_CASTING casting, PyArrayObject **operands, PyObject *type_tup, PyArray_Descr **out_dtypes, PyUFuncGenericFunction *out_innerloop, void **out_innerloopdata)
NPY_NO_EXPORT int PyUFunc_DivisionTypeResolution (PyUFuncObject *ufunc, NPY_CASTING casting, PyArrayObject **operands, PyObject *type_tup, PyArray_Descr **out_dtypes, PyUFuncGenericFunction *out_innerloop, void **out_innerloopdata)
static NpyAuxDataufunc_masker_data_clone (NpyAuxData *data)
static void unmasked_ufunc_loop_as_masked (char **args, npy_intp *dimensions, npy_intp *steps, NpyAuxData *innerloopdata)
NPY_NO_EXPORT int PyUFunc_DefaultTypeResolutionMasked (PyUFuncObject *ufunc, NPY_CASTING casting, PyArrayObject **operands, PyObject *type_tup, PyArray_Descr **out_dtypes, PyUFuncGenericMaskedFunction *out_innerloop, NpyAuxData **out_innerloopdata)
static int ufunc_loop_matches (PyUFuncObject *self, PyArrayObject **op, NPY_CASTING input_casting, NPY_CASTING output_casting, int any_object, int use_min_scalar, int *types, int *out_no_castable_output, char *out_err_src_typecode, char *out_err_dst_typecode)
static int set_ufunc_loop_data_types (PyUFuncObject *self, PyArrayObject **op, PyArray_Descr **out_dtype, int *types)
static int find_ufunc_matching_userloop (PyUFuncObject *self, PyArrayObject **op, NPY_CASTING input_casting, NPY_CASTING output_casting, int any_object, int use_min_scalar, PyArray_Descr **out_dtype, PyUFuncGenericFunction *out_innerloop, void **out_innerloopdata, int *out_no_castable_output, char *out_err_src_typecode, char *out_err_dst_typecode)
static int find_ufunc_specified_userloop (PyUFuncObject *self, int n_specified, int *specified_types, PyArrayObject **op, NPY_CASTING casting, int any_object, int use_min_scalar, PyArray_Descr **out_dtype, PyUFuncGenericFunction *out_innerloop, void **out_innerloopdata)
static int dtype_kind_to_simplified_ordering (char kind)
static int should_use_min_scalar (PyArrayObject **op, int nop)
NPY_NO_EXPORT int find_best_ufunc_inner_loop (PyUFuncObject *self, PyArrayObject **op, NPY_CASTING input_casting, NPY_CASTING output_casting, int any_object, PyArray_Descr **out_dtype, PyUFuncGenericFunction *out_innerloop, void **out_innerloopdata)
NPY_NO_EXPORT int find_specified_ufunc_inner_loop (PyUFuncObject *self, PyObject *type_tup, PyArrayObject **op, NPY_CASTING casting, int any_object, PyArray_Descr **out_dtype, PyUFuncGenericFunction *out_innerloop, void **out_innerloopdata)

Define Documentation

#define _UMATHMODULE
#define NPY_NO_DEPRECATED_API

Function Documentation

static int dtype_kind_to_simplified_ordering ( char  kind) [static]
Provides an ordering for the dtype 'kind' character codes, to help determine when to use the min_scalar_type function. This groups 'kind' into boolean, integer, floating point, and everything else.

Boolean kind
Unsigned int kind
Signed int kind
Float kind
Complex kind
Anything else

References PyArray_DescrFromType(), and _PyArray_Descr::type_num.

Referenced by set_ufunc_loop_data_types().

static PyArray_Descr* ensure_dtype_nbo ( PyArray_Descr type) [static]
Returns a new reference to type if it is already NBO, otherwise returns a copy converted to NBO.

Referenced by PyUFunc_MultiplicationTypeResolution().

NPY_NO_EXPORT int find_best_ufunc_inner_loop ( PyUFuncObject self,
PyArrayObject **  op,
NPY_CASTING  input_casting,
NPY_CASTING  output_casting,
int  any_object,
PyArray_Descr **  out_dtype,
PyUFuncGenericFunction out_innerloop,
void **  out_innerloopdata 
)
Does a linear search for the best inner loop of the ufunc.
Note that if an error is returned, the caller must free the non-zero references in out_dtype. This function does not do its own clean-up.

For making a better error message on coercion error
If the ufunc has userloops, search for them.
Error
A loop was found
Determine the UFunc loop. This could in general be much faster, and a better way to implement it might be for the ufunc to provide a function which gives back the result type and inner loop function.
A default fast mechanism could be provided for functions which follow the most typical pattern, when all functions have signatures "xx...x -> x" for some built-in data type x, as follows.

System Message: ERROR/3 (<string>, line 9) Unexpected indentation.

<blockquote>

  • Use PyArray_ResultType to get the output type
  • Look up the inner loop in a table based on the output type_num

</blockquote>

The method for finding the loop in the previous code did not appear consistent (as noted by some asymmetry in the generated coercion tables for np.add).
Copy the types into an int array for matching
Error
Found a match
Save the inner loop and its data
If no function was found, throw an error
TODO: We should try again if the casting rule is same_kind
or unsafe, and look for a function more liberally.

Referenced by PyUFunc_DefaultTypeResolution().

NPY_NO_EXPORT int find_specified_ufunc_inner_loop ( PyUFuncObject self,
PyObject *  type_tup,
PyArrayObject **  op,
NPY_CASTING  casting,
int  any_object,
PyArray_Descr **  out_dtype,
PyUFuncGenericFunction out_innerloop,
void **  out_innerloopdata 
)
Does a linear search for the inner loop of the ufunc specified by type_tup.
Note that if an error is returned, the caller must free the non-zero references in out_dtype. This function does not do its own clean-up.

For making a better error message on coercion error
Fill in specified_types from the tuple or string
If the ufunc has userloops, search for them.
Error
Found matching loop
Copy the types into an int array for matching
Error
It worked
Save the inner loop and its data
Didn't work
If no function was found, throw an error

Referenced by PyUFunc_DefaultTypeResolution().

static int find_ufunc_matching_userloop ( PyUFuncObject self,
PyArrayObject **  op,
NPY_CASTING  input_casting,
NPY_CASTING  output_casting,
int  any_object,
int  use_min_scalar,
PyArray_Descr **  out_dtype,
PyUFuncGenericFunction out_innerloop,
void **  out_innerloopdata,
int *  out_no_castable_output,
char *  out_err_src_typecode,
char *  out_err_dst_typecode 
) [static]
Does a search through the arguments and the loops

Use this to try to avoid repeating the same userdef loop search
Error
Found a match
Save the inner loop and its data
Didn't find a match

References NPY_MAXARGS, set_ufunc_loop_data_types(), should_use_min_scalar(), and ufunc_loop_matches().

static int find_ufunc_specified_userloop ( PyUFuncObject self,
int  n_specified,
int *  specified_types,
PyArrayObject **  op,
NPY_CASTING  casting,
int  any_object,
int  use_min_scalar,
PyArray_Descr **  out_dtype,
PyUFuncGenericFunction out_innerloop,
void **  out_innerloopdata 
) [static]
Does a search through the arguments and the loops

Use this to try to avoid repeating the same userdef loop search
It works
Save the inner loop and its data
Didn't match
Error
Didn't find a match

static PyObject* get_datetime_metacobj_from_dtype ( PyArray_Descr dtype) [static]
This function returns the a new reference to the capsule with the datetime metadata.

NOTE: This function is copied from datetime.c in multiarray,
because umath and multiarray are not linked together.

Check that the dtype has metadata
Check that the dtype has unit metadata

static const char* npy_casting_to_string ( NPY_CASTING  casting) [static]
NPY_NO_EXPORT int PyUFunc_AbsoluteTypeResolution ( PyUFuncObject ufunc,
NPY_CASTING  casting,
PyArrayObject **  operands,
PyObject *  type_tup,
PyArray_Descr **  out_dtypes,
PyUFuncGenericFunction out_innerloop,
void **  out_innerloopdata 
)
This function applies special type resolution rules for the absolute ufunc. This ufunc converts complex -> float, so isn't covered by the simple unary type resolution.
Returns 0 on success, -1 on error.

Use the default for complex types, to find the loop producing float

NPY_NO_EXPORT int PyUFunc_AdditionTypeResolution ( PyUFuncObject ufunc,
NPY_CASTING  casting,
PyArrayObject **  operands,
PyObject *  type_tup,
PyArray_Descr **  out_dtypes,
PyUFuncGenericFunction out_innerloop,
void **  out_innerloopdata 
)
This function applies the type resolution rules for addition. In particular, there are a number of special cases with datetime:

System Message: ERROR/3 (<string>, line 3) Unexpected indentation.

<blockquote> m8[<A>] + m8[<B>] => m8[gcd(<A>,<B>)] + m8[gcd(<A>,<B>)] m8[<A>] + int => m8[<A>] + m8[<A>] int + m8[<A>] => m8[<A>] + m8[<A>] M8[<A>] + int => M8[<A>] + m8[<A>] int + M8[<A>] => m8[<A>] + M8[<A>] M8[<A>] + m8[<B>] => M8[gcd(<A>,<B>)] + m8[gcd(<A>,<B>)] m8[<A>] + M8[<B>] => m8[gcd(<A>,<B>)] + M8[gcd(<A>,<B>)]</blockquote>

System Message: WARNING/2 (<string>, line 10) Block quote ends without a blank line; unexpected unindent.
TODO: Non-linear time unit cases require highly special-cased loops
M8[<A>] + m8[Y|M|B] m8[Y|M|B] + M8[<A>]

Use the default when datetime and timedelta are not involved
m8[<A>] + m8[<B>] => m8[gcd(<A>,<B>)] + m8[gcd(<A>,<B>)]
m8[<A>] + M8[<B>] => m8[gcd(<A>,<B>)] + M8[gcd(<A>,<B>)]
Make a new NPY_TIMEDELTA, and copy the datetime's metadata
m8[<A>] + int => m8[<A>] + m8[<A>]
M8[<A>] + m8[<B>] => M8[gcd(<A>,<B>)] + m8[gcd(<A>,<B>)]
Make a new NPY_TIMEDELTA, and copy the datetime's metadata
M8[<A>] + int => M8[<A>] + m8[<A>]
Make a new NPY_TIMEDELTA, and copy type1's metadata
int + m8[<A>] => m8[<A>] + m8[<A>]
Make a new NPY_TIMEDELTA, and copy type2's metadata
Check against the casting rules
Search in the functions list

NPY_NO_EXPORT int PyUFunc_DefaultTypeResolution ( PyUFuncObject ufunc,
NPY_CASTING  casting,
PyArrayObject **  operands,
PyObject *  type_tup,
PyArray_Descr **  out_dtypes,
PyUFuncGenericFunction out_innerloop,
void **  out_innerloopdata 
)
This function applies the default type resolution rules

for the provided ufunc, filling out_dtypes, out_innerloop, and out_innerloopdata.

Returns 0 on success, -1 on error.

Decide the casting rules for inputs and outputs. We want NPY_SAFE_CASTING or stricter, so that the loop selection code doesn't choose an integer loop for float inputs, for example.
Find the best ufunc inner loop, and fill in the dtypes
Find the specified ufunc inner loop, and fill in the dtypes

References find_best_ufunc_inner_loop(), find_specified_ufunc_inner_loop(), _tagPyUFuncObject::nin, _tagPyUFuncObject::nout, NPY_SAFE_CASTING, PyArray_DESCR, and PyTypeNum_ISOBJECT.

Referenced by PyUFunc_MultiplicationTypeResolution(), PyUFunc_SimpleUnaryOperationTypeResolution(), and timedelta_dtype_with_copied_meta().

NPY_NO_EXPORT int PyUFunc_DefaultTypeResolutionMasked ( PyUFuncObject ufunc,
NPY_CASTING  casting,
PyArrayObject **  operands,
PyObject *  type_tup,
PyArray_Descr **  out_dtypes,
PyUFuncGenericMaskedFunction out_innerloop,
NpyAuxData **  out_innerloopdata 
)
This function calls the unmasked type resolution function of the

ufunc, then wraps it with a function which only calls the inner loop where the mask is True.

Returns 0 on success, -1 on error.

Create a new NpyAuxData object for the masker data
Get the unmasked ufunc inner loop
Return the loop function + aux data

NPY_NO_EXPORT int PyUFunc_DivisionTypeResolution ( PyUFuncObject ufunc,
NPY_CASTING  casting,
PyArrayObject **  operands,
PyObject *  type_tup,
PyArray_Descr **  out_dtypes,
PyUFuncGenericFunction out_innerloop,
void **  out_innerloopdata 
)
This function applies the type resolution rules for division. In particular, there are a number of special cases with datetime:

System Message: ERROR/3 (<string>, line 3) Unexpected indentation.

<blockquote> m8[<A>] / m8[<B>] to m8[gcd(<A>,<B>)] / m8[gcd(<A>,<B>)] -> float64 m8[<A>] / int## to m8[<A>] / int64 -> m8[<A>] m8[<A>] / float## to m8[<A>] / float64 -> m8[<A>]</blockquote>

Use the default when datetime and timedelta are not involved
m8[<A>] / m8[<B>] to m8[gcd(<A>,<B>)] / m8[gcd(<A>,<B>)] -> float64
m8[<A>] / int## => m8[<A>] / int64
m8[<A>] / float## => m8[<A>] / float64
Check against the casting rules
Search in the functions list

NPY_NO_EXPORT int PyUFunc_MultiplicationTypeResolution ( PyUFuncObject ufunc,
NPY_CASTING  casting,
PyArrayObject **  operands,
PyObject *  type_tup,
PyArray_Descr **  out_dtypes,
PyUFuncGenericFunction out_innerloop,
void **  out_innerloopdata 
)
This function applies the type resolution rules for multiplication. In particular, there are a number of special cases with datetime:

System Message: ERROR/3 (<string>, line 3) Unexpected indentation.

<blockquote> int## * m8[<A>] => int64 * m8[<A>] m8[<A>] * int## => m8[<A>] * int64 float## * m8[<A>] => float64 * m8[<A>] m8[<A>] * float## => m8[<A>] * float64</blockquote>

Use the default when datetime and timedelta are not involved
m8[<A>] * int## => m8[<A>] * int64
m8[<A>] * float## => m8[<A>] * float64
int## * m8[<A>] => int64 * m8[<A>]
float## * m8[<A>] => float64 * m8[<A>]
Check against the casting rules
Search in the functions list

References _tagPyUFuncObject::data, ensure_dtype_nbo(), _tagPyUFuncObject::functions, _tagPyUFuncObject::name, NPY_DOUBLE, NPY_LONGLONG, NPY_TIMEDELTA, _tagPyUFuncObject::ntypes, PyArray_DESCR, PyArray_DescrFromType(), PyArray_DescrNewFromType(), PyArray_PromoteTypes(), PyTypeNum_ISDATETIME, PyTypeNum_ISFLOAT, PyTypeNum_ISINTEGER, PyUFunc_DefaultTypeResolution(), PyUFunc_ValidateCasting(), PyUString_ConcatAndDel, PyUString_FromFormat, PyUString_FromString, and _tagPyUFuncObject::types.

NPY_NO_EXPORT int PyUFunc_OnesLikeTypeResolution ( PyUFuncObject ufunc,
NPY_CASTING   NPY_UNUSEDcasting,
PyArrayObject **  operands,
PyObject *  type_tup,
PyArray_Descr **  out_dtypes,
PyUFuncGenericFunction out_innerloop,
void **  out_innerloopdata 
)
The ones_like function shouldn't really be a ufunc, but while it still is, this provides type resolution that always forces UNSAFE casting.
NPY_NO_EXPORT int PyUFunc_SimpleBinaryComparisonTypeResolution ( PyUFuncObject ufunc,
NPY_CASTING  casting,
PyArrayObject **  operands,
PyObject *  type_tup,
PyArray_Descr **  out_dtypes,
PyUFuncGenericFunction out_innerloop,
void **  out_innerloopdata 
)
This function applies special type resolution rules for the case where all the functions have the pattern XX->bool, using PyArray_ResultType instead of a linear search to get the best loop.
Note that a simpler linear search through the functions loop is still done, but switching to a simple array lookup for built-in types would be better at some point.
Returns 0 on success, -1 on error.

Use the default type resolution if there's a custom data type or object arrays.
Input types are the result type
If the type tuple isn't a single-element tuple, let the default type resolution handle this one.
Output type is always boolean
Check against the casting rules
If we have a built-in type, search in the functions list

NPY_NO_EXPORT int PyUFunc_SimpleBinaryOperationTypeResolution ( PyUFuncObject ufunc,
NPY_CASTING  casting,
PyArrayObject **  operands,
PyObject *  type_tup,
PyArray_Descr **  out_dtypes,
PyUFuncGenericFunction out_innerloop,
void **  out_innerloopdata 
)
This function applies special type resolution rules for the case where all the functions have the pattern XX->X, using PyArray_ResultType instead of a linear search to get the best loop.
Note that a simpler linear search through the functions loop is still done, but switching to a simple array lookup for built-in types would be better at some point.
Returns 0 on success, -1 on error.

Use the default type resolution if there's a custom data type or object arrays.
Input types are the result type
If the type tuple isn't a single-element tuple, let the default type resolution handle this one.
Check against the casting rules
If we have a built-in type, search in the functions list

NPY_NO_EXPORT int PyUFunc_SimpleUnaryOperationTypeResolution ( PyUFuncObject ufunc,
NPY_CASTING  casting,
PyArrayObject **  operands,
PyObject *  type_tup,
PyArray_Descr **  out_dtypes,
PyUFuncGenericFunction out_innerloop,
void **  out_innerloopdata 
)
This function applies special type resolution rules for the case where all the functions have the pattern X->X, copying the input descr directly so that metadata is maintained.
Note that a simpler linear search through the functions loop is still done, but switching to a simple array lookup for built-in types would be better at some point.
Returns 0 on success, -1 on error.

Use the default type resolution if there's a custom data type or object arrays.
Input types are the result type
If the type tuple isn't a single-element tuple, let the default type resolution handle this one.
Check against the casting rules
If we have a built-in type, search in the functions list

References PyUFunc_DefaultTypeResolution().

NPY_NO_EXPORT int PyUFunc_SubtractionTypeResolution ( PyUFuncObject ufunc,
NPY_CASTING  casting,
PyArrayObject **  operands,
PyObject *  type_tup,
PyArray_Descr **  out_dtypes,
PyUFuncGenericFunction out_innerloop,
void **  out_innerloopdata 
)
This function applies the type resolution rules for subtraction. In particular, there are a number of special cases with datetime:

System Message: ERROR/3 (<string>, line 3) Unexpected indentation.

<blockquote> m8[<A>] - m8[<B>] => m8[gcd(<A>,<B>)] - m8[gcd(<A>,<B>)] m8[<A>] - int => m8[<A>] - m8[<A>] int - m8[<A>] => m8[<A>] - m8[<A>] M8[<A>] - int => M8[<A>] - m8[<A>] M8[<A>] - m8[<B>] => M8[gcd(<A>,<B>)] - m8[gcd(<A>,<B>)]</blockquote>

System Message: WARNING/2 (<string>, line 8) Block quote ends without a blank line; unexpected unindent.
TODO: Non-linear time unit cases require highly special-cased loops
M8[<A>] - m8[Y|M|B]

Use the default when datetime and timedelta are not involved
m8[<A>] - m8[<B>] => m8[gcd(<A>,<B>)] - m8[gcd(<A>,<B>)]
m8[<A>] - int => m8[<A>] - m8[<A>]
M8[<A>] - m8[<B>] => M8[gcd(<A>,<B>)] - m8[gcd(<A>,<B>)]
Make a new NPY_TIMEDELTA, and copy the datetime's metadata
M8[<A>] - int => M8[<A>] - m8[<A>]
Make a new NPY_TIMEDELTA, and copy type1's metadata
M8[<A>] - M8[<B>] => M8[gcd(<A>,<B>)] - M8[gcd(<A>,<B>)]
Make a new NPY_TIMEDELTA, and copy type1's metadata
int - m8[<A>] => m8[<A>] - m8[<A>]
Check against the casting rules
Search in the functions list

NPY_NO_EXPORT int PyUFunc_ValidateCasting ( PyUFuncObject ufunc,
NPY_CASTING  casting,
PyArrayObject **  operands,
PyArray_Descr **  dtypes 
)
Validates that the input operands can be cast to

the input types, and the output types can be cast to the output operands where provided.

Returns 0 on success, -1 (with exception raised) on validation failure.

References _tagPyUFuncObject::name, _tagPyUFuncObject::nin, _tagPyUFuncObject::nout, npy_casting_to_string(), PyArray_CanCastArrayTo(), PyArray_CanCastTypeTo(), PyArray_DESCR, PyUString_ConcatAndDel, PyUString_FromFormat, and PyUString_FromString.

Referenced by PyUFunc_MultiplicationTypeResolution().

static int set_ufunc_loop_data_types ( PyUFuncObject self,
PyArrayObject **  op,
PyArray_Descr **  out_dtype,
int *  types 
) [static]
static int should_use_min_scalar ( PyArrayObject **  op,
int  nop 
) [static]

Determine if there are any scalars, and if so, whether the maximum "kind" of the scalars surpasses the maximum "kind" of the arrays
Indicate whether to use the min_scalar_type function

Referenced by find_ufunc_matching_userloop().

static PyArray_Descr* timedelta_dtype_with_copied_meta ( PyArray_Descr dtype) [static]
Creates a new NPY_TIMEDELTA dtype, copying the datetime metadata from the given dtype.

NOTE: This function is copied from datetime.c in multiarray,
because umath and multiarray are not linked together.

References PyUFunc_DefaultTypeResolution().

static int ufunc_loop_matches ( PyUFuncObject self,
PyArrayObject **  op,
NPY_CASTING  input_casting,
NPY_CASTING  output_casting,
int  any_object,
int  use_min_scalar,
int *  types,
int *  out_no_castable_output,
char *  out_err_src_typecode,
char *  out_err_dst_typecode 
) [static]

First check if all the inputs can be safely cast to the types for this function
If no inputs are objects and there are more than one loop, don't allow conversion to object. The rationale behind this is mostly performance. Except for custom ufuncs built with just one object-parametered inner loop, only the types that are supported are implemented. Trying the object version of logical_or on float arguments doesn't seem right.
If all the inputs are scalars, use the regular promotion rules, not the special value-checking ones.
If all the inputs were ok, then check casting back to the outputs.

Referenced by find_ufunc_matching_userloop().

static NpyAuxData* ufunc_masker_data_clone ( NpyAuxData data) [static]

Allocate a new one
Copy the data (unmasked data doesn't have object semantics)

References PyArray_DESCR, and _PyArray_Descr::type.

static void unmasked_ufunc_loop_as_masked ( char **  args,
npy_intp dimensions,
npy_intp steps,
NpyAuxData innerloopdata 
) [static]
This function wraps a regular unmasked ufunc inner loop as a masked ufunc inner loop, only calling the function for elements where the mask is True.

Put the aux data into local variables
Process the data as runs of unmasked values
Skip masked values
Process unmasked values (assumes unmasked loop doesn't mess with the 'args' pointer values)