diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5afb47d7e64..56091b12084 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -36,7 +36,7 @@
- Add implementations for `HashSet`, `HashMap`, `BTreeSet`, `BTreeMap` (https://github.com/unicode-org/icu4x/pull/4268, https://github.com/unicode-org/icu4x/pull/4274, https://github.com/unicode-org/icu4x/pull/4295)
- Improvements to `databake::test_bake!()` (https://github.com/unicode-org/icu4x/pull/4182)
- `fixed_decimal`
- - Experimental rounding increment support (https://github.com/unicode-org/icu4x/pull/4219)
+ - Experimental rounding increment support (https://github.com/unicode-org/icu4x/pull/4219, https://github.com/unicode-org/icu4x/pull/4246)
- `litemap`
- Implement `databake::Bake` on `LiteMap` (https://github.com/unicode-org/icu4x/pull/4275)
- `tinystr`
diff --git a/tools/ffi_coverage/src/allowlist.rs b/tools/ffi_coverage/src/allowlist.rs
index 53a396adbd6..6d7a4b17680 100644
--- a/tools/ffi_coverage/src/allowlist.rs
+++ b/tools/ffi_coverage/src/allowlist.rs
@@ -317,6 +317,20 @@ lazy_static::lazy_static! {
"fixed_decimal::FixedDecimal::expanded_to_increment",
"fixed_decimal::FixedDecimal::trunc_to_increment",
"fixed_decimal::FixedDecimal::trunced_to_increment",
+ "fixed_decimal::FixedDecimal::ceil_to_increment",
+ "fixed_decimal::FixedDecimal::ceiled_to_increment",
+ "fixed_decimal::FixedDecimal::floor_to_increment",
+ "fixed_decimal::FixedDecimal::floored_to_increment",
+ "fixed_decimal::FixedDecimal::half_ceil_to_increment",
+ "fixed_decimal::FixedDecimal::half_ceiled_to_increment",
+ "fixed_decimal::FixedDecimal::half_even_to_increment",
+ "fixed_decimal::FixedDecimal::half_evened_to_increment",
+ "fixed_decimal::FixedDecimal::half_expand_to_increment",
+ "fixed_decimal::FixedDecimal::half_expanded_to_increment",
+ "fixed_decimal::FixedDecimal::half_floor_to_increment",
+ "fixed_decimal::FixedDecimal::half_floored_to_increment",
+ "fixed_decimal::FixedDecimal::half_trunc_to_increment",
+ "fixed_decimal::FixedDecimal::half_trunced_to_increment",
// Stuff that does not need to be exposed over FFI
// Especially for stuff that are Rust specific like conversion traits
diff --git a/utils/fixed_decimal/src/decimal.rs b/utils/fixed_decimal/src/decimal.rs
index 12616bc92e0..fc791b0e6c4 100644
--- a/utils/fixed_decimal/src/decimal.rs
+++ b/utils/fixed_decimal/src/decimal.rs
@@ -349,6 +349,108 @@ impl FixedDecimal {
}
}
+ /// Returns the relative ordering of the digits after `magnitude` with respect to 5.
+ #[cfg(feature = "experimental")]
+ fn half_at_next_magnitude(&self, magnitude: i16) -> Ordering {
+ #[cfg(debug_assertions)] // Depends on having no trailing zeroes.
+ self.check_invariants();
+
+ match self.digit_at_next_position(magnitude).cmp(&5) {
+ // If the next digit is equal to 5, we can know if we're at exactly 5
+ // by comparing the next magnitude with the last nonzero magnitude of
+ // the number.
+ Ordering::Equal => match (magnitude - 1).cmp(&self.nonzero_magnitude_end()) {
+ Ordering::Greater => {
+ // `magnitude - 1` has non-zero digits at its right,
+ // meaning the number overall must be greater than 5.
+ Ordering::Greater
+ }
+ Ordering::Equal => {
+ // `magnitude - 1` is the last digit of the number,
+ // meaning the number is exactly 5.
+ Ordering::Equal
+ }
+ Ordering::Less => {
+ debug_assert!(false, "digit `magnitude - 1` should not be zero");
+ Ordering::Less
+ }
+ },
+ // If the next digit is either greater or less than 5,
+ // we know that the digits cannot sum to exactly 5.
+ ord => ord,
+ }
+ }
+
+ /// Returns the relative ordering of the digits from `magnitude` onwards
+ /// with respect to the half increment of `increment`.
+ #[cfg(feature = "experimental")]
+ fn half_increment_at_magnitude(
+ &self,
+ magnitude: i16,
+ increment: RoundingIncrement,
+ ) -> Ordering {
+ #[cfg(debug_assertions)] // Depends on having no trailing zeroes.
+ self.check_invariants();
+
+ match increment {
+ RoundingIncrement::MultiplesOf1 => self.half_at_next_magnitude(magnitude),
+ RoundingIncrement::MultiplesOf2 => {
+ let current_digit = self.digit_at(magnitude);
+
+ // Equivalent to "if current_digit is odd".
+ if current_digit & 0x01 == 1 {
+ match magnitude.cmp(&self.nonzero_magnitude_end()) {
+ Ordering::Greater => {
+ // `magnitude` has non-zero digits at its right,
+ // meaning the number overall must be greater than
+ // the half increment.
+ Ordering::Greater
+ }
+ Ordering::Equal => {
+ // `magnitude` is the last digit of the number,
+ // meaning the number is exactly at a half increment.
+ Ordering::Equal
+ }
+ Ordering::Less => {
+ debug_assert!(false, "digit `magnitude` should not be zero");
+ Ordering::Less
+ }
+ }
+ } else {
+ // Even numbers are always below the half increment.
+ Ordering::Less
+ }
+ }
+ RoundingIncrement::MultiplesOf5 => {
+ let current_digit = self.digit_at(magnitude);
+ match (current_digit % 5).cmp(&2) {
+ Ordering::Equal => {
+ // Need to know if the number exceeds 2.5.
+ self.half_at_next_magnitude(magnitude)
+ }
+ // If the next digit is either greater or less than the half increment,
+ // we know that the digits cannot sum to exactly it.
+ ord => ord,
+ }
+ }
+ RoundingIncrement::MultiplesOf25 => {
+ let current_digit = self.digit_at(magnitude);
+ let prev_digit = self.digit_at_previous_position(magnitude);
+ let number = prev_digit * 10 + current_digit;
+
+ match (number % 25).cmp(&12) {
+ Ordering::Equal => {
+ // Need to know if the number exceeds 12.5.
+ self.half_at_next_magnitude(magnitude)
+ }
+ // If the next digit is either greater or less than the half increment,
+ // we know that the digits cannot sum to exactly it.
+ ord => ord,
+ }
+ }
+ }
+ }
+
/// Checks if this number is already rounded to the specified magnitude and
/// increment.
#[cfg(feature = "experimental")]
@@ -1380,6 +1482,19 @@ impl FixedDecimal {
/// assert_eq!("4", dec.to_string());
/// ```
pub fn half_trunc(&mut self, position: i16) {
+ #[cfg(feature = "experimental")]
+ {
+ self.half_trunc_to_increment(position, RoundingIncrement::MultiplesOf1);
+ }
+
+ #[cfg(not(feature = "experimental"))]
+ {
+ self.half_trunc_internal(position);
+ }
+ }
+
+ #[cfg(not(feature = "experimental"))]
+ fn half_trunc_internal(&mut self, position: i16) {
let digit_after_position = self.digit_at_next_position(position);
let should_expand = match digit_after_position.cmp(&5) {
Ordering::Less => false,
@@ -1398,6 +1513,51 @@ impl FixedDecimal {
}
}
+ /// Half Truncates the number on the right to a particular position and rounding increment,
+ /// deleting digits if necessary.
+ ///
+ ///
+ /// 🚧 This code is experimental; it may change at any time, in breaking or non-breaking ways,
+ /// including in SemVer minor releases. Use with caution.
+ ///
#3929
+ ///
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use fixed_decimal::{FixedDecimal, RoundingIncrement};
+ /// # use std::str::FromStr;
+ ///
+ /// let mut dec = FixedDecimal::from_str("-3.5").unwrap();
+ /// dec.half_trunc_to_increment(0, RoundingIncrement::MultiplesOf2);
+ /// assert_eq!("-4", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("7.57").unwrap();
+ /// dec.half_trunc_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ /// assert_eq!("7.5", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("5.45").unwrap();
+ /// dec.half_trunc_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ /// assert_eq!("5.50", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("9.99").unwrap();
+ /// dec.half_trunc_to_increment(-1, RoundingIncrement::MultiplesOf25);
+ /// assert_eq!("10.0", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("9.99").unwrap();
+ /// dec.half_trunc_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ /// assert_eq!("9.98", dec.to_string());
+ /// ```
+ #[cfg(feature = "experimental")]
+ pub fn half_trunc_to_increment(&mut self, position: i16, increment: RoundingIncrement) {
+ // Only expand if the rounding position is strictly greater than the half increment.
+ // At the half increment, `half_trunc` always truncates.
+ let should_expand =
+ self.half_increment_at_magnitude(position, increment) == Ordering::Greater;
+
+ if should_expand {
+ self.expand_to_increment(position, increment);
+ } else {
+ self.trunc_to_increment(position, increment);
+ }
+ }
+
/// Half Truncates the number on the right to a particular position, deleting
/// digits if necessary.
///
@@ -1425,6 +1585,62 @@ impl FixedDecimal {
self
}
+ /// Half Truncates the number on the right to a particular position and rounding increment,
+ /// deleting digits if necessary.
+ ///
+ ///
+ /// 🚧 This code is experimental; it may change at any time, in breaking or non-breaking ways,
+ /// including in SemVer minor releases. Use with caution.
+ ///
#3929
+ ///
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use fixed_decimal::{FixedDecimal, RoundingIncrement};
+ /// # use std::str::FromStr;
+ ///
+ /// let mut dec = FixedDecimal::from_str("-3.5").unwrap();
+ /// assert_eq!(
+ /// "-4",
+ /// dec.half_trunced_to_increment(0, RoundingIncrement::MultiplesOf2)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("7.57").unwrap();
+ /// assert_eq!(
+ /// "7.5",
+ /// dec.half_trunced_to_increment(-1, RoundingIncrement::MultiplesOf5)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("5.45").unwrap();
+ /// assert_eq!(
+ /// "5.50",
+ /// dec.half_trunced_to_increment(-2, RoundingIncrement::MultiplesOf25)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("9.99").unwrap();
+ /// assert_eq!(
+ /// "10.0",
+ /// dec.half_trunced_to_increment(-1, RoundingIncrement::MultiplesOf25)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("9.99").unwrap();
+ /// assert_eq!(
+ /// "9.98",
+ /// dec.half_trunced_to_increment(-2, RoundingIncrement::MultiplesOf2)
+ /// .to_string()
+ /// );
+ /// ```
+ #[cfg(feature = "experimental")]
+ pub fn half_trunced_to_increment(
+ mut self,
+ position: i16,
+ increment: RoundingIncrement,
+ ) -> Self {
+ self.half_trunc_to_increment(position, increment);
+ self
+ }
+
/// Take the expand of the number at a particular position.
///
/// # Examples
@@ -1884,6 +2100,19 @@ impl FixedDecimal {
/// assert_eq!("2", dec.to_string());
/// ```
pub fn half_expand(&mut self, position: i16) {
+ #[cfg(feature = "experimental")]
+ {
+ self.half_expand_to_increment(position, RoundingIncrement::MultiplesOf1);
+ }
+
+ #[cfg(not(feature = "experimental"))]
+ {
+ self.half_expand_internal(position);
+ }
+ }
+
+ #[cfg(not(feature = "experimental"))]
+ pub fn half_expand_internal(&mut self, position: i16) {
let digit_after_position = self.digit_at_next_position(position);
if digit_after_position >= 5 {
@@ -1893,6 +2122,49 @@ impl FixedDecimal {
}
}
+ /// Take the half expand of the number at a particular position and rounding increment.
+ ///
+ ///
+ /// 🚧 This code is experimental; it may change at any time, in breaking or non-breaking ways,
+ /// including in SemVer minor releases. Use with caution.
+ ///
#3929
+ ///
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use fixed_decimal::{FixedDecimal, RoundingIncrement};
+ /// # use std::str::FromStr;
+ ///
+ /// let mut dec = FixedDecimal::from_str("-3.5").unwrap();
+ /// dec.half_expand_to_increment(0, RoundingIncrement::MultiplesOf2);
+ /// assert_eq!("-4", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("7.57").unwrap();
+ /// dec.half_expand_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ /// assert_eq!("7.5", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("5.45").unwrap();
+ /// dec.half_expand_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ /// assert_eq!("5.50", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("9.99").unwrap();
+ /// dec.half_expand_to_increment(-1, RoundingIncrement::MultiplesOf25);
+ /// assert_eq!("10.0", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("9.99").unwrap();
+ /// dec.half_expand_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ /// assert_eq!("10.00", dec.to_string());
+ /// ```
+ #[cfg(feature = "experimental")]
+ pub fn half_expand_to_increment(&mut self, position: i16, increment: RoundingIncrement) {
+ // Only truncate if the rounding position is strictly less than the half increment.
+ // At the half increment, `half_expand` always expands.
+ let should_trunc = self.half_increment_at_magnitude(position, increment) == Ordering::Less;
+
+ if should_trunc {
+ self.trunc_to_increment(position, increment);
+ } else {
+ self.expand_to_increment(position, increment);
+ }
+ }
+
/// Take the half expand of the number at a particular position.
///
/// # Examples
@@ -1917,6 +2189,61 @@ impl FixedDecimal {
self
}
+ /// Take the half expand of the number at a particular position and rounding increment.
+ ///
+ ///
+ /// 🚧 This code is experimental; it may change at any time, in breaking or non-breaking ways,
+ /// including in SemVer minor releases. Use with caution.
+ ///
#3929
+ ///
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use fixed_decimal::{FixedDecimal, RoundingIncrement};
+ /// # use std::str::FromStr;
+ ///
+ /// let mut dec = FixedDecimal::from_str("-3.5").unwrap();
+ /// assert_eq!(
+ /// "-4",
+ /// dec.half_expanded_to_increment(0, RoundingIncrement::MultiplesOf2)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("7.57").unwrap();
+ /// assert_eq!(
+ /// "7.5",
+ /// dec.half_expanded_to_increment(-1, RoundingIncrement::MultiplesOf5)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("5.45").unwrap();
+ /// assert_eq!(
+ /// "5.50",
+ /// dec.half_expanded_to_increment(-2, RoundingIncrement::MultiplesOf25)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("9.99").unwrap();
+ /// assert_eq!(
+ /// "10.0",
+ /// dec.half_expanded_to_increment(-1, RoundingIncrement::MultiplesOf25)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("9.99").unwrap();
+ /// assert_eq!(
+ /// "10.00",
+ /// dec.half_expanded_to_increment(-2, RoundingIncrement::MultiplesOf2)
+ /// .to_string()
+ /// );
+ /// ```
+ #[cfg(feature = "experimental")]
+ pub fn half_expanded_to_increment(
+ mut self,
+ position: i16,
+ increment: RoundingIncrement,
+ ) -> Self {
+ self.half_expand_to_increment(position, increment);
+ self
+ }
+
/// Take the ceiling of the number at a particular position.
///
/// # Examples
@@ -1942,6 +2269,19 @@ impl FixedDecimal {
/// assert_eq!("2", dec.to_string());
/// ```
pub fn ceil(&mut self, position: i16) {
+ #[cfg(feature = "experimental")]
+ {
+ self.ceil_to_increment(position, RoundingIncrement::MultiplesOf1);
+ }
+
+ #[cfg(not(feature = "experimental"))]
+ {
+ self.ceil_internal(position);
+ }
+ }
+
+ #[cfg(not(feature = "experimental"))]
+ fn ceil_internal(&mut self, position: i16) {
if self.sign == Sign::Negative {
self.trunc(position);
return;
@@ -1950,6 +2290,46 @@ impl FixedDecimal {
self.expand(position);
}
+ /// Take the ceiling of the number at a particular position and rounding increment.
+ ///
+ ///
+ /// 🚧 This code is experimental; it may change at any time, in breaking or non-breaking ways,
+ /// including in SemVer minor releases. Use with caution.
+ ///
#3929
+ ///
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use fixed_decimal::{FixedDecimal, RoundingIncrement};
+ /// # use std::str::FromStr;
+ ///
+ /// let mut dec = FixedDecimal::from_str("-3.5").unwrap();
+ /// dec.ceil_to_increment(0, RoundingIncrement::MultiplesOf2);
+ /// assert_eq!("-2", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("7.57").unwrap();
+ /// dec.ceil_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ /// assert_eq!("8.0", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("-5.45").unwrap();
+ /// dec.ceil_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ /// assert_eq!("-5.25", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("9.99").unwrap();
+ /// dec.ceil_to_increment(-1, RoundingIncrement::MultiplesOf25);
+ /// assert_eq!("10.0", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("-9.99").unwrap();
+ /// dec.ceil_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ /// assert_eq!("-9.98", dec.to_string());
+ /// ```
+ #[cfg(feature = "experimental")]
+ pub fn ceil_to_increment(&mut self, position: i16, increment: RoundingIncrement) {
+ if self.sign == Sign::Negative {
+ self.trunc_to_increment(position, increment);
+ return;
+ }
+
+ self.expand_to_increment(position, increment);
+ }
+
/// Take the ceiling of the number at a particular position.
///
/// # Examples
@@ -1974,21 +2354,72 @@ impl FixedDecimal {
self
}
- /// Take the half ceiling of the number at a particular position.
+ /// Take the ceiling of the number at a particular position and rounding increment.
+ ///
+ ///
+ /// 🚧 This code is experimental; it may change at any time, in breaking or non-breaking ways,
+ /// including in SemVer minor releases. Use with caution.
+ ///
#3929
+ ///
///
/// # Examples
///
/// ```
- /// use fixed_decimal::FixedDecimal;
+ /// use fixed_decimal::{FixedDecimal, RoundingIncrement};
/// # use std::str::FromStr;
///
- /// let mut dec = FixedDecimal::from_str("-1.5").unwrap();
- /// dec.half_ceil(0);
- /// assert_eq!("-1", dec.to_string());
- /// let mut dec = FixedDecimal::from_str("0.4").unwrap();
- /// dec.half_ceil(0);
- /// assert_eq!("0", dec.to_string());
- /// let mut dec = FixedDecimal::from_str("0.5").unwrap();
+ /// let mut dec = FixedDecimal::from_str("-3.5").unwrap();
+ /// assert_eq!(
+ /// "-2",
+ /// dec.ceiled_to_increment(0, RoundingIncrement::MultiplesOf2)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("7.57").unwrap();
+ /// assert_eq!(
+ /// "8.0",
+ /// dec.ceiled_to_increment(-1, RoundingIncrement::MultiplesOf5)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("-5.45").unwrap();
+ /// assert_eq!(
+ /// "-5.25",
+ /// dec.ceiled_to_increment(-2, RoundingIncrement::MultiplesOf25)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("9.99").unwrap();
+ /// assert_eq!(
+ /// "10.0",
+ /// dec.ceiled_to_increment(-1, RoundingIncrement::MultiplesOf25)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("-9.99").unwrap();
+ /// assert_eq!(
+ /// "-9.98",
+ /// dec.ceiled_to_increment(-2, RoundingIncrement::MultiplesOf2)
+ /// .to_string()
+ /// );
+ /// ```
+ #[cfg(feature = "experimental")]
+ pub fn ceiled_to_increment(mut self, position: i16, increment: RoundingIncrement) -> Self {
+ self.ceil_to_increment(position, increment);
+ self
+ }
+
+ /// Take the half ceiling of the number at a particular position.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use fixed_decimal::FixedDecimal;
+ /// # use std::str::FromStr;
+ ///
+ /// let mut dec = FixedDecimal::from_str("-1.5").unwrap();
+ /// dec.half_ceil(0);
+ /// assert_eq!("-1", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("0.4").unwrap();
+ /// dec.half_ceil(0);
+ /// assert_eq!("0", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("0.5").unwrap();
/// dec.half_ceil(0);
/// assert_eq!("1", dec.to_string());
/// let mut dec = FixedDecimal::from_str("0.6").unwrap();
@@ -1999,6 +2430,19 @@ impl FixedDecimal {
/// assert_eq!("2", dec.to_string());
/// ```
pub fn half_ceil(&mut self, position: i16) {
+ #[cfg(feature = "experimental")]
+ {
+ self.half_ceil_to_increment(position, RoundingIncrement::MultiplesOf1);
+ }
+
+ #[cfg(not(feature = "experimental"))]
+ {
+ self.half_ceil_internal(position);
+ }
+ }
+
+ #[cfg(not(feature = "experimental"))]
+ fn half_ceil_internal(&mut self, position: i16) {
if self.sign == Sign::Negative {
self.half_trunc(position);
return;
@@ -2007,6 +2451,46 @@ impl FixedDecimal {
self.half_expand(position);
}
+ /// Take the half ceiling of the number at a particular position and rounding increment.
+ ///
+ ///
+ /// 🚧 This code is experimental; it may change at any time, in breaking or non-breaking ways,
+ /// including in SemVer minor releases. Use with caution.
+ ///
#3929
+ ///
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use fixed_decimal::{FixedDecimal, RoundingIncrement};
+ /// # use std::str::FromStr;
+ ///
+ /// let mut dec = FixedDecimal::from_str("-3.5").unwrap();
+ /// dec.half_ceil_to_increment(0, RoundingIncrement::MultiplesOf2);
+ /// assert_eq!("-4", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("7.57").unwrap();
+ /// dec.half_ceil_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ /// assert_eq!("7.5", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("-5.45").unwrap();
+ /// dec.half_ceil_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ /// assert_eq!("-5.50", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("9.99").unwrap();
+ /// dec.half_ceil_to_increment(-1, RoundingIncrement::MultiplesOf25);
+ /// assert_eq!("10.0", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("-9.99").unwrap();
+ /// dec.half_ceil_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ /// assert_eq!("-9.98", dec.to_string());
+ /// ```
+ #[cfg(feature = "experimental")]
+ pub fn half_ceil_to_increment(&mut self, position: i16, increment: RoundingIncrement) {
+ if self.sign == Sign::Negative {
+ self.half_trunc_to_increment(position, increment);
+ return;
+ }
+
+ self.half_expand_to_increment(position, increment);
+ }
+
/// Take the half ceiling of the number at a particular position.
///
/// # Examples
@@ -2031,6 +2515,57 @@ impl FixedDecimal {
self
}
+ /// Take the half ceiling of the number at a particular position and rounding increment.
+ ///
+ ///
+ /// 🚧 This code is experimental; it may change at any time, in breaking or non-breaking ways,
+ /// including in SemVer minor releases. Use with caution.
+ ///
#3929
+ ///
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use fixed_decimal::{FixedDecimal, RoundingIncrement};
+ /// # use std::str::FromStr;
+ ///
+ /// let mut dec = FixedDecimal::from_str("-3.5").unwrap();
+ /// assert_eq!(
+ /// "-4",
+ /// dec.half_ceiled_to_increment(0, RoundingIncrement::MultiplesOf2)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("7.57").unwrap();
+ /// assert_eq!(
+ /// "7.5",
+ /// dec.half_ceiled_to_increment(-1, RoundingIncrement::MultiplesOf5)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("-5.45").unwrap();
+ /// assert_eq!(
+ /// "-5.50",
+ /// dec.half_ceiled_to_increment(-2, RoundingIncrement::MultiplesOf25)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("9.99").unwrap();
+ /// assert_eq!(
+ /// "10.0",
+ /// dec.half_ceiled_to_increment(-1, RoundingIncrement::MultiplesOf25)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("-9.99").unwrap();
+ /// assert_eq!(
+ /// "-9.98",
+ /// dec.half_ceiled_to_increment(-2, RoundingIncrement::MultiplesOf2)
+ /// .to_string()
+ /// );
+ /// ```
+ #[cfg(feature = "experimental")]
+ pub fn half_ceiled_to_increment(mut self, position: i16, increment: RoundingIncrement) -> Self {
+ self.half_ceil_to_increment(position, increment);
+ self
+ }
+
/// Take the floor of the number at a particular position.
///
/// # Examples
@@ -2056,6 +2591,19 @@ impl FixedDecimal {
/// assert_eq!("1", dec.to_string());
/// ```
pub fn floor(&mut self, position: i16) {
+ #[cfg(feature = "experimental")]
+ {
+ self.floor_to_increment(position, RoundingIncrement::MultiplesOf1);
+ }
+
+ #[cfg(not(feature = "experimental"))]
+ {
+ self.floor_internal(position);
+ }
+ }
+
+ #[cfg(not(feature = "experimental"))]
+ pub fn floor_internal(&mut self, position: i16) {
if self.sign == Sign::Negative {
self.expand(position);
return;
@@ -2064,6 +2612,46 @@ impl FixedDecimal {
self.trunc(position);
}
+ /// Take the floor of the number at a particular position and rounding increment.
+ ///
+ ///
+ /// 🚧 This code is experimental; it may change at any time, in breaking or non-breaking ways,
+ /// including in SemVer minor releases. Use with caution.
+ ///
#3929
+ ///
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use fixed_decimal::{FixedDecimal, RoundingIncrement};
+ /// # use std::str::FromStr;
+ ///
+ /// let mut dec = FixedDecimal::from_str("-3.5").unwrap();
+ /// dec.floor_to_increment(0, RoundingIncrement::MultiplesOf2);
+ /// assert_eq!("-4", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("7.57").unwrap();
+ /// dec.floor_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ /// assert_eq!("7.5", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("-5.45").unwrap();
+ /// dec.floor_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ /// assert_eq!("-5.50", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("9.99").unwrap();
+ /// dec.floor_to_increment(-1, RoundingIncrement::MultiplesOf25);
+ /// assert_eq!("7.5", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("-9.99").unwrap();
+ /// dec.floor_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ /// assert_eq!("-10.00", dec.to_string());
+ /// ```
+ #[cfg(feature = "experimental")]
+ pub fn floor_to_increment(&mut self, position: i16, increment: RoundingIncrement) {
+ if self.sign == Sign::Negative {
+ self.expand_to_increment(position, increment);
+ return;
+ }
+
+ self.trunc_to_increment(position, increment);
+ }
+
/// Take the floor of the number at a particular position.
///
/// # Examples
@@ -2088,6 +2676,57 @@ impl FixedDecimal {
self
}
+ /// Take the floor of the number at a particular position and rounding increment.
+ ///
+ ///
+ /// 🚧 This code is experimental; it may change at any time, in breaking or non-breaking ways,
+ /// including in SemVer minor releases. Use with caution.
+ ///
#3929
+ ///
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use fixed_decimal::{FixedDecimal, RoundingIncrement};
+ /// # use std::str::FromStr;
+ ///
+ /// let mut dec = FixedDecimal::from_str("-3.5").unwrap();
+ /// assert_eq!(
+ /// "-4",
+ /// dec.floored_to_increment(0, RoundingIncrement::MultiplesOf2)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("7.57").unwrap();
+ /// assert_eq!(
+ /// "7.5",
+ /// dec.floored_to_increment(-1, RoundingIncrement::MultiplesOf5)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("-5.45").unwrap();
+ /// assert_eq!(
+ /// "-5.50",
+ /// dec.floored_to_increment(-2, RoundingIncrement::MultiplesOf25)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("9.99").unwrap();
+ /// assert_eq!(
+ /// "7.5",
+ /// dec.floored_to_increment(-1, RoundingIncrement::MultiplesOf25)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("-9.99").unwrap();
+ /// assert_eq!(
+ /// "-10.00",
+ /// dec.floored_to_increment(-2, RoundingIncrement::MultiplesOf2)
+ /// .to_string()
+ /// );
+ /// ```
+ #[cfg(feature = "experimental")]
+ pub fn floored_to_increment(mut self, position: i16, increment: RoundingIncrement) -> Self {
+ self.floor_to_increment(position, increment);
+ self
+ }
+
/// Take the half floor of the number at a particular position.
///
/// # Examples
@@ -2113,6 +2752,19 @@ impl FixedDecimal {
/// assert_eq!("1", dec.to_string());
/// ```
pub fn half_floor(&mut self, position: i16) {
+ #[cfg(feature = "experimental")]
+ {
+ self.half_floor_to_increment(position, RoundingIncrement::MultiplesOf1);
+ }
+
+ #[cfg(not(feature = "experimental"))]
+ {
+ self.half_floor_internal(position);
+ }
+ }
+
+ #[cfg(not(feature = "experimental"))]
+ fn half_floor_internal(&mut self, position: i16) {
if self.sign == Sign::Negative {
self.half_expand(position);
return;
@@ -2121,6 +2773,46 @@ impl FixedDecimal {
self.half_trunc(position);
}
+ /// Take the half floor of the number at a particular position and rounding increment.
+ ///
+ ///
+ /// 🚧 This code is experimental; it may change at any time, in breaking or non-breaking ways,
+ /// including in SemVer minor releases. Use with caution.
+ ///
#3929
+ ///
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use fixed_decimal::{FixedDecimal, RoundingIncrement};
+ /// # use std::str::FromStr;
+ ///
+ /// let mut dec = FixedDecimal::from_str("-3.5").unwrap();
+ /// dec.half_floor_to_increment(0, RoundingIncrement::MultiplesOf2);
+ /// assert_eq!("-4", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("7.57").unwrap();
+ /// dec.half_floor_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ /// assert_eq!("7.5", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("-5.45").unwrap();
+ /// dec.half_floor_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ /// assert_eq!("-5.50", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("9.99").unwrap();
+ /// dec.half_floor_to_increment(-1, RoundingIncrement::MultiplesOf25);
+ /// assert_eq!("10.0", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("-9.99").unwrap();
+ /// dec.half_floor_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ /// assert_eq!("-10.00", dec.to_string());
+ /// ```
+ #[cfg(feature = "experimental")]
+ pub fn half_floor_to_increment(&mut self, position: i16, increment: RoundingIncrement) {
+ if self.sign == Sign::Negative {
+ self.half_expand_to_increment(position, increment);
+ return;
+ }
+
+ self.half_trunc_to_increment(position, increment);
+ }
+
/// Take the half floor of the number at a particular position.
///
/// # Examples
@@ -2145,31 +2837,99 @@ impl FixedDecimal {
self
}
- /// Take the half even of the number at a particular position.
+ /// Take the half floor of the number at a particular position and rounding increment.
+ ///
+ ///
+ /// 🚧 This code is experimental; it may change at any time, in breaking or non-breaking ways,
+ /// including in SemVer minor releases. Use with caution.
+ ///
#3929
+ ///
///
/// # Examples
///
/// ```
- /// use fixed_decimal::FixedDecimal;
+ /// use fixed_decimal::{FixedDecimal, RoundingIncrement};
/// # use std::str::FromStr;
///
- /// let mut dec = FixedDecimal::from_str("-1.5").unwrap();
- /// dec.half_even(0);
- /// assert_eq!("-2", dec.to_string());
- /// let mut dec = FixedDecimal::from_str("0.4").unwrap();
- /// dec.half_even(0);
- /// assert_eq!("0", dec.to_string());
- /// let mut dec = FixedDecimal::from_str("0.5").unwrap();
- /// dec.half_even(0);
- /// assert_eq!("0", dec.to_string());
- /// let mut dec = FixedDecimal::from_str("0.6").unwrap();
- /// dec.half_even(0);
- /// assert_eq!("1", dec.to_string());
- /// let mut dec = FixedDecimal::from_str("1.5").unwrap();
- /// dec.half_even(0);
- /// assert_eq!("2", dec.to_string());
- /// ```
+ /// let mut dec = FixedDecimal::from_str("-3.5").unwrap();
+ /// assert_eq!(
+ /// "-4",
+ /// dec.half_floored_to_increment(0, RoundingIncrement::MultiplesOf2)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("7.57").unwrap();
+ /// assert_eq!(
+ /// "7.5",
+ /// dec.half_floored_to_increment(-1, RoundingIncrement::MultiplesOf5)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("-5.45").unwrap();
+ /// assert_eq!(
+ /// "-5.50",
+ /// dec.half_floored_to_increment(-2, RoundingIncrement::MultiplesOf25)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("9.99").unwrap();
+ /// assert_eq!(
+ /// "10.0",
+ /// dec.half_floored_to_increment(-1, RoundingIncrement::MultiplesOf25)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("-9.99").unwrap();
+ /// assert_eq!(
+ /// "-10.00",
+ /// dec.half_floored_to_increment(-2, RoundingIncrement::MultiplesOf2)
+ /// .to_string()
+ /// );
+ /// ```
+ #[cfg(feature = "experimental")]
+ pub fn half_floored_to_increment(
+ mut self,
+ position: i16,
+ increment: RoundingIncrement,
+ ) -> Self {
+ self.half_floor_to_increment(position, increment);
+ self
+ }
+
+ /// Take the half even of the number at a particular position.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use fixed_decimal::FixedDecimal;
+ /// # use std::str::FromStr;
+ ///
+ /// let mut dec = FixedDecimal::from_str("-1.5").unwrap();
+ /// dec.half_even(0);
+ /// assert_eq!("-2", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("0.4").unwrap();
+ /// dec.half_even(0);
+ /// assert_eq!("0", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("0.5").unwrap();
+ /// dec.half_even(0);
+ /// assert_eq!("0", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("0.6").unwrap();
+ /// dec.half_even(0);
+ /// assert_eq!("1", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("1.5").unwrap();
+ /// dec.half_even(0);
+ /// assert_eq!("2", dec.to_string());
+ /// ```
pub fn half_even(&mut self, position: i16) {
+ #[cfg(feature = "experimental")]
+ {
+ self.half_even_to_increment(position, RoundingIncrement::MultiplesOf1);
+ }
+
+ #[cfg(not(feature = "experimental"))]
+ {
+ self.half_even_internal(position);
+ }
+ }
+
+ #[cfg(not(feature = "experimental"))]
+ pub fn half_even_internal(&mut self, position: i16) {
let digit_after_position = self.digit_at_next_position(position);
let should_expand = match digit_after_position.cmp(&5) {
Ordering::Less => false,
@@ -2191,6 +2951,86 @@ impl FixedDecimal {
}
}
+ /// Take the half even of the number at a particular position and rounding increment.
+ ///
+ ///
+ /// 🚧 This code is experimental; it may change at any time, in breaking or non-breaking ways,
+ /// including in SemVer minor releases. Use with caution.
+ ///
#3929
+ ///
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use fixed_decimal::{FixedDecimal, RoundingIncrement};
+ /// # use std::str::FromStr;
+ ///
+ /// let mut dec = FixedDecimal::from_str("-3.5").unwrap();
+ /// dec.half_even_to_increment(0, RoundingIncrement::MultiplesOf2);
+ /// assert_eq!("-4", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("7.57").unwrap();
+ /// dec.half_even_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ /// assert_eq!("7.5", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("5.45").unwrap();
+ /// dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ /// assert_eq!("5.50", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("9.99").unwrap();
+ /// dec.half_even_to_increment(-1, RoundingIncrement::MultiplesOf25);
+ /// assert_eq!("10.0", dec.to_string());
+ /// let mut dec = FixedDecimal::from_str("9.99").unwrap();
+ /// dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ /// assert_eq!("10.00", dec.to_string());
+ /// ```
+ #[cfg(feature = "experimental")]
+ pub fn half_even_to_increment(&mut self, position: i16, increment: RoundingIncrement) {
+ let should_expand = match self.half_increment_at_magnitude(position, increment) {
+ Ordering::Greater => true,
+ Ordering::Less => false,
+ Ordering::Equal => match increment {
+ RoundingIncrement::MultiplesOf1 => {
+ // Expand if odd, truncate if even.
+ self.digit_at(position) & 0x01 == 1
+ }
+ RoundingIncrement::MultiplesOf2 => {
+ let current_digit = self.digit_at(position);
+ let previous_digit = self.digit_at_previous_position(position);
+ let full = previous_digit * 10 + current_digit;
+
+ // This essentially expands to the "even" increments,
+ // or the increments that are in the even places on the
+ // rounding range: [0, 4, 8, 12, 16, 20, ...].
+ // Equivalent to `(full / 2) is odd`.
+ //
+ // Examples:
+ // - 37 should truncate, since 37 % 20 = 17, which truncates to 16.
+ // 37 / 2 = 18, which is even.
+ // - 83 should expand, since 83 % 20 = 3, which expands to 4.
+ // 83 / 2 = 41, which is odd.
+ (full >> 1) & 0x01 == 1
+ }
+ RoundingIncrement::MultiplesOf5 => {
+ // Expand 7.5 to 10 and truncate 2.5 to 0.
+ self.digit_at(position) == 7
+ }
+ RoundingIncrement::MultiplesOf25 => {
+ let current_digit = self.digit_at(position);
+ let prev_digit = self.digit_at_previous_position(position);
+ let full_number = prev_digit * 10 + current_digit;
+
+ // Expand `37.5` to 50 and `87.5` to 100.
+ // Truncate `12.5` to 0 and `62.5` to 50.
+ full_number == 37 || full_number == 87
+ }
+ },
+ };
+
+ if should_expand {
+ self.expand_to_increment(position, increment);
+ } else {
+ self.trunc_to_increment(position, increment);
+ }
+ }
+
/// Take the half even of the number at a particular position.
///
/// # Examples
@@ -2215,6 +3055,57 @@ impl FixedDecimal {
self
}
+ /// Take the half even of the number at a particular position and rounding increment.
+ ///
+ ///
+ /// 🚧 This code is experimental; it may change at any time, in breaking or non-breaking ways,
+ /// including in SemVer minor releases. Use with caution.
+ ///
#3929
+ ///
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use fixed_decimal::{FixedDecimal, RoundingIncrement};
+ /// # use std::str::FromStr;
+ ///
+ /// let mut dec = FixedDecimal::from_str("-3.5").unwrap();
+ /// assert_eq!(
+ /// "-4",
+ /// dec.half_evened_to_increment(0, RoundingIncrement::MultiplesOf2)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("7.57").unwrap();
+ /// assert_eq!(
+ /// "7.5",
+ /// dec.half_evened_to_increment(-1, RoundingIncrement::MultiplesOf5)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("5.45").unwrap();
+ /// assert_eq!(
+ /// "5.50",
+ /// dec.half_evened_to_increment(-2, RoundingIncrement::MultiplesOf25)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("9.99").unwrap();
+ /// assert_eq!(
+ /// "10.0",
+ /// dec.half_evened_to_increment(-1, RoundingIncrement::MultiplesOf25)
+ /// .to_string()
+ /// );
+ /// let mut dec = FixedDecimal::from_str("9.99").unwrap();
+ /// assert_eq!(
+ /// "10.00",
+ /// dec.half_evened_to_increment(-2, RoundingIncrement::MultiplesOf2)
+ /// .to_string()
+ /// );
+ /// ```
+ #[cfg(feature = "experimental")]
+ pub fn half_evened_to_increment(mut self, position: i16, increment: RoundingIncrement) -> Self {
+ self.half_even_to_increment(position, increment);
+ self
+ }
+
/// Concatenate another `FixedDecimal` into the end of this `FixedDecimal`.
///
/// All nonzero digits in `other` must have lower magnitude than nonzero digits in `self`.
@@ -3993,267 +4884,715 @@ fn test_rounding() {
assert_eq!("2.79", dec.to_string());
}
-#[test]
-fn test_concatenate() {
- #[derive(Debug)]
- struct TestCase {
- pub input_1: &'static str,
- pub input_2: &'static str,
- pub expected: Option<&'static str>,
- }
- let cases = [
- TestCase {
- input_1: "123",
- input_2: "0.456",
- expected: Some("123.456"),
- },
- TestCase {
- input_1: "0.456",
- input_2: "123",
- expected: None,
- },
- TestCase {
- input_1: "123",
- input_2: "0.0456",
- expected: Some("123.0456"),
- },
- TestCase {
- input_1: "0.0456",
- input_2: "123",
- expected: None,
- },
- TestCase {
- input_1: "100",
- input_2: "0.456",
- expected: Some("100.456"),
- },
- TestCase {
- input_1: "0.456",
- input_2: "100",
- expected: None,
- },
- TestCase {
- input_1: "100",
- input_2: "0.001",
- expected: Some("100.001"),
- },
- TestCase {
- input_1: "0.001",
- input_2: "100",
- expected: None,
- },
- TestCase {
- input_1: "123000",
- input_2: "456",
- expected: Some("123456"),
- },
- TestCase {
- input_1: "456",
- input_2: "123000",
- expected: None,
- },
- TestCase {
- input_1: "5",
- input_2: "5",
- expected: None,
- },
- TestCase {
- input_1: "120",
- input_2: "25",
- expected: None,
- },
- TestCase {
- input_1: "1.1",
- input_2: "0.2",
- expected: None,
- },
- TestCase {
- input_1: "0",
- input_2: "222",
- expected: Some("222"),
- },
- TestCase {
- input_1: "222",
- input_2: "0",
- expected: Some("222"),
- },
- TestCase {
- input_1: "0",
- input_2: "0",
- expected: Some("0"),
- },
- TestCase {
- input_1: "000",
- input_2: "0",
- expected: Some("000"),
- },
- TestCase {
- input_1: "0.00",
- input_2: "0",
- expected: Some("0.00"),
- },
- ];
- for cas in &cases {
- let fd1 = FixedDecimal::from_str(cas.input_1).unwrap();
- let fd2 = FixedDecimal::from_str(cas.input_2).unwrap();
- match fd1.concatenated_end(fd2) {
- Ok(fd) => {
- assert_eq!(cas.expected, Some(fd.to_string().as_str()), "{cas:?}");
- }
- Err(_) => {
- assert!(cas.expected.is_none(), "{cas:?}");
- }
- }
- }
-}
+#[test]
+fn test_concatenate() {
+ #[derive(Debug)]
+ struct TestCase {
+ pub input_1: &'static str,
+ pub input_2: &'static str,
+ pub expected: Option<&'static str>,
+ }
+ let cases = [
+ TestCase {
+ input_1: "123",
+ input_2: "0.456",
+ expected: Some("123.456"),
+ },
+ TestCase {
+ input_1: "0.456",
+ input_2: "123",
+ expected: None,
+ },
+ TestCase {
+ input_1: "123",
+ input_2: "0.0456",
+ expected: Some("123.0456"),
+ },
+ TestCase {
+ input_1: "0.0456",
+ input_2: "123",
+ expected: None,
+ },
+ TestCase {
+ input_1: "100",
+ input_2: "0.456",
+ expected: Some("100.456"),
+ },
+ TestCase {
+ input_1: "0.456",
+ input_2: "100",
+ expected: None,
+ },
+ TestCase {
+ input_1: "100",
+ input_2: "0.001",
+ expected: Some("100.001"),
+ },
+ TestCase {
+ input_1: "0.001",
+ input_2: "100",
+ expected: None,
+ },
+ TestCase {
+ input_1: "123000",
+ input_2: "456",
+ expected: Some("123456"),
+ },
+ TestCase {
+ input_1: "456",
+ input_2: "123000",
+ expected: None,
+ },
+ TestCase {
+ input_1: "5",
+ input_2: "5",
+ expected: None,
+ },
+ TestCase {
+ input_1: "120",
+ input_2: "25",
+ expected: None,
+ },
+ TestCase {
+ input_1: "1.1",
+ input_2: "0.2",
+ expected: None,
+ },
+ TestCase {
+ input_1: "0",
+ input_2: "222",
+ expected: Some("222"),
+ },
+ TestCase {
+ input_1: "222",
+ input_2: "0",
+ expected: Some("222"),
+ },
+ TestCase {
+ input_1: "0",
+ input_2: "0",
+ expected: Some("0"),
+ },
+ TestCase {
+ input_1: "000",
+ input_2: "0",
+ expected: Some("000"),
+ },
+ TestCase {
+ input_1: "0.00",
+ input_2: "0",
+ expected: Some("0.00"),
+ },
+ ];
+ for cas in &cases {
+ let fd1 = FixedDecimal::from_str(cas.input_1).unwrap();
+ let fd2 = FixedDecimal::from_str(cas.input_2).unwrap();
+ match fd1.concatenated_end(fd2) {
+ Ok(fd) => {
+ assert_eq!(cas.expected, Some(fd.to_string().as_str()), "{cas:?}");
+ }
+ Err(_) => {
+ assert!(cas.expected.is_none(), "{cas:?}");
+ }
+ }
+ }
+}
+
+#[test]
+#[cfg(feature = "experimental")]
+fn test_rounding_increment() {
+ // Test Truncate Right
+ let mut dec = FixedDecimal::from(4235970).multiplied_pow10(-3);
+ assert_eq!("4235.970", dec.to_string());
+
+ dec.trunc_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("4235.96", dec.to_string());
+
+ dec.trunc_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ assert_eq!("4235.5", dec.to_string());
+
+ dec.trunc_to_increment(0, RoundingIncrement::MultiplesOf25);
+ assert_eq!("4225", dec.to_string());
+
+ dec.trunc_to_increment(5, RoundingIncrement::MultiplesOf5);
+ assert_eq!("00000", dec.to_string());
+
+ dec.trunc_to_increment(2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("00000", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("-99.999").unwrap();
+ dec.trunc_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("-99.75", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("1234.56").unwrap();
+ dec.trunc_to_increment(-1, RoundingIncrement::MultiplesOf2);
+ assert_eq!("1234.4", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.009").unwrap();
+ dec.trunc_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ assert_eq!("0.0", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.60").unwrap();
+ dec.trunc_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("0.50", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.40").unwrap();
+ dec.trunc_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("0.25", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.7000000099").unwrap();
+ dec.trunc_to_increment(-3, RoundingIncrement::MultiplesOf2);
+ assert_eq!("0.700", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("5").unwrap();
+ dec.trunc_to_increment(0, RoundingIncrement::MultiplesOf25);
+ assert_eq!("0", dec.to_string());
+
+ let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MIN);
+ dec.trunc_to_increment(i16::MIN, RoundingIncrement::MultiplesOf2);
+ assert_eq!(FixedDecimal::from(6).multiplied_pow10(i16::MIN), dec);
+
+ let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MIN);
+ dec.trunc_to_increment(i16::MIN, RoundingIncrement::MultiplesOf5);
+ assert_eq!(FixedDecimal::from(5).multiplied_pow10(i16::MIN), dec);
+
+ let mut dec = FixedDecimal::from(70).multiplied_pow10(i16::MIN);
+ dec.trunc_to_increment(i16::MIN, RoundingIncrement::MultiplesOf25);
+ assert_eq!(FixedDecimal::from(50).multiplied_pow10(i16::MIN), dec);
+
+ let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX);
+ dec.trunc_to_increment(i16::MAX, RoundingIncrement::MultiplesOf2);
+ assert_eq!(FixedDecimal::from(6).multiplied_pow10(i16::MAX), dec);
+
+ let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX);
+ dec.trunc_to_increment(i16::MAX, RoundingIncrement::MultiplesOf5);
+ assert_eq!(FixedDecimal::from(5).multiplied_pow10(i16::MAX), dec);
+
+ let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX);
+ dec.trunc_to_increment(i16::MAX, RoundingIncrement::MultiplesOf25);
+ assert_eq!(FixedDecimal::from(0).multiplied_pow10(i16::MAX), dec);
+
+ // Test Expand
+ let mut dec = FixedDecimal::from(4235970).multiplied_pow10(-3);
+ assert_eq!("4235.970", dec.to_string());
+
+ dec.expand_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("4235.98", dec.to_string());
+
+ dec.expand_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ assert_eq!("4236.0", dec.to_string());
+
+ dec.expand_to_increment(0, RoundingIncrement::MultiplesOf25);
+ assert_eq!("4250", dec.to_string());
+
+ dec.expand_to_increment(5, RoundingIncrement::MultiplesOf5);
+ assert_eq!("500000", dec.to_string());
+
+ dec.expand_to_increment(2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("500000", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("-99.999").unwrap();
+ dec.expand_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("-100.00", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("1234.56").unwrap();
+ dec.expand_to_increment(-1, RoundingIncrement::MultiplesOf2);
+ assert_eq!("1234.6", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.009").unwrap();
+ dec.expand_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ assert_eq!("0.5", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.60").unwrap();
+ dec.expand_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("0.75", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.40").unwrap();
+ dec.expand_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("0.50", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.7000000099").unwrap();
+ dec.expand_to_increment(-3, RoundingIncrement::MultiplesOf2);
+ assert_eq!("0.702", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("5").unwrap();
+ dec.expand_to_increment(0, RoundingIncrement::MultiplesOf25);
+ assert_eq!("25", dec.to_string());
+
+ let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MIN);
+ dec.expand_to_increment(i16::MIN, RoundingIncrement::MultiplesOf2);
+ assert_eq!(FixedDecimal::from(8).multiplied_pow10(i16::MIN), dec);
+
+ let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MIN);
+ dec.expand_to_increment(i16::MIN, RoundingIncrement::MultiplesOf5);
+ assert_eq!(FixedDecimal::from(10).multiplied_pow10(i16::MIN), dec);
+
+ let mut dec = FixedDecimal::from(70).multiplied_pow10(i16::MIN);
+ dec.expand_to_increment(i16::MIN, RoundingIncrement::MultiplesOf25);
+ assert_eq!(FixedDecimal::from(75).multiplied_pow10(i16::MIN), dec);
+
+ let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX);
+ dec.expand_to_increment(i16::MAX, RoundingIncrement::MultiplesOf2);
+ assert_eq!(FixedDecimal::from(8).multiplied_pow10(i16::MAX), dec);
+
+ let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX);
+ dec.expand_to_increment(i16::MAX, RoundingIncrement::MultiplesOf5);
+ assert_eq!(FixedDecimal::from(0).multiplied_pow10(i16::MAX), dec);
+
+ let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX);
+ dec.expand_to_increment(i16::MAX, RoundingIncrement::MultiplesOf25);
+ assert_eq!(FixedDecimal::from(0).multiplied_pow10(i16::MAX), dec);
+
+ // Test Half Truncate Right
+ let mut dec = FixedDecimal::from(4235970).multiplied_pow10(-3);
+ assert_eq!("4235.970", dec.to_string());
+
+ dec.half_trunc_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("4235.96", dec.to_string());
+
+ dec.half_trunc_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ assert_eq!("4236.0", dec.to_string());
+
+ dec.half_trunc_to_increment(0, RoundingIncrement::MultiplesOf25);
+ assert_eq!("4225", dec.to_string());
+
+ dec.half_trunc_to_increment(5, RoundingIncrement::MultiplesOf5);
+ assert_eq!("00000", dec.to_string());
+
+ dec.half_trunc_to_increment(2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("00000", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("-99.999").unwrap();
+ dec.half_trunc_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("-100.00", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("1234.56").unwrap();
+ dec.half_trunc_to_increment(-1, RoundingIncrement::MultiplesOf2);
+ assert_eq!("1234.6", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.009").unwrap();
+ dec.half_trunc_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ assert_eq!("0.0", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.60").unwrap();
+ dec.half_trunc_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("0.50", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.40").unwrap();
+ dec.half_trunc_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("0.50", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.7000000099").unwrap();
+ dec.half_trunc_to_increment(-3, RoundingIncrement::MultiplesOf2);
+ assert_eq!("0.700", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("5").unwrap();
+ dec.half_trunc_to_increment(0, RoundingIncrement::MultiplesOf25);
+ assert_eq!("0", dec.to_string());
+
+ let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MIN);
+ dec.half_trunc_to_increment(i16::MIN, RoundingIncrement::MultiplesOf2);
+ assert_eq!(FixedDecimal::from(6).multiplied_pow10(i16::MIN), dec);
+
+ let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MIN);
+ dec.half_trunc_to_increment(i16::MIN, RoundingIncrement::MultiplesOf5);
+ assert_eq!(FixedDecimal::from(10).multiplied_pow10(i16::MIN), dec);
+
+ let mut dec = FixedDecimal::from(70).multiplied_pow10(i16::MIN);
+ dec.half_trunc_to_increment(i16::MIN, RoundingIncrement::MultiplesOf25);
+ assert_eq!(FixedDecimal::from(75).multiplied_pow10(i16::MIN), dec);
+
+ let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX);
+ dec.half_trunc_to_increment(i16::MAX, RoundingIncrement::MultiplesOf2);
+ assert_eq!(FixedDecimal::from(6).multiplied_pow10(i16::MAX), dec);
+
+ let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX);
+ dec.half_trunc_to_increment(i16::MAX, RoundingIncrement::MultiplesOf5);
+ assert_eq!(FixedDecimal::from(5).multiplied_pow10(i16::MAX), dec);
+
+ let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX);
+ dec.half_trunc_to_increment(i16::MAX, RoundingIncrement::MultiplesOf25);
+ assert_eq!(FixedDecimal::from(0).multiplied_pow10(i16::MAX), dec);
+
+ // Test Half Expand
+ let mut dec = FixedDecimal::from(4235970).multiplied_pow10(-3);
+ assert_eq!("4235.970", dec.to_string());
+
+ dec.half_expand_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("4235.98", dec.to_string());
+
+ dec.half_expand_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ assert_eq!("4236.0", dec.to_string());
+
+ dec.half_expand_to_increment(0, RoundingIncrement::MultiplesOf25);
+ assert_eq!("4225", dec.to_string());
+
+ dec.half_expand_to_increment(5, RoundingIncrement::MultiplesOf5);
+ assert_eq!("00000", dec.to_string());
+
+ dec.half_expand_to_increment(2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("00000", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("-99.999").unwrap();
+ dec.half_expand_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("-100.00", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("1234.56").unwrap();
+ dec.half_expand_to_increment(-1, RoundingIncrement::MultiplesOf2);
+ assert_eq!("1234.6", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.009").unwrap();
+ dec.half_expand_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ assert_eq!("0.0", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.60").unwrap();
+ dec.half_expand_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("0.50", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.40").unwrap();
+ dec.half_expand_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("0.50", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.7000000099").unwrap();
+ dec.half_expand_to_increment(-3, RoundingIncrement::MultiplesOf2);
+ assert_eq!("0.700", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("5").unwrap();
+ dec.half_expand_to_increment(0, RoundingIncrement::MultiplesOf25);
+ assert_eq!("0", dec.to_string());
+
+ let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MIN);
+ dec.half_expand_to_increment(i16::MIN, RoundingIncrement::MultiplesOf2);
+ assert_eq!(FixedDecimal::from(8).multiplied_pow10(i16::MIN), dec);
+
+ let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MIN);
+ dec.half_expand_to_increment(i16::MIN, RoundingIncrement::MultiplesOf5);
+ assert_eq!(FixedDecimal::from(10).multiplied_pow10(i16::MIN), dec);
+
+ let mut dec = FixedDecimal::from(70).multiplied_pow10(i16::MIN);
+ dec.half_expand_to_increment(i16::MIN, RoundingIncrement::MultiplesOf25);
+ assert_eq!(FixedDecimal::from(75).multiplied_pow10(i16::MIN), dec);
+
+ let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX);
+ dec.half_expand_to_increment(i16::MAX, RoundingIncrement::MultiplesOf2);
+ assert_eq!(FixedDecimal::from(8).multiplied_pow10(i16::MAX), dec);
+
+ // Test Ceil
+ let mut dec = FixedDecimal::from(4235970).multiplied_pow10(-3);
+ assert_eq!("4235.970", dec.to_string());
+
+ dec.ceil_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("4235.98", dec.to_string());
+
+ dec.ceil_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ assert_eq!("4236.0", dec.to_string());
+
+ dec.ceil_to_increment(0, RoundingIncrement::MultiplesOf25);
+ assert_eq!("4250", dec.to_string());
+
+ dec.ceil_to_increment(5, RoundingIncrement::MultiplesOf5);
+ assert_eq!("500000", dec.to_string());
+
+ dec.ceil_to_increment(2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("500000", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("-99.999").unwrap();
+ dec.ceil_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("-99.75", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("1234.56").unwrap();
+ dec.ceil_to_increment(-1, RoundingIncrement::MultiplesOf2);
+ assert_eq!("1234.6", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.009").unwrap();
+ dec.ceil_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ assert_eq!("0.5", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.60").unwrap();
+ dec.ceil_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("0.75", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.40").unwrap();
+ dec.ceil_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("0.50", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.7000000099").unwrap();
+ dec.ceil_to_increment(-3, RoundingIncrement::MultiplesOf2);
+ assert_eq!("0.702", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("5").unwrap();
+ dec.ceil_to_increment(0, RoundingIncrement::MultiplesOf25);
+ assert_eq!("25", dec.to_string());
+
+ let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MIN);
+ dec.ceil_to_increment(i16::MIN, RoundingIncrement::MultiplesOf2);
+ assert_eq!(FixedDecimal::from(8).multiplied_pow10(i16::MIN), dec);
+
+ let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MIN);
+ dec.ceil_to_increment(i16::MIN, RoundingIncrement::MultiplesOf5);
+ assert_eq!(FixedDecimal::from(10).multiplied_pow10(i16::MIN), dec);
+
+ let mut dec = FixedDecimal::from(70).multiplied_pow10(i16::MIN);
+ dec.ceil_to_increment(i16::MIN, RoundingIncrement::MultiplesOf25);
+ assert_eq!(FixedDecimal::from(75).multiplied_pow10(i16::MIN), dec);
+
+ let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX);
+ dec.ceil_to_increment(i16::MAX, RoundingIncrement::MultiplesOf2);
+ assert_eq!(FixedDecimal::from(8).multiplied_pow10(i16::MAX), dec);
+
+ // Test Half Ceil
+ let mut dec = FixedDecimal::from(4235970).multiplied_pow10(-3);
+ assert_eq!("4235.970", dec.to_string());
+
+ dec.half_ceil_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("4235.98", dec.to_string());
+
+ dec.half_ceil_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ assert_eq!("4236.0", dec.to_string());
+
+ dec.half_ceil_to_increment(0, RoundingIncrement::MultiplesOf25);
+ assert_eq!("4225", dec.to_string());
+
+ dec.half_ceil_to_increment(5, RoundingIncrement::MultiplesOf5);
+ assert_eq!("00000", dec.to_string());
+
+ dec.half_ceil_to_increment(2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("00000", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("-99.999").unwrap();
+ dec.half_ceil_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("-100.00", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("1234.56").unwrap();
+ dec.half_ceil_to_increment(-1, RoundingIncrement::MultiplesOf2);
+ assert_eq!("1234.6", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.009").unwrap();
+ dec.half_ceil_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ assert_eq!("0.0", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.60").unwrap();
+ dec.half_ceil_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("0.50", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.40").unwrap();
+ dec.half_ceil_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("0.50", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.7000000099").unwrap();
+ dec.half_ceil_to_increment(-3, RoundingIncrement::MultiplesOf2);
+ assert_eq!("0.700", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("5").unwrap();
+ dec.half_ceil_to_increment(0, RoundingIncrement::MultiplesOf25);
+ assert_eq!("0", dec.to_string());
+
+ let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MIN);
+ dec.half_ceil_to_increment(i16::MIN, RoundingIncrement::MultiplesOf2);
+ assert_eq!(FixedDecimal::from(8).multiplied_pow10(i16::MIN), dec);
+
+ let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MIN);
+ dec.half_ceil_to_increment(i16::MIN, RoundingIncrement::MultiplesOf5);
+ assert_eq!(FixedDecimal::from(10).multiplied_pow10(i16::MIN), dec);
+
+ let mut dec = FixedDecimal::from(70).multiplied_pow10(i16::MIN);
+ dec.half_ceil_to_increment(i16::MIN, RoundingIncrement::MultiplesOf25);
+ assert_eq!(FixedDecimal::from(75).multiplied_pow10(i16::MIN), dec);
-#[test]
-#[cfg(feature = "experimental")]
-fn test_rounding_increment() {
- // Test Truncate Right
+ let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX);
+ dec.half_ceil_to_increment(i16::MAX, RoundingIncrement::MultiplesOf2);
+ assert_eq!(FixedDecimal::from(8).multiplied_pow10(i16::MAX), dec);
+
+ // Test Floor
let mut dec = FixedDecimal::from(4235970).multiplied_pow10(-3);
assert_eq!("4235.970", dec.to_string());
- dec.trunc_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ dec.floor_to_increment(-2, RoundingIncrement::MultiplesOf2);
assert_eq!("4235.96", dec.to_string());
- dec.trunc_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ dec.floor_to_increment(-1, RoundingIncrement::MultiplesOf5);
assert_eq!("4235.5", dec.to_string());
- dec.trunc_to_increment(0, RoundingIncrement::MultiplesOf25);
+ dec.floor_to_increment(0, RoundingIncrement::MultiplesOf25);
assert_eq!("4225", dec.to_string());
- dec.trunc_to_increment(5, RoundingIncrement::MultiplesOf5);
+ dec.floor_to_increment(5, RoundingIncrement::MultiplesOf5);
assert_eq!("00000", dec.to_string());
- dec.trunc_to_increment(2, RoundingIncrement::MultiplesOf2);
+ dec.floor_to_increment(2, RoundingIncrement::MultiplesOf2);
assert_eq!("00000", dec.to_string());
let mut dec = FixedDecimal::from_str("-99.999").unwrap();
- dec.trunc_to_increment(-2, RoundingIncrement::MultiplesOf25);
- assert_eq!("-99.75", dec.to_string());
+ dec.floor_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("-100.00", dec.to_string());
let mut dec = FixedDecimal::from_str("1234.56").unwrap();
- dec.trunc_to_increment(-1, RoundingIncrement::MultiplesOf2);
+ dec.floor_to_increment(-1, RoundingIncrement::MultiplesOf2);
assert_eq!("1234.4", dec.to_string());
let mut dec = FixedDecimal::from_str("0.009").unwrap();
- dec.trunc_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ dec.floor_to_increment(-1, RoundingIncrement::MultiplesOf5);
assert_eq!("0.0", dec.to_string());
let mut dec = FixedDecimal::from_str("0.60").unwrap();
- dec.trunc_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ dec.floor_to_increment(-2, RoundingIncrement::MultiplesOf25);
assert_eq!("0.50", dec.to_string());
let mut dec = FixedDecimal::from_str("0.40").unwrap();
- dec.trunc_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ dec.floor_to_increment(-2, RoundingIncrement::MultiplesOf25);
assert_eq!("0.25", dec.to_string());
let mut dec = FixedDecimal::from_str("0.7000000099").unwrap();
- dec.trunc_to_increment(-3, RoundingIncrement::MultiplesOf2);
+ dec.floor_to_increment(-3, RoundingIncrement::MultiplesOf2);
assert_eq!("0.700", dec.to_string());
let mut dec = FixedDecimal::from_str("5").unwrap();
- dec.trunc_to_increment(0, RoundingIncrement::MultiplesOf25);
+ dec.floor_to_increment(0, RoundingIncrement::MultiplesOf25);
assert_eq!("0", dec.to_string());
let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MIN);
- dec.trunc_to_increment(i16::MIN, RoundingIncrement::MultiplesOf2);
+ dec.floor_to_increment(i16::MIN, RoundingIncrement::MultiplesOf2);
assert_eq!(FixedDecimal::from(6).multiplied_pow10(i16::MIN), dec);
let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MIN);
- dec.trunc_to_increment(i16::MIN, RoundingIncrement::MultiplesOf5);
+ dec.floor_to_increment(i16::MIN, RoundingIncrement::MultiplesOf5);
assert_eq!(FixedDecimal::from(5).multiplied_pow10(i16::MIN), dec);
let mut dec = FixedDecimal::from(70).multiplied_pow10(i16::MIN);
- dec.trunc_to_increment(i16::MIN, RoundingIncrement::MultiplesOf25);
+ dec.floor_to_increment(i16::MIN, RoundingIncrement::MultiplesOf25);
assert_eq!(FixedDecimal::from(50).multiplied_pow10(i16::MIN), dec);
let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX);
- dec.trunc_to_increment(i16::MAX, RoundingIncrement::MultiplesOf2);
+ dec.floor_to_increment(i16::MAX, RoundingIncrement::MultiplesOf2);
assert_eq!(FixedDecimal::from(6).multiplied_pow10(i16::MAX), dec);
- let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX);
- dec.trunc_to_increment(i16::MAX, RoundingIncrement::MultiplesOf5);
- assert_eq!(FixedDecimal::from(5).multiplied_pow10(i16::MAX), dec);
+ // Test Half Floor
+ let mut dec = FixedDecimal::from(4235970).multiplied_pow10(-3);
+ assert_eq!("4235.970", dec.to_string());
+
+ dec.half_floor_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("4235.96", dec.to_string());
+
+ dec.half_floor_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ assert_eq!("4236.0", dec.to_string());
+
+ dec.half_floor_to_increment(0, RoundingIncrement::MultiplesOf25);
+ assert_eq!("4225", dec.to_string());
+
+ dec.half_floor_to_increment(5, RoundingIncrement::MultiplesOf5);
+ assert_eq!("00000", dec.to_string());
+
+ dec.half_floor_to_increment(2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("00000", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("-99.999").unwrap();
+ dec.half_floor_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("-100.00", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("1234.56").unwrap();
+ dec.half_floor_to_increment(-1, RoundingIncrement::MultiplesOf2);
+ assert_eq!("1234.6", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.009").unwrap();
+ dec.half_floor_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ assert_eq!("0.0", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.60").unwrap();
+ dec.half_floor_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("0.50", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.40").unwrap();
+ dec.half_floor_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("0.50", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("0.7000000099").unwrap();
+ dec.half_floor_to_increment(-3, RoundingIncrement::MultiplesOf2);
+ assert_eq!("0.700", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("5").unwrap();
+ dec.half_floor_to_increment(0, RoundingIncrement::MultiplesOf25);
+ assert_eq!("0", dec.to_string());
+
+ let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MIN);
+ dec.half_floor_to_increment(i16::MIN, RoundingIncrement::MultiplesOf2);
+ assert_eq!(FixedDecimal::from(6).multiplied_pow10(i16::MIN), dec);
+
+ let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MIN);
+ dec.half_floor_to_increment(i16::MIN, RoundingIncrement::MultiplesOf5);
+ assert_eq!(FixedDecimal::from(10).multiplied_pow10(i16::MIN), dec);
+
+ let mut dec = FixedDecimal::from(70).multiplied_pow10(i16::MIN);
+ dec.half_floor_to_increment(i16::MIN, RoundingIncrement::MultiplesOf25);
+ assert_eq!(FixedDecimal::from(75).multiplied_pow10(i16::MIN), dec);
let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX);
- dec.trunc_to_increment(i16::MAX, RoundingIncrement::MultiplesOf25);
- assert_eq!(FixedDecimal::from(0).multiplied_pow10(i16::MAX), dec);
+ dec.half_floor_to_increment(i16::MAX, RoundingIncrement::MultiplesOf2);
+ assert_eq!(FixedDecimal::from(6).multiplied_pow10(i16::MAX), dec);
- // Test Expand
+ // Test Half Even
let mut dec = FixedDecimal::from(4235970).multiplied_pow10(-3);
assert_eq!("4235.970", dec.to_string());
- dec.expand_to_increment(-2, RoundingIncrement::MultiplesOf2);
- assert_eq!("4235.98", dec.to_string());
+ dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("4235.96", dec.to_string());
- dec.expand_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ dec.half_even_to_increment(-1, RoundingIncrement::MultiplesOf5);
assert_eq!("4236.0", dec.to_string());
- dec.expand_to_increment(0, RoundingIncrement::MultiplesOf25);
- assert_eq!("4250", dec.to_string());
+ dec.half_even_to_increment(0, RoundingIncrement::MultiplesOf25);
+ assert_eq!("4225", dec.to_string());
- dec.expand_to_increment(5, RoundingIncrement::MultiplesOf5);
- assert_eq!("500000", dec.to_string());
+ dec.half_even_to_increment(5, RoundingIncrement::MultiplesOf5);
+ assert_eq!("00000", dec.to_string());
- dec.expand_to_increment(2, RoundingIncrement::MultiplesOf2);
- assert_eq!("500000", dec.to_string());
+ dec.half_even_to_increment(2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("00000", dec.to_string());
let mut dec = FixedDecimal::from_str("-99.999").unwrap();
- dec.expand_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf25);
assert_eq!("-100.00", dec.to_string());
let mut dec = FixedDecimal::from_str("1234.56").unwrap();
- dec.expand_to_increment(-1, RoundingIncrement::MultiplesOf2);
+ dec.half_even_to_increment(-1, RoundingIncrement::MultiplesOf2);
assert_eq!("1234.6", dec.to_string());
let mut dec = FixedDecimal::from_str("0.009").unwrap();
- dec.expand_to_increment(-1, RoundingIncrement::MultiplesOf5);
- assert_eq!("0.5", dec.to_string());
+ dec.half_even_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ assert_eq!("0.0", dec.to_string());
let mut dec = FixedDecimal::from_str("0.60").unwrap();
- dec.expand_to_increment(-2, RoundingIncrement::MultiplesOf25);
- assert_eq!("0.75", dec.to_string());
+ dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("0.50", dec.to_string());
let mut dec = FixedDecimal::from_str("0.40").unwrap();
- dec.expand_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf25);
assert_eq!("0.50", dec.to_string());
let mut dec = FixedDecimal::from_str("0.7000000099").unwrap();
- dec.expand_to_increment(-3, RoundingIncrement::MultiplesOf2);
- assert_eq!("0.702", dec.to_string());
+ dec.half_even_to_increment(-3, RoundingIncrement::MultiplesOf2);
+ assert_eq!("0.700", dec.to_string());
let mut dec = FixedDecimal::from_str("5").unwrap();
- dec.expand_to_increment(0, RoundingIncrement::MultiplesOf25);
- assert_eq!("25", dec.to_string());
+ dec.half_even_to_increment(0, RoundingIncrement::MultiplesOf25);
+ assert_eq!("0", dec.to_string());
let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MIN);
- dec.expand_to_increment(i16::MIN, RoundingIncrement::MultiplesOf2);
+ dec.half_even_to_increment(i16::MIN, RoundingIncrement::MultiplesOf2);
assert_eq!(FixedDecimal::from(8).multiplied_pow10(i16::MIN), dec);
let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MIN);
- dec.expand_to_increment(i16::MIN, RoundingIncrement::MultiplesOf5);
+ dec.half_even_to_increment(i16::MIN, RoundingIncrement::MultiplesOf5);
assert_eq!(FixedDecimal::from(10).multiplied_pow10(i16::MIN), dec);
let mut dec = FixedDecimal::from(70).multiplied_pow10(i16::MIN);
- dec.expand_to_increment(i16::MIN, RoundingIncrement::MultiplesOf25);
+ dec.half_even_to_increment(i16::MIN, RoundingIncrement::MultiplesOf25);
assert_eq!(FixedDecimal::from(75).multiplied_pow10(i16::MIN), dec);
let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX);
- dec.expand_to_increment(i16::MAX, RoundingIncrement::MultiplesOf2);
+ dec.half_even_to_increment(i16::MAX, RoundingIncrement::MultiplesOf2);
assert_eq!(FixedDecimal::from(8).multiplied_pow10(i16::MAX), dec);
- let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX);
- dec.expand_to_increment(i16::MAX, RoundingIncrement::MultiplesOf5);
- assert_eq!(FixedDecimal::from(0).multiplied_pow10(i16::MAX), dec);
-
- let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX);
- dec.expand_to_increment(i16::MAX, RoundingIncrement::MultiplesOf25);
- assert_eq!(FixedDecimal::from(0).multiplied_pow10(i16::MAX), dec);
-
// Test specific cases
-
let mut dec = FixedDecimal::from_str("1.108").unwrap();
dec.expand_to_increment(-2, RoundingIncrement::MultiplesOf2);
assert_eq!("1.12", dec.to_string());
@@ -4369,4 +5708,88 @@ fn test_rounding_increment() {
let mut dec = FixedDecimal::from_str("0.50").unwrap();
dec.expand_to_increment(-2, RoundingIncrement::MultiplesOf25);
assert_eq!("0.50", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("1.1025").unwrap();
+ dec.half_trunc_to_increment(-3, RoundingIncrement::MultiplesOf5);
+ assert_eq!("1.100", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("1.10125").unwrap();
+ dec.half_expand_to_increment(-4, RoundingIncrement::MultiplesOf25);
+ assert_eq!("1.1025", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("-1.25").unwrap();
+ dec.half_ceil_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ assert_eq!("-1.0", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("-1.251").unwrap();
+ dec.half_ceil_to_increment(-1, RoundingIncrement::MultiplesOf5);
+ assert_eq!("-1.5", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("-1.125").unwrap();
+ dec.half_floor_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("-1.25", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("2.71").unwrap();
+ dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("2.72", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("2.73").unwrap();
+ dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("2.72", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("2.75").unwrap();
+ dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("2.76", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("2.77").unwrap();
+ dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("2.76", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("2.79").unwrap();
+ dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("2.80", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("2.41").unwrap();
+ dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("2.40", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("2.43").unwrap();
+ dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("2.44", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("2.45").unwrap();
+ dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("2.44", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("2.47").unwrap();
+ dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("2.48", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("2.49").unwrap();
+ dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf2);
+ assert_eq!("2.48", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("2.725").unwrap();
+ dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf5);
+ assert_eq!("2.70", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("2.775").unwrap();
+ dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf5);
+ assert_eq!("2.80", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("2.875").unwrap();
+ dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("3.00", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("2.375").unwrap();
+ dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("2.50", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("2.125").unwrap();
+ dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("2.00", dec.to_string());
+
+ let mut dec = FixedDecimal::from_str("2.625").unwrap();
+ dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf25);
+ assert_eq!("2.50", dec.to_string());
}
diff --git a/utils/fixed_decimal/tests/rounding.rs b/utils/fixed_decimal/tests/rounding.rs
index a02bf5e2aba..6d403bdfa30 100644
--- a/utils/fixed_decimal/tests/rounding.rs
+++ b/utils/fixed_decimal/tests/rounding.rs
@@ -336,3 +336,90 @@ pub fn extra_rounding_mode_cases() {
}
}
}
+
+#[test]
+#[cfg(feature = "experimental")]
+pub fn test_ecma402_table_with_increments() {
+ use fixed_decimal::RoundingIncrement;
+
+ #[rustfmt::skip] // Don't split everything on its own line. Makes it look a lot nicer.
+ #[allow(clippy::type_complexity)]
+ let cases: [(_, _, [(_, fn(&mut FixedDecimal, i16, RoundingIncrement), _, _, _, _, _); 9]); 3] = [
+ ("two", RoundingIncrement::MultiplesOf2, [
+ ("ceil", FixedDecimal::ceil_to_increment, "-1.4", "0.4", "0.6", "0.6", "1.6"),
+ ("floor", FixedDecimal::floor_to_increment, "-1.6", "0.4", "0.4", "0.6", "1.4"),
+ ("expand", FixedDecimal::expand_to_increment, "-1.6", "0.4", "0.6", "0.6", "1.6"),
+ ("trunc", FixedDecimal::trunc_to_increment, "-1.4", "0.4", "0.4", "0.6", "1.4"),
+ ("half_ceil", FixedDecimal::half_ceil_to_increment, "-1.4", "0.4", "0.6", "0.6", "1.6"),
+ ("half_floor", FixedDecimal::half_floor_to_increment, "-1.6", "0.4", "0.4", "0.6", "1.4"),
+ ("half_expand", FixedDecimal::half_expand_to_increment, "-1.6", "0.4", "0.6", "0.6", "1.6"),
+ ("half_trunc", FixedDecimal::half_trunc_to_increment, "-1.4", "0.4", "0.4", "0.6", "1.4"),
+ ("half_even", FixedDecimal::half_even_to_increment, "-1.6", "0.4", "0.4", "0.6", "1.6"),
+ ]),
+ ("five", RoundingIncrement::MultiplesOf5, [
+ ("ceil", FixedDecimal::ceil_to_increment, "-1.5", "0.5", "0.5", "1.0", "1.5"),
+ ("floor", FixedDecimal::floor_to_increment, "-1.5", "0.0", "0.5", "0.5", "1.5"),
+ ("expand", FixedDecimal::expand_to_increment, "-1.5", "0.5", "0.5", "1.0", "1.5"),
+ ("trunc", FixedDecimal::trunc_to_increment, "-1.5", "0.0", "0.5", "0.5", "1.5"),
+ ("half_ceil", FixedDecimal::half_ceil_to_increment, "-1.5", "0.5", "0.5", "0.5", "1.5"),
+ ("half_floor", FixedDecimal::half_floor_to_increment, "-1.5", "0.5", "0.5", "0.5", "1.5"),
+ ("half_expand", FixedDecimal::half_expand_to_increment, "-1.5", "0.5", "0.5", "0.5", "1.5"),
+ ("half_trunc", FixedDecimal::half_trunc_to_increment, "-1.5", "0.5", "0.5", "0.5", "1.5"),
+ ("half_even", FixedDecimal::half_even_to_increment, "-1.5", "0.5", "0.5", "0.5", "1.5"),
+ ]),
+ ("twenty-five", RoundingIncrement::MultiplesOf25, [
+ ("ceil", FixedDecimal::ceil_to_increment, "-0.0", "2.5", "2.5", "2.5", "2.5"),
+ ("floor", FixedDecimal::floor_to_increment, "-2.5", "0.0", "0.0", "0.0", "0.0"),
+ ("expand", FixedDecimal::expand_to_increment, "-2.5", "2.5", "2.5", "2.5", "2.5"),
+ ("trunc", FixedDecimal::trunc_to_increment, "-0.0", "0.0", "0.0", "0.0", "0.0"),
+ ("half_ceil", FixedDecimal::half_ceil_to_increment, "-2.5", "0.0", "0.0", "0.0", "2.5"),
+ ("half_floor", FixedDecimal::half_floor_to_increment, "-2.5", "0.0", "0.0", "0.0", "2.5"),
+ ("half_expand", FixedDecimal::half_expand_to_increment, "-2.5", "0.0", "0.0", "0.0", "2.5"),
+ ("half_trunc", FixedDecimal::half_trunc_to_increment, "-2.5", "0.0", "0.0", "0.0", "2.5"),
+ ("half_even", FixedDecimal::half_even_to_increment, "-2.5", "0.0", "0.0", "0.0", "2.5"),
+ ]),
+ ];
+
+ for (increment_str, increment, cases) in cases {
+ for (rounding_mode, f, e1, e2, e3, e4, e5) in cases {
+ let mut fd1: FixedDecimal = "-1.5".parse().unwrap();
+ let mut fd2: FixedDecimal = "0.4".parse().unwrap();
+ let mut fd3: FixedDecimal = "0.5".parse().unwrap();
+ let mut fd4: FixedDecimal = "0.6".parse().unwrap();
+ let mut fd5: FixedDecimal = "1.5".parse().unwrap();
+ // The original ECMA-402 table tests rounding at magnitude 0.
+ // However, testing rounding at magnitude -1 gives more
+ // interesting test cases for increments.
+ f(&mut fd1, -1, increment);
+ f(&mut fd2, -1, increment);
+ f(&mut fd3, -1, increment);
+ f(&mut fd4, -1, increment);
+ f(&mut fd5, -1, increment);
+ assert_eq!(
+ fd1.write_to_string(),
+ e1,
+ "-1.5 failed for {rounding_mode} with increments of {increment_str}"
+ );
+ assert_eq!(
+ fd2.write_to_string(),
+ e2,
+ "0.4 failed for {rounding_mode} with increments of {increment_str}"
+ );
+ assert_eq!(
+ fd3.write_to_string(),
+ e3,
+ "0.5 failed for {rounding_mode} with increments of {increment_str}"
+ );
+ assert_eq!(
+ fd4.write_to_string(),
+ e4,
+ "0.6 failed for {rounding_mode} with increments of {increment_str}"
+ );
+ assert_eq!(
+ fd5.write_to_string(),
+ e5,
+ "1.5 failed for {rounding_mode} with increments of {increment_str}"
+ );
+ }
+ }
+}