Skip to content

Type promotion rules regression (Trac #1798) #2391

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
numpy-gitbot opened this issue Oct 19, 2012 · 4 comments
Closed

Type promotion rules regression (Trac #1798) #2391

numpy-gitbot opened this issue Oct 19, 2012 · 4 comments

Comments

@numpy-gitbot
Copy link

Original ticket http://projects.scipy.org/numpy/ticket/1798 on 2011-04-11 by @mwiebe, assigned to @mwiebe.

[scalar float64]*[array int8] should produce [array float64], but when the value of the scalar float64 is small, it may produce [array float16] or [array float32]. Here is the current behavior:

>>> 3.1*np.ones(2,dtype=np.int8)
array([ 3.09960938,  3.09960938], dtype=float16)
>>> 1e10*np.ones(2,dtype=np.int8)
array([  1.00000000e+10,   1.00000000e+10], dtype=float32)
>>> 1e40*np.ones(2,dtype=np.int8)
array([  1.00000000e+40,   1.00000000e+40])

I propose a fix in two parts.

  1. Fix this in the PyArray_ResultType/numpy.result_type function of the type promotion API. In particular, the algorithm should track the promoted array and scalar types separately, then if the kind of the promoted scalar type is greater than the kind of the promoted array type, continue the promotion of the promoted array type with the scalars without using minscalartype.
  2. Change the ufunc to detect binary operators during creation, and set a flag for it. Then, during evaluation, use PyArray_ResultType to do the type promotion for binary operators instead of the existing slow linear search. The ufunc doesn't have a flags field, but it does have a field called 'check_return' which is unused, and could be repurposed as a flags field without changing the size of the python type.
@numpy-gitbot
Copy link
Author

@charris wrote on 2011-04-11

I don't think the conversion should depend on the size. The old numpy behavior for scalars was python int -> long (or was it long long, I need to check), python float -> double, python complex -> complex128, other types were achieved by explicit casts, i.e., np.int8(5).

@numpy-gitbot
Copy link
Author

@mwiebe wrote on 2011-04-11

The old behavior depended on the scalar value in the same way, except it only used the scalar's value to detect int -> uint. This is so that [float64 scalar]*[float32 array] produces a [float32 array] instead of a [float64 array]. Without this rule, using float32 arrays is almost impossible since they will be promoted to float64 in many circumstances. I generalized it to also use the value to avoid obvious overflows.

1.5.x and earlier:

>>> 100000*np.ones(2,dtype=np.int8)
array([-31072, -31072], dtype=int16)
>>> 1e60*np.ones(2,dtype=np.float32)
array([ Inf,  Inf], dtype=float32)

1.6 and later:

>>> 100000*np.ones(2,dtype=np.int8)
array([100000, 100000], dtype=int32)
>>> 1e60*np.ones(2,dtype=np.float32)
array([  1.00000000e+60,   1.00000000e+60])

@numpy-gitbot
Copy link
Author

@mwiebe wrote on 2011-04-13

Proposed fix here: #73

@numpy-gitbot
Copy link
Author

@mwiebe wrote on 2011-04-22

Fixed in fbdc4b7 (master) and cc55973 (1.6.x).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant