Issue
Fixes #177839.
Summary
For eps > 0.5 the clamp bounds invert (lo = eps > hi = 1 - eps). The scalar and CUDA kernels resolve this as x < lo ? lo : (x > hi ? hi : x), so lo wins. Two paths disagreed and produced a sign-flipped result:
- CPU vectorized:
vec::clamp=min(hi, max(lo, x)), sohiwon. - MPS
logit:clampWithTensor, alsomin(max(x, lo), hi), sohiwon.
Both now apply lo last (nested blendv on CPU, nested select on MPS), matching scalar and CUDA. CUDA already conformed, so all three backends agree. eps > 0.5 is mathematically ill-defined; the goal is cross-backend consistency.
Tests
Added test_logit_vectorized_matches_scalar (eps {0.49, 0.51, 0.6, 0.9} x 4 dtypes, bit-exact vs the scalar kernel) and an eps=0.6 sample_inputs_logit sample so test_ops.py and the MPS consistency tests cover eps > 0.5. Verified on Apple Silicon: test_mps.py -k logit, test_ops.py -k logit, and test_unary_ufuncs.py -k logit pass, including the previously failing test_output_grad_match_logit_mps_float32.
BC-breaking?
No.
Pull Request resolved: #181297
Approved by: https://github.com/jansel
SOCIAL SHARE CARD GENERATOR