Skip to content

Backport 7258, BUG: fix divmod for numpy scalars and arrays. #7297

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

Merged
merged 6 commits into from
Feb 21, 2016

Conversation

charris
Copy link
Member

@charris charris commented Feb 21, 2016

Backport #7258

This fixes the problems with divmod in #7224 and brings divmod for numpy float64 scalars and arrays into agreement with divmod for Python floats. Tests are added to enforce the new behavior and assures that the results for small integers scaled by powers of two are exact.

Too keep the scalar and array math in sync, both the scalar math and loop code is based on a new npy_divmod function in npy_math.

EDIT: I changed the name to npy_divmod.

divmod example, Python floats

In [1]: a = 78 * 6e-8

In [2]: b = 6e-8

In [3]: divmod(a, b)
Out[3]: (77.0, 5.999999999999965e-08)

Before this commit numpy float64 gave

In [4]: divmod(float64(a), float64(b))
Out[4]: (78.0, 0.0)

After this commit numpy float64 gives

In [4]: divmod(float64(a), float64(b))
Out[4]: (77.0, 5.9999999999999651e-08)

The new function is taken from the Python version of float_divmod and
computes the result of floor_division and modulus together so that they
can be kept compatible. This should also result in the '//' and '%'
operators applied to np.float64 and Python float returning the same
values.

The intent is to implement the ufuncs floor_divide and remainder using
the npy_divmod so that their results will also match those of '//' and
'%' while providing consistency between the two.

Note that npy_divmod uses fmod, which is very slow. As a result, the
floor_division and remainder functions are about 4x slower than the
previous versions based on the floor function, but should be more
accurate.
The following numpy scalar floating functions are reimplemented
using the npy_divmod function.

- remainder ('%')
- floor_division ('//')
- divmod

Note that numpy scalars warn on zero division rather than raise.

divmod example, Python floats

    In [1]: a = 78 * 6e-8

    In [2]: b = 6e-8

    In [3]: divmod(a, b)
    Out[3]: (77.0, 5.999999999999965e-08)

Before this commit numpy float64 gave

    In [4]: divmod(float64(a), float64(b))
    Out[4]: (78.0, 0.0)

After this commit numpy float64 gives

    In [4]: divmod(float64(a), float64(b))
    Out[4]: (77.0, 5.9999999999999651e-08)
The floor function is no longer needed in scalarmath as its use has been
replaced by the new pymodf function.
The following numpy ufuncs are reimplemented using the npy_divmod
function.

- remainder ('%')
- floor_divide ('//')

Example of differences

Currently

    In [1]: a = np.array(78 * 6e-8)

    In [2]: b = np.array(6e-8)

    In [3]: a // b
    Out[3]: 77.0

    In [4]: a % b
    Out[4]: 5.9999999999999651e-08

Previously

    In [1]: a = np.array(78 * 6e-8)

    In [2]: b = np.array(6e-8)

    In [3]: a // b
    Out[3]: 78.0

    In [4]: a % b
    Out[4]: 0.0

The first agrees with the Python values for the same operation and is a
bit more accurate for the input values as represented internally.

Closes numpy#7224.
Add tests for some corner cases involving inf, zero, and nan.
Check that small integers are handled exactly.
The floor_divide (//) and remainder (%) functions are complementary
in the sense that a ~= (a % b) + (a // b).
@charris charris added this to the 1.11.0 release milestone Feb 21, 2016
charris added a commit that referenced this pull request Feb 21, 2016
Backport 7258, BUG: fix divmod for numpy scalars and arrays.
@charris charris merged commit 5183b22 into numpy:maintenance/1.11.x Feb 21, 2016
@charris charris deleted the backport-7258 branch February 21, 2016 20:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant