Skip to content

Fix python float scalars rounding through float32 - #4181

Draft
AKnassa wants to merge 1 commit into
ml-explore:mainfrom
AKnassa:fix-float64-python-scalars
Draft

Fix python float scalars rounding through float32#4181
AKnassa wants to merge 1 commit into
ml-explore:mainfrom
AKnassa:fix-float64-python-scalars

Conversation

@AKnassa

@AKnassa AKnassa commented Aug 11, 2026

Copy link
Copy Markdown

Proposed changes

Fixes #4159 and Fixes #4160 — both come from the same line of code.

When a plain Python float is used together with a float64 array, the value is
turned into a C float before the array is built. The dtype comes out correct,
but the number has already lost precision:

a = mx.array([1.0], dtype=mx.float64)
(a * 0.1).item()                                 # 0.10000000149011612  (= float32(0.1))
mx.full((2,), 0.37, dtype=mx.float64)[0].item()  # 0.3700000047683716

Both should be exact.

This looks like a missed call site rather than a deliberate choice. #2861 fixed
this same pattern in python/src/convert.cpp, but to_array in
python/src/utils.cpp was never updated. This change mirrors that fix: cast to
double when the target dtype is float64, and keep casting to float for
every other dtype.

Since to_array is the path every Python-scalar operand takes, this also fixes
the same rounding in mx.maximum, mx.minimum, mx.where, mx.clip,
full_like, and the in-place operators on float64 arrays. Nothing changes for
float16, bfloat16 or float32.

Testing

Extended test_double_keeps_precision (added by #2861) to cover the operand and
the full / full_like paths. It fails before this change and passes after.

Full Python suite on a CPU-only build (MLX_BUILD_METAL=OFF): 819 tests, no new
failures. float64 is CPU-only in MLX, so that is where this behaviour lives,
but note the GPU suite was not run on my machine.

Checklist

  • I have read the CONTRIBUTING document
  • I have run pre-commit run --all-files to format my code / installed pre-commit prior to committing changes
  • I have added tests that prove my fix is effective or that my feature works
  • I have updated the necessary documentation (if needed) — no documentation change needed, there is no API or signature change

A python float used as an operand of a float64 array, or as the fill
value of full/full_like, was cast to a C float before the array was
constructed. The result had dtype float64 but carried only float32
precision, so mx.array([1.0], mx.float64) * 0.1 gave
0.10000000149011612 rather than 0.1.

to_array now casts to double when the target dtype is float64, which
mirrors the conversion already used in convert.cpp. Every other dtype
keeps rounding through float exactly as before.

Fixes ml-explore#4159
Fixes ml-explore#4160
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant