Post by Stephan HoyerI am also concerned about adding more special cases for NumPy scalars vs
arrays. These cases are already confusing (e.g., making no distinction
between 0d arrays and scalars) and poorly documented.
Post by Nathaniel SmithOn Mon, Oct 24, 2016 at 3:41 PM, Charles R Harris
Post by Charles R HarrisHi All,
I've been thinking about this some (a lot) more and have an alternate
proposal for the behavior of the `**` operator
if both base and power are numpy/python scalar integers, convert to
python
Post by Charles R Harrisintegers and call the `**` operator. That would solve both the
precision and
Post by Charles R Harriscompatibility problems and I think is the option of least surprise. For
those who need type preservation and modular arithmetic, the np.power
function remains, although the type conversions can be surpirising as it
seems that the base and power should play different roles in
determining
Post by Charles R Harristhe type, at least to me.
Array, 0-d or not, are treated differently from scalars and integers
raised
Post by Charles R Harristo negative integer powers always raise an error.
I think this solves most problems and would not be difficult to
implement.
My main concern about this is that it adds more special cases to numpy
scalars, and a new behavioral deviation between 0d arrays and scalars,
when ideally we should be trying to reduce the
duplication/discrepancies between these. It's also inconsistent with
how other operations on integer scalars work, e.g. regular addition
In [8]: np.int64(2 ** 63 - 1) + 1
overflow encountered in long_scalars
#!/home/njs/.user-python3.5-64bit/bin/python3.5
Out[8]: -9223372036854775808
So I'm inclined to try and keep it simple, like in your previous
proposal... theoretically of course it would be nice to have the
perfect solution here, but at this point it feels like we might be
overthinking this trying to get that last 1% of improvement. The thing
where 2 ** -1 returns 0 is just broken and bites people so we should
definitely fix it, but beyond that I'm not sure it really matters
*that* much what we do, and "special cases aren't special enough to
break the rules" and all that.
What I have been concerned about are the follow combinations that currently
return floats
num: <type 'numpy.int8'>, exp: <type 'numpy.int8'>, res: <type
'numpy.float32'>
num: <type 'numpy.int16'>, exp: <type 'numpy.int8'>, res: <type
'numpy.float32'>
num: <type 'numpy.int16'>, exp: <type 'numpy.int16'>, res: <type
'numpy.float32'>
num: <type 'numpy.int32'>, exp: <type 'numpy.int8'>, res: <type
'numpy.float64'>
num: <type 'numpy.int32'>, exp: <type 'numpy.int16'>, res: <type
'numpy.float64'>
num: <type 'numpy.int32'>, exp: <type 'numpy.int32'>, res: <type
'numpy.float64'>
num: <type 'numpy.int64'>, exp: <type 'numpy.int8'>, res: <type
'numpy.float64'>
num: <type 'numpy.int64'>, exp: <type 'numpy.int16'>, res: <type
'numpy.float64'>
num: <type 'numpy.int64'>, exp: <type 'numpy.int32'>, res: <type
'numpy.float64'>
num: <type 'numpy.int64'>, exp: <type 'numpy.int64'>, res: <type
'numpy.float64'>
num: <type 'numpy.int64'>, exp: <type 'numpy.int64'>, res: <type
'numpy.float64'>
num: <type 'numpy.uint64'>, exp: <type 'numpy.int8'>, res: <type
'numpy.float64'>
num: <type 'numpy.uint64'>, exp: <type 'numpy.int16'>, res: <type
'numpy.float64'>
num: <type 'numpy.uint64'>, exp: <type 'numpy.int32'>, res: <type
'numpy.float64'>
num: <type 'numpy.uint64'>, exp: <type 'numpy.int64'>, res: <type
'numpy.float64'>
num: <type 'numpy.uint64'>, exp: <type 'numpy.int64'>, res: <type
'numpy.float64'>
The other combinations of signed and unsigned integers to signed powers
currently raise ValueError due to the change to the power ufunc. The
exceptions that aren't covered by uint64 + signed (which won't change) seem
to occur when the exponent can be safely cast to the base type. I suspect
that people have already come to depend on that, especially as python
integers on 64 bit linux convert to int64. So in those cases we should
perhaps raise a FutureWarning instead of an error.
Chuck