8000 dtype keyword doesn't work as expected for generalized ufuncs · Issue #3222 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

dtype keyword doesn't work as expected for generalized ufuncs #3222

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
pv opened this issue Apr 10, 2013 · 6 comments
Closed

dtype keyword doesn't work as expected for generalized ufuncs #3222

pv opened this issue Apr 10, 2013 · 6 comments
Labels
00 - Bug 57 - Close? Issues which may be closable unless discussion continued component: numpy.linalg

Comments

@pv
Copy link
Member
pv commented Apr 10, 2013

With the generalized ufuncs in gh-2954 / gh-3220:

>>> import numpy as np
>>> np.linalg._umath_linalg.eigvals.signature
'(m,m)->(m)'
>>> np.linalg._umath_linalg.eigvals.types    
['f->F', 'd->D', 'D->D']
>>> a = np.array([[1.+2j,2+3j], [3+4j,4+5j]], dtype=np.cdouble)
>>> np.linalg._umath_linalg.eigvals(a, dtype=np.complex128)
__main__:1: DeprecationWarning: Implicitly casting between incompatible kinds. In a future numpy release, this will raise an error. Use casting="unsafe" if this is intentional.
__main__:1: ComplexWarning: Casting complex values to real discards the imaginary part
array([-0.37228132+0.j,  5.37228132+0.j])
>>> np.linalg._umath_linalg.eigvals(a)
array([-0.35670389-0.26307815j,  5.35670389+7.26307815j])
>>> b = np.array([[1.,2], [3,4]], dtype=np.float64)
>>> np.linalg._umath_linalg.eigvals(b, dtype=np.float64)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: No loop matching the specified signature was found for ufunc eigvals
@ovillellas
Copy link

The gufunc for eig/eigvals is somewhat special, as the real versions return complex values (as some eigenvalues may be complex, and in a gufunc we need to know the storage of the result). May it be possible the error is due to that? using a single dtype seems not enough as I guess it forces all the operands to have that type, including the result. In eigvals there is no single implementation that returns something that can be converted to a float64.

@njsmith
Copy link
Member
njsmith commented Apr 11, 2013

The complicated real->complex type for eigvals explains why
dtype=np.float64 raises an error - it's looking for a "d->d" loop, and
there isn't one. But I don't understand why dtype=np.cdouble produces an
output with zero imaginary parts. That just makes... no sense at all.

On Thu, Apr 11, 2013 at 10:45 AM, Óscar Villellas Guillén <
notifications@github.com> wrote:

The gufunc for eig/eigvals is somewhat special, as the real versions
return complex values (as some eigenvalues may be complex, and in a gufunc
we need to know the storage of the result). May it be possible the error is
due to that? using a single dtype seems not enough as I guess it forces all
the operands to have that type, including the result. In eigvals there is
no single implementation that returns something that can be converted to a
float64.


Reply to this email directly or view it on GitHubhttps://github.com//issues/3222#issuecomment-16225360
.

@ovillellas
Copy link

@njsmith And there is that ComplexWarning that makes no sense at all to me. It is likely related... maybe for some reason it is converting complex->double->complex? that would explain the warning and the result, but it would be some really weird behavior.

@charris
Copy link
Member
charris commented Feb 22, 2014

This is still broken in 1.9-devel. The scipy version gives

In [17]: eigvals(a)
Out[17]: array([-0.35670389-0.26307815j,  5.35670389+7.26307815j])

Even the real part of the numpy function look wrong.

@charris charris added this to the 1.9 blockers milestone Feb 22, 2014
@charris charris removed this from the 1.9 blockers milestone Feb 22, 2014
@rgommers
Copy link
Member

This seems fixed:

In [1]: %paste
>>> import numpy as np
>>> np.linalg._umath_linalg.eigvals.signature

## -- End pasted text --
Out[1]: '(m,m)->(m)'

In [2]: np.linalg._umath_linalg.eigvals.types
Out[2]: ['f->F', 'd->D', 'D->D']

In [3]: a = np.array([[1.+2j,2+3j], [3+4j,4+5j]], dtype=np.cdouble)

In [4]: a
Out[4]: 
array([[1.+2.j, 2.+3.j],
       [3.+4.j, 4.+5.j]])

In [5]: np.linalg._umath_linalg.eigvals(a, dtype=np.complex128)
Out[5]: array([-0.35670389-0.26307815j,  5.35670389+7.26307815j])

In [6]: np.linalg._umath_linalg.eigvals(a)
Out[6]: array([-0.35670389-0.26307815j,  5.35670389+7.26307815j])

So no more warnings, and results match.

This part is unchanged

In [7]: b = np.array([[1.,2], [3,4]], dtype=np.float64)

In [8]: np.linalg._umath_linalg.eigvals(b, dtype=np.float64)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-8-08fb89892334> in <module>
----> 1 np.linalg._umath_linalg.eigvals(b, dtype=np.float64)

TypeError: No loop matching the specified signature and casting was found for ufunc eigvals

In [9]: np.__version__
Out[9]: '1.19.4'

but as @njsmith explained there is no d->d loop, so this is expected - it's not even clear what that's supposed to do. If only the real part of the complex result is desired, np.linalg._umath_linalg.eigvals(b).real should do it.

Can be closed I think?

@rgommers rgommers added the 57 - Close? Issues which may be closable unless discussion continued label Dec 30, 2020
@seberg
Copy link
Member
seberg commented Oct 4, 2021

Agreed with Ralf's comment, the issue is fixed and the rest is correct behaviour.

@seberg seberg closed this as completed Oct 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
00 - Bug 57 - Close? Issues which may be closable unless discussion continued component: numpy.linalg
Projects
None yet
Development

No branches or pull requests

7 participants
0