IndexLamba (Loopy) arithmetic semantics are incompatible with NumPy arithmetic semantics
Context: Adding more support for arithmetic operations in !7 (merged)
Among other differences, NumPy likes to convert some values to double before applying arithmetic operations on them, while loopy generally follows C semantics and doesn't. For instance, for the kernel
knl = lp.make_kernel("{:}", "",
[lp.GlobalArg("f32", shape=(), dtype=np.float32),
lp.GlobalArg("i32", shape=(), dtype=np.int32)])
we have
>>> from loopy.type_inference import TypeInferenceMapper
>>> tim = TypeInferenceMapper(knl)
>>> from pymbolic import parse
>>> tim(parse("f32 * i32"))
np:dtype('float32')
while
>>> np.result_type(np.float32, np.int32)
dtype('float64')
In !7 (merged), I've used np.result_type
to determine the output type of the arithmetic operation, but that doesn't change the types that are used in the arithmetic operation in the generated loopy code. The tests I added in !7 (merged) aren't comprehensive enough to detect most differences in the output (between Loopy/NumPy). They detect a difference in the implementation of truediv
. However, this issue extends beyond just truediv
and applies to all binary arithmetic operations.
There are a number of options here, and all of them are somewhat bad:
- Drop NumPy compatibility and adopt Loopy arithmetic semantics (assuming the subtraction bug is fixed) for both operations and output types
- Use NumPy semantics for the output type, but Loopy semantics for the operation (which is what is currently done in !7 (merged))
- Use NumPy semantics by adding explicit type casts where appropriate when the IndexLambda (at the time the operation is generated)
Arrayzy followed the first option. @xywei, how was this addressed in lappy?