Skip to content

BUG: Do not elide complex abs() #9110

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 5 commits into from
May 15, 2017
Merged

Conversation

juliantaylor
Copy link
Contributor

complex abs() results in float so it cannot be elided.

Closes gh-9109

complex abs() results in float so it cannot be elided.

Closes numpygh-9109
@juliantaylor
Copy link
Contributor Author

as far as I can tell abs() the only special unary ufunc that changes types

@@ -2850,6 +2850,9 @@ def test_temporary_with_cast(self):
d = f.astype(np.float64)
assert_equal(((f + f) + d).dtype, np.dtype('f8'))

c = np.ones(100000, dtype=np.complex)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might add note as to why large size is needed to test elision.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might make sense to move the elide test into its own class, its currently in binop but abs is a unary

@charris charris added this to the 1.13.0 release milestone May 12, 2017
@@ -565,7 +565,7 @@ array_negative(PyArrayObject *m1)
static PyObject *
array_absolute(PyArrayObject *m1)
{
if (can_elide_temp_unary(m1)) {
if (can_elide_temp_unary(m1) && !PyArray_ISCOMPLEX(m1)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this also going to fail for any user type that overrides abs too? #4730 comes to mind, and problems with a quaternion type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm right, it shouldn't elide object arrays at all it only does that for unary not bianry probably I forgot to update both places.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

though abs(object-array) is again an object array regardless of what __abs__ does

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm referring to registering custom ufunc loops for new dtypes

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue number should have been #9003

@eric-wieser
Copy link
Member

eric-wieser commented May 12, 2017

In general, it's not safe to elide any op on a user-defined dtype - assumptions about commutivity and heterogeneity are both likely to be wrong. If you could detect the ufunc loop before calling it, then you wouldn't need to make those assumptions.

Unfortunately, it seems that __array_ufunc__ makes it impossible to know what the result type is.

@juliantaylor
Copy link
Contributor Author

disabled elision for all non-basic types for unary ops, they were already disable for binaries.
Also added some longdouble tests and some cleanup.

As in binary operations, only elide unary operations on basic types to
avoid odd interactions e.g. with user dtypes.
@eric-wieser
Copy link
Member

Why are object arrays not safe to elide?

@juliantaylor
Copy link
Contributor Author

juliantaylor commented May 12, 2017

they may be, but it is probably not worth the time thinking about it as they are likely to slow to profit anyway.

@charris
Copy link
Member

charris commented May 15, 2017

@eric-wieser Are you OK with this?

@@ -359,7 +359,7 @@ can_elide_temp_unary(PyArrayObject * m1)
{
int cannot;
if (Py_REFCNT(m1) != 1 || !PyArray_CheckExact(m1) ||
PyArray_DESCR(m1)->type_num == NPY_VOID ||
PyArray_DESCR(m1)->type_num >= NPY_OBJECT ||
Copy link
Member

@eric-wieser eric-wieser May 15, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just !PyTypeNum_ISNUMBER(m)? Do we want to include NPY_HALF here too? Or does that have ee->f loops which would cause this to fail?

If NPY_HALF is not ok, then I'd rather have an explicit enumeration of bad types here, with an explanation in a line comment of why each is bad.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the ee->f loop is only used for non fast powers which is not elided (though it could be, albeit with not much performance gain as normal pow is very slow)
adding a test for that is a good idea though

Copy link
Contributor Author

@juliantaylor juliantaylor May 15, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also I think that just tells the inner ufunc loop too cast per element, do the pow and cast back, the output buffer is actually still float16 so it can be elided.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is so, no test needed then
using ISNUMBER is much better, added that

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably fix the release notes to say that elision is added for builtin numeric types

Copy link
Member

@eric-wieser eric-wieser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@charris charris merged commit f8c2b7f into numpy:master May 15, 2017
@charris
Copy link
Member

charris commented May 15, 2017

Thanks Julian. And thanks Eric for reviewin, and feel free to do the merge without waiting on me.

@charris charris removed the 09 - Backport-Candidate PRs tagged should be backported label May 16, 2017
@charris charris changed the title BUG: do not elide complex abs() BUG: Do not elide complex abs() May 18, 2017
@charris charris removed this from the 1.13.0 release milestone May 18, 2017
@juliantaylor juliantaylor deleted the abs-no-elide branch May 20, 2017 14:02
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.

3 participants