Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions crates/float/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,28 @@ impl Div for Float {
}
}

impl Float {
pub fn frac(self) -> Result<Float, FloatError> {
let Float(a) = self;
let calldata = DecimalFloat::fracCall { a }.abi_encode();

execute_call(Bytes::from(calldata), |output| {
let decoded = DecimalFloat::fracCall::abi_decode_returns(output.as_ref())?;
Ok(Float(decoded))
})
}

pub fn floor(self) -> Result<Float, FloatError> {
let Float(a) = self;
let calldata = DecimalFloat::floorCall { a }.abi_encode();

execute_call(Bytes::from(calldata), |output| {
let decoded = DecimalFloat::floorCall::abi_decode_returns(output.as_ref())?;
Ok(Float(decoded))
})
}
}
Comment on lines +316 to +336
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot Jun 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Consider consolidating impl blocks for better code organization.

The frac and floor methods are correctly implemented and follow the established patterns. However, having a separate impl block for these methods creates unnecessary fragmentation.

Consider moving these methods to the main impl block (starting at line 137) to keep all Float methods together:

-impl Float {
-    pub fn frac(self) -> Result<Float, FloatError> {
-        let Float(a) = self;
-        let calldata = DecimalFloat::fracCall { a }.abi_encode();
-
-        execute_call(Bytes::from(calldata), |output| {
-            let decoded = DecimalFloat::fracCall::abi_decode_returns(output.as_ref())?;
-            Ok(Float(decoded))
-        })
-    }
-
-    pub fn floor(self) -> Result<Float, FloatError> {
-        let Float(a) = self;
-        let calldata = DecimalFloat::floorCall { a }.abi_encode();
-
-        execute_call(Bytes::from(calldata), |output| {
-            let decoded = DecimalFloat::floorCall::abi_decode_returns(output.as_ref())?;
-            Ok(Float(decoded))
-        })
-    }
-}

And add these methods to the main impl block instead.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In crates/float/src/lib.rs between lines 326 and 346, the frac and floor methods
are implemented in a separate impl block, causing fragmentation. To fix this,
move these methods into the main Float impl block that starts around line 137,
consolidating all Float methods into a single impl block for better organization
and maintainability.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this isn't needed and organization will be updated later anyway

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@0xgleb Understood! You're right that the core functionality is what matters for this PR. The frac and floor methods are implemented correctly and follow the established patterns. Code organization can indeed be addressed in a future refactoring when you're ready to tackle the broader structural improvements.

🐰💼
Rabbit filing away organizational notes for later


impl Neg for Float {
type Output = Result<Self, FloatError>;

Expand Down Expand Up @@ -718,4 +740,84 @@ mod tests {
FloatError::DecimalFloat(DecimalFloatErrors::ExponentOverflow(_))
));
}

#[test]
fn test_frac_and_floor_integers() {
let int_float = Float::parse("12345".to_string()).unwrap();
let floor = int_float.floor().unwrap();
let frac = int_float.frac().unwrap();
let zero = Float::parse("0".to_string()).unwrap();

assert!(int_float.eq(floor).unwrap());
assert!(frac.eq(zero).unwrap());

let int_float = Float::parse("-98765".to_string()).unwrap();
let floor = int_float.floor().unwrap();
let frac = int_float.frac().unwrap();
let zero = Float::parse("0".to_string()).unwrap();

assert!(int_float.eq(floor).unwrap());
assert!(frac.eq(zero).unwrap());

let recombined = (floor + frac).unwrap();
assert!(int_float.eq(recombined).unwrap());
}

#[test]
fn test_frac_and_floor_floats() {
let float = Float::parse("12345.6789".to_string()).unwrap();
let floor = float.floor().unwrap();
let frac = float.frac().unwrap();

let expected_floor = Float::parse("12345".to_string()).unwrap();
let expected_frac = Float::parse("0.6789".to_string()).unwrap();

assert!(floor.eq(expected_floor).unwrap());
assert!(frac.eq(expected_frac).unwrap());
}

proptest! {
#[test]
fn test_frac_floor_properties(float in arb_float()) {
let floor = float.floor().unwrap();
let frac = float.frac().unwrap();

let zero = Float::parse("0".to_string()).unwrap();

prop_assert!(
floor.frac().unwrap().eq(zero).unwrap(),
"floor.frac() is not zero: {}",
floor.show_unpacked().unwrap()
);

prop_assert!(
frac.floor().unwrap().eq(zero).unwrap(),
"frac.floor() is not zero: {}",
frac.show_unpacked().unwrap()
);

let recombined = (floor + frac).unwrap();
prop_assert!(
float.eq(recombined).unwrap(),
"original: {}, floor: {}, frac: {}, recombined: {}",
float.show_unpacked().unwrap(),
floor.show_unpacked().unwrap(),
frac.show_unpacked().unwrap(),
recombined.show_unpacked().unwrap()
);

let one = Float::parse("1".to_string()).unwrap();
let neg_one = one.neg().unwrap();
prop_assert!(
frac.lt(one).unwrap(),
"frac not < 1: {}",
frac.show_unpacked().unwrap()
);
prop_assert!(
frac.gt(neg_one).unwrap(),
"frac not > -1: {}",
frac.show_unpacked().unwrap()
);
}
}
}