Skip to content
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

Add notes on overwriting gufunc inputs to docs #4957

Merged
merged 4 commits into from
Jan 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 4 additions & 1 deletion docs/source/reference/jit-compilation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,10 @@ Vectorized functions (ufuncs and DUFuncs)
for the function you are implementing.

If your function doesn't take an output array, you should omit the "arrow"
in the layout string (e.g. ``"(n),(n)"``).
in the layout string (e.g. ``"(n),(n)"``). When doing this, it is important
to be aware that changes to the input arrays cannot always be relied on to be
visible outside the execution of the ufunc, as NumPy may pass in temporary
arrays as inputs (for example, if a cast is required).

.. seealso::
Specification of the `layout string <http://docs.scipy.org/doc/numpy/reference/c-api.generalized-ufuncs.html#details-of-signature>`_
Expand Down
43 changes: 43 additions & 0 deletions docs/source/user/vectorize.rst
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,49 @@ complicated inputs, depending on their shapes::
Use it to ensure the generated code does not fallback to
:term:`object mode`.

.. _overwriting-input-values:

Overwriting input values
------------------------

In most cases, writing to inputs may also appear to work - however, this
behaviour cannot be relied on. Consider the following example function::

@guvectorize([(float64[:], float64[:])], '()->()')
def init_values(invals, outvals):
invals[0] = 6.5
outvals[0] = 4.2

Calling the `init_values` function with an array of `float64` type results in
visible changes to the input::

>>> invals = np.zeros(shape=(3, 3), dtype=np.float64)
>>> outvals = init_values(invals)
>>> invals
array([[6.5, 6.5, 6.5],
[6.5, 6.5, 6.5],
[6.5, 6.5, 6.5]])
>>> outvals
array([[4.2, 4.2, 4.2],
[4.2, 4.2, 4.2],
[4.2, 4.2, 4.2]])

This works because NumPy can pass the input data directly into the `init_values`
function as the data `dtype` matches that of the declared argument. However, it
may also create and pass in a temporary array, in which case changes to the
input are lost. For example, this can occur when casting is required. To
demonstrate, we can use an array of `float32` with the `init_values` function::

>>> invals = np.zeros(shape=(3, 3), dtype=np.float32)
>>> outvals = init_values(invals)
>>> invals
array([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]], dtype=float32)

In this case, there is no change to the `invals` array because the temporary
casted array was mutated instead.

.. _dynamic-universal-functions:

Dynamic universal functions
Expand Down