Open
Description
Apropos #7447 (CC @ewmoore @charris):
I was curious about what was going on here, and it looks much uglier than we realized :-(
Little test script that tries doing 4 ** -4
using different types:
Old testing script (and results)
signed_int_types = [np.int8, np.int16, np.int32, np.int64, int]
all_int_types = signed_int_types + [np.uint8, np.uint16, np.uint32, np.uint64]
for base_type in all_int_types:
for exponent_type in signed_int_types:
result = base_type(4) ** exponent_type(-4)
print("{} ** {} -> {} ({})".format(base_type.__name__,
exponent_type.__name__,
result.__class__.__name__,
result))
On current master (after #7447 is merged):
int8 ** int8 -> float32 (0.00390625)
int8 ** int16 -> int16 (0)
int8 ** int32 -> int32 (0)
int8 ** int64 -> int64 (0)
int8 ** int -> int64 (0)
int16 ** int8 -> float32 (0.00390625)
int16 ** int16 -> float32 (0.00390625)
int16 ** int32 -> int32 (0)
int16 ** int64 -> int64 (0)
int16 ** int -> int64 (0)
int32 ** int8 -> float64 (0.00390625)
int32 ** int16 -> float64 (0.00390625)
int32 ** int32 -> float64 (0.00390625)
int32 ** int64 -> int64 (0)
int32 ** int -> int64 (0)
int64 ** int8 -> float64 (0.00390625)
int64 ** int16 -> float64 (0.00390625)
int64 ** int32 -> float64 (0.00390625)
int64 ** int64 -> float64 (0.00390625)
int64 ** int -> float64 (0.00390625)
int ** int8 -> int64 (0)
int ** int16 -> int64 (0)
int ** int32 -> int64 (0)
int ** int64 -> float64 (0.00390625)
int ** int -> float (0.00390625)
uint8 ** int8 -> int16 (0)
uint8 ** int16 -> int16 (0)
uint8 ** int32 -> int32 (0)
uint8 ** int64 -> int64 (0)
uint8 ** int -> int64 (0)
uint16 ** int8 -> int32 (0)
uint16 ** int16 -> int32 (0)
uint16 ** int32 -> int32 (0)
uint16 ** int64 -> int64 (0)
uint16 ** int -> int64 (0)
uint32 ** int8 -> int64 (0)
uint32 ** int16 -> int64 (0)
uint32 ** int32 -> int64 (0)
uint32 ** int64 -> int64 (0)
uint32 ** int -> int64 (0)
uint64 ** int8 -> float64 (0.00390625)
uint64 ** int16 -> float64 (0.00390625)
uint64 ** int32 -> float64 (0.00390625)
uint64 ** int64 -> float64 (0.00390625)
uint64 ** int -> float64 (0.00390625)
This is all extremely extremely weird and inconsistent...
Summary/edit by @seberg 2019-05-23:
On current master (and 1.16) we now error for many of these cases as found using the modified snippet:
signed_int_types = [np.int8, np.int16, np.int32, np.int64, int]
all_int_types = signed_int_types + [np.uint8, np.uint16, np.uint32, np.uint64]
for base_type in all_int_types:
for exponent_type in signed_int_types:
try:
result = base_type(4) ** exponent_type(-4)
except Exception as e:
result = e
print("{} ** {} -> {} ({})".format(base_type.__name__,
exponent_type.__name__,
result.__class__.__name__,
result))
Giving (again 1.16, master shortly before 1.17):
int8 ** int8 -> ValueError (Integers to negative integer powers are not allowed.)
int8 ** int16 -> ValueError (Integers to negative integer powers are not allowed.)
int8 ** int32 -> ValueError (Integers to negative integer powers are not allowed.)
int8 ** int64 -> ValueError (Integers to negative integer powers are not allowed.)
int8 ** int -> ValueError (Integers to negative integer powers are not allowed.)
int16 ** int8 -> ValueError (Integers to negative integer powers are not allowed.)
int16 ** int16 -> ValueError (Integers to negative integer powers are not allowed.)
int16 ** int32 -> ValueError (Integers to negative integer powers are not allowed.)
int16 ** int64 -> ValueError (Integers to negative integer powers are not allowed.)
int16 ** int -> ValueError (Integers to negative integer powers are not allowed.)
int32 ** int8 -> ValueError (Integers to negative integer powers are not allowed.)
int32 ** int16 -> ValueError (Integers to negative integer powers are not allowed.)
int32 ** int32 -> ValueError (Integers to negative integer powers are not allowed.)
int32 ** int64 -> ValueError (Integers to negative integer powers are not allowed.)
int32 ** int -> ValueError (Integers to negative integer powers are not allowed.)
int64 ** int8 -> ValueError (Integers to negative integer powers are not allowed.)
int64 ** int16 -> ValueError (Integers to negative integer powers are not allowed.)
int64 ** int32 -> ValueError (Integers to negative integer powers are not allowed.)
int64 ** int64 -> ValueError (Integers to negative integer powers are not allowed.)
int64 ** int -> ValueError (Integers to negative integer powers are not allowed.)
int ** int8 -> ValueError (Integers to negative integer powers are not allowed.)
int ** int16 -> ValueError (Integers to negative integer powers are not allowed.)
int ** int32 -> ValueError (Integers to negative integer powers are not allowed.)
int ** int64 -> ValueError (Integers to negative integer powers are not allowed.)
int ** int -> float (0.00390625)
uint8 ** int8 -> ValueError (Integers to negative integer powers are not allowed.)
uint8 ** int16 -> ValueError (Integers to negative integer powers are not allowed.)
uint8 ** int32 -> ValueError (Integers to negative integer powers are not allowed.)
uint8 ** int64 -> ValueError (Integers to negative integer powers are not allowed.)
uint8 ** int -> ValueError (Integers to negative integer powers are not allowed.)
uint16 ** int8 -> ValueError (Integers to negative integer powers are not allowed.)
uint16 ** int16 -> ValueError (Integers to negative integer powers are not allowed.)
uint16 ** int32 -> ValueError (Integers to negative integer powers are not allowed.)
uint16 ** int64 -> ValueError (Integers to negative integer powers are not allowed.)
uint16 ** int -> ValueError (Integers to negative integer powers are not allowed.)
uint32 ** int8 -> ValueError (Integers to negative integer powers are not allowed.)
uint32 ** int16 -> ValueError (Integers to negative integer powers are not allowed.)
uint32 ** int32 -> ValueError (Integers to negative integer powers are not allowed.)
uint32 ** int64 -> ValueError (Integers to negative integer powers are not allowed.)
uint32 ** int -> ValueError (Integers to negative integer powers are not allowed.)
uint64 ** int8 -> float64 (0.00390625)
uint64 ** int16 -> float64 (0.00390625)
uint64 ** int32 -> float64 (0.00390625)
uint64 ** int64 -> float64 (0.00390625)
uint64 ** int -> float64 (0.00390625)
So the integer+integer which use float as a common type are a bit strange in this sense.