<br><br>On Monday, November 12, 2012, Benjamin Root  wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br><br>On Monday, November 12, 2012, Olivier Delalleau  wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">2012/11/12 Nathaniel Smith <span dir="ltr"><<a>njs@pobox.com</a>></span><br>
<div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div><div>On Mon, Nov 12, 2012 at 8:54 PM, Matthew Brett <<a>matthew.brett@gmail.com</a>> wrote:<br>
> Hi,<br>
><br>
> I wanted to check that everyone knows about and is happy with the<br>
> scalar casting changes from 1.6.0.<br>
><br>
> Specifically, the rules for (array, scalar) casting have changed such<br>
> that the resulting dtype depends on the _value_ of the scalar.<br>
><br>
> Mark W has documented these changes here:<br>
><br>
> <a href="http://docs.scipy.org/doc/numpy/reference/ufuncs.html#casting-rules" target="_blank">http://docs.scipy.org/doc/numpy/reference/ufuncs.html#casting-rules</a><br>
> <a href="http://docs.scipy.org/doc/numpy/reference/generated/numpy.result_type.html" target="_blank">http://docs.scipy.org/doc/numpy/reference/generated/numpy.result_type.html</a><br>
> <a href="http://docs.scipy.org/doc/numpy/reference/generated/numpy.promote_types.html" target="_blank">http://docs.scipy.org/doc/numpy/reference/generated/numpy.promote_types.html</a><br>
><br>
> Specifically, as of 1.6.0:<br>
><br>
> In [19]: arr = np.array([1.], dtype=np.float32)<br>
><br>
> In [20]: (arr + (2**16-1)).dtype<br>
> Out[20]: dtype('float32')<br>
><br>
> In [21]: (arr + (2**16)).dtype<br>
> Out[21]: dtype('float64')<br>
><br>
> In [25]: arr = np.array([1.], dtype=np.int8)<br>
><br>
> In [26]: (arr + 127).dtype<br>
> Out[26]: dtype('int8')<br>
><br>
> In [27]: (arr + 128).dtype<br>
> Out[27]: dtype('int16')<br>
><br>
> There's discussion about the changes here:<br>
><br>
> <a href="http://mail.scipy.org/pipermail/numpy-discussion/2011-September/058563.html" target="_blank">http://mail.scipy.org/pipermail/numpy-discussion/2011-September/058563.html</a><br>
> <a href="http://mail.scipy.org/pipermail/numpy-discussion/2011-March/055156.html" target="_blank">http://mail.scipy.org/pipermail/numpy-discussion/2011-March/055156.html</a><br>
> <a href="http://mail.scipy.org/pipermail/numpy-discussion/2012-February/060381.html" target="_blank">http://mail.scipy.org/pipermail/numpy-discussion/2012-February/060381.html</a><br>
><br>
> It seems to me that this change is hard to explain, and does what you<br>
> want only some of the time, making it a false friend.<br>
<br>
</div></div>The old behaviour was that in these cases, the scalar was always cast<br>
to the type of the array, right? So<br>
  np.array([1], dtype=np.int8) + 256<br>
returned 1? Is that the behaviour you prefer?<br>
<br>
I agree that the 1.6 behaviour is surprising and somewhat<br>
inconsistent. There are many places where you can get an overflow in<br>
numpy, and in all the other cases we just let the overflow happen. And<br>
in fact you can still get an overflow with arr + scalar operations, so<br>
this doesn't really fix anything.<br>
<br>
I find the specific handling of unsigned -> signed and float32 -><br>
float64 upcasting confusing as well. (Sure, 2**16 isn't exactly<br>
representable as a float32, but it doesn't *overflow*, it just gives<br>
you 2.0**16... if I'm using float32 then I presumably don't care that<br>
much about exact representability, so it's surprising that numpy is<br>
working to enforce it, and definitely a separate decision from what to<br>
do about overflow.)<br>
<br>
None of those threads seem to really get into the question of what the<br>
best behaviour here *is*, though.<br>
<br>
Possibly the most defensible choice is to treat ufunc(arr, scalar)<br>
operations as performing an implicit cast of the scalar to arr's<br>
dtype, and using the standard implicit casting rules -- which I think<br>
means, raising an error if !can_cast(scalar, arr.dtype,<br>
casting="safe")</blockquote><div><br>I like this suggestion. It may break some existing code, but I think it'd be for the best. The current behavior can be very confusing.<br><br>-=- Olivier<br></div></div>

</blockquote><div><br></div><div><br></div><div>"break some existing code"</div><div><br></div><div>I really should set up an email filter for this phrase and have it send back an email automatically: "Are you nuts?!"</div>

<div><br></div><div>We just resolved an issue where the "safe" casting rule unexpectedly broke existing code with regards to unplaced operations.  The solution was to warn about the change in the upcoming release and to throw errors in a later release.  Playing around with fundemental things like this need to be done methodically and carefully.</div>

<div><br></div><div>Cheers!</div><div>Ben Root<span></span></div></blockquote><div><br></div><div><br></div><div>Stupid autocorrect:  unplaced --> inplace <span></span></div>