<div class="gmail_quote">On Tue, Apr 12, 2011 at 11:17 AM, Charles R Harris <span dir="ltr"><<a href="mailto:charlesr.harris@gmail.com">charlesr.harris@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<br><br><div class="gmail_quote"><div class="im">On Tue, Apr 12, 2011 at 11:56 AM, Robert Kern <span dir="ltr"><<a href="mailto:robert.kern@gmail.com" target="_blank">robert.kern@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204, 204, 204);padding-left:1ex">

<div>On Tue, Apr 12, 2011 at 12:27, Charles R Harris<br>
<<a href="mailto:charlesr.harris@gmail.com" target="_blank">charlesr.harris@gmail.com</a>> wrote:<br>
<br>
> IIRC, the behavior with respect to scalars sort of happened in the code on<br>
> the fly, so this is a good discussion to have. We should end up with<br>
> documented rules and tests to enforce them. I agree with Mark that the tests<br>
> have been deficient up to this point.<br>
<br>
</div>It's been documented for a long time now.<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>
<div><div></div><div><br></div></div></blockquote></div><div><br>Nope, the kind stuff is missing. Note the cast to float32 that Mark pointed out. Also that the casting of python integers depends on their sign and magnitude.<br>

<br>In [1]: ones(3, '?') + 0<br>Out[1]: array([1, 1, 1], dtype=int8)<br><br>In [2]: ones(3, '?') + 1000<br>Out[2]: array([1001, 1001, 1001], dtype=int16)<br></div></div></blockquote><div> </div><div>This is the behaviour with master - it's a good idea to cross-check with an older NumPy. I think we're discussing 3 things here, what NumPy 1.5 and earlier did, what NumPy 1.6 beta currently does, and what people think NumPy did. The old implementation had a bit of a spaghetti-factor to it, and had problems like asymmetry and silent overflows. The new implementation is in my opinion cleaner and follows well-defined semantics while trying to stay true to the old implementation. I admit the documentation I wrote doesn't fully explain them, but here's the rule for a set of arbitrary arrays (not necessarily just 2):</div>
<div><br></div><div>- if all the arrays are scalars, do type promotion on the types as is</div><div>- otherwise, do type promotion on min_scalar_type(a) of each array a</div><div><br></div><div>The function min_scalar_type returns the array type if a has >= 1 dimensions, or the smallest type of the same kind (allowing int->uint in the case of positive-valued signed integers) to which the value can be cast without overflow if a has 0 dimensions.</div>
<div><br></div><meta http-equiv="content-type" content="text/html; charset=utf-8"><div>The promote_types function used for the type promotion is symmetric and associative, so the result won't change when shuffling the inputs. There's a bit of a wrinkle in the implementation to handle the fact that the uint type values aren't a strict subset of the same-sized int type values, but otherwise this is what happens.</div>
<div><br></div><div><a href="https://github.com/numpy/numpy/blob/master/numpy/core/src/multiarray/convert_datatype.c#L1075">https://github.com/numpy/numpy/blob/master/numpy/core/src/multiarray/convert_datatype.c#L1075</a></div>
<div><br></div><div>The change I'm proposing is to modify this as follows:</div><div><br></div><div><meta http-equiv="content-type" content="text/html; charset=utf-8"><div>- if all the arrays are scalars, do type promotion on the types as is</div>
<div>- if the maximum kind of all the scalars is > the maximum kind of all the arrays, do type promotion on the types as is</div><div>- otherwise, do type promotion on min_scalar_type(a) of each array a</div><div><br></div>
<div>One case where this may not capture a possible desired semantics is [complex128 scalar] * [float32 array] -> [complex128]. In this case [complex64] may be desired. This is directly analogous to the original [float64 scalar] * [int8 array], however, and in the latter case it's clear a float64 should result.</div>
<div><br></div></div><div>-Mark</div></div>