Address CUDA ReduceL2 negative results and add test coverage (#28681)
This pull request significantly improves the numerical correctness and
robustness of L1 and L2 reduction operations (norms) for integer types
on both CPU and CUDA backends. The main changes address integer
overflow, undefined behavior, and precision loss in norm calculations,
especially for edge cases like minimum representable integers and large
accumulations. The changes also ensure consistency between CPU and CUDA
implementations, and add detailed documentation for future
maintainability.
**Numerical correctness and overflow handling for integer norm
reductions:**
* On CPU, L1 and L2 reductions (`ReduceAggregatorL1` and
`ReduceAggregatorL2` in `reduction_ops.h`) now accumulate in double
precision to avoid integer overflow and undefined behavior, with Kahan
summation for int64+ to minimize precision loss. Results are clamped to
the maximum representable value to prevent overflow.
[[1]](diffhunk://#diff-ca0c9224442a3c46251b0fb7326aacc1469bdee20ab409b930556f439d560015R722-R805)
[[2]](diffhunk://#diff-ca0c9224442a3c46251b0fb7326aacc1469bdee20ab409b930556f439d560015R814-R893)
* Introduced a `saturating_abs` function on CPU and a device-side
`Impl_SaturatingAbs` kernel on CUDA to safely compute the absolute value
for signed integer types, clamping to `max()` if `abs(min())` would
overflow.
[[1]](diffhunk://#diff-ca0c9224442a3c46251b0fb7326aacc1469bdee20ab409b930556f439d560015R722-R805)
[[2]](diffhunk://#diff-f7138acd21464814d1793c9d334bee07d0cbe69719691e67efe3b2e23e4d06c7R516-R566)
[[3]](diffhunk://#diff-945ab1deb57e1ff44b790cb2054537c252e23b7c7c374f44da66475361910abdR110-R119)
**CUDA backend improvements and consistency:**
* For integer reductions on CUDA, the input is cast to double before
reduction, and the result is cast back to integer with saturating
semantics (using PTX `cvt.sat`), matching the CPU's explicit clamping.
This avoids precision loss and undefined behavior.
* For no-op reductions (where input and output counts are equal), norm
operations now use the saturating absolute value kernel to ensure
non-negative results, even for edge-case values like `INT_MIN`.
[[1]](diffhunk://#diff-ee5316fc3898058f70e942d9a84de36be4c7da09f144633a2504236430d5d033L209-R217)
[[2]](diffhunk://#diff-ee5316fc3898058f70e942d9a84de36be4c7da09f144633a2504236430d5d033L592-R607)
[[3]](diffhunk://#diff-ee5316fc3898058f70e942d9a84de36be4c7da09f144633a2504236430d5d033L778-R794)
**Documentation and maintainability:**
* Added detailed comments explaining the rationale and numerical
properties of the new implementations, including why double precision is
used, the limitations of float, and the behavior for large reductions
and edge cases.
[[1]](diffhunk://#diff-ca0c9224442a3c46251b0fb7326aacc1469bdee20ab409b930556f439d560015R722-R805)
[[2]](diffhunk://#diff-ca0c9224442a3c46251b0fb7326aacc1469bdee20ab409b930556f439d560015R814-R893)
[[3]](diffhunk://#diff-f7138acd21464814d1793c9d334bee07d0cbe69719691e67efe3b2e23e4d06c7R516-R566)
[[4]](diffhunk://#diff-ee5316fc3898058f70e942d9a84de36be4c7da09f144633a2504236430d5d033L807-R861)
These changes make norm reductions for integer types safe,
mathematically correct, and consistent across CPU and CUDA, even for
extreme or previously problematic inputs.