Skip to main content

rain_math_float/
lib.rs

1use alloy::hex::FromHex;
2use alloy::primitives::{Bytes, B256};
3use alloy::{sol, sol_types::SolCall};
4use revm::primitives::{fixed_bytes, U256};
5use serde::{Deserialize, Serialize};
6use std::ops::{Add, Div, Mul, Neg, Sub};
7use wasm_bindgen_utils::prelude::*;
8
9#[cfg(any(test, feature = "test-harness"))]
10use alloy::primitives::aliases::I224;
11
12pub mod error;
13mod evm;
14pub mod js_api;
15#[cfg(any(test, feature = "test-harness"))]
16pub mod tables;
17
18use error::DecimalFloatErrorSelector;
19pub use error::FloatError;
20use evm::execute_call;
21#[cfg(any(test, feature = "test-harness"))]
22use evm::execute_test_call;
23
24sol!(
25    #![sol(all_derives)]
26    DecimalFloat,
27    "abi/DecimalFloat.json"
28);
29
30#[cfg(any(test, feature = "test-harness"))]
31sol!(
32    #![sol(all_derives)]
33    TestDecimalFloat,
34    "abi/TestDecimalFloat.json"
35);
36
37#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize, Hash)]
38#[wasm_bindgen]
39pub struct Float(B256);
40
41impl Float {
42    /// Creates a new `Float` from the given 32-byte value `B256`.
43    pub const fn from_raw(value: B256) -> Self {
44        Float(value)
45    }
46
47    /// Getter for inner 32-bytes value of this Float instance as `B256`.
48    pub fn get_inner(&self) -> B256 {
49        self.0
50    }
51
52    /// Sets the inner 32-byte value of this float from the given `B256`.
53    pub fn set_inner(&mut self, value: B256) {
54        self.0 = value;
55    }
56
57    /// Converts a fixed-point decimal value to a `Float` using the specified number of decimals.
58    ///
59    /// # Arguments
60    ///
61    /// * `value` - The fixed-point decimal value as a `U256`.
62    /// * `decimals` - The number of decimals in the fixed-point representation.
63    ///
64    /// # Returns
65    ///
66    /// * `Ok(Float)` - The resulting `Float` value.
67    /// * `Err(FloatError)` - If the conversion fails.
68    ///
69    /// # Example
70    ///
71    /// ```
72    /// use rain_math_float::Float;
73    /// use alloy::primitives::U256;
74    ///
75    /// // 123.45 with 2 decimals is represented as 12345
76    /// let value = U256::from(12345u64);
77    /// let decimals = 2u8;
78    /// let float = Float::from_fixed_decimal(value, decimals)?;
79    /// assert_eq!(float.format()?, "123.45");
80    ///
81    /// anyhow::Ok(())
82    /// ```
83    pub fn from_fixed_decimal(value: U256, decimals: u8) -> Result<Self, FloatError> {
84        let calldata = DecimalFloat::fromFixedDecimalLosslessCall { value, decimals }.abi_encode();
85
86        execute_call(Bytes::from(calldata), |output| {
87            let decoded =
88                DecimalFloat::fromFixedDecimalLosslessCall::abi_decode_returns(output.as_ref())?;
89            Ok(Float(decoded))
90        })
91    }
92
93    /// Converts a `Float` to a fixed-point decimal value using the specified number of decimals.
94    ///
95    /// # Arguments
96    ///
97    /// * `decimals` - The number of decimals in the fixed-point representation.
98    ///
99    /// # Returns
100    ///
101    /// * `Ok(U256)` - The resulting fixed-point decimal value.
102    /// * `Err(FloatError)` - If the conversion fails.
103    ///
104    /// # Example
105    ///
106    /// ```
107    /// use rain_math_float::Float;
108    /// use alloy::primitives::U256;
109    ///
110    /// // 123.45 with 2 decimals becomes 12345
111    /// let float = Float::parse("123.45".to_string())?;
112    /// let fixed = float.to_fixed_decimal(2)?;
113    /// assert_eq!(fixed, U256::from(12345u64));
114    ///
115    /// anyhow::Ok(())
116    /// ```
117    pub fn to_fixed_decimal(self, decimals: u8) -> Result<U256, FloatError> {
118        let Float(float) = self;
119        let calldata = DecimalFloat::toFixedDecimalLosslessCall { float, decimals }.abi_encode();
120
121        execute_call(Bytes::from(calldata), |output| {
122            let decoded =
123                DecimalFloat::toFixedDecimalLosslessCall::abi_decode_returns(output.as_ref())?;
124            Ok(decoded)
125        })
126    }
127
128    /// Converts a fixed-point decimal value to a `Float` using the specified number of decimals lossy.
129    ///
130    /// # Arguments
131    ///
132    /// * `value` - The fixed-point decimal value as a `U256`.
133    /// * `decimals` - The number of decimals in the fixed-point representation.
134    ///
135    /// # Returns
136    ///
137    /// * `Ok((Float, bool))` - The resulting `Float` value and a boolean indicating if the conversion was lossless.
138    /// * `Err(FloatError)` - If the conversion fails.
139    ///
140    /// # Example
141    ///
142    /// ```
143    /// use rain_math_float::Float;
144    /// use alloy::primitives::U256;
145    ///
146    /// // 123.45 with 2 decimals is represented as 12345
147    /// let value = U256::from(12345u64);
148    /// let decimals = 2u8;
149    /// let (float, lossless) = Float::from_fixed_decimal_lossy(value, decimals)?;
150    /// assert_eq!(float.format()?, "123.45");
151    /// assert!(lossless);
152    ///
153    /// anyhow::Ok(())
154    /// ```
155    pub fn from_fixed_decimal_lossy(value: U256, decimals: u8) -> Result<(Self, bool), FloatError> {
156        let calldata = DecimalFloat::fromFixedDecimalLossyCall { value, decimals }.abi_encode();
157
158        execute_call(Bytes::from(calldata), |output| {
159            let decoded =
160                DecimalFloat::fromFixedDecimalLossyCall::abi_decode_returns(output.as_ref())?;
161            Ok((Float(decoded._0), decoded._1))
162        })
163    }
164
165    /// Converts a `Float` to a fixed-point decimal value using the specified number of decimals lossy.
166    ///
167    /// # Arguments
168    ///
169    /// * `decimals` - The number of decimals in the fixed-point representation.
170    ///
171    /// # Returns
172    ///
173    /// * `Ok((U256, bool))` - The resulting fixed-point decimal value and a boolean indicating if the conversion was lossless.
174    /// * `Err(FloatError)` - If the conversion fails.
175    ///
176    /// # Example
177    ///
178    /// ```
179    /// use rain_math_float::Float;
180    /// use alloy::primitives::U256;
181    ///
182    /// // 123.45 with 2 decimals becomes 12345
183    /// let float = Float::from_fixed_decimal(U256::from(12345), 3)?;
184    /// let (fixed, lossless) = float.to_fixed_decimal_lossy(2)?;
185    /// assert_eq!(fixed, U256::from(1234u64));
186    /// assert!(!lossless);
187    ///
188    /// anyhow::Ok(())
189    /// ```
190    pub fn to_fixed_decimal_lossy(self, decimals: u8) -> Result<(U256, bool), FloatError> {
191        let Float(float) = self;
192        let calldata = DecimalFloat::toFixedDecimalLossyCall { float, decimals }.abi_encode();
193
194        execute_call(Bytes::from(calldata), |output| {
195            let decoded =
196                DecimalFloat::toFixedDecimalLossyCall::abi_decode_returns(output.as_ref())?;
197            Ok((decoded._0, decoded._1))
198        })
199    }
200
201    /// Packs a coefficient and exponent into a `Float` in a lossless manner.
202    ///
203    /// # Arguments
204    ///
205    /// * `coefficient` - The coefficient as an `I224`.
206    /// * `exponent` - The exponent as an `i32`.
207    ///
208    /// # Returns
209    ///
210    /// * `Ok(Float)` - The packed float.
211    /// * `Err(FloatError)` - If the packing fails (e.g., overflow).
212    ///
213    /// # Example
214    ///
215    /// ```
216    /// use std::str::FromStr;
217    /// use alloy::primitives::aliases::I224;
218    /// use rain_math_float::{Float, FloatError};
219    ///
220    /// let coefficient = I224::from_str("314")?;
221    /// let exponent = -2;
222    /// let float = Float::pack_lossless(coefficient, exponent)?;
223    /// assert_eq!(float.format()?, "3.14");
224    ///
225    /// anyhow::Ok(())
226    /// ```
227    #[cfg(any(test, feature = "test-harness"))]
228    pub fn pack_lossless(coefficient: I224, exponent: i32) -> Result<Self, FloatError> {
229        let calldata = TestDecimalFloat::packLosslessCall {
230            coefficient,
231            exponent,
232        }
233        .abi_encode();
234
235        execute_test_call(Bytes::from(calldata), |output| {
236            let decoded = TestDecimalFloat::packLosslessCall::abi_decode_returns(output.as_ref())?;
237            Ok(Float(decoded))
238        })
239    }
240
241    /// The signed coefficient and exponent the library unpacks from this float.
242    /// The signed coefficient and exponent the library unpacks from this float.
243    #[cfg(any(test, feature = "test-harness"))]
244    pub fn unpack(self) -> Result<(alloy::primitives::I256, alloy::primitives::I256), FloatError> {
245        let Float(float) = self;
246        let calldata = TestDecimalFloat::unpackCall { float }.abi_encode();
247
248        execute_test_call(Bytes::from(calldata), |output| {
249            let TestDecimalFloat::unpackReturn {
250                _0: coefficient,
251                _1: exponent,
252            } = TestDecimalFloat::unpackCall::abi_decode_returns(output.as_ref())?;
253
254            Ok((coefficient, exponent))
255        })
256    }
257
258    /// `<coefficient>e<exponent>`, as unpacked by the library.
259    /// `<coefficient>e<exponent>`, as unpacked by the library.
260    #[cfg(any(test, feature = "test-harness"))]
261    pub fn show_unpacked(self) -> Result<String, FloatError> {
262        let (coefficient, exponent) = self.unpack()?;
263        Ok(format!("{coefficient}e{exponent}"))
264    }
265
266    /// Parses a decimal string into a `Float`.
267    ///
268    /// # Arguments
269    ///
270    /// * `str` - The string to parse.
271    ///
272    /// # Returns
273    ///
274    /// * `Ok(Float)` - The parsed float.
275    /// * `Err(FloatError)` - If parsing fails.
276    ///
277    /// # Example
278    ///
279    /// ```
280    /// use rain_math_float::Float;
281    ///
282    /// let float = Float::parse("3.1415".to_string())?;
283    /// assert_eq!(float.format()?, "3.1415");
284    ///
285    /// anyhow::Ok(())
286    /// ```
287    pub fn parse(str: String) -> Result<Self, FloatError> {
288        let calldata = DecimalFloat::parseCall { str }.abi_encode();
289
290        execute_call(Bytes::from(calldata), |output| {
291            let DecimalFloat::parseReturn {
292                _0: error_selector,
293                _1: parsed_float,
294            } = DecimalFloat::parseCall::abi_decode_returns(output.as_ref())?;
295
296            if error_selector != fixed_bytes!("00000000") {
297                let selector = DecimalFloatErrorSelector::try_from(error_selector);
298                return Err(FloatError::DecimalFloatSelector(selector));
299            }
300
301            Ok(Float(parsed_float))
302        })
303    }
304
305    /// Returns the 32-byte hexadecimal string representation of the float.
306    ///
307    /// # Returns
308    ///
309    /// * `String` - The 32-byte hex string.
310    ///
311    /// # Example
312    ///
313    /// ```
314    /// use rain_math_float::Float;
315    /// let float = Float::from_hex("0x0000000000000000000000000000000000000000000000000000000000000005").unwrap();
316    /// assert_eq!(float.as_hex(), "0x0000000000000000000000000000000000000000000000000000000000000005");
317    /// ```
318    pub fn as_hex(self) -> String {
319        alloy::hex::encode_prefixed(self.0)
320    }
321
322    /// Constructs a `Float` from a 32-byte hexadecimal string.
323    ///
324    /// # Arguments
325    ///
326    /// * `hex` - The 32-byte hex string to parse.
327    ///
328    /// # Returns
329    ///
330    /// * `Ok(Float)` - The float parsed from the hex string.
331    /// * `Err(FloatError)` - If the hex string is not valid or not 32 bytes.
332    ///
333    /// # Example
334    ///
335    /// ```
336    /// use rain_math_float::Float;
337    /// let float = Float::from_hex("0x0000000000000000000000000000000000000000000000000000000000000005")?;
338    /// assert_eq!(float.as_hex(), "0x0000000000000000000000000000000000000000000000000000000000000005");
339    /// anyhow::Ok(())
340    /// ```
341    pub fn from_hex(hex: &str) -> Result<Self, FloatError> {
342        let bytes = B256::from_hex(hex).map_err(|_| FloatError::InvalidHex(hex.to_string()))?;
343        Ok(Float(bytes))
344    }
345
346    /// Returns the maximum positive value that can be represented as a `Float`.
347    ///
348    /// # Returns
349    ///
350    /// * `Ok(Float)` - The maximum positive value.
351    /// * `Err(FloatError)` - If the EVM call fails.
352    ///
353    /// # Example
354    ///
355    /// ```
356    /// use rain_math_float::Float;
357    ///
358    /// let max_pos = Float::max_positive_value()?;
359    /// let zero = Float::parse("0".to_string())?;
360    ///
361    /// // Max positive is greater than zero
362    /// assert!(max_pos.gt(zero)?);
363    ///
364    /// // Max positive is greater than any normal large number
365    /// let big_number = Float::parse("999999999999999999999".to_string())?;
366    /// assert!(max_pos.gt(big_number)?);
367    ///
368    /// anyhow::Ok(())
369    /// ```
370    pub fn max_positive_value() -> Result<Self, FloatError> {
371        let calldata = DecimalFloat::maxPositiveValueCall {}.abi_encode();
372
373        execute_call(Bytes::from(calldata), |output| {
374            let decoded = DecimalFloat::maxPositiveValueCall::abi_decode_returns(output.as_ref())?;
375            Ok(Float(decoded))
376        })
377    }
378
379    /// Returns the minimum positive value that can be represented as a `Float`.
380    ///
381    /// # Returns
382    ///
383    /// * `Ok(Float)` - The minimum positive value.
384    /// * `Err(FloatError)` - If the EVM call fails.
385    ///
386    /// # Example
387    ///
388    /// ```
389    /// use rain_math_float::Float;
390    ///
391    /// let min_pos = Float::min_positive_value()?;
392    /// let zero = Float::parse("0".to_string())?;
393    ///
394    /// // Min positive is greater than zero but smaller than any other positive number
395    /// assert!(min_pos.gt(zero)?);
396    ///
397    /// let small_number = Float::parse("0.000000000000000001".to_string())?;
398    /// assert!(min_pos.lt(small_number)?);
399    ///
400    /// anyhow::Ok(())
401    /// ```
402    pub fn min_positive_value() -> Result<Self, FloatError> {
403        let calldata = DecimalFloat::minPositiveValueCall {}.abi_encode();
404
405        execute_call(Bytes::from(calldata), |output| {
406            let decoded = DecimalFloat::minPositiveValueCall::abi_decode_returns(output.as_ref())?;
407            Ok(Float(decoded))
408        })
409    }
410
411    /// Returns the maximum negative value that can be represented as a `Float`.
412    ///
413    /// # Returns
414    ///
415    /// * `Ok(Float)` - The maximum negative value (closest to zero).
416    /// * `Err(FloatError)` - If the EVM call fails.
417    ///
418    /// # Example
419    ///
420    /// ```
421    /// use rain_math_float::Float;
422    ///
423    /// let max_neg = Float::max_negative_value()?;
424    /// let zero = Float::parse("0".to_string())?;
425    ///
426    /// // Max negative is less than zero but greater than any other negative number
427    /// assert!(max_neg.lt(zero)?);
428    ///
429    /// let small_negative = Float::parse("-0.000000000000000001".to_string())?;
430    /// assert!(max_neg.gt(small_negative)?);
431    ///
432    /// anyhow::Ok(())
433    /// ```
434    pub fn max_negative_value() -> Result<Self, FloatError> {
435        let calldata = DecimalFloat::maxNegativeValueCall {}.abi_encode();
436
437        execute_call(Bytes::from(calldata), |output| {
438            let decoded = DecimalFloat::maxNegativeValueCall::abi_decode_returns(output.as_ref())?;
439            Ok(Float(decoded))
440        })
441    }
442
443    /// Returns the minimum negative value that can be represented as a `Float`.
444    ///
445    /// # Returns
446    ///
447    /// * `Ok(Float)` - The minimum negative value (furthest from zero).
448    /// * `Err(FloatError)` - If the EVM call fails.
449    ///
450    /// # Example
451    ///
452    /// ```
453    /// use rain_math_float::Float;
454    ///
455    /// let min_neg = Float::min_negative_value()?;
456    /// let zero = Float::parse("0".to_string())?;
457    ///
458    /// // Min negative is less than zero
459    /// assert!(min_neg.lt(zero)?);
460    ///
461    /// // Min negative is less than any normal negative number
462    /// let big_negative = Float::parse("-999999999999999999999".to_string())?;
463    /// assert!(min_neg.lt(big_negative)?);
464    ///
465    /// anyhow::Ok(())
466    /// ```
467    pub fn min_negative_value() -> Result<Self, FloatError> {
468        let calldata = DecimalFloat::minNegativeValueCall {}.abi_encode();
469
470        execute_call(Bytes::from(calldata), |output| {
471            let decoded = DecimalFloat::minNegativeValueCall::abi_decode_returns(output.as_ref())?;
472            Ok(Float(decoded))
473        })
474    }
475
476    /// Returns the zero value of a `Float` in its maximized representation.
477    ///
478    /// # Returns
479    ///
480    /// * `Ok(Float)` - The zero value.
481    /// * `Err(FloatError)` - If the EVM call fails.
482    ///
483    /// # Example
484    ///
485    /// ```
486    /// use rain_math_float::Float;
487    ///
488    /// let zero = Float::zero()?;
489    /// assert!(zero.is_zero()?);
490    /// assert_eq!(zero.format()?, "0");
491    ///
492    /// // Should be equal to parsed zero
493    /// let parsed_zero = Float::parse("0".to_string())?;
494    /// assert!(zero.eq(parsed_zero)?);
495    ///
496    /// anyhow::Ok(())
497    /// ```
498    pub fn zero() -> Result<Self, FloatError> {
499        let calldata = DecimalFloat::zeroCall {}.abi_encode();
500
501        execute_call(Bytes::from(calldata), |output| {
502            let decoded = DecimalFloat::zeroCall::abi_decode_returns(output.as_ref())?;
503            Ok(Float(decoded))
504        })
505    }
506
507    /// Returns the default minimum value for scientific notation formatting (1e-4).
508    ///
509    /// Values smaller than this (in absolute value) will be formatted in scientific notation.
510    ///
511    /// # Returns
512    ///
513    /// * `Ok(Float)` - The default minimum (1e-4).
514    /// * `Err(FloatError)` - If the EVM call fails.
515    ///
516    /// # Example
517    ///
518    /// ```
519    /// use rain_math_float::Float;
520    ///
521    /// let min = Float::format_default_scientific_min()?;
522    /// assert_eq!(min.format()?, "0.0001");
523    ///
524    /// anyhow::Ok(())
525    /// ```
526    pub fn format_default_scientific_min() -> Result<Self, FloatError> {
527        let calldata = DecimalFloat::FORMAT_DEFAULT_SCIENTIFIC_MINCall {}.abi_encode();
528
529        execute_call(Bytes::from(calldata), |output| {
530            let decoded = DecimalFloat::FORMAT_DEFAULT_SCIENTIFIC_MINCall::abi_decode_returns(
531                output.as_ref(),
532            )?;
533            Ok(Float(decoded))
534        })
535    }
536
537    /// Returns the default maximum value for scientific notation formatting (1e9).
538    ///
539    /// Values larger than this (in absolute value) will be formatted in scientific notation.
540    ///
541    /// # Returns
542    ///
543    /// * `Ok(Float)` - The default maximum (1e9).
544    /// * `Err(FloatError)` - If the EVM call fails.
545    ///
546    /// # Example
547    ///
548    /// ```
549    /// use rain_math_float::Float;
550    ///
551    /// let max = Float::format_default_scientific_max()?;
552    /// assert_eq!(max.format()?, "1000000000");
553    ///
554    /// anyhow::Ok(())
555    /// ```
556    pub fn format_default_scientific_max() -> Result<Self, FloatError> {
557        let calldata = DecimalFloat::FORMAT_DEFAULT_SCIENTIFIC_MAXCall {}.abi_encode();
558
559        execute_call(Bytes::from(calldata), |output| {
560            let decoded = DecimalFloat::FORMAT_DEFAULT_SCIENTIFIC_MAXCall::abi_decode_returns(
561                output.as_ref(),
562            )?;
563            Ok(Float(decoded))
564        })
565    }
566
567    /// Formats the float as a decimal string using default scientific notation range (1e-4 to 1e9).
568    ///
569    /// Values within the range [1e-4, 1e9] will use decimal notation.
570    /// Values outside this range will use scientific notation.
571    ///
572    /// # Returns
573    ///
574    /// * `Ok(String)` - The formatted string.
575    /// * `Err(FloatError)` - If formatting fails.
576    ///
577    /// # Examples
578    ///
579    /// Values within the default range use decimal notation:
580    /// ```
581    /// use rain_math_float::Float;
582    ///
583    /// // At the boundaries (inclusive)
584    /// assert_eq!(Float::parse("0.0001".to_string())?.format()?, "0.0001");  // 1e-4
585    /// assert_eq!(Float::parse("1000000000".to_string())?.format()?, "1000000000");  // 1e9
586    ///
587    /// // Within range
588    /// assert_eq!(Float::parse("2.5".to_string())?.format()?, "2.5");
589    /// assert_eq!(Float::parse("123.456".to_string())?.format()?, "123.456");
590    /// assert_eq!(Float::parse("0.001".to_string())?.format()?, "0.001");
591    /// assert_eq!(Float::parse("1000000".to_string())?.format()?, "1000000");
592    ///
593    /// anyhow::Ok(())
594    /// ```
595    ///
596    /// Values outside the default range use scientific notation:
597    /// ```
598    /// use rain_math_float::Float;
599    ///
600    /// // Smaller than 1e-4
601    /// assert_eq!(Float::parse("0.00001".to_string())?.format()?, "1e-5");
602    /// assert_eq!(Float::parse("0.000001".to_string())?.format()?, "1e-6");
603    ///
604    /// // Larger than 1e9
605    /// assert_eq!(Float::parse("10000000000".to_string())?.format()?, "1e10");
606    /// assert_eq!(Float::parse("123000000000".to_string())?.format()?, "1.23e11");
607    ///
608    /// anyhow::Ok(())
609    /// ```
610    pub fn format(self) -> Result<String, FloatError> {
611        let Float(a) = self;
612        let calldata = DecimalFloat::format_1Call { a }.abi_encode();
613
614        execute_call(Bytes::from(calldata), |output| {
615            let decoded = DecimalFloat::format_1Call::abi_decode_returns(output.as_ref())?;
616            Ok(decoded)
617        })
618    }
619
620    /// Formats the float as a decimal string with explicit scientific notation control.
621    ///
622    /// # Arguments
623    ///
624    /// * `scientific` - If true, always use scientific notation. If false, use decimal notation.
625    ///
626    /// # Returns
627    ///
628    /// * `Ok(String)` - The formatted string.
629    /// * `Err(FloatError)` - If formatting fails.
630    ///
631    /// # Example
632    ///
633    /// ```
634    /// use rain_math_float::Float;
635    ///
636    /// let float = Float::parse("3.14".to_string())?;
637    /// assert_eq!(float.format_with_scientific(false)?, "3.14");
638    /// assert_eq!(float.format_with_scientific(true)?, "3.14");
639    ///
640    /// anyhow::Ok(())
641    /// ```
642    pub fn format_with_scientific(self, scientific: bool) -> Result<String, FloatError> {
643        let Float(a) = self;
644        let calldata = DecimalFloat::format_0Call { a, scientific }.abi_encode();
645
646        execute_call(Bytes::from(calldata), |output| {
647            let decoded = DecimalFloat::format_0Call::abi_decode_returns(output.as_ref())?;
648            Ok(decoded)
649        })
650    }
651
652    /// Formats the float as a decimal string with a custom scientific notation range.
653    ///
654    /// # Arguments
655    ///
656    /// * `scientific_min` - Values smaller than this (in absolute value) use scientific notation.
657    /// * `scientific_max` - Values larger than this (in absolute value) use scientific notation.
658    ///
659    /// # Returns
660    ///
661    /// * `Ok(String)` - The formatted string.
662    /// * `Err(FloatError)` - If formatting fails.
663    ///
664    /// # Example
665    ///
666    /// ```
667    /// use rain_math_float::Float;
668    ///
669    /// let float = Float::parse("0.001".to_string())?;
670    /// let min = Float::parse("0.01".to_string())?;
671    /// let max = Float::parse("100".to_string())?;
672    /// assert_eq!(float.format_with_range(min, max)?, "1e-3");
673    ///
674    /// anyhow::Ok(())
675    /// ```
676    pub fn format_with_range(
677        self,
678        scientific_min: Self,
679        scientific_max: Self,
680    ) -> Result<String, FloatError> {
681        let Float(a) = self;
682        let Float(scientific_min_inner) = scientific_min;
683        let Float(scientific_max_inner) = scientific_max;
684        let calldata = DecimalFloat::format_2Call {
685            a,
686            scientificMin: scientific_min_inner,
687            scientificMax: scientific_max_inner,
688        }
689        .abi_encode();
690
691        execute_call(Bytes::from(calldata), |output| {
692            let decoded = DecimalFloat::format_2Call::abi_decode_returns(output.as_ref())?;
693            Ok(decoded)
694        })
695    }
696
697    /// Returns `true` if `self` is less than `b`.
698    ///
699    /// # Arguments
700    ///
701    /// * `b` - The `Float` value to compare with `self`.
702    ///
703    /// # Returns
704    ///
705    /// * `Ok(true)` if `self` is less than `b`.
706    /// * `Ok(false)` if `self` is not less than `b`.
707    /// * `Err(FloatError)` if the comparison fails due to an error in the underlying EVM call or decoding.
708    ///
709    /// # Example
710    ///
711    /// ```
712    /// use rain_math_float::Float;
713    ///
714    /// let a = Float::parse("1.0".to_string())?;
715    /// let b = Float::parse("2.0".to_string())?;
716    /// assert!(a.lt(b)?);
717    ///
718    /// anyhow::Ok(())
719    /// ```
720    pub fn lt(self, b: Self) -> Result<bool, FloatError> {
721        let Float(a) = self;
722        let Float(b) = b;
723        let calldata = DecimalFloat::ltCall { a, b }.abi_encode();
724
725        execute_call(Bytes::from(calldata), |output| {
726            let decoded = DecimalFloat::ltCall::abi_decode_returns(output.as_ref())?;
727            Ok(decoded)
728        })
729    }
730
731    /// Returns `true` if `self` is equal to `b`.
732    ///
733    /// # Arguments
734    ///
735    /// * `b` - The `Float` value to compare with `self`.
736    ///
737    /// # Returns
738    ///
739    /// * `Ok(true)` if `self` is equal to `b`.
740    /// * `Ok(false)` if `self` is not equal to `b`.
741    /// * `Err(FloatError)` if the comparison fails due to an error in the underlying EVM call or decoding.
742    ///
743    /// # Example
744    ///
745    /// ```
746    /// use rain_math_float::Float;
747    ///
748    /// let a = Float::parse("3.14".to_string())?;
749    /// let b = Float::parse("3.14".to_string())?;
750    /// assert!(a.eq(b)?);
751    ///
752    /// anyhow::Ok(())
753    /// ```
754    pub fn eq(self, b: Self) -> Result<bool, FloatError> {
755        let Float(a) = self;
756        let Float(b) = b;
757        let calldata = DecimalFloat::eqCall { a, b }.abi_encode();
758
759        execute_call(Bytes::from(calldata), |output| {
760            let decoded = DecimalFloat::eqCall::abi_decode_returns(output.as_ref())?;
761            Ok(decoded)
762        })
763    }
764
765    /// Returns `true` if `self` is greater than `b`.
766    ///
767    /// # Arguments
768    ///
769    /// * `b` - The `Float` value to compare with `self`.
770    ///
771    /// # Returns
772    ///
773    /// * `Ok(true)` if `self` is greater than `b`.
774    /// * `Ok(false)` if `self` is not greater than `b`.
775    /// * `Err(FloatError)` if the comparison fails due to an error in the underlying EVM call or decoding.
776    ///
777    /// # Example
778    ///
779    /// ```
780    /// use rain_math_float::Float;
781    ///
782    /// let a = Float::parse("5.0".to_string())?;
783    /// let b = Float::parse("2.0".to_string())?;
784    /// assert!(a.gt(b)?);
785    ///
786    /// anyhow::Ok(())
787    /// ```
788    pub fn gt(self, b: Self) -> Result<bool, FloatError> {
789        let Float(a) = self;
790        let Float(b) = b;
791        let calldata = DecimalFloat::gtCall { a, b }.abi_encode();
792
793        execute_call(Bytes::from(calldata), |output| {
794            let decoded = DecimalFloat::gtCall::abi_decode_returns(output.as_ref())?;
795            Ok(decoded)
796        })
797    }
798
799    /// Returns the multiplicative inverse of the float.
800    ///
801    /// # Returns
802    ///
803    /// * `Ok(Float)` - The inverse.
804    /// * `Err(FloatError)` - If inversion fails.
805    ///
806    /// # Example
807    ///
808    /// ```
809    /// use rain_math_float::Float;
810    ///
811    /// let x = Float::parse("2.0".to_string())?;
812    /// let inv = x.inv()?;
813    /// assert!(inv.format()?.starts_with("0.5"));
814    ///
815    /// anyhow::Ok(())
816    /// ```
817    pub fn inv(self) -> Result<Self, FloatError> {
818        let Float(a) = self;
819        let calldata = DecimalFloat::invCall { a }.abi_encode();
820
821        execute_call(Bytes::from(calldata), |output| {
822            let decoded = DecimalFloat::invCall::abi_decode_returns(output.as_ref())?;
823            Ok(Float(decoded))
824        })
825    }
826
827    /// Returns the absolute value of the float.
828    ///
829    /// # Returns
830    ///
831    /// * `Ok(Float)` - The absolute value.
832    /// * `Err(FloatError)` - If the operation fails.
833    ///
834    /// # Example
835    ///
836    /// ```
837    /// use rain_math_float::Float;
838    ///
839    /// let x = Float::parse("-3.14".to_string())?;
840    /// let abs = x.abs()?;
841    /// assert_eq!(abs.format()?, "3.14");
842    ///
843    /// anyhow::Ok(())
844    /// ```
845    pub fn abs(self) -> Result<Float, FloatError> {
846        let Float(a) = self;
847        let calldata = DecimalFloat::absCall { a }.abi_encode();
848
849        execute_call(Bytes::from(calldata), |output| {
850            let decoded = DecimalFloat::absCall::abi_decode_returns(output.as_ref())?;
851            Ok(Float(decoded))
852        })
853    }
854
855    /// Returns `true` if `self` is less than or equal to `b`.
856    ///
857    /// # Arguments
858    ///
859    /// * `b` - The `Float` value to compare with `self`.
860    ///
861    /// # Returns
862    ///
863    /// * `Ok(true)` if `self` is less than or equal to `b`.
864    /// * `Ok(false)` if `self` is not less than or equal to `b`.
865    /// * `Err(FloatError)` if the comparison fails due to an error in the underlying EVM call or decoding.
866    ///
867    /// # Example
868    ///
869    /// ```
870    /// use rain_math_float::Float;
871    ///
872    /// let a = Float::parse("1.0".to_string())?;
873    /// let b = Float::parse("2.0".to_string())?;
874    /// assert!(a.lte(b)?);
875    ///
876    /// anyhow::Ok(())
877    /// ```
878    pub fn lte(self, b: Self) -> Result<bool, FloatError> {
879        let Float(a) = self;
880        let Float(b) = b;
881        let calldata = DecimalFloat::lteCall { a, b }.abi_encode();
882
883        execute_call(Bytes::from(calldata), |output| {
884            let decoded = DecimalFloat::lteCall::abi_decode_returns(output.as_ref())?;
885            Ok(decoded)
886        })
887    }
888
889    /// Returns `true` if `self` is greater than or equal to `b`.
890    ///
891    /// # Arguments
892    ///
893    /// * `b` - The `Float` value to compare with `self`.
894    ///
895    /// # Returns
896    ///
897    /// * `Ok(true)` if `self` is greater than or equal to `b`.
898    /// * `Ok(false)` if `self` is not greater than or equal to `b`.
899    /// * `Err(FloatError)` if the comparison fails due to an error in the underlying EVM call or decoding.
900    ///
901    /// # Example
902    ///
903    /// ```
904    /// use rain_math_float::Float;
905    ///
906    /// let a = Float::parse("2.0".to_string())?;
907    /// let b = Float::parse("1.0".to_string())?;
908    /// assert!(a.gte(b)?);
909    ///
910    /// anyhow::Ok(())
911    /// ```
912    pub fn gte(self, b: Self) -> Result<bool, FloatError> {
913        let Float(a) = self;
914        let Float(b) = b;
915        let calldata = DecimalFloat::gteCall { a, b }.abi_encode();
916
917        execute_call(Bytes::from(calldata), |output| {
918            let decoded = DecimalFloat::gteCall::abi_decode_returns(output.as_ref())?;
919            Ok(decoded)
920        })
921    }
922}
923
924impl Add for Float {
925    type Output = Result<Self, FloatError>;
926
927    /// Adds two floats.
928    ///
929    /// # Returns
930    ///
931    /// * `Ok(Float)` - The sum.
932    /// * `Err(FloatError)` - If addition fails.
933    ///
934    /// # Example
935    ///
936    /// ```
937    /// use rain_math_float::Float;
938    ///
939    /// let a = Float::parse("1.5".to_string())?;
940    /// let b = Float::parse("2.5".to_string())?;
941    /// let sum = (a + b)?;
942    /// assert_eq!(sum.format()?, "4");
943    ///
944    /// anyhow::Ok(())
945    /// ```
946    fn add(self, b: Self) -> Self::Output {
947        let Float(a) = self;
948        let Float(b) = b;
949        let calldata = DecimalFloat::addCall { a, b }.abi_encode();
950
951        execute_call(Bytes::from(calldata), |output| {
952            let decoded = DecimalFloat::addCall::abi_decode_returns(output.as_ref())?;
953            Ok(Float(decoded))
954        })
955    }
956}
957
958impl Sub for Float {
959    type Output = Result<Self, FloatError>;
960
961    /// Subtracts `b` from `self`.
962    ///
963    /// # Returns
964    ///
965    /// * `Ok(Float)` - The difference.
966    /// * `Err(FloatError)` - If subtraction fails.
967    ///
968    /// # Example
969    ///
970    /// ```
971    /// use rain_math_float::Float;
972    ///
973    /// let a = Float::parse("5.0".to_string())?;
974    /// let b = Float::parse("2.0".to_string())?;
975    /// let diff = (a - b)?;
976    /// assert_eq!(diff.format()?, "3");
977    ///
978    /// anyhow::Ok(())
979    /// ```
980    fn sub(self, b: Self) -> Self::Output {
981        let Float(a) = self;
982        let Float(b) = b;
983        let calldata = DecimalFloat::subCall { a, b }.abi_encode();
984
985        execute_call(Bytes::from(calldata), |output| {
986            let decoded = DecimalFloat::subCall::abi_decode_returns(output.as_ref())?;
987            Ok(Float(decoded))
988        })
989    }
990}
991
992impl Mul for Float {
993    type Output = Result<Self, FloatError>;
994
995    /// Multiplies two floats.
996    ///
997    /// # Returns
998    ///
999    /// * `Ok(Float)` - The product.
1000    /// * `Err(FloatError)` - If multiplication fails.
1001    ///
1002    /// # Example
1003    ///
1004    /// ```
1005    /// use rain_math_float::Float;
1006    ///
1007    /// let a = Float::parse("2.0".to_string())?;
1008    /// let b = Float::parse("3.0".to_string())?;
1009    /// let product = (a * b)?;
1010    /// assert_eq!(product.format()?, "6");
1011    ///
1012    /// anyhow::Ok(())
1013    /// ```
1014    fn mul(self, b: Self) -> Self::Output {
1015        let Float(a) = self;
1016        let Float(b) = b;
1017        let calldata = DecimalFloat::mulCall { a, b }.abi_encode();
1018
1019        execute_call(Bytes::from(calldata), |output| {
1020            let decoded = DecimalFloat::mulCall::abi_decode_returns(output.as_ref())?;
1021            Ok(Float(decoded))
1022        })
1023    }
1024}
1025
1026impl Div for Float {
1027    type Output = Result<Self, FloatError>;
1028
1029    /// Divides `self` by `b`.
1030    ///
1031    /// # Returns
1032    ///
1033    /// * `Ok(Float)` - The quotient.
1034    /// * `Err(FloatError)` - If division fails.
1035    ///
1036    /// # Example
1037    ///
1038    /// ```
1039    /// use rain_math_float::Float;
1040    ///
1041    /// let a = Float::parse("6.0".to_string())?;
1042    /// let b = Float::parse("2.0".to_string())?;
1043    /// let quotient = (a / b)?;
1044    /// assert_eq!(quotient.format()?, "3");
1045    ///
1046    /// anyhow::Ok(())
1047    /// ```
1048    fn div(self, b: Self) -> Self::Output {
1049        let Float(a) = self;
1050        let Float(b) = b;
1051        let calldata = DecimalFloat::divCall { a, b }.abi_encode();
1052
1053        execute_call(Bytes::from(calldata), |output| {
1054            let decoded = DecimalFloat::divCall::abi_decode_returns(output.as_ref())?;
1055            Ok(Float(decoded))
1056        })
1057    }
1058}
1059
1060impl Float {
1061    /// Returns the integer part of the float (truncation toward zero).
1062    ///
1063    /// # Returns
1064    ///
1065    /// * `Ok(Float)` - The integer part.
1066    /// * `Err(FloatError)` - If the operation fails.
1067    ///
1068    /// # Example
1069    ///
1070    /// ```
1071    /// use rain_math_float::Float;
1072    ///
1073    /// let x = Float::parse("3.75".to_string())?;
1074    /// let int = x.integer()?;
1075    /// assert_eq!(int.format()?, "3");
1076    ///
1077    /// let y = Float::parse("-3.75".to_string())?;
1078    /// let int_y = y.integer()?;
1079    /// assert_eq!(int_y.format()?, "-3");
1080    ///
1081    /// anyhow::Ok(())
1082    /// ```
1083    pub fn integer(self) -> Result<Float, FloatError> {
1084        let Float(a) = self;
1085        let calldata = DecimalFloat::integerCall { a }.abi_encode();
1086
1087        execute_call(Bytes::from(calldata), |output| {
1088            let decoded = DecimalFloat::integerCall::abi_decode_returns(output.as_ref())?;
1089            Ok(Float(decoded))
1090        })
1091    }
1092
1093    /// Returns the fractional part of the float.
1094    ///
1095    /// # Returns
1096    ///
1097    /// * `Ok(Float)` - The fractional part.
1098    /// * `Err(FloatError)` - If the operation fails.
1099    ///
1100    /// # Example
1101    ///
1102    /// ```
1103    /// use rain_math_float::Float;
1104    ///
1105    /// let x = Float::parse("3.75".to_string())?;
1106    /// let frac = x.frac()?;
1107    /// assert_eq!(frac.format()?, "0.75");
1108    ///
1109    /// anyhow::Ok(())
1110    /// ```
1111    pub fn frac(self) -> Result<Float, FloatError> {
1112        let Float(a) = self;
1113        let calldata = DecimalFloat::fracCall { a }.abi_encode();
1114
1115        execute_call(Bytes::from(calldata), |output| {
1116            let decoded = DecimalFloat::fracCall::abi_decode_returns(output.as_ref())?;
1117            Ok(Float(decoded))
1118        })
1119    }
1120
1121    /// Returns the floor of the float.
1122    ///
1123    /// # Returns
1124    ///
1125    /// * `Ok(Float)` - The floored value.
1126    /// * `Err(FloatError)` - If the operation fails.
1127    ///
1128    /// # Example
1129    ///
1130    /// ```
1131    /// use rain_math_float::Float;
1132    ///
1133    /// let x = Float::parse("3.75".to_string())?;
1134    /// let floor = x.floor()?;
1135    /// assert_eq!(floor.format()?, "3");
1136    ///
1137    /// anyhow::Ok(())
1138    /// ```
1139    pub fn floor(self) -> Result<Float, FloatError> {
1140        let Float(a) = self;
1141        let calldata = DecimalFloat::floorCall { a }.abi_encode();
1142
1143        execute_call(Bytes::from(calldata), |output| {
1144            let decoded = DecimalFloat::floorCall::abi_decode_returns(output.as_ref())?;
1145            Ok(Float(decoded))
1146        })
1147    }
1148
1149    /// Returns the minimum of `self` and `b`.
1150    ///
1151    /// # Arguments
1152    ///
1153    /// * `b` - The other `Float` to compare with.
1154    ///
1155    /// # Returns
1156    ///
1157    /// * `Ok(Float)` - The minimum value.
1158    /// * `Err(FloatError)` - If the operation fails.
1159    ///
1160    /// # Example
1161    ///
1162    /// ```
1163    /// use rain_math_float::Float;
1164    ///
1165    /// let a = Float::parse("1.0".to_string())?;
1166    /// let b = Float::parse("2.0".to_string())?;
1167    /// let min = a.min(b)?;
1168    /// assert_eq!(min.format()?, "1");
1169    ///
1170    /// anyhow::Ok(())
1171    /// ```
1172    pub fn min(self, b: Self) -> Result<Self, FloatError> {
1173        let Float(a) = self;
1174        let Float(b) = b;
1175        let calldata = DecimalFloat::minCall { a, b }.abi_encode();
1176
1177        execute_call(Bytes::from(calldata), |output| {
1178            let decoded = DecimalFloat::minCall::abi_decode_returns(output.as_ref())?;
1179            Ok(Float(decoded))
1180        })
1181    }
1182
1183    /// Returns the maximum of `self` and `b`.
1184    ///
1185    /// # Arguments
1186    ///
1187    /// * `b` - The other `Float` to compare with.
1188    ///
1189    /// # Returns
1190    ///
1191    /// * `Ok(Float)` - The maximum value.
1192    /// * `Err(FloatError)` - If the operation fails.
1193    ///
1194    /// # Example
1195    ///
1196    /// ```
1197    /// use rain_math_float::Float;
1198    ///
1199    /// let a = Float::parse("1.0".to_string())?;
1200    /// let b = Float::parse("2.0".to_string())?;
1201    /// let max = a.max(b)?;
1202    /// assert_eq!(max.format()?, "2");
1203    ///
1204    /// anyhow::Ok(())
1205    /// ```
1206    pub fn max(self, b: Self) -> Result<Self, FloatError> {
1207        let Float(a) = self;
1208        let Float(b) = b;
1209        let calldata = DecimalFloat::maxCall { a, b }.abi_encode();
1210
1211        execute_call(Bytes::from(calldata), |output| {
1212            let decoded = DecimalFloat::maxCall::abi_decode_returns(output.as_ref())?;
1213            Ok(Float(decoded))
1214        })
1215    }
1216
1217    /// Checks if the float is zero.
1218    ///
1219    /// # Returns
1220    ///
1221    /// * `Ok(true)` if the float is zero.
1222    /// * `Ok(false)` if the float is not zero.
1223    /// * `Err(FloatError)` if the operation fails.
1224    ///
1225    /// # Example
1226    ///
1227    /// ```
1228    /// use rain_math_float::Float;
1229    ///
1230    /// let zero = Float::parse("0".to_string())?;
1231    /// assert!(zero.is_zero()?);
1232    /// let nonzero = Float::parse("1.23".to_string())?;
1233    /// assert!(!nonzero.is_zero()?);
1234    ///
1235    /// anyhow::Ok(())
1236    /// ```
1237    pub fn is_zero(self) -> Result<bool, FloatError> {
1238        let Float(a) = self;
1239        let calldata = DecimalFloat::isZeroCall { a }.abi_encode();
1240
1241        execute_call(Bytes::from(calldata), |output| {
1242            let decoded = DecimalFloat::isZeroCall::abi_decode_returns(output.as_ref())?;
1243            Ok(decoded)
1244        })
1245    }
1246}
1247
1248impl Neg for Float {
1249    type Output = Result<Self, FloatError>;
1250
1251    /// Returns the negation of the float.
1252    ///
1253    /// # Returns
1254    ///
1255    /// * `Ok(Float)` - The negated value.
1256    /// * `Err(FloatError)` - If the operation fails.
1257    ///
1258    /// # Example
1259    ///
1260    /// ```
1261    /// use rain_math_float::Float;
1262    ///
1263    /// let x = Float::parse("3.14".to_string())?;
1264    /// let neg = (-x)?;
1265    /// assert_eq!(neg.format()?, "-3.14");
1266    ///
1267    /// anyhow::Ok(())
1268    /// ```
1269    fn neg(self) -> Self::Output {
1270        let Float(a) = self;
1271        let calldata = DecimalFloat::minusCall { a }.abi_encode();
1272
1273        execute_call(Bytes::from(calldata), |output| {
1274            let decoded = DecimalFloat::minusCall::abi_decode_returns(output.as_ref())?;
1275            Ok(Float(decoded))
1276        })
1277    }
1278}
1279
1280impl From<B256> for Float {
1281    fn from(value: B256) -> Self {
1282        Float(value)
1283    }
1284}
1285
1286impl From<Float> for B256 {
1287    fn from(value: Float) -> Self {
1288        value.0
1289    }
1290}
1291#[cfg(test)]
1292mod tests {
1293    use super::*;
1294    use proptest::prelude::*;
1295    use serde_json::json;
1296
1297    /// Float::default() equals parsed "0".
1298    #[test]
1299    fn test_default() {
1300        let zero = Float::parse("0".to_string()).unwrap();
1301        assert!(zero.eq(Float::default()).unwrap());
1302    }
1303
1304    prop_compose! {
1305        fn arb_float()(
1306            coefficient in any::<I224>(),
1307            exponent in any::<i32>(),
1308        ) -> Float {
1309            Float::pack_lossless(coefficient, exponent).unwrap()
1310        }
1311    }
1312
1313    /// JSON serialize then deserialize preserves equality and hex representation.
1314    #[test]
1315    fn test_serde() {
1316        let float = Float::parse("1.1341234234625468391".to_string()).unwrap();
1317        let serialized = serde_json::to_string(&float).unwrap();
1318        assert_eq!(
1319            serialized,
1320            json!("0xffffffed00000000000000000000000000000000000000009d642872ad59a7e7").to_string()
1321        );
1322        let deserialized: Float = serde_json::from_str(&serialized).unwrap();
1323        assert!(float.eq(deserialized).unwrap());
1324    }
1325
1326    proptest! {
1327        #[test]
1328        /// JSON round-trip preserves equality and serialized form for all floats.
1329        fn proptest_serde(float in arb_float()) {
1330            let serialized = serde_json::to_string(&float).unwrap();
1331            let deserialized: Float = serde_json::from_str(&serialized).unwrap();
1332            prop_assert!(float.eq(deserialized).unwrap());
1333            let re_serialized = serde_json::to_string(&deserialized).unwrap();
1334            prop_assert_eq!(serialized, re_serialized);
1335        }
1336    }
1337
1338    proptest! {
1339        #[test]
1340        /// as_hex() then from_hex() round-trips to identical hex.
1341        fn test_as_from_hex(float in arb_float()) {
1342            let hex = float.as_hex();
1343            let parsed = Float::from_hex(&hex).unwrap();
1344            prop_assert_eq!(parsed.as_hex(), hex);
1345        }
1346    }
1347}