Skip to content

Type promotion regression #73

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 40 additions & 4 deletions doc/source/reference/c-api.array.rst
Original file line number Diff line number Diff line change
Expand Up @@ -958,30 +958,60 @@ Converting data types
returned when the value will not overflow or be truncated to
an integer when converting to a smaller type.

This is almost the same as the result of
PyArray_CanCastTypeTo(PyArray_MinScalarType(arr), totype, casting),
but it also handles a special case arising because the set
of uint values is not a subset of the int values for types with the
same number of bits.

.. cfunction:: PyArray_Descr* PyArray_MinScalarType(PyArrayObject* arr)

.. versionadded:: 1.6

If *arr* is an array, returns its data type descriptor, but if
*arr* is an array scalar (has 0 dimensions), it finds the data type
of smallest kind and size to which the value may be converted
of smallest size to which the value may be converted
without overflow or truncation to an integer.

This function will not demote complex to float or anything to
boolean, but will demote a signed integer to an unsigned integer
when the scalar value is positive.

.. cfunction:: PyArray_Descr* PyArray_PromoteTypes(PyArray_Descr* type1, PyArray_Descr* type2)

.. versionadded:: 1.6

Finds the data type of smallest size and kind to which *type1* and
*type2* may be safely converted.
*type2* may be safely converted. This function is symmetric and
associative.

.. cfunction:: PyArray_Descr* PyArray_ResultType(npy_intp narrs, PyArrayObject**arrs, npy_intp ndtypes, PyArray_Descr**dtypes)

.. versionadded:: 1.6

This applies PyArray_PromoteTypes to all the inputs, along with
This applies type promotion to all the inputs,
using the NumPy rules for combining scalars and arrays, to
determine the output type of a set of operands. This is the
same result type that ufuncs produce.
same result type that ufuncs produce. The specific algorithm
used is as follows.

Categories are determined by first checking which of boolean,
integer (int/uint), or floating point (float/complex) the maximum
kind of all the arrays and the scalars are.

If there are only scalars or the maximum category of the scalars
is higher than the maximum category of the arrays,
the data types are combined with :cfunc:`PyArray_PromoteTypes`
to produce the return value.

Otherwise, PyArray_MinScalarType is called on each array, and
the resulting data types are all combined with
:cfunc:`PyArray_PromoteTypes` to produce the return value.

The set of int values is not a subset of the uint values for types
with the same number of bits, something not reflected in
:cfunc:`PyArray_MinScalarType`, but handled as a special case in
PyArray_ResultType.

.. cfunction:: int PyArray_ObjectType(PyObject* op, int mintype)

Expand Down Expand Up @@ -2287,6 +2317,9 @@ Array Scalars

.. cfunction:: NPY_SCALARKIND PyArray_ScalarKind(int typenum, PyArrayObject** arr)

See the function :cfunc:`PyArray_MinScalarType` for an alternative
mechanism introduced in NumPy 1.6.0.

Return the kind of scalar represented by *typenum* and the array
in *\*arr* (if *arr* is not ``NULL`` ). The array is assumed to be
rank-0 and only used if *typenum* represents a signed integer. If
Expand All @@ -2300,6 +2333,9 @@ Array Scalars

.. cfunction:: int PyArray_CanCoerceScalar(char thistype, char neededtype, NPY_SCALARKIND scalar)

See the function :cfunc:`PyArray_ResultType` for details of
NumPy type promotion, updated in NumPy 1.6.0.

Implements the rules for scalar coercion. Scalars are only
silently coerced from thistype to neededtype if this function
returns nonzero. If scalar is :cdata:`NPY_NOSCALAR`, then this
Expand Down
51 changes: 48 additions & 3 deletions doc/source/reference/ufuncs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,13 @@ Casting Rules
.. index::
pair: ufunc; casting rules

.. note::

In NumPy 1.6.0, a type promotion API was created to encapsulate the
mechansim for determining output types. See the functions
:func:`result_type`, :func:`promote_types`, and
:func:`min_scalar_type` for more details.

At the core of every ufunc is a one-dimensional strided loop that
implements the actual function for a specific type combination. When a
ufunc is created, it is given a static list of inner loops and a
Expand Down Expand Up @@ -267,19 +274,56 @@ types, are interpreted accordingly in ufuncs) without worrying about
whether the precision of the scalar constant will cause upcasting on
your large (small precision) array.


:class:`ufunc`
==============

Optional keyword arguments
--------------------------

All ufuncs take optional keyword arguments. These represent rather
advanced usage and will not typically be used by most Numpy users.
All ufuncs take optional keyword arguments. Most of these represent
advanced usage and will not typically be used.

.. index::
pair: ufunc; keyword arguments

*out*

.. versionadded:: 1.6

The first output can provided as either a positional or a keyword parameter.

*casting*

.. versionadded:: 1.6

Provides a policy for what kind of casting is permitted. For compatibility
with previous versions of NumPy, this defaults to 'unsafe'. May be 'no',
'equiv', 'safe', 'same_kind', or 'unsafe'. See :func:`can_cast` for
explanations of the parameter values.

*order*

.. versionadded:: 1.6

Specifies the calculation iteration order/memory layout of the output array.
Defaults to 'K'. 'C' means the output should be C-contiguous, 'F' means
F-contiguous, 'A' means F-contiguous if the inputs are F-contiguous, C-contiguous
otherwise, and 'K' means to match the element ordering of the inputs
as closely as possible.

*dtype*

.. versionadded:: 1.6

Overrides the dtype of the calculation and output arrays. Similar to *sig*.

*subok*

.. versionadded:: 1.6

Defaults to true. If set to false, the output will always be a strict
array, not a subtype.

*sig*

Either a data-type, a tuple of data-types, or a special signature
Expand All @@ -304,6 +348,7 @@ advanced usage and will not typically be used by most Numpy users.
in a loop.



Attributes
----------

Expand Down
67 changes: 59 additions & 8 deletions numpy/add_newdocs.py
Original file line number Diff line number Diff line change
Expand Up @@ -1552,14 +1552,25 @@ def luf(lamdaexpr, *args, **kwargs):
Data type, scalar, or array to cast from.
totype : dtype or dtype specifier
Data type to cast to.
casting : casting rule
May be any of 'no', 'equiv', 'safe', 'same_kind', or 'unsafe'.
casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional
Controls what kind of data casting may occur.

* 'no' means the data types should not be cast at all.
* 'equiv' means only byte-order changes are allowed.
* 'safe' means only casts which can preserve values are allowed.
* 'same_kind' means only safe casts or casts within a kind,
like float64 to float32, are allowed.
* 'unsafe' means any data conversions may be done.

Returns
-------
out : bool
True if cast can occur according to the casting rule.

See also
--------
dtype, result_type

Examples
--------

Expand Down Expand Up @@ -1635,6 +1646,8 @@ def luf(lamdaexpr, *args, **kwargs):
kind to which both ``type1`` and ``type2`` may be safely cast.
The returned data type is always in native byte order.

This function is symmetric and associative.

Parameters
----------
type1 : dtype or dtype specifier
Expand All @@ -1647,10 +1660,13 @@ def luf(lamdaexpr, *args, **kwargs):
out : dtype
The promoted data type.

Notes
-----
.. versionadded:: 1.6.0

See Also
--------
issctype, issubsctype, issubdtype, obj2sctype, sctype2char,
maximum_sctype, min_scalar_type
result_type, dtype, can_cast

Examples
--------
Expand Down Expand Up @@ -1678,7 +1694,7 @@ def luf(lamdaexpr, *args, **kwargs):
and smallest scalar kind which can hold its value. For non-scalar
array ``a``, returns the vector's dtype unmodified.

As a special case, floating point values are not demoted to integers,
Floating point values are not demoted to integers,
and complex values are not demoted to floats.

Parameters
Expand All @@ -1691,11 +1707,13 @@ def luf(lamdaexpr, *args, **kwargs):
out : dtype
The minimal data type.

Notes
-----
.. versionadded:: 1.6.0

See Also
--------
issctype, issubsctype, issubdtype, obj2sctype, sctype2char,
maximum_sctype, promote_types
result_type, promote_types, dtype, can_cast

Examples
--------
Expand Down Expand Up @@ -1745,6 +1763,33 @@ def luf(lamdaexpr, *args, **kwargs):
out : dtype
The result type.

See also
--------
dtype, promote_types, min_scalar_type, can_cast

Notes
-----
.. versionadded:: 1.6.0

The specific algorithm used is as follows.

Categories are determined by first checking which of boolean,
integer (int/uint), or floating point (float/complex) the maximum
kind of all the arrays and the scalars are.

If there are only scalars or the maximum category of the scalars
is higher than the maximum category of the arrays,
the data types are combined with :func:`promote_types`
to produce the return value.

Otherwise, `min_scalar_type` is called on each array, and
the resulting data types are all combined with :func:`promote_types`
to produce the return value.

The set of int values is not a subset of the uint values for types
with the same number of bits, something not reflected in
:func:`min_scalar_type`, but handled as a special case in `result_type`.

Examples
--------
>>> np.result_type(3, np.arange(7, dtype='i1'))
Expand Down Expand Up @@ -1911,9 +1956,9 @@ def luf(lamdaexpr, *args, **kwargs):
* 'no' means the data types should not be cast at all.
* 'equiv' means only byte-order changes are allowed.
* 'safe' means only casts which can preserve values are allowed.
* 'unsafe' means any data conversions may be done.
* 'same_kind' means only safe casts or casts within a kind,
like float64 to float32, are allowed.
* 'unsafe' means any data conversions may be done.

Returns
-------
Expand All @@ -1926,6 +1971,8 @@ def luf(lamdaexpr, *args, **kwargs):

Notes
-----
.. versionadded:: 1.6.0

The subscripts string is a comma-separated list of subscript labels,
where each label refers to a dimension of the corresponding operand.
Repeated subscripts labels in one operand take the diagonal. For example,
Expand Down Expand Up @@ -5496,6 +5543,10 @@ def luf(lamdaexpr, *args, **kwargs):
Make a new copy of the data-type object. If ``False``, the result
may just be a reference to a built-in data-type object.

See also
--------
result_type

Examples
--------
Using array-scalar type:
Expand Down
Loading