-
Notifications
You must be signed in to change notification settings - Fork 176
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor module imports and add rounding module
- Loading branch information
Showing
3 changed files
with
141 additions
and
135 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
// This file is part of ICU4X. For terms of use, please see the file | ||
// called LICENSE at the top level of the ICU4X source tree | ||
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). | ||
|
||
//! This file contains the implementation of the rounding algorithm and the related functions & types. | ||
|
||
// Adapters to convert runtime dispatched calls into const-inlined methods. | ||
// This allows reducing the codesize for the common case of no increment. | ||
|
||
#[derive(Copy, Clone, PartialEq)] | ||
struct NoIncrement; | ||
|
||
trait IncrementLike: Copy + Sized + PartialEq { | ||
const MULTIPLES_OF_1: Option<Self>; | ||
const MULTIPLES_OF_2: Option<Self>; | ||
const MULTIPLES_OF_5: Option<Self>; | ||
const MULTIPLES_OF_25: Option<Self>; | ||
} | ||
|
||
impl IncrementLike for RoundingIncrement { | ||
const MULTIPLES_OF_1: Option<Self> = Some(Self::MultiplesOf1); | ||
|
||
const MULTIPLES_OF_2: Option<Self> = Some(Self::MultiplesOf2); | ||
|
||
const MULTIPLES_OF_5: Option<Self> = Some(Self::MultiplesOf5); | ||
|
||
const MULTIPLES_OF_25: Option<Self> = Some(Self::MultiplesOf25); | ||
} | ||
|
||
impl IncrementLike for NoIncrement { | ||
const MULTIPLES_OF_1: Option<Self> = Some(Self); | ||
|
||
const MULTIPLES_OF_2: Option<Self> = None; | ||
|
||
const MULTIPLES_OF_5: Option<Self> = None; | ||
|
||
const MULTIPLES_OF_25: Option<Self> = None; | ||
} | ||
|
||
/// Mode used in a rounding operation. | ||
/// | ||
/// # Comparative table of rounding modes | ||
/// | ||
/// | Value | Ceil | Expand | Floor | Trunc | HalfCeil | HalfExpand | HalfFloor | HalfTrunc | HalfEven | | ||
/// |:-----:|:----:|:------:|:-----:|:-----:|:--------:|:----------:|:---------:|:---------:|:--------:| | ||
/// | +1.8 | +2 | +2 | +1 | +1 | +2 | +2 | +2 | +2 | +2 | | ||
/// | +1.5 | " | " | " | " | " | " | +1 | +1 | " | | ||
/// | +1.2 | " | " | " | " | +1 | +1 | " | " | +1 | | ||
/// | +0.8 | +1 | +1 | 0 | 0 | " | " | " | " | " | | ||
/// | +0.5 | " | " | " | " | " | " | 0 | 0 | 0 | | ||
/// | +0.2 | " | " | " | " | 0 | 0 | " | " | " | | ||
/// | -0.2 | 0 | -1 | -1 | " | " | " | " | " | " | | ||
/// | -0.5 | " | " | " | " | " | -1 | -1 | " | " | | ||
/// | -0.8 | " | " | " | " | -1 | " | " | -1 | -1 | | ||
/// | -1.2 | -1 | -2 | -2 | -1 | " | " | " | " | " | | ||
/// | -1.5 | " | " | " | " | " | -2 | -2 | " | -2 | | ||
/// | -1.8 | " | " | " | " | -2 | " | " | -2 | " | | ||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] | ||
#[non_exhaustive] | ||
pub enum RoundingMode { | ||
/// Round up, or towards positive infinity. | ||
Ceil, | ||
/// Round away from zero, or towards infinity. | ||
Expand, | ||
/// Round down, or towards negative infinity. | ||
Floor, | ||
/// Round towards zero, or away from infinity. | ||
Trunc, | ||
/// Round to the nearest integer, resolving ties by rounding up. | ||
HalfCeil, | ||
/// Round to the nearest integer, resolving ties by rounding away from zero. | ||
HalfExpand, | ||
/// Round to the nearest integer, resolving ties by rounding down. | ||
HalfFloor, | ||
/// Round to the nearest integer, resolving ties by rounding towards zero. | ||
HalfTrunc, | ||
/// Round to the nearest integer, resolving ties by rounding towards the nearest even integer. | ||
HalfEven, | ||
} | ||
|
||
/// Increment used in a rounding operation. | ||
/// | ||
/// Forces a rounding operation to round to only multiples of the specified increment. | ||
/// | ||
/// # Example | ||
/// | ||
/// ``` | ||
/// use fixed_decimal::{FixedDecimal, RoundingIncrement, RoundingMode}; | ||
/// use writeable::assert_writeable_eq; | ||
/// # use std::str::FromStr; | ||
/// let dec = FixedDecimal::from_str("-7.266").unwrap(); | ||
/// let mode = RoundingMode::Expand; | ||
/// let increments = [ | ||
/// // .266 normally expands to .27 when rounding on position -2... | ||
/// (RoundingIncrement::MultiplesOf1, "-7.27"), | ||
/// // ...however, when rounding to multiples of 2, .266 expands to .28, since the next multiple | ||
/// // of 2 bigger than the least significant digit of the rounded value (7) is 8. | ||
/// (RoundingIncrement::MultiplesOf2, "-7.28"), | ||
/// // .266 expands to .30, since the next multiple of 5 bigger than 7 is 10. | ||
/// (RoundingIncrement::MultiplesOf5, "-7.30"), | ||
/// // .266 expands to .50, since the next multiple of 25 bigger than 27 is 50. | ||
/// // Note how we compare against 27 instead of only 7, because the increment applies to | ||
/// // the two least significant digits of the rounded value instead of only the least | ||
/// // significant digit. | ||
/// (RoundingIncrement::MultiplesOf25, "-7.50"), | ||
/// ]; | ||
/// | ||
/// for (increment, expected) in increments { | ||
/// assert_writeable_eq!( | ||
/// dec.clone().rounded_with_mode_and_increment( | ||
/// -2, | ||
/// mode, | ||
/// increment | ||
/// ), | ||
/// expected | ||
/// ); | ||
/// } | ||
/// ``` | ||
#[derive(Debug, Eq, PartialEq, Clone, Copy, Default)] | ||
#[non_exhaustive] | ||
pub enum RoundingIncrement { | ||
/// Round the least significant digit to any digit (0-9). | ||
/// | ||
/// This is the default rounding increment for all the methods that don't take a | ||
/// `RoundingIncrement` as an argument. | ||
#[default] | ||
MultiplesOf1, | ||
/// Round the least significant digit to multiples of two (0, 2, 4, 6, 8). | ||
MultiplesOf2, | ||
/// Round the least significant digit to multiples of five (0, 5). | ||
MultiplesOf5, | ||
/// Round the two least significant digits to multiples of twenty-five (0, 25, 50, 75). | ||
/// | ||
/// With this increment, the rounding position index will match the least significant digit | ||
/// of the multiple of 25; e.g. the number .264 expanded at position -2 using increments of 25 | ||
/// will give .50 as a result, since the next multiple of 25 bigger than 26 is 50. | ||
MultiplesOf25, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters