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}