# [Numpy-discussion] Odd numerical difference between Numpy 1.5.1 and Numpy > 1.5.1

Mark Wiebe mwwiebe at gmail.com
Wed Apr 13 18:34:06 EDT 2011

```On Tue, Apr 12, 2011 at 11:51 AM, Mark Wiebe <mwwiebe at gmail.com> wrote:

> <snip>
>
here's the rule for a set of arbitrary arrays (not necessarily just 2):
>
> - if all the arrays are scalars, do type promotion on the types as is
> - otherwise, do type promotion on min_scalar_type(a) of each array a
>
> 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.
>
> 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.
>
>
> https://github.com/numpy/numpy/blob/master/numpy/core/src/multiarray/convert_datatype.c#L1075
>
> The change I'm proposing is to modify this as follows:
>
> - if all the arrays are scalars, do type promotion on the types as is
> - if the maximum kind of all the scalars is > the maximum kind of all the
> arrays, do type promotion on the types as is
> - otherwise, do type promotion on min_scalar_type(a) of each array a
>
> 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.
>

I've implemented what I suggested, and improved the documentation to better
explain what's going on. One thing I adjusted slightly is instead of using
the existing kinds, I used three categories: boolean, integer (int/uint),
and floating point (float/complex). This way, we get [float32 array] + 0j
producing a [complex64 array] instead of a [complex128 array], while still
fixing the original regression.