Implement round-half-even float.fromhex in common float_ops#8234
Implement round-half-even float.fromhex in common float_ops#8234youknowone wants to merge 5 commits into
Conversation
Add float_ops::from_hex returning Result<f64, HexFloatError>, which parses the coefficient and exponent, rounds round-half-even over the full exponent range, and detects overflow. Route float.fromhex through it: raise OverflowError for values too large to represent and ValueError for invalid input. Remove the expectedFailure on test_from_hex. Assisted-by: Claude
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughAdds a new ChangesHex Float Parsing
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Caller as Python Caller
participant PyFloat as PyFloat.fromhex
participant FloatOps as float_ops::from_hex
participant Finish as finish_hex
Caller->>PyFloat: fromhex(string)
PyFloat->>FloatOps: from_hex(string.as_str())
FloatOps->>FloatOps: parse whitespace, sign, inf/nan, 0x prefix, digits, exponent
FloatOps->>Finish: finish_hex(remaining, sign, value)
Finish-->>FloatOps: Ok(f64) or HexFloatError
FloatOps-->>PyFloat: Result<f64, HexFloatError>
alt Overflow
PyFloat-->>Caller: raise OverflowError
else TooLong / Invalid
PyFloat-->>Caller: raise ValueError
else Ok
PyFloat-->>Caller: return float
end
Related Issues: None referenced in the provided summary. Related PRs: None referenced in the provided summary. Suggested labels: rust, float, parsing Suggested reviewers: None specified. 🐰 A hex string hops through digits and dots, 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
crates/common/src/float_ops.rs (1)
503-515: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueUse
is_ascii_digit()hereClippy will flag this manual digit test;
hex_byte_at(bytes, idx).is_ascii_digit()is clearer and removes the duplicate lookup.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/common/src/float_ops.rs` around lines 503 - 515, The hex float exponent parsing in float_ops::hex_byte_at/exp handling uses a manual byte range check that Clippy flags and repeats the same lookup. Update the digit validation in this block to use the byte’s is_ascii_digit() method instead, and keep the surrounding exp_start/index advancement logic unchanged so the parsing behavior stays the same.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@crates/common/src/float_ops.rs`:
- Around line 503-515: The hex float exponent parsing in
float_ops::hex_byte_at/exp handling uses a manual byte range check that Clippy
flags and repeats the same lookup. Update the digit validation in this block to
use the byte’s is_ascii_digit() method instead, and keep the surrounding
exp_start/index advancement logic unchanged so the parsing behavior stays the
same.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: c4465655-ccab-4da5-bcd7-babda2b29650
⛔ Files ignored due to path filters (1)
Lib/test/test_float.pyis excluded by!Lib/**
📒 Files selected for processing (2)
crates/common/src/float_ops.rscrates/vm/src/builtins/float.rs
📦 Library DependenciesThe following Lib/ modules were modified. Here are their dependencies: [x] test: cpython/Lib/test/test_float.py (TODO: 3) dependencies: dependent tests: (no tests depend on float) Legend:
|
…prefix Assisted-by: Claude
|
Thanks for the review — addressed in 51b3c1a:
— commented by Claude |
Assisted-by: Claude
… sre_engine Assisted-by: Claude
|
Update on the whitespace helper (after some more thought on where it belongs): instead of For the record, on two related questions that came up: the hex-float parser can't be borrowed from — commented by Claude |
Remove the private copy of is_py_ascii_whitespace in bytes_inner.rs and import the shared rustpython_common::wtf8::is_py_ascii_whitespace. Assisted-by: Claude
ShaharNaveh
left a comment
There was a problem hiding this comment.
thanks for addressing the review:)
Summary
float.fromhexdelegated toliteral::float::from_hex, which is backed byhexf_parse. That reader is meant for exact literals: it rejects any inexact hexadecimal input and cannot tell overflow apart from a parse error, sofloat.fromhexcould not round and never raisedOverflowError.test_from_hexwas consequently marked@unittest.expectedFailure.This adds a dedicated hex-float reader in
common::float_opsthat reproduces the coefficient/exponent parsing, round-half-even rounding, and overflow detection thatfloat.fromhexrequires, and routes the classmethod through it.Changes
common::float_ops::from_hex(&str) -> Result<f64, HexFloatError>: round-half-even over the full exponent range (subnormals down to0x1p-1074), theinf/nanspellings, surrounding ASCII whitespace, a saturating exponent parse, andInvalid/TooLong/Overflowerror kinds.float.fromhexnow mapsOverflow → OverflowErrorandInvalid/TooLong → ValueError, with the messages Python uses.@unittest.expectedFailurefromtest_from_hex.inf/nansign bits, whitespace, and the error kinds.Verification
from_hexoutput was compared bit-for-bit against CPython'sfloat.fromhexover 125,000 inputs (curated + fuzzed, including near-halfway rounding and theDBL_MAXboundary): 0 mismatches.cargo test -p rustpython-commonandpython -m test test_floatpass, withtest_from_hexnow green.— commented by Claude
Summary by CodeRabbit
float.fromhex()now supports a broader set of Python-style hexadecimal floating-point inputs, includinginf,nan, signs, whitespace, and full exponent parsing.