binary() returns a different result dtype depending on the array backend.
On numpy and dask+numpy the output keeps the input dtype, because _cpu_binary allocates np.empty(data.shape, dtype=data.dtype). On cupy and dask+cupy the output is always float32, because _run_cupy_binary allocates cupy.empty(..., dtype='f4').
Reproducer with a float64 input:
numpy -> float64
dask -> float64
cupy -> float32
dask+cupy -> float32
Every other classifier in classify.py routes through _cpu_bin, which fixes the output to float32, so binary is the only classifier whose result dtype depends on the backend. Preserving the input dtype also cannot hold the NaN sentinel that binary writes for non-finite cells when the input is an integer array.
Proposed fix: allocate float32 in _cpu_binary so all four backends agree.
Found by the accuracy sweep (Cat 5, backend inconsistency).
binary()returns a different result dtype depending on the array backend.On numpy and dask+numpy the output keeps the input dtype, because
_cpu_binaryallocatesnp.empty(data.shape, dtype=data.dtype). On cupy and dask+cupy the output is always float32, because_run_cupy_binaryallocatescupy.empty(..., dtype='f4').Reproducer with a float64 input:
Every other classifier in
classify.pyroutes through_cpu_bin, which fixes the output to float32, sobinaryis the only classifier whose result dtype depends on the backend. Preserving the input dtype also cannot hold the NaN sentinel thatbinarywrites for non-finite cells when the input is an integer array.Proposed fix: allocate float32 in
_cpu_binaryso all four backends agree.Found by the accuracy sweep (Cat 5, backend inconsistency).