diff --git a/components/datetime/src/format/datetime.rs b/components/datetime/src/format/datetime.rs index eb4200f47c4..36164adaf80 100644 --- a/components/datetime/src/format/datetime.rs +++ b/components/datetime/src/format/datetime.rs @@ -11,7 +11,7 @@ use crate::provider::pattern::runtime::PatternMetadata; use crate::provider::pattern::PatternItem; use core::fmt::{self, Write}; -use fixed_decimal::FixedDecimal; +use fixed_decimal::SignedFixedDecimal; use icu_calendar::types::{DayOfWeekInMonth, IsoWeekday}; use icu_decimal::FixedDecimalFormatter; use writeable::{Part, Writeable}; @@ -20,7 +20,7 @@ use writeable::{Part, Writeable}; fn try_write_number( result: &mut W, fixed_decimal_format: Option<&FixedDecimalFormatter>, - mut num: FixedDecimal, + mut num: SignedFixedDecimal, length: FieldLength, ) -> Result, fmt::Error> where @@ -115,7 +115,7 @@ where } (FieldSymbol::Year(Year::Calendar), l) => { input!(year = input.year); - let mut year = FixedDecimal::from(year.era_year_or_extended()); + let mut year = SignedFixedDecimal::from(year.era_year_or_extended()); if matches!(l, FieldLength::Two) { // 'yy' and 'YY' truncate year.set_max_position(2); @@ -157,9 +157,12 @@ where input!(related_iso = year.related_iso()); // Always in latin digits according to spec - FixedDecimal::from(related_iso) - .padded_start(l.to_len() as i16) - .write_to(w)?; + { + let mut num = SignedFixedDecimal::from(related_iso); + num.pad_start(l.to_len() as i16); + num + } + .write_to(w)?; Ok(()) } (FieldSymbol::Month(_), l @ (FieldLength::One | FieldLength::Two)) => { @@ -180,17 +183,20 @@ where Ok(MonthPlaceholderValue::NumericPattern(substitution_pattern)) => { debug_assert!(l == FieldLength::One); if let Some(fdf) = fdf { + let mut num = SignedFixedDecimal::from(month.ordinal); + num.pad_start(l.to_len() as i16); substitution_pattern - .interpolate([fdf.format( - &FixedDecimal::from(month.ordinal).padded_start(l.to_len() as i16), - )]) + .interpolate([fdf.format(&num)]) .write_to(w)?; Ok(()) } else { w.with_part(Part::ERROR, |w| { substitution_pattern - .interpolate([FixedDecimal::from(month.ordinal) - .padded_start(l.to_len() as i16)]) + .interpolate([{ + let mut num = SignedFixedDecimal::from(month.ordinal); + num.pad_start(l.to_len() as i16); + num + }]) .write_to(w) })?; Err(DateTimeWriteError::FixedDecimalFormatterNotLoaded) @@ -295,9 +301,12 @@ where input!(nanosecond = input.nanosecond); // Formatting with fractional seconds - let mut s = FixedDecimal::from(second.number()); - let _infallible = - s.concatenate_end(FixedDecimal::from(nanosecond.number()).multiplied_pow10(-9)); + let mut s = SignedFixedDecimal::from(second.number()); + let _infallible = s.concatenate_end( + SignedFixedDecimal::from(nanosecond.number()) + .absolute + .multiplied_pow10(-9), + ); debug_assert!(_infallible.is_ok()); let position = -(decimal_second as i16); s.trunc(position); @@ -514,7 +523,7 @@ mod tests { try_write_number( &mut writeable::adapters::CoreWriteAsPartsWrite(&mut s), Some(&fixed_decimal_format), - FixedDecimal::from(*value), + SignedFixedDecimal::from(*value), *length, ) .unwrap() diff --git a/components/datetime/src/format/time_zone.rs b/components/datetime/src/format/time_zone.rs index 6fc870ed845..1e3bd8f1528 100644 --- a/components/datetime/src/format/time_zone.rs +++ b/components/datetime/src/format/time_zone.rs @@ -8,7 +8,7 @@ use crate::pattern::TimeZoneDataPayloadsBorrowed; use crate::provider::time_zones::MetazoneId; use crate::{fields::FieldLength, input::ExtractedInput}; use core::fmt; -use fixed_decimal::FixedDecimal; +use fixed_decimal::SignedFixedDecimal; use icu_calendar::{Date, Iso, Time}; use icu_decimal::FixedDecimalFormatter; use icu_timezone::provider::EPOCH; @@ -241,33 +241,34 @@ impl FormatTimeZone for LocalizedOffsetFormat { &self, sink: &mut S, ) -> fmt::Result { - self.fdf - .format( - &FixedDecimal::from(self.offset.hours_part()) - .with_sign_display(fixed_decimal::SignDisplay::Always) - .padded_start(if self.length == FieldLength::Four { - 2 - } else { - 0 - }), - ) - .write_to(sink)?; + let fd = { + let mut fd = SignedFixedDecimal::from(self.offset.hours_part()) + .with_sign_display(fixed_decimal::SignDisplay::Always); + fd.pad_start(if self.length == FieldLength::Four { + 2 + } else { + 0 + }); + fd + }; + self.fdf.format(&fd).write_to(sink)?; if self.length == FieldLength::Four || self.offset.minutes_part() != 0 || self.offset.seconds_part() != 0 { + let mut signed_fdf = SignedFixedDecimal::from(self.offset.minutes_part()); + signed_fdf.absolute.pad_start(2); sink.write_str(self.separator)?; - self.fdf - .format(&FixedDecimal::from(self.offset.minutes_part()).padded_start(2)) - .write_to(sink)?; + self.fdf.format(&signed_fdf).write_to(sink)?; } if self.offset.seconds_part() != 0 { sink.write_str(self.separator)?; - self.fdf - .format(&FixedDecimal::from(self.offset.seconds_part()).padded_start(2)) - .write_to(sink)?; + + let mut signed_fdf = SignedFixedDecimal::from(self.offset.seconds_part()); + signed_fdf.absolute.pad_start(2); + self.fdf.format(&signed_fdf).write_to(sink)?; } Ok(()) @@ -579,10 +580,13 @@ impl Iso8601Format { } // Always in latin digits according to spec - FixedDecimal::from(offset.hours_part()) - .padded_start(2) - .with_sign_display(fixed_decimal::SignDisplay::Always) - .write_to(sink)?; + { + let mut fd = SignedFixedDecimal::from(offset.hours_part()) + .with_sign_display(fixed_decimal::SignDisplay::Always); + fd.pad_start(2); + fd + } + .write_to(sink)?; if self.minutes == IsoMinutes::Required || (self.minutes == IsoMinutes::Optional && offset.minutes_part() != 0) @@ -590,18 +594,24 @@ impl Iso8601Format { if self.extended { sink.write_char(':')?; } - FixedDecimal::from(offset.minutes_part()) - .padded_start(2) - .write_to(sink)?; + { + let mut fd = SignedFixedDecimal::from(offset.minutes_part()); + fd.pad_start(2); + fd + } + .write_to(sink)?; } if self.seconds == IsoSeconds::Optional && offset.seconds_part() != 0 { if self.extended { sink.write_char(':')?; } - FixedDecimal::from(offset.seconds_part()) - .padded_start(2) - .write_to(sink)?; + { + let mut fd = SignedFixedDecimal::from(offset.seconds_part()); + fd.pad_start(2); + fd + } + .write_to(sink)?; } Ok(()) diff --git a/components/decimal/README.md b/components/decimal/README.md index 65489a067fc..1170fb74f83 100644 --- a/components/decimal/README.md +++ b/components/decimal/README.md @@ -15,7 +15,7 @@ follow [icu4x#275](https://github.com/unicode-org/icu4x/issues/275). ### Format a number with Bangla digits ```rust -use fixed_decimal::FixedDecimal; +use fixed_decimal::SignedFixedDecimal; use icu::decimal::FixedDecimalFormatter; use icu::locale::locale; use writeable::assert_writeable_eq; @@ -26,7 +26,7 @@ let fdf = FixedDecimalFormatter::try_new( ) .expect("locale should be present"); -let fixed_decimal = FixedDecimal::from(1000007); +let fixed_decimal = SignedFixedDecimal::from(1000007); assert_writeable_eq!(fdf.format(&fixed_decimal), "১০,০০,০০৭"); ``` @@ -34,7 +34,7 @@ assert_writeable_eq!(fdf.format(&fixed_decimal), "১০,০০,০০৭"); ### Format a number with digits after the decimal separator ```rust -use fixed_decimal::FixedDecimal; +use fixed_decimal::SignedFixedDecimal; use icu::decimal::FixedDecimalFormatter; use icu::locale::Locale; use writeable::assert_writeable_eq; @@ -43,7 +43,11 @@ let fdf = FixedDecimalFormatter::try_new(Default::default(), Default::default()) .expect("locale should be present"); -let fixed_decimal = FixedDecimal::from(200050).multiplied_pow10(-2); +let fixed_decimal = { + let mut decimal = SignedFixedDecimal::from(200050); + decimal.multiply_pow10(-2); + decimal +}; assert_writeable_eq!(fdf.format(&fixed_decimal), "2,000.50"); ``` @@ -54,7 +58,7 @@ Numbering systems specified in the `-u-nu` subtag will be followed as long as th symbols for that numbering system. ```rust -use fixed_decimal::FixedDecimal; +use fixed_decimal::SignedFixedDecimal; use icu::decimal::FixedDecimalFormatter; use icu::locale::locale; use writeable::assert_writeable_eq; @@ -65,7 +69,7 @@ let fdf = FixedDecimalFormatter::try_new( ) .expect("locale should be present"); -let fixed_decimal = FixedDecimal::from(1000007); +let fixed_decimal = SignedFixedDecimal::from(1000007); assert_writeable_eq!(fdf.format(&fixed_decimal), "๑,๐๐๐,๐๐๗"); ``` diff --git a/components/decimal/benches/fixed_decimal_format.rs b/components/decimal/benches/fixed_decimal_format.rs index bff8d3d3c2b..09ab4d36031 100644 --- a/components/decimal/benches/fixed_decimal_format.rs +++ b/components/decimal/benches/fixed_decimal_format.rs @@ -8,7 +8,7 @@ use rand_pcg::Lcg64Xsh32; use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use fixed_decimal::FixedDecimal; +use fixed_decimal::SignedFixedDecimal; use icu_decimal::{FixedDecimalFormatter, FixedDecimalFormatterPreferences}; use icu_locale_core::locale; @@ -34,7 +34,7 @@ fn overview_bench(c: &mut Criterion) { // ranging from -1e9 to 1e9. let fdf = FixedDecimalFormatter::try_new(prefs, options).unwrap(); for &num in &nums { - let fd = FixedDecimal::from(black_box(num)); + let fd = SignedFixedDecimal::from(black_box(num)); fdf.format_to_string(&fd); } }); diff --git a/components/decimal/src/format.rs b/components/decimal/src/format.rs index 5eeb331aeb9..967e65a85df 100644 --- a/components/decimal/src/format.rs +++ b/components/decimal/src/format.rs @@ -7,15 +7,15 @@ use crate::grouper; use crate::options::*; use crate::provider::*; -use fixed_decimal::FixedDecimal; use fixed_decimal::Sign; +use fixed_decimal::SignedFixedDecimal; use writeable::Writeable; /// An intermediate structure returned by [`FixedDecimalFormatter`](crate::FixedDecimalFormatter). /// Use [`Writeable`][Writeable] to render the formatted decimal to a string or buffer. #[derive(Debug, PartialEq, Clone)] pub struct FormattedFixedDecimal<'l> { - pub(crate) value: &'l FixedDecimal, + pub(crate) value: &'l SignedFixedDecimal, pub(crate) options: &'l FixedDecimalFormatterOptions, pub(crate) symbols: &'l DecimalSymbolsV2<'l>, pub(crate) digits: &'l DecimalDigitsV1, @@ -41,7 +41,7 @@ impl Writeable for FormattedFixedDecimal<'_> { if let Some(affixes) = affixes { sink.write_str(affixes.0)?; } - let range = self.value.magnitude_range(); + let range = self.value.absolute.magnitude_range(); let upper_magnitude = *range.end(); for m in range.rev() { if m == -1 { diff --git a/components/decimal/src/grouper.rs b/components/decimal/src/grouper.rs index 89bd16ae963..fc8ec6d281f 100644 --- a/components/decimal/src/grouper.rs +++ b/components/decimal/src/grouper.rs @@ -56,7 +56,7 @@ fn test_grouper() { use crate::options; use crate::provider::*; use crate::FixedDecimalFormatter; - use fixed_decimal::FixedDecimal; + use fixed_decimal::SignedFixedDecimal; use icu_provider::prelude::*; use icu_provider_adapters::fixed::FixedProvider; use icu_provider_adapters::fork::ForkByMarkerProvider; @@ -154,7 +154,11 @@ fn test_grouper() { ]; for cas in &cases { for i in 0..4 { - let dec = FixedDecimal::from(1).multiplied_pow10((i as i16) + 3); + let dec = { + let mut dec = SignedFixedDecimal::from(1); + dec.multiply_pow10((i as i16) + 3); + dec + }; let provider_symbols = FixedProvider::::from_owned( crate::provider::DecimalSymbolsV2 { grouping_sizes: cas.sizes, diff --git a/components/decimal/src/lib.rs b/components/decimal/src/lib.rs index ffa65821138..1bf8218baa5 100644 --- a/components/decimal/src/lib.rs +++ b/components/decimal/src/lib.rs @@ -15,7 +15,7 @@ //! ## Format a number with Bangla digits //! //! ``` -//! use fixed_decimal::FixedDecimal; +//! use fixed_decimal::SignedFixedDecimal; //! use icu::decimal::FixedDecimalFormatter; //! use icu::locale::locale; //! use writeable::assert_writeable_eq; @@ -26,7 +26,7 @@ //! ) //! .expect("locale should be present"); //! -//! let fixed_decimal = FixedDecimal::from(1000007); +//! let fixed_decimal = SignedFixedDecimal::from(1000007); //! //! assert_writeable_eq!(fdf.format(&fixed_decimal), "১০,০০,০০৭"); //! ``` @@ -34,7 +34,7 @@ //! ## Format a number with digits after the decimal separator //! //! ``` -//! use fixed_decimal::FixedDecimal; +//! use fixed_decimal::SignedFixedDecimal; //! use icu::decimal::FixedDecimalFormatter; //! use icu::locale::Locale; //! use writeable::assert_writeable_eq; @@ -43,7 +43,11 @@ //! FixedDecimalFormatter::try_new(Default::default(), Default::default()) //! .expect("locale should be present"); //! -//! let fixed_decimal = FixedDecimal::from(200050).multiplied_pow10(-2); +//! let fixed_decimal = { +//! let mut decimal = SignedFixedDecimal::from(200050); +//! decimal.multiply_pow10(-2); +//! decimal +//! }; //! //! assert_writeable_eq!(fdf.format(&fixed_decimal), "2,000.50"); //! ``` @@ -54,7 +58,7 @@ //! symbols for that numbering system. //! //! ``` -//! use fixed_decimal::FixedDecimal; +//! use fixed_decimal::SignedFixedDecimal; //! use icu::decimal::FixedDecimalFormatter; //! use icu::locale::locale; //! use writeable::assert_writeable_eq; @@ -65,7 +69,7 @@ //! ) //! .expect("locale should be present"); //! -//! let fixed_decimal = FixedDecimal::from(1000007); +//! let fixed_decimal = SignedFixedDecimal::from(1000007); //! //! assert_writeable_eq!(fdf.format(&fixed_decimal), "๑,๐๐๐,๐๐๗"); //! ``` @@ -99,7 +103,7 @@ pub(crate) mod size_test_macro; pub use format::FormattedFixedDecimal; use alloc::string::String; -use fixed_decimal::FixedDecimal; +use fixed_decimal::SignedFixedDecimal; use icu_locale_core::locale; use icu_locale_core::preferences::{ define_preferences, extensions::unicode::keywords::NumberingSystem, @@ -120,7 +124,7 @@ define_preferences!( } ); -/// A formatter for [`FixedDecimal`], rendering decimal digits in an i18n-friendly way. +/// A formatter for [`SignedFixedDecimal`], rendering decimal digits in an i18n-friendly way. /// /// [`FixedDecimalFormatter`] supports: /// @@ -197,8 +201,8 @@ impl FixedDecimalFormatter { }) } - /// Formats a [`FixedDecimal`], returning a [`FormattedFixedDecimal`]. - pub fn format<'l>(&'l self, value: &'l FixedDecimal) -> FormattedFixedDecimal<'l> { + /// Formats a [`SignedFixedDecimal`], returning a [`FormattedFixedDecimal`]. + pub fn format<'l>(&'l self, value: &'l SignedFixedDecimal) -> FormattedFixedDecimal<'l> { FormattedFixedDecimal { value, options: &self.options, @@ -207,8 +211,8 @@ impl FixedDecimalFormatter { } } - /// Formats a [`FixedDecimal`], returning a [`String`]. - pub fn format_to_string(&self, value: &FixedDecimal) -> String { + /// Formats a [`SignedFixedDecimal`], returning a [`String`]. + pub fn format_to_string(&self, value: &SignedFixedDecimal) -> String { self.format(value).write_to_string().into_owned() } } diff --git a/components/decimal/src/provider.rs b/components/decimal/src/provider.rs index 9f0f580f94e..b85ea474b2e 100644 --- a/components/decimal/src/provider.rs +++ b/components/decimal/src/provider.rs @@ -132,7 +132,7 @@ impl<'data> DecimalSymbolStrsBuilder<'data> { } } -/// Symbols and metadata required for formatting a [`FixedDecimal`](crate::FixedDecimal). +/// Symbols and metadata required for formatting a [`SignedFixedDecimal`](crate::SignedFixedDecimal). /// ///
/// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, diff --git a/components/experimental/src/compactdecimal/format.rs b/components/experimental/src/compactdecimal/format.rs index 272788d8bdc..9449a737c51 100644 --- a/components/experimental/src/compactdecimal/format.rs +++ b/components/experimental/src/compactdecimal/format.rs @@ -3,7 +3,7 @@ // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). use alloc::borrow::Cow; -use fixed_decimal::{CompactDecimal, FixedDecimal}; +use fixed_decimal::{CompactDecimal, SignedFixedDecimal}; use writeable::Writeable; use zerovec::maps::ZeroMap2dCursor; @@ -25,7 +25,7 @@ impl FormattedCompactDecimal<'_> { /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::SignedFixedDecimal; /// use icu::experimental::compactdecimal::CompactDecimalFormatter; /// use icu::locale::locale; /// use writeable::assert_writeable_eq; @@ -62,7 +62,7 @@ impl Writeable for FormattedCompactDecimal<'_> { } else { let plural_map = self.plural_map.as_ref().ok_or(core::fmt::Error)?; let chosen_pattern = (|| { - if self.value.significand() == &FixedDecimal::from(1) { + if self.value.significand() == &SignedFixedDecimal::from(1) { if let Some(pattern) = plural_map.get1(&Count::Explicit1) { return Some(pattern); } diff --git a/components/experimental/src/compactdecimal/formatter.rs b/components/experimental/src/compactdecimal/formatter.rs index 16ab40e3ed2..ce5f47ab757 100644 --- a/components/experimental/src/compactdecimal/formatter.rs +++ b/components/experimental/src/compactdecimal/formatter.rs @@ -13,7 +13,7 @@ use crate::compactdecimal::{ }; use alloc::borrow::Cow; use core::convert::TryFrom; -use fixed_decimal::{CompactDecimal, FixedDecimal}; +use fixed_decimal::{CompactDecimal, SignedFixedDecimal}; use icu_decimal::{FixedDecimalFormatter, FixedDecimalFormatterPreferences}; use icu_locale_core::preferences::{ define_preferences, extensions::unicode::keywords::NumberingSystem, prefs_convert, @@ -313,7 +313,7 @@ impl CompactDecimalFormatter { /// assert_writeable_eq!(short_english.format_i64(-1_172_700), "-1.2M"); /// ``` pub fn format_i64(&self, value: i64) -> FormattedCompactDecimal<'_> { - let unrounded = FixedDecimal::from(value); + let unrounded = SignedFixedDecimal::from(value); self.format_fixed_decimal(unrounded) } @@ -378,11 +378,11 @@ impl CompactDecimalFormatter { use fixed_decimal::FloatPrecision::RoundTrip; // NOTE: This first gets the shortest representation of the f64, which // manifests as double rounding. - let partly_rounded = FixedDecimal::try_from_f64(value, RoundTrip)?; + let partly_rounded = SignedFixedDecimal::try_from_f64(value, RoundTrip)?; Ok(self.format_fixed_decimal(partly_rounded)) } - /// Formats a [`FixedDecimal`] by automatically scaling and rounding it. + /// Formats a [`SignedFixedDecimal`] by automatically scaling and rounding it. /// /// The result may have a fractional digit only if it is compact and its /// significand is less than 10. Trailing fractional 0s are omitted. @@ -393,7 +393,7 @@ impl CompactDecimalFormatter { /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::SignedFixedDecimal; /// use icu::experimental::compactdecimal::CompactDecimalFormatter; /// use icu::locale::locale; /// use writeable::assert_writeable_eq; @@ -405,38 +405,38 @@ impl CompactDecimalFormatter { /// .unwrap(); /// /// assert_writeable_eq!( - /// short_english.format_fixed_decimal(FixedDecimal::from(0)), + /// short_english.format_fixed_decimal(SignedFixedDecimal::from(0)), /// "0" /// ); /// assert_writeable_eq!( - /// short_english.format_fixed_decimal(FixedDecimal::from(2)), + /// short_english.format_fixed_decimal(SignedFixedDecimal::from(2)), /// "2" /// ); /// assert_writeable_eq!( - /// short_english.format_fixed_decimal(FixedDecimal::from(843)), + /// short_english.format_fixed_decimal(SignedFixedDecimal::from(843)), /// "843" /// ); /// assert_writeable_eq!( - /// short_english.format_fixed_decimal(FixedDecimal::from(2207)), + /// short_english.format_fixed_decimal(SignedFixedDecimal::from(2207)), /// "2.2K" /// ); /// assert_writeable_eq!( - /// short_english.format_fixed_decimal(FixedDecimal::from(15127)), + /// short_english.format_fixed_decimal(SignedFixedDecimal::from(15127)), /// "15K" /// ); /// assert_writeable_eq!( - /// short_english.format_fixed_decimal(FixedDecimal::from(3010349)), + /// short_english.format_fixed_decimal(SignedFixedDecimal::from(3010349)), /// "3M" /// ); /// assert_writeable_eq!( - /// short_english.format_fixed_decimal(FixedDecimal::from(-13132)), + /// short_english.format_fixed_decimal(SignedFixedDecimal::from(-13132)), /// "-13K" /// ); /// /// // The sign display on the FixedDecimal is respected: /// assert_writeable_eq!( /// short_english.format_fixed_decimal( - /// FixedDecimal::from(2500) + /// SignedFixedDecimal::from(2500) /// .with_sign_display(fixed_decimal::SignDisplay::ExceptZero) /// ), /// "+2.5K" @@ -480,12 +480,13 @@ impl CompactDecimalFormatter { /// "-1.2M" /// ); /// ``` - pub fn format_fixed_decimal(&self, value: FixedDecimal) -> FormattedCompactDecimal<'_> { - let log10_type = value.nonzero_magnitude_start(); + pub fn format_fixed_decimal(&self, value: SignedFixedDecimal) -> FormattedCompactDecimal<'_> { + let log10_type = value.absolute.nonzero_magnitude_start(); let (mut plural_map, mut exponent) = self.plural_map_and_exponent_for_magnitude(log10_type); - let mut significand = value.multiplied_pow10(-i16::from(exponent)); + let mut significand = value.clone(); + significand.multiply_pow10(-i16::from(exponent)); // If we have just one digit before the decimal point… - if significand.nonzero_magnitude_start() == 0 { + if significand.absolute.nonzero_magnitude_start() == 0 { // …round to one fractional digit… significand.round(-1); } else { @@ -493,7 +494,8 @@ impl CompactDecimalFormatter { // so round to eliminate the fractional part. significand.round(0); } - let rounded_magnitude = significand.nonzero_magnitude_start() + i16::from(exponent); + let rounded_magnitude = + significand.absolute.nonzero_magnitude_start() + i16::from(exponent); if rounded_magnitude > log10_type { // We got bumped up a magnitude by rounding. // This means that `significand` is a power of 10. @@ -502,14 +504,14 @@ impl CompactDecimalFormatter { // to avoid iterating twice (we only need to look at the next key), // but this obscures the logic and the map is tiny. (plural_map, exponent) = self.plural_map_and_exponent_for_magnitude(rounded_magnitude); - significand = - significand.multiplied_pow10(i16::from(old_exponent) - i16::from(exponent)); + significand = significand.clone(); + significand.multiply_pow10(i16::from(old_exponent) - i16::from(exponent)); // There is no need to perform any rounding: `significand`, being // a power of 10, is as round as it gets, and since `exponent` can // only have become larger, it is already the correct rounding of // `unrounded` to the precision we want to show. } - significand.trim_end(); + significand.absolute.trim_end(); FormattedCompactDecimal { formatter: self, plural_map, @@ -622,7 +624,7 @@ impl CompactDecimalFormatter { value: &'l CompactDecimal, ) -> Result, ExponentError> { let log10_type = - value.significand().nonzero_magnitude_start() + i16::from(value.exponent()); + value.significand().absolute.nonzero_magnitude_start() + i16::from(value.exponent()); let (plural_map, expected_exponent) = self.plural_map_and_exponent_for_magnitude(log10_type); diff --git a/components/experimental/src/dimension/currency/format.rs b/components/experimental/src/dimension/currency/format.rs index dd9b8802998..fe35bd626ea 100644 --- a/components/experimental/src/dimension/currency/format.rs +++ b/components/experimental/src/dimension/currency/format.rs @@ -2,7 +2,7 @@ // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). -use fixed_decimal::FixedDecimal; +use fixed_decimal::SignedFixedDecimal; use icu_decimal::FixedDecimalFormatter; use writeable::Writeable; @@ -14,7 +14,7 @@ use crate::dimension::provider::currency; use crate::dimension::provider::currency::CurrencyEssentialsV1; pub struct FormattedCurrency<'l> { - pub(crate) value: &'l FixedDecimal, + pub(crate) value: &'l SignedFixedDecimal, pub(crate) currency_code: CurrencyCode, pub(crate) options: &'l CurrencyFormatterOptions, pub(crate) essential: &'l CurrencyEssentialsV1<'l>, diff --git a/components/experimental/src/dimension/currency/formatter.rs b/components/experimental/src/dimension/currency/formatter.rs index 92e1accad51..ec08f236a3b 100644 --- a/components/experimental/src/dimension/currency/formatter.rs +++ b/components/experimental/src/dimension/currency/formatter.rs @@ -4,7 +4,7 @@ //! Experimental. -use fixed_decimal::FixedDecimal; +use fixed_decimal::SignedFixedDecimal; use icu_decimal::{ options::FixedDecimalFormatterOptions, FixedDecimalFormatter, FixedDecimalFormatterPreferences, }; @@ -131,7 +131,7 @@ impl CurrencyFormatter { }) } - /// Formats a [`FixedDecimal`] value for the given currency code. + /// Formats a [`SignedFixedDecimal`] value for the given currency code. /// /// # Examples /// ``` @@ -152,7 +152,7 @@ impl CurrencyFormatter { /// ``` pub fn format_fixed_decimal<'l>( &'l self, - value: &'l FixedDecimal, + value: &'l SignedFixedDecimal, currency_code: CurrencyCode, ) -> FormattedCurrency<'l> { FormattedCurrency { diff --git a/components/experimental/src/dimension/currency/long_format.rs b/components/experimental/src/dimension/currency/long_format.rs index eb2d6926ae1..1ad7ce6a50c 100644 --- a/components/experimental/src/dimension/currency/long_format.rs +++ b/components/experimental/src/dimension/currency/long_format.rs @@ -2,7 +2,7 @@ // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). -use fixed_decimal::FixedDecimal; +use fixed_decimal::SignedFixedDecimal; use icu_decimal::FixedDecimalFormatter; use icu_plurals::PluralRules; @@ -14,7 +14,7 @@ use crate::dimension::provider::extended_currency::CurrencyExtendedDataV1; use super::CurrencyCode; pub struct LongFormattedCurrency<'l> { - pub(crate) value: &'l FixedDecimal, + pub(crate) value: &'l SignedFixedDecimal, // TODO: use this if the display name is not exist and make the extended data optional. pub(crate) _currency_code: CurrencyCode, pub(crate) extended: &'l CurrencyExtendedDataV1<'l>, diff --git a/components/experimental/src/dimension/currency/long_formatter.rs b/components/experimental/src/dimension/currency/long_formatter.rs index 0c746a6c775..31004ab9adf 100644 --- a/components/experimental/src/dimension/currency/long_formatter.rs +++ b/components/experimental/src/dimension/currency/long_formatter.rs @@ -4,7 +4,7 @@ //! Experimental. -use fixed_decimal::FixedDecimal; +use fixed_decimal::SignedFixedDecimal; use icu_decimal::{options::FixedDecimalFormatterOptions, FixedDecimalFormatter}; use icu_plurals::PluralRules; use icu_provider::prelude::*; @@ -149,7 +149,7 @@ impl LongCurrencyFormatter { }) } - /// Formats in the long format a [`FixedDecimal`] value for the given currency code. + /// Formats in the long format a [`SignedFixedDecimal`] value for the given currency code. /// /// # Examples /// ``` @@ -170,7 +170,7 @@ impl LongCurrencyFormatter { /// ``` pub fn format_fixed_decimal<'l>( &'l self, - value: &'l FixedDecimal, + value: &'l SignedFixedDecimal, currency_code: CurrencyCode, ) -> LongFormattedCurrency<'l> { LongFormattedCurrency { diff --git a/components/experimental/src/dimension/percent/format.rs b/components/experimental/src/dimension/percent/format.rs index e485755e6f4..f1382471ea3 100644 --- a/components/experimental/src/dimension/percent/format.rs +++ b/components/experimental/src/dimension/percent/format.rs @@ -2,7 +2,7 @@ // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). -use fixed_decimal::{FixedDecimal, Sign}; +use fixed_decimal::{Sign, SignedFixedDecimal}; use icu_decimal::FixedDecimalFormatter; use crate::alloc::borrow::ToOwned; @@ -26,7 +26,7 @@ impl Writeable for Append { } pub struct FormattedPercent<'l> { - pub(crate) value: &'l FixedDecimal, + pub(crate) value: &'l SignedFixedDecimal, pub(crate) essential: &'l PercentEssentialsV1<'l>, pub(crate) options: &'l PercentFormatterOptions, pub(crate) fixed_decimal_formatter: &'l FixedDecimalFormatter, diff --git a/components/experimental/src/dimension/percent/formatter.rs b/components/experimental/src/dimension/percent/formatter.rs index a1fe31c1794..23303dc42b1 100644 --- a/components/experimental/src/dimension/percent/formatter.rs +++ b/components/experimental/src/dimension/percent/formatter.rs @@ -4,7 +4,7 @@ //! Experimental. -use fixed_decimal::FixedDecimal; +use fixed_decimal::SignedFixedDecimal; use icu_decimal::options::FixedDecimalFormatterOptions; use icu_decimal::{FixedDecimalFormatter, FixedDecimalFormatterPreferences}; use icu_locale_core::preferences::{ @@ -110,7 +110,7 @@ impl PercentFormatter { ) } - /// Formats a [`FixedDecimal`] value for the given percent code. + /// Formats a [`SignedFixedDecimal`] value for the given percent code. /// /// # Examples /// ``` @@ -128,7 +128,7 @@ impl PercentFormatter { /// formatted_percent.write_to(&mut sink).unwrap(); /// assert_eq!(sink.as_str(), "12,345.67%"); /// ``` - pub fn format<'l>(&'l self, value: &'l FixedDecimal) -> FormattedPercent<'l> { + pub fn format<'l>(&'l self, value: &'l SignedFixedDecimal) -> FormattedPercent<'l> { FormattedPercent { value, essential: self.essential.get(), diff --git a/components/experimental/src/dimension/units/format.rs b/components/experimental/src/dimension/units/format.rs index 09c4b8de315..a39ab1cac8f 100644 --- a/components/experimental/src/dimension/units/format.rs +++ b/components/experimental/src/dimension/units/format.rs @@ -5,13 +5,13 @@ //! Experimental. use crate::dimension::provider::units::UnitsDisplayNameV1; -use fixed_decimal::FixedDecimal; +use fixed_decimal::SignedFixedDecimal; use icu_decimal::FixedDecimalFormatter; use icu_plurals::PluralRules; use writeable::{impl_display_with_writeable, Writeable}; pub struct FormattedUnit<'l> { - pub(crate) value: &'l FixedDecimal, + pub(crate) value: &'l SignedFixedDecimal, // TODO: review using options and essentials. // pub(crate) _options: &'l UnitsFormatterOptions, // pub(crate) essential: &'l UnitsEssentialsV1<'l>, diff --git a/components/experimental/src/dimension/units/formatter.rs b/components/experimental/src/dimension/units/formatter.rs index 4adcef69f51..049ebdfc20e 100644 --- a/components/experimental/src/dimension/units/formatter.rs +++ b/components/experimental/src/dimension/units/formatter.rs @@ -4,7 +4,7 @@ //! Experimental. -use fixed_decimal::FixedDecimal; +use fixed_decimal::SignedFixedDecimal; use icu_decimal::options::FixedDecimalFormatterOptions; use icu_decimal::{FixedDecimalFormatter, FixedDecimalFormatterPreferences}; use icu_locale_core::preferences::{ @@ -176,8 +176,8 @@ impl UnitsFormatter { }) } - /// Formats a [`FixedDecimal`] value for the given unit. - pub fn format_fixed_decimal<'l>(&'l self, value: &'l FixedDecimal) -> FormattedUnit<'l> { + /// Formats a [`SignedFixedDecimal`] value for the given unit. + pub fn format_fixed_decimal<'l>(&'l self, value: &'l SignedFixedDecimal) -> FormattedUnit<'l> { FormattedUnit { value, display_name: self.display_name.get(), diff --git a/components/experimental/src/duration/format.rs b/components/experimental/src/duration/format.rs index 74fbbf9a0e1..b3b3e851240 100644 --- a/components/experimental/src/duration/format.rs +++ b/components/experimental/src/duration/format.rs @@ -8,7 +8,7 @@ use super::validated_options::Unit; use core::fmt; use core::fmt::Write; use either::Either; -use fixed_decimal::{FixedDecimal, SignDisplay}; +use fixed_decimal::{SignDisplay, SignedFixedDecimal, UnsignedFixedDecimal}; use icu_decimal::FormattedFixedDecimal; use smallvec::SmallVec; use writeable::{adapters::WithPart, PartsWrite, Writeable}; @@ -69,17 +69,17 @@ pub struct FormattedDuration<'l> { } /// Exists to allow creating lists of heterogeneous [`Writeable`]s to pass to [`ListFormatter`]. -/// The (Unit, FixedDecimal) pair is used to crerate [`FormattedUnit`]s. -type HeterogenousToFormatter = Either; +/// The (Unit, SignedFixedDecimal) pair is used to crerate [`FormattedUnit`]s. +type HeterogenousToFormatter = Either; /// Describes a formatted duration. #[derive(Default)] struct DigitalDuration { - hours: Option, + hours: Option, add_hour_minute_separator: bool, - minutes: Option, + minutes: Option, add_minute_second_separator: bool, - seconds: Option, + seconds: Option, } impl DigitalDuration { @@ -150,7 +150,7 @@ impl FormattedDuration<'_> { // 5. Let numberingSystem be durationFormat.[[NumberingSystem]]. // 6. Perform ! CreateDataPropertyOrThrow(nfOpts, "numberingSystem", numberingSystem). - let mut fd = FixedDecimal::from(self.duration.hours); + let mut fd = SignedFixedDecimal::from(self.duration.hours); // Since we construct the FixedDecimal from an unsigned hours value, we need to set the sign manually. fd.set_sign(self.duration.get_sign()); @@ -158,7 +158,7 @@ impl FormattedDuration<'_> { // 7. If hoursStyle is "2-digit", then if self.fmt.options.hour == FieldStyle::TwoDigit { // a. Perform ! CreateDataPropertyOrThrow(nfOpts, "minimumIntegerDigits", 2𝔽). - fd.pad_start(2); + fd.absolute.pad_start(2); } // 8. If signDisplayed is false, then @@ -196,7 +196,7 @@ impl FormattedDuration<'_> { // 5. Let nfOpts be OrdinaryObjectCreate(null). // 6. Let numberingSystem be durationFormat.[[NumberingSystem]]. // 7. Perform ! CreateDataPropertyOrThrow(nfOpts, "numberingSystem", numberingSystem). - let mut fd = FixedDecimal::from(self.duration.minutes); + let mut fd = SignedFixedDecimal::from(self.duration.minutes); // Since we construct the FixedDecimal from an unsigned minutes value, we need to set the sign manually. fd.set_sign(self.duration.get_sign()); @@ -204,7 +204,7 @@ impl FormattedDuration<'_> { // 8. If minutesStyle is "2-digit", then if self.fmt.options.minute == FieldStyle::TwoDigit { // a. Perform ! CreateDataPropertyOrThrow(nfOpts, "minimumIntegerDigits", 2𝔽). - fd.pad_start(2); + fd.absolute.pad_start(2); } // 9. If signDisplayed is false, then @@ -228,9 +228,9 @@ impl FormattedDuration<'_> { /// then adds the first non-fractional unit and returns it. /// /// Divergence from standard: adds the first non-fractional unit as well. - fn add_fractional_digits(&self) -> FixedDecimal { + fn add_fractional_digits(&self) -> SignedFixedDecimal { let mut prev_val = self.duration.nanoseconds; - let mut prev_formatted = FixedDecimal::from(prev_val % 1000); + let mut prev_formatted = SignedFixedDecimal::from(prev_val % 1000); for (style, val) in [ (self.fmt.options.microsecond, self.duration.microseconds), (self.fmt.options.millisecond, self.duration.milliseconds), @@ -238,14 +238,18 @@ impl FormattedDuration<'_> { ] { if style == FieldStyle::Fractional { let val = val + prev_val / 1000; - prev_formatted = FixedDecimal::from(val % 1000) - .concatenated_end(prev_formatted.multiplied_pow10(-3)) + prev_formatted.absolute = UnsignedFixedDecimal::from(val % 1000) + .concatenated_end(prev_formatted.absolute.multiplied_pow10(-3)) .unwrap(); + prev_val = val; } else { - return FixedDecimal::from(val) - .concatenated_end(prev_formatted.multiplied_pow10(-3)) - .unwrap(); + return SignedFixedDecimal::new( + prev_formatted.sign, + UnsignedFixedDecimal::from(val) + .concatenated_end(prev_formatted.absolute.multiplied_pow10(-3)) + .unwrap(), + ); } } @@ -256,7 +260,7 @@ impl FormattedDuration<'_> { /// Formats numeric seconds to sink. Requires seconds formatting style to be either Numeric or TwoDigit. fn format_numeric_seconds( &self, - mut second_fd: FixedDecimal, + mut second_fd: SignedFixedDecimal, formatted_digital_duration: &mut DigitalDuration, sign_displayed: &mut bool, ) { @@ -286,7 +290,7 @@ impl FormattedDuration<'_> { // 8. If secondsStyle is "2-digit", then if self.fmt.options.second == FieldStyle::TwoDigit { // a. Perform ! CreateDataPropertyOrThrow(nfOpts, "minimumIntegerDigits", 2𝔽). - second_fd.pad_start(2); + second_fd.absolute.pad_start(2); } // 9. If signDisplayed is false, then @@ -303,7 +307,7 @@ impl FormattedDuration<'_> { // a. Let maximumFractionDigits be 9𝔽. // b. Let minimumFractionDigits be +0𝔽. second_fd.trunc(-9); - second_fd.pad_end(0); + second_fd.absolute.pad_end(0); } // 12. Else, FractionalDigits::Fixed(i) => { @@ -311,7 +315,7 @@ impl FormattedDuration<'_> { // a. Let maximumFractionDigits be durationFormat.[[FractionalDigits]]. second_fd.trunc(-i); // b. Let minimumFractionDigits be durationFormat.[[FractionalDigits]]. - second_fd.pad_end(-i); + second_fd.absolute.pad_end(-i); } // 13. Perform ! CreateDataPropertyOrThrow(nfOpts, "maximumFractionDigits", maximumFractionDigits). // 14. Perform ! CreateDataPropertyOrThrow(nfOpts, "minimumFractionDigits", minimumFractionDigits). // 15. Perform ! CreateDataPropertyOrThrow(nfOpts, "roundingMode", "trunc"). @@ -352,7 +356,7 @@ impl FormattedDuration<'_> { // a. Set secondsValue to secondsValue + AddFractionalDigits(durationFormat, duration). self.add_fractional_digits() } else { - FixedDecimal::from(self.duration.seconds) + SignedFixedDecimal::from(self.duration.seconds) }; // 9. Let secondsDisplay be durationFormat.[[SecondsDisplay]]. @@ -485,7 +489,7 @@ impl FormattedDuration<'_> { } // f. Else, else { - let mut formatted_value = FixedDecimal::from(value); + let mut formatted_value = SignedFixedDecimal::from(value); formatted_value.set_sign(self.duration.get_sign()); // i. Let nfOpts be OrdinaryObjectCreate(null). @@ -501,7 +505,7 @@ impl FormattedDuration<'_> { // i. Let maximumFractionDigits be 9𝔽. formatted_value.trunc(-9); // ii. Let minimumFractionDigits be +0𝔽. - formatted_value.pad_end(0); + formatted_value.absolute.pad_end(0); } // c. Else, FractionalDigits::Fixed(i) => { @@ -509,7 +513,7 @@ impl FormattedDuration<'_> { // i. Let maximumFractionDigits be durationFormat.[[FractionalDigits]]. formatted_value.trunc(-i); // ii. Let minimumFractionDigits be durationFormat.[[FractionalDigits]]. - formatted_value.pad_end(-i); + formatted_value.absolute.pad_end(-i); } } // d. Perform ! CreateDataPropertyOrThrow(nfOpts, "maximumFractionDigits", maximumFractionDigits). // e. Perform ! CreateDataPropertyOrThrow(nfOpts, "minimumFractionDigits", minimumFractionDigits). diff --git a/components/experimental/src/relativetime/format.rs b/components/experimental/src/relativetime/format.rs index d56ae5c284b..b76b1e87c18 100644 --- a/components/experimental/src/relativetime/format.rs +++ b/components/experimental/src/relativetime/format.rs @@ -4,7 +4,7 @@ use alloc::fmt::Write; -use fixed_decimal::FixedDecimal; +use fixed_decimal::SignedFixedDecimal; use writeable::Writeable; use crate::relativetime::{ @@ -28,7 +28,7 @@ pub mod parts { pub struct FormattedRelativeTime<'a> { pub(crate) formatter: &'a RelativeTimeFormatter, pub(crate) options: &'a RelativeTimeFormatterOptions, - pub(crate) value: FixedDecimal, + pub(crate) value: SignedFixedDecimal, pub(crate) is_negative: bool, } @@ -36,12 +36,12 @@ impl Writeable for FormattedRelativeTime<'_> { fn write_to_parts(&self, sink: &mut S) -> core::fmt::Result { if self.options.numeric == Numeric::Auto { let relatives = &self.formatter.rt.get().relatives; - if self.value.magnitude_range() == (0..=0) { + if self.value.absolute.magnitude_range() == (0..=0) { // Can be cast without overflow as it is a single digit. let i8_value = if self.is_negative { - -(self.value.digit_at(0) as i8) + -(self.value.absolute.digit_at(0) as i8) } else { - self.value.digit_at(0) as i8 + self.value.absolute.digit_at(0) as i8 }; if let Some(v) = relatives.get(&i8_value) { sink.with_part(parts::LITERAL, |s| s.write_str(v))?; diff --git a/components/experimental/src/relativetime/relativetime.rs b/components/experimental/src/relativetime/relativetime.rs index 8d4c074d36c..6d596dbc8b5 100644 --- a/components/experimental/src/relativetime/relativetime.rs +++ b/components/experimental/src/relativetime/relativetime.rs @@ -2,7 +2,7 @@ // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). -use fixed_decimal::{FixedDecimal, Sign}; +use fixed_decimal::{Sign, SignedFixedDecimal}; use icu_decimal::{ options::FixedDecimalFormatterOptions, provider::DecimalDigitsV1Marker, provider::DecimalSymbolsV2Marker, FixedDecimalFormatter, FixedDecimalFormatterPreferences, @@ -34,7 +34,7 @@ prefs_convert!(RelativeTimeFormatterPreferences, PluralRulesPreferences); /// # Example /// /// ``` -/// use fixed_decimal::FixedDecimal; +/// use fixed_decimal::SignedFixedDecimal; /// use icu::experimental::relativetime::{ /// RelativeTimeFormatter, RelativeTimeFormatterOptions, /// }; @@ -48,11 +48,11 @@ prefs_convert!(RelativeTimeFormatterPreferences, PluralRulesPreferences); /// .expect("locale should be present"); /// /// assert_writeable_eq!( -/// relative_time_formatter.format(FixedDecimal::from(5i8)), +/// relative_time_formatter.format(SignedFixedDecimal::from(5i8)), /// "in 5 seconds" /// ); /// assert_writeable_eq!( -/// relative_time_formatter.format(FixedDecimal::from(-10i8)), +/// relative_time_formatter.format(SignedFixedDecimal::from(-10i8)), /// "10 seconds ago" /// ); /// ``` @@ -60,7 +60,7 @@ prefs_convert!(RelativeTimeFormatterPreferences, PluralRulesPreferences); /// # Example /// /// ``` -/// use fixed_decimal::FixedDecimal; +/// use fixed_decimal::SignedFixedDecimal; /// use icu::experimental::relativetime::options::Numeric; /// use icu::experimental::relativetime::{ /// RelativeTimeFormatter, RelativeTimeFormatterOptions, @@ -77,26 +77,26 @@ prefs_convert!(RelativeTimeFormatterPreferences, PluralRulesPreferences); /// .expect("locale should be present"); /// /// assert_writeable_eq!( -/// relative_time_formatter.format(FixedDecimal::from(0u8)), +/// relative_time_formatter.format(SignedFixedDecimal::from(0u8)), /// "hoy" /// ); /// assert_writeable_eq!( -/// relative_time_formatter.format(FixedDecimal::from(-2i8)), +/// relative_time_formatter.format(SignedFixedDecimal::from(-2i8)), /// "anteayer" /// ); /// assert_writeable_eq!( -/// relative_time_formatter.format(FixedDecimal::from(2u8)), +/// relative_time_formatter.format(SignedFixedDecimal::from(2u8)), /// "pasado mañana" /// ); /// assert_writeable_eq!( -/// relative_time_formatter.format(FixedDecimal::from(15i8)), +/// relative_time_formatter.format(SignedFixedDecimal::from(15i8)), /// "dentro de 15 d" /// ); /// ``` /// /// # Example /// ``` -/// use fixed_decimal::FixedDecimal; +/// use fixed_decimal::SignedFixedDecimal; /// use icu::experimental::relativetime::{ /// RelativeTimeFormatter, RelativeTimeFormatterOptions, /// }; @@ -110,11 +110,11 @@ prefs_convert!(RelativeTimeFormatterPreferences, PluralRulesPreferences); /// .expect("locale should be present"); /// /// assert_writeable_eq!( -/// relative_time_formatter.format(FixedDecimal::from(3u8)), +/// relative_time_formatter.format(SignedFixedDecimal::from(3u8)), /// "৩ বছরে" /// ); /// assert_writeable_eq!( -/// relative_time_formatter.format(FixedDecimal::from(-15i8)), +/// relative_time_formatter.format(SignedFixedDecimal::from(-15i8)), /// "১৫ বছর পূর্বে" /// ); /// ``` @@ -379,7 +379,7 @@ impl RelativeTimeFormatter { /// Format a `value` according to the locale and formatting options of /// [`RelativeTimeFormatter`]. - pub fn format(&self, value: FixedDecimal) -> FormattedRelativeTime<'_> { + pub fn format(&self, value: SignedFixedDecimal) -> FormattedRelativeTime<'_> { let is_negative = value.sign() == Sign::Negative; FormattedRelativeTime { options: &self.options, diff --git a/components/experimental/tests/relativetime/tests.rs b/components/experimental/tests/relativetime/tests.rs index 292550ee072..d7133d45738 100644 --- a/components/experimental/tests/relativetime/tests.rs +++ b/components/experimental/tests/relativetime/tests.rs @@ -2,7 +2,7 @@ // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). -use fixed_decimal::FixedDecimal; +use fixed_decimal::SignedFixedDecimal; use icu_experimental::relativetime::{ options::Numeric, RelativeTimeFormatter, RelativeTimeFormatterOptions, }; @@ -23,7 +23,7 @@ macro_rules! generate_test { $( assert_writeable_eq!( - relative_time_formatter.format(FixedDecimal::from($en_time)), + relative_time_formatter.format(SignedFixedDecimal::from($en_time)), $en_expected ); )+ @@ -36,7 +36,7 @@ macro_rules! generate_test { $( assert_writeable_eq!( - relative_time_formatter.format(FixedDecimal::from($ar_time)), + relative_time_formatter.format(SignedFixedDecimal::from($ar_time)), $ar_expected ); )+ diff --git a/components/plurals/benches/operands.rs b/components/plurals/benches/operands.rs index d1e724870ba..3f1835d0f11 100644 --- a/components/plurals/benches/operands.rs +++ b/components/plurals/benches/operands.rs @@ -5,7 +5,7 @@ mod fixtures; use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use fixed_decimal::FixedDecimal; +use fixed_decimal::SignedFixedDecimal; use icu_plurals::PluralOperands; fn operands(c: &mut Criterion) { @@ -27,7 +27,11 @@ fn operands(c: &mut Criterion) { .expect("Failed to parse a number into an operands."); } for s in &data.fixed_decimals { - let f: FixedDecimal = FixedDecimal::from(s.value).multiplied_pow10(s.exponent); + let f: SignedFixedDecimal = { + let mut dec = SignedFixedDecimal::from(s.value); + dec.multiply_pow10(s.exponent); + dec + }; let _: PluralOperands = PluralOperands::from(black_box(&f)); } }) @@ -96,7 +100,11 @@ fn operands(c: &mut Criterion) { c.bench_function("plurals/operands/create/from_fixed_decimal", |b| { b.iter(|| { for s in &data.fixed_decimals { - let f: FixedDecimal = FixedDecimal::from(s.value).multiplied_pow10(s.exponent); + let f: SignedFixedDecimal = { + let mut dec = SignedFixedDecimal::from(s.value); + dec.multiply_pow10(s.exponent); + dec + }; let _: PluralOperands = PluralOperands::from(black_box(&f)); } }); @@ -104,9 +112,21 @@ fn operands(c: &mut Criterion) { { let samples = [ - FixedDecimal::from(1_i128).multiplied_pow10(0), - FixedDecimal::from(123450_i128).multiplied_pow10(-4), - FixedDecimal::from(2500_i128).multiplied_pow10(-2), + { + let mut dec = SignedFixedDecimal::from(1_i128); + dec.multiply_pow10(0); + dec + }, + { + let mut dec = SignedFixedDecimal::from(123450_i128); + dec.multiply_pow10(-4); + dec + }, + { + let mut dec = SignedFixedDecimal::from(2500_i128); + dec.multiply_pow10(-2); + dec + }, ]; let mut group = c.benchmark_group("plurals/operands/create/from_fixed_decimal/samples"); for s in samples.iter() { diff --git a/components/plurals/src/operands.rs b/components/plurals/src/operands.rs index c951c991f14..301beb3a7e2 100644 --- a/components/plurals/src/operands.rs +++ b/components/plurals/src/operands.rs @@ -2,7 +2,7 @@ // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). -use fixed_decimal::{CompactDecimal, FixedDecimal}; +use fixed_decimal::{CompactDecimal, SignedFixedDecimal}; /// A full plural operands representation of a number. See [CLDR Plural Rules](http://unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules) for complete operands description. /// @@ -16,12 +16,12 @@ use fixed_decimal::{CompactDecimal, FixedDecimal}; /// /// - Integers, signed and unsigned /// - Strings representing an arbitrary-precision decimal -/// - [`FixedDecimal`] +/// - [`SignedFixedDecimal`] /// /// This crate does not support selection from a floating-point number, because floats are not /// capable of carrying trailing zeros, which are required for proper plural rule selection. For /// example, in English, "1 star" has a different plural form than "1.0 stars", but this -/// distinction cannot be represented using a float. Clients should use [`FixedDecimal`] instead. +/// distinction cannot be represented using a float. Clients should use [`SignedFixedDecimal`] instead. /// /// # Examples /// @@ -63,10 +63,10 @@ use fixed_decimal::{CompactDecimal, FixedDecimal}; /// ); /// ``` /// -/// From [`FixedDecimal`] +/// From [`SignedFixedDecimal`] /// /// ``` -/// use fixed_decimal::FixedDecimal; +/// use fixed_decimal::SignedFixedDecimal; /// use icu::plurals::rules::RawPluralOperands; /// use icu::plurals::PluralOperands; /// @@ -79,7 +79,11 @@ use fixed_decimal::{CompactDecimal, FixedDecimal}; /// t: 45, /// c: 0, /// }), -/// (&FixedDecimal::from(12345).multiplied_pow10(-2)).into() +/// (&{ +/// let mut decimal = SignedFixedDecimal::from(12345); +/// decimal.multiply_pow10(-2); +/// decimal +/// }).into() /// ); /// ``` #[derive(Debug, Clone, Copy, PartialEq, Default)] @@ -226,24 +230,24 @@ impl_integer_type!(u8 u16 u32 u64 u128 usize); impl_signed_integer_type!(i8 i16 i32 i64 i128 isize); impl PluralOperands { - fn from_significand_and_exponent(dec: &FixedDecimal, exp: u8) -> PluralOperands { + fn from_significand_and_exponent(dec: &SignedFixedDecimal, exp: u8) -> PluralOperands { let exp_i16 = i16::from(exp); - let mag_range = dec.magnitude_range(); + let mag_range = dec.absolute.magnitude_range(); let mag_high = core::cmp::min(17, *mag_range.end() + exp_i16); let mag_low = core::cmp::max(-18, *mag_range.start() + exp_i16); let mut i: u64 = 0; for magnitude in (0..=mag_high).rev() { i *= 10; - i += dec.digit_at(magnitude - exp_i16) as u64; + i += dec.absolute.digit_at(magnitude - exp_i16) as u64; } let mut f: u64 = 0; let mut t: u64 = 0; let mut w: usize = 0; for magnitude in (mag_low..=-1).rev() { - let digit = dec.digit_at(magnitude - exp_i16) as u64; + let digit = dec.absolute.digit_at(magnitude - exp_i16) as u64; f *= 10; f += digit; if digit != 0 { @@ -287,10 +291,10 @@ impl PluralOperands { } } -impl From<&FixedDecimal> for PluralOperands { - /// Converts a [`fixed_decimal::FixedDecimal`] to [`PluralOperands`]. Retains at most 18 +impl From<&SignedFixedDecimal> for PluralOperands { + /// Converts a [`fixed_decimal::SignedFixedDecimal`] to [`PluralOperands`]. Retains at most 18 /// digits each from the integer and fraction parts. - fn from(dec: &FixedDecimal) -> Self { + fn from(dec: &SignedFixedDecimal) -> Self { Self::from_significand_and_exponent(dec, 0) } } @@ -303,14 +307,14 @@ impl From<&CompactDecimal> for PluralOperands { /// /// ``` /// use fixed_decimal::CompactDecimal; - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::SignedFixedDecimal; /// use icu::locale::locale; /// use icu::plurals::rules::RawPluralOperands; /// use icu::plurals::PluralCategory; /// use icu::plurals::PluralOperands; /// use icu::plurals::PluralRules; /// - /// let fixed_decimal = "1000000.20".parse::().unwrap(); + /// let fixed_decimal = "1000000.20".parse::().unwrap(); /// let compact_decimal = "1.00000020c6".parse::().unwrap(); /// /// assert_eq!( diff --git a/components/plurals/src/rules/runtime/ast.rs b/components/plurals/src/rules/runtime/ast.rs index f2a96773d79..a4276452dc1 100644 --- a/components/plurals/src/rules/runtime/ast.rs +++ b/components/plurals/src/rules/runtime/ast.rs @@ -491,7 +491,7 @@ mod test { } ); - let fd = fixed_decimal::FixedDecimal::from(1); + let fd = fixed_decimal::SignedFixedDecimal::from(1); let operands = PluralOperands::from(&fd); assert!(test_rule(&rule, &operands),); } @@ -502,27 +502,27 @@ mod test { let ref_rule = reference::parse(input.as_bytes()).expect("Failed to parse Rule"); let rule = Rule::try_from(&ref_rule).expect("Failed to convert Rule"); - let fd = fixed_decimal::FixedDecimal::from(0); + let fd = fixed_decimal::SignedFixedDecimal::from(0); let operands = PluralOperands::from(&fd); assert!(test_rule(&rule, &operands),); - let fd = fixed_decimal::FixedDecimal::from(13); + let fd = fixed_decimal::SignedFixedDecimal::from(13); let operands = PluralOperands::from(&fd); assert!(!test_rule(&rule, &operands),); - let fd = fixed_decimal::FixedDecimal::from(103); + let fd = fixed_decimal::SignedFixedDecimal::from(103); let operands = PluralOperands::from(&fd); assert!(test_rule(&rule, &operands),); - let fd = fixed_decimal::FixedDecimal::from(113); + let fd = fixed_decimal::SignedFixedDecimal::from(113); let operands = PluralOperands::from(&fd); assert!(!test_rule(&rule, &operands),); - let fd = fixed_decimal::FixedDecimal::from(178); + let fd = fixed_decimal::SignedFixedDecimal::from(178); let operands = PluralOperands::from(&fd); assert!(!test_rule(&rule, &operands),); - let fd = fixed_decimal::FixedDecimal::from(0); + let fd = fixed_decimal::SignedFixedDecimal::from(0); let operands = PluralOperands::from(&fd); assert!(test_rule(&rule, &operands),); } diff --git a/components/plurals/tests/fixtures/mod.rs b/components/plurals/tests/fixtures/mod.rs index 989a676e068..cc3e69b8548 100644 --- a/components/plurals/tests/fixtures/mod.rs +++ b/components/plurals/tests/fixtures/mod.rs @@ -2,7 +2,7 @@ // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). -use fixed_decimal::FixedDecimal; +use fixed_decimal::SignedFixedDecimal; #[cfg(feature = "experimental")] use icu_plurals::PluralOperands; use icu_plurals::{PluralCategory, PluralRuleType}; @@ -40,9 +40,11 @@ pub struct FixedDecimalInput { pow10: i16, } -impl From<&FixedDecimalInput> for FixedDecimal { +impl From<&FixedDecimalInput> for SignedFixedDecimal { fn from(f: &FixedDecimalInput) -> Self { - FixedDecimal::from(f.from).multiplied_pow10(f.pow10) + let mut dec = SignedFixedDecimal::from(f.from); + dec.multiply_pow10(f.pow10); + dec } } diff --git a/components/plurals/tests/operands.rs b/components/plurals/tests/operands.rs index 228b1c989f0..b0500d5f058 100644 --- a/components/plurals/tests/operands.rs +++ b/components/plurals/tests/operands.rs @@ -4,7 +4,7 @@ mod fixtures; -use fixed_decimal::FixedDecimal; +use fixed_decimal::SignedFixedDecimal; #[cfg(feature = "experimental")] use icu_plurals::rules::RawPluralOperands; use icu_plurals::PluralOperands; @@ -61,7 +61,7 @@ fn test_from_fixed_decimals() { serde_json::from_str(include_str!("fixtures/operands.json")) .expect("Failed to read a fixture"); for test in test_set.from_test { - let input: FixedDecimal = FixedDecimal::from(&test.input); + let input: SignedFixedDecimal = SignedFixedDecimal::from(&test.input); let actual: PluralOperands = PluralOperands::from(&input); let expected: PluralOperands = PluralOperands::from(test.expected.clone()); assert_eq!( diff --git a/ffi/capi/bindings/c/FixedDecimal.d.h b/ffi/capi/bindings/c/FixedDecimal.d.h deleted file mode 100644 index fe07a99af4d..00000000000 --- a/ffi/capi/bindings/c/FixedDecimal.d.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef FixedDecimal_D_H -#define FixedDecimal_D_H - -#include -#include -#include -#include -#include "diplomat_runtime.h" - - - - - -typedef struct FixedDecimal FixedDecimal; - - - - -#endif // FixedDecimal_D_H diff --git a/ffi/capi/bindings/c/FixedDecimal.h b/ffi/capi/bindings/c/FixedDecimal.h deleted file mode 100644 index 90bb4565bd6..00000000000 --- a/ffi/capi/bindings/c/FixedDecimal.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef FixedDecimal_H -#define FixedDecimal_H - -#include -#include -#include -#include -#include "diplomat_runtime.h" - -#include "FixedDecimalParseError.d.h" -#include "FixedDecimalRoundingIncrement.d.h" -#include "FixedDecimalRoundingMode.d.h" -#include "FixedDecimalSign.d.h" -#include "FixedDecimalSignDisplay.d.h" - -#include "FixedDecimal.d.h" - - - - - - -FixedDecimal* icu4x_FixedDecimal_from_int32_mv1(int32_t v); - -FixedDecimal* icu4x_FixedDecimal_from_uint32_mv1(uint32_t v); - -FixedDecimal* icu4x_FixedDecimal_from_int64_mv1(int64_t v); - -FixedDecimal* icu4x_FixedDecimal_from_uint64_mv1(uint64_t v); - -typedef struct icu4x_FixedDecimal_from_double_with_integer_precision_mv1_result {union {FixedDecimal* ok; }; bool is_ok;} icu4x_FixedDecimal_from_double_with_integer_precision_mv1_result; -icu4x_FixedDecimal_from_double_with_integer_precision_mv1_result icu4x_FixedDecimal_from_double_with_integer_precision_mv1(double f); - -typedef struct icu4x_FixedDecimal_from_double_with_lower_magnitude_mv1_result {union {FixedDecimal* ok; }; bool is_ok;} icu4x_FixedDecimal_from_double_with_lower_magnitude_mv1_result; -icu4x_FixedDecimal_from_double_with_lower_magnitude_mv1_result icu4x_FixedDecimal_from_double_with_lower_magnitude_mv1(double f, int16_t magnitude); - -typedef struct icu4x_FixedDecimal_from_double_with_significant_digits_mv1_result {union {FixedDecimal* ok; }; bool is_ok;} icu4x_FixedDecimal_from_double_with_significant_digits_mv1_result; -icu4x_FixedDecimal_from_double_with_significant_digits_mv1_result icu4x_FixedDecimal_from_double_with_significant_digits_mv1(double f, uint8_t digits); - -typedef struct icu4x_FixedDecimal_from_double_with_round_trip_precision_mv1_result {union {FixedDecimal* ok; }; bool is_ok;} icu4x_FixedDecimal_from_double_with_round_trip_precision_mv1_result; -icu4x_FixedDecimal_from_double_with_round_trip_precision_mv1_result icu4x_FixedDecimal_from_double_with_round_trip_precision_mv1(double f); - -typedef struct icu4x_FixedDecimal_from_string_mv1_result {union {FixedDecimal* ok; FixedDecimalParseError err;}; bool is_ok;} icu4x_FixedDecimal_from_string_mv1_result; -icu4x_FixedDecimal_from_string_mv1_result icu4x_FixedDecimal_from_string_mv1(DiplomatStringView v); - -uint8_t icu4x_FixedDecimal_digit_at_mv1(const FixedDecimal* self, int16_t magnitude); - -int16_t icu4x_FixedDecimal_magnitude_start_mv1(const FixedDecimal* self); - -int16_t icu4x_FixedDecimal_magnitude_end_mv1(const FixedDecimal* self); - -int16_t icu4x_FixedDecimal_nonzero_magnitude_start_mv1(const FixedDecimal* self); - -int16_t icu4x_FixedDecimal_nonzero_magnitude_end_mv1(const FixedDecimal* self); - -bool icu4x_FixedDecimal_is_zero_mv1(const FixedDecimal* self); - -void icu4x_FixedDecimal_multiply_pow10_mv1(FixedDecimal* self, int16_t power); - -FixedDecimalSign icu4x_FixedDecimal_sign_mv1(const FixedDecimal* self); - -void icu4x_FixedDecimal_set_sign_mv1(FixedDecimal* self, FixedDecimalSign sign); - -void icu4x_FixedDecimal_apply_sign_display_mv1(FixedDecimal* self, FixedDecimalSignDisplay sign_display); - -void icu4x_FixedDecimal_trim_start_mv1(FixedDecimal* self); - -void icu4x_FixedDecimal_trim_end_mv1(FixedDecimal* self); - -void icu4x_FixedDecimal_pad_start_mv1(FixedDecimal* self, int16_t position); - -void icu4x_FixedDecimal_pad_end_mv1(FixedDecimal* self, int16_t position); - -void icu4x_FixedDecimal_set_max_position_mv1(FixedDecimal* self, int16_t position); - -void icu4x_FixedDecimal_round_mv1(FixedDecimal* self, int16_t position); - -void icu4x_FixedDecimal_ceil_mv1(FixedDecimal* self, int16_t position); - -void icu4x_FixedDecimal_expand_mv1(FixedDecimal* self, int16_t position); - -void icu4x_FixedDecimal_floor_mv1(FixedDecimal* self, int16_t position); - -void icu4x_FixedDecimal_trunc_mv1(FixedDecimal* self, int16_t position); - -void icu4x_FixedDecimal_round_with_mode_mv1(FixedDecimal* self, int16_t position, FixedDecimalRoundingMode mode); - -void icu4x_FixedDecimal_round_with_mode_and_increment_mv1(FixedDecimal* self, int16_t position, FixedDecimalRoundingMode mode, FixedDecimalRoundingIncrement increment); - -typedef struct icu4x_FixedDecimal_concatenate_end_mv1_result { bool is_ok;} icu4x_FixedDecimal_concatenate_end_mv1_result; -icu4x_FixedDecimal_concatenate_end_mv1_result icu4x_FixedDecimal_concatenate_end_mv1(FixedDecimal* self, FixedDecimal* other); - -void icu4x_FixedDecimal_to_string_mv1(const FixedDecimal* self, DiplomatWrite* write); - - -void icu4x_FixedDecimal_destroy_mv1(FixedDecimal* self); - - - - - -#endif // FixedDecimal_H diff --git a/ffi/capi/bindings/c/FixedDecimalFormatter.h b/ffi/capi/bindings/c/FixedDecimalFormatter.h index cab6788337e..467ae865065 100644 --- a/ffi/capi/bindings/c/FixedDecimalFormatter.h +++ b/ffi/capi/bindings/c/FixedDecimalFormatter.h @@ -9,9 +9,9 @@ #include "DataError.d.h" #include "DataProvider.d.h" -#include "FixedDecimal.d.h" #include "FixedDecimalGroupingStrategy.d.h" #include "Locale.d.h" +#include "SignedFixedDecimal.d.h" #include "FixedDecimalFormatter.d.h" @@ -26,7 +26,7 @@ icu4x_FixedDecimalFormatter_create_with_grouping_strategy_mv1_result icu4x_Fixed typedef struct icu4x_FixedDecimalFormatter_create_with_manual_data_mv1_result {union {FixedDecimalFormatter* ok; DataError err;}; bool is_ok;} icu4x_FixedDecimalFormatter_create_with_manual_data_mv1_result; icu4x_FixedDecimalFormatter_create_with_manual_data_mv1_result icu4x_FixedDecimalFormatter_create_with_manual_data_mv1(DiplomatStringView plus_sign_prefix, DiplomatStringView plus_sign_suffix, DiplomatStringView minus_sign_prefix, DiplomatStringView minus_sign_suffix, DiplomatStringView decimal_separator, DiplomatStringView grouping_separator, uint8_t primary_group_size, uint8_t secondary_group_size, uint8_t min_group_size, DiplomatCharView digits, FixedDecimalGroupingStrategy_option grouping_strategy); -void icu4x_FixedDecimalFormatter_format_mv1(const FixedDecimalFormatter* self, const FixedDecimal* value, DiplomatWrite* write); +void icu4x_FixedDecimalFormatter_format_mv1(const FixedDecimalFormatter* self, const SignedFixedDecimal* value, DiplomatWrite* write); void icu4x_FixedDecimalFormatter_destroy_mv1(FixedDecimalFormatter* self); diff --git a/ffi/capi/bindings/c/FixedDecimalRoundingMode.d.h b/ffi/capi/bindings/c/FixedDecimalRoundingMode.d.h deleted file mode 100644 index c98368c991e..00000000000 --- a/ffi/capi/bindings/c/FixedDecimalRoundingMode.d.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef FixedDecimalRoundingMode_D_H -#define FixedDecimalRoundingMode_D_H - -#include -#include -#include -#include -#include "diplomat_runtime.h" - - - - - -typedef enum FixedDecimalRoundingMode { - FixedDecimalRoundingMode_Ceil = 0, - FixedDecimalRoundingMode_Expand = 1, - FixedDecimalRoundingMode_Floor = 2, - FixedDecimalRoundingMode_Trunc = 3, - FixedDecimalRoundingMode_HalfCeil = 4, - FixedDecimalRoundingMode_HalfExpand = 5, - FixedDecimalRoundingMode_HalfFloor = 6, - FixedDecimalRoundingMode_HalfTrunc = 7, - FixedDecimalRoundingMode_HalfEven = 8, -} FixedDecimalRoundingMode; - -typedef struct FixedDecimalRoundingMode_option {union { FixedDecimalRoundingMode ok; }; bool is_ok; } FixedDecimalRoundingMode_option; - - - -#endif // FixedDecimalRoundingMode_D_H diff --git a/ffi/capi/bindings/c/FixedDecimalRoundingMode.h b/ffi/capi/bindings/c/FixedDecimalRoundingMode.h deleted file mode 100644 index 2752b7129f8..00000000000 --- a/ffi/capi/bindings/c/FixedDecimalRoundingMode.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef FixedDecimalRoundingMode_H -#define FixedDecimalRoundingMode_H - -#include -#include -#include -#include -#include "diplomat_runtime.h" - - -#include "FixedDecimalRoundingMode.d.h" - - - - - - - - - - - -#endif // FixedDecimalRoundingMode_H diff --git a/ffi/capi/bindings/c/FixedDecimalSignedRoundingMode.d.h b/ffi/capi/bindings/c/FixedDecimalSignedRoundingMode.d.h new file mode 100644 index 00000000000..388a092c0bc --- /dev/null +++ b/ffi/capi/bindings/c/FixedDecimalSignedRoundingMode.d.h @@ -0,0 +1,30 @@ +#ifndef FixedDecimalSignedRoundingMode_D_H +#define FixedDecimalSignedRoundingMode_D_H + +#include +#include +#include +#include +#include "diplomat_runtime.h" + + + + + +typedef enum FixedDecimalSignedRoundingMode { + FixedDecimalSignedRoundingMode_Expand = 0, + FixedDecimalSignedRoundingMode_Trunc = 1, + FixedDecimalSignedRoundingMode_HalfExpand = 2, + FixedDecimalSignedRoundingMode_HalfTrunc = 3, + FixedDecimalSignedRoundingMode_HalfEven = 4, + FixedDecimalSignedRoundingMode_Ceil = 5, + FixedDecimalSignedRoundingMode_Floor = 6, + FixedDecimalSignedRoundingMode_HalfCeil = 7, + FixedDecimalSignedRoundingMode_HalfFloor = 8, +} FixedDecimalSignedRoundingMode; + +typedef struct FixedDecimalSignedRoundingMode_option {union { FixedDecimalSignedRoundingMode ok; }; bool is_ok; } FixedDecimalSignedRoundingMode_option; + + + +#endif // FixedDecimalSignedRoundingMode_D_H diff --git a/ffi/capi/bindings/c/FixedDecimalSignedRoundingMode.h b/ffi/capi/bindings/c/FixedDecimalSignedRoundingMode.h new file mode 100644 index 00000000000..77bcbbb78df --- /dev/null +++ b/ffi/capi/bindings/c/FixedDecimalSignedRoundingMode.h @@ -0,0 +1,23 @@ +#ifndef FixedDecimalSignedRoundingMode_H +#define FixedDecimalSignedRoundingMode_H + +#include +#include +#include +#include +#include "diplomat_runtime.h" + + +#include "FixedDecimalSignedRoundingMode.d.h" + + + + + + + + + + + +#endif // FixedDecimalSignedRoundingMode_H diff --git a/ffi/capi/bindings/c/PluralOperands.h b/ffi/capi/bindings/c/PluralOperands.h index 01d55dd5d3c..3ce2c18c19f 100644 --- a/ffi/capi/bindings/c/PluralOperands.h +++ b/ffi/capi/bindings/c/PluralOperands.h @@ -7,8 +7,8 @@ #include #include "diplomat_runtime.h" -#include "FixedDecimal.d.h" #include "FixedDecimalParseError.d.h" +#include "SignedFixedDecimal.d.h" #include "PluralOperands.d.h" @@ -20,7 +20,7 @@ typedef struct icu4x_PluralOperands_from_string_mv1_result {union {PluralOperands* ok; FixedDecimalParseError err;}; bool is_ok;} icu4x_PluralOperands_from_string_mv1_result; icu4x_PluralOperands_from_string_mv1_result icu4x_PluralOperands_from_string_mv1(DiplomatStringView s); -PluralOperands* icu4x_PluralOperands_from_fixed_decimal_mv1(const FixedDecimal* x); +PluralOperands* icu4x_PluralOperands_from_fixed_decimal_mv1(const SignedFixedDecimal* x); void icu4x_PluralOperands_destroy_mv1(PluralOperands* self); diff --git a/ffi/capi/bindings/c/SignedFixedDecimal.d.h b/ffi/capi/bindings/c/SignedFixedDecimal.d.h new file mode 100644 index 00000000000..ae3a9fd8441 --- /dev/null +++ b/ffi/capi/bindings/c/SignedFixedDecimal.d.h @@ -0,0 +1,19 @@ +#ifndef SignedFixedDecimal_D_H +#define SignedFixedDecimal_D_H + +#include +#include +#include +#include +#include "diplomat_runtime.h" + + + + + +typedef struct SignedFixedDecimal SignedFixedDecimal; + + + + +#endif // SignedFixedDecimal_D_H diff --git a/ffi/capi/bindings/c/SignedFixedDecimal.h b/ffi/capi/bindings/c/SignedFixedDecimal.h new file mode 100644 index 00000000000..d703e1cc38e --- /dev/null +++ b/ffi/capi/bindings/c/SignedFixedDecimal.h @@ -0,0 +1,102 @@ +#ifndef SignedFixedDecimal_H +#define SignedFixedDecimal_H + +#include +#include +#include +#include +#include "diplomat_runtime.h" + +#include "FixedDecimalParseError.d.h" +#include "FixedDecimalRoundingIncrement.d.h" +#include "FixedDecimalSign.d.h" +#include "FixedDecimalSignDisplay.d.h" +#include "FixedDecimalSignedRoundingMode.d.h" + +#include "SignedFixedDecimal.d.h" + + + + + + +SignedFixedDecimal* icu4x_SignedFixedDecimal_from_int32_mv1(int32_t v); + +SignedFixedDecimal* icu4x_SignedFixedDecimal_from_uint32_mv1(uint32_t v); + +SignedFixedDecimal* icu4x_SignedFixedDecimal_from_int64_mv1(int64_t v); + +SignedFixedDecimal* icu4x_SignedFixedDecimal_from_uint64_mv1(uint64_t v); + +typedef struct icu4x_SignedFixedDecimal_from_double_with_integer_precision_mv1_result {union {SignedFixedDecimal* ok; }; bool is_ok;} icu4x_SignedFixedDecimal_from_double_with_integer_precision_mv1_result; +icu4x_SignedFixedDecimal_from_double_with_integer_precision_mv1_result icu4x_SignedFixedDecimal_from_double_with_integer_precision_mv1(double f); + +typedef struct icu4x_SignedFixedDecimal_from_double_with_lower_magnitude_mv1_result {union {SignedFixedDecimal* ok; }; bool is_ok;} icu4x_SignedFixedDecimal_from_double_with_lower_magnitude_mv1_result; +icu4x_SignedFixedDecimal_from_double_with_lower_magnitude_mv1_result icu4x_SignedFixedDecimal_from_double_with_lower_magnitude_mv1(double f, int16_t magnitude); + +typedef struct icu4x_SignedFixedDecimal_from_double_with_significant_digits_mv1_result {union {SignedFixedDecimal* ok; }; bool is_ok;} icu4x_SignedFixedDecimal_from_double_with_significant_digits_mv1_result; +icu4x_SignedFixedDecimal_from_double_with_significant_digits_mv1_result icu4x_SignedFixedDecimal_from_double_with_significant_digits_mv1(double f, uint8_t digits); + +typedef struct icu4x_SignedFixedDecimal_from_double_with_round_trip_precision_mv1_result {union {SignedFixedDecimal* ok; }; bool is_ok;} icu4x_SignedFixedDecimal_from_double_with_round_trip_precision_mv1_result; +icu4x_SignedFixedDecimal_from_double_with_round_trip_precision_mv1_result icu4x_SignedFixedDecimal_from_double_with_round_trip_precision_mv1(double f); + +typedef struct icu4x_SignedFixedDecimal_from_string_mv1_result {union {SignedFixedDecimal* ok; FixedDecimalParseError err;}; bool is_ok;} icu4x_SignedFixedDecimal_from_string_mv1_result; +icu4x_SignedFixedDecimal_from_string_mv1_result icu4x_SignedFixedDecimal_from_string_mv1(DiplomatStringView v); + +uint8_t icu4x_SignedFixedDecimal_digit_at_mv1(const SignedFixedDecimal* self, int16_t magnitude); + +int16_t icu4x_SignedFixedDecimal_magnitude_start_mv1(const SignedFixedDecimal* self); + +int16_t icu4x_SignedFixedDecimal_magnitude_end_mv1(const SignedFixedDecimal* self); + +int16_t icu4x_SignedFixedDecimal_nonzero_magnitude_start_mv1(const SignedFixedDecimal* self); + +int16_t icu4x_SignedFixedDecimal_nonzero_magnitude_end_mv1(const SignedFixedDecimal* self); + +bool icu4x_SignedFixedDecimal_is_zero_mv1(const SignedFixedDecimal* self); + +void icu4x_SignedFixedDecimal_multiply_pow10_mv1(SignedFixedDecimal* self, int16_t power); + +FixedDecimalSign icu4x_SignedFixedDecimal_sign_mv1(const SignedFixedDecimal* self); + +void icu4x_SignedFixedDecimal_set_sign_mv1(SignedFixedDecimal* self, FixedDecimalSign sign); + +void icu4x_SignedFixedDecimal_apply_sign_display_mv1(SignedFixedDecimal* self, FixedDecimalSignDisplay sign_display); + +void icu4x_SignedFixedDecimal_trim_start_mv1(SignedFixedDecimal* self); + +void icu4x_SignedFixedDecimal_trim_end_mv1(SignedFixedDecimal* self); + +void icu4x_SignedFixedDecimal_pad_start_mv1(SignedFixedDecimal* self, int16_t position); + +void icu4x_SignedFixedDecimal_pad_end_mv1(SignedFixedDecimal* self, int16_t position); + +void icu4x_SignedFixedDecimal_set_max_position_mv1(SignedFixedDecimal* self, int16_t position); + +void icu4x_SignedFixedDecimal_round_mv1(SignedFixedDecimal* self, int16_t position); + +void icu4x_SignedFixedDecimal_ceil_mv1(SignedFixedDecimal* self, int16_t position); + +void icu4x_SignedFixedDecimal_expand_mv1(SignedFixedDecimal* self, int16_t position); + +void icu4x_SignedFixedDecimal_floor_mv1(SignedFixedDecimal* self, int16_t position); + +void icu4x_SignedFixedDecimal_trunc_mv1(SignedFixedDecimal* self, int16_t position); + +void icu4x_SignedFixedDecimal_round_with_mode_mv1(SignedFixedDecimal* self, int16_t position, FixedDecimalSignedRoundingMode mode); + +void icu4x_SignedFixedDecimal_round_with_mode_and_increment_mv1(SignedFixedDecimal* self, int16_t position, FixedDecimalSignedRoundingMode mode, FixedDecimalRoundingIncrement increment); + +typedef struct icu4x_SignedFixedDecimal_concatenate_end_mv1_result { bool is_ok;} icu4x_SignedFixedDecimal_concatenate_end_mv1_result; +icu4x_SignedFixedDecimal_concatenate_end_mv1_result icu4x_SignedFixedDecimal_concatenate_end_mv1(SignedFixedDecimal* self, SignedFixedDecimal* other); + +void icu4x_SignedFixedDecimal_to_string_mv1(const SignedFixedDecimal* self, DiplomatWrite* write); + + +void icu4x_SignedFixedDecimal_destroy_mv1(SignedFixedDecimal* self); + + + + + +#endif // SignedFixedDecimal_H diff --git a/ffi/capi/bindings/cpp/icu4x/FixedDecimal.d.hpp b/ffi/capi/bindings/cpp/icu4x/FixedDecimal.d.hpp deleted file mode 100644 index 2a500c9b281..00000000000 --- a/ffi/capi/bindings/cpp/icu4x/FixedDecimal.d.hpp +++ /dev/null @@ -1,115 +0,0 @@ -#ifndef icu4x_FixedDecimal_D_HPP -#define icu4x_FixedDecimal_D_HPP - -#include -#include -#include -#include -#include -#include -#include "../diplomat_runtime.hpp" - -namespace icu4x { -namespace capi { struct FixedDecimal; } -class FixedDecimal; -struct FixedDecimalLimitError; -class FixedDecimalParseError; -class FixedDecimalRoundingIncrement; -class FixedDecimalRoundingMode; -class FixedDecimalSign; -class FixedDecimalSignDisplay; -} - - -namespace icu4x { -namespace capi { - struct FixedDecimal; -} // namespace capi -} // namespace - -namespace icu4x { -class FixedDecimal { -public: - - inline static std::unique_ptr from(int32_t v); - - inline static std::unique_ptr from(uint32_t v); - - inline static std::unique_ptr from(int64_t v); - - inline static std::unique_ptr from(uint64_t v); - - inline static diplomat::result, icu4x::FixedDecimalLimitError> from_double_with_integer_precision(double f); - - inline static diplomat::result, icu4x::FixedDecimalLimitError> from_double_with_lower_magnitude(double f, int16_t magnitude); - - inline static diplomat::result, icu4x::FixedDecimalLimitError> from_double_with_significant_digits(double f, uint8_t digits); - - inline static diplomat::result, icu4x::FixedDecimalLimitError> from_double_with_round_trip_precision(double f); - - inline static diplomat::result, icu4x::FixedDecimalParseError> from_string(std::string_view v); - - inline uint8_t digit_at(int16_t magnitude) const; - - inline int16_t magnitude_start() const; - - inline int16_t magnitude_end() const; - - inline int16_t nonzero_magnitude_start() const; - - inline int16_t nonzero_magnitude_end() const; - - inline bool is_zero() const; - - inline void multiply_pow10(int16_t power); - - inline icu4x::FixedDecimalSign sign() const; - - inline void set_sign(icu4x::FixedDecimalSign sign); - - inline void apply_sign_display(icu4x::FixedDecimalSignDisplay sign_display); - - inline void trim_start(); - - inline void trim_end(); - - inline void pad_start(int16_t position); - - inline void pad_end(int16_t position); - - inline void set_max_position(int16_t position); - - inline void round(int16_t position); - - inline void ceil(int16_t position); - - inline void expand(int16_t position); - - inline void floor(int16_t position); - - inline void trunc(int16_t position); - - inline void round_with_mode(int16_t position, icu4x::FixedDecimalRoundingMode mode); - - inline void round_with_mode_and_increment(int16_t position, icu4x::FixedDecimalRoundingMode mode, icu4x::FixedDecimalRoundingIncrement increment); - - inline diplomat::result concatenate_end(icu4x::FixedDecimal& other); - - inline std::string to_string() const; - - inline const icu4x::capi::FixedDecimal* AsFFI() const; - inline icu4x::capi::FixedDecimal* AsFFI(); - inline static const icu4x::FixedDecimal* FromFFI(const icu4x::capi::FixedDecimal* ptr); - inline static icu4x::FixedDecimal* FromFFI(icu4x::capi::FixedDecimal* ptr); - inline static void operator delete(void* ptr); -private: - FixedDecimal() = delete; - FixedDecimal(const icu4x::FixedDecimal&) = delete; - FixedDecimal(icu4x::FixedDecimal&&) noexcept = delete; - FixedDecimal operator=(const icu4x::FixedDecimal&) = delete; - FixedDecimal operator=(icu4x::FixedDecimal&&) noexcept = delete; - static void operator delete[](void*, size_t) = delete; -}; - -} // namespace -#endif // icu4x_FixedDecimal_D_HPP diff --git a/ffi/capi/bindings/cpp/icu4x/FixedDecimal.hpp b/ffi/capi/bindings/cpp/icu4x/FixedDecimal.hpp deleted file mode 100644 index 1be991f7b45..00000000000 --- a/ffi/capi/bindings/cpp/icu4x/FixedDecimal.hpp +++ /dev/null @@ -1,298 +0,0 @@ -#ifndef icu4x_FixedDecimal_HPP -#define icu4x_FixedDecimal_HPP - -#include "FixedDecimal.d.hpp" - -#include -#include -#include -#include -#include -#include -#include "../diplomat_runtime.hpp" -#include "FixedDecimalLimitError.hpp" -#include "FixedDecimalParseError.hpp" -#include "FixedDecimalRoundingIncrement.hpp" -#include "FixedDecimalRoundingMode.hpp" -#include "FixedDecimalSign.hpp" -#include "FixedDecimalSignDisplay.hpp" - - -namespace icu4x { -namespace capi { - extern "C" { - - icu4x::capi::FixedDecimal* icu4x_FixedDecimal_from_int32_mv1(int32_t v); - - icu4x::capi::FixedDecimal* icu4x_FixedDecimal_from_uint32_mv1(uint32_t v); - - icu4x::capi::FixedDecimal* icu4x_FixedDecimal_from_int64_mv1(int64_t v); - - icu4x::capi::FixedDecimal* icu4x_FixedDecimal_from_uint64_mv1(uint64_t v); - - typedef struct icu4x_FixedDecimal_from_double_with_integer_precision_mv1_result {union {icu4x::capi::FixedDecimal* ok; }; bool is_ok;} icu4x_FixedDecimal_from_double_with_integer_precision_mv1_result; - icu4x_FixedDecimal_from_double_with_integer_precision_mv1_result icu4x_FixedDecimal_from_double_with_integer_precision_mv1(double f); - - typedef struct icu4x_FixedDecimal_from_double_with_lower_magnitude_mv1_result {union {icu4x::capi::FixedDecimal* ok; }; bool is_ok;} icu4x_FixedDecimal_from_double_with_lower_magnitude_mv1_result; - icu4x_FixedDecimal_from_double_with_lower_magnitude_mv1_result icu4x_FixedDecimal_from_double_with_lower_magnitude_mv1(double f, int16_t magnitude); - - typedef struct icu4x_FixedDecimal_from_double_with_significant_digits_mv1_result {union {icu4x::capi::FixedDecimal* ok; }; bool is_ok;} icu4x_FixedDecimal_from_double_with_significant_digits_mv1_result; - icu4x_FixedDecimal_from_double_with_significant_digits_mv1_result icu4x_FixedDecimal_from_double_with_significant_digits_mv1(double f, uint8_t digits); - - typedef struct icu4x_FixedDecimal_from_double_with_round_trip_precision_mv1_result {union {icu4x::capi::FixedDecimal* ok; }; bool is_ok;} icu4x_FixedDecimal_from_double_with_round_trip_precision_mv1_result; - icu4x_FixedDecimal_from_double_with_round_trip_precision_mv1_result icu4x_FixedDecimal_from_double_with_round_trip_precision_mv1(double f); - - typedef struct icu4x_FixedDecimal_from_string_mv1_result {union {icu4x::capi::FixedDecimal* ok; icu4x::capi::FixedDecimalParseError err;}; bool is_ok;} icu4x_FixedDecimal_from_string_mv1_result; - icu4x_FixedDecimal_from_string_mv1_result icu4x_FixedDecimal_from_string_mv1(diplomat::capi::DiplomatStringView v); - - uint8_t icu4x_FixedDecimal_digit_at_mv1(const icu4x::capi::FixedDecimal* self, int16_t magnitude); - - int16_t icu4x_FixedDecimal_magnitude_start_mv1(const icu4x::capi::FixedDecimal* self); - - int16_t icu4x_FixedDecimal_magnitude_end_mv1(const icu4x::capi::FixedDecimal* self); - - int16_t icu4x_FixedDecimal_nonzero_magnitude_start_mv1(const icu4x::capi::FixedDecimal* self); - - int16_t icu4x_FixedDecimal_nonzero_magnitude_end_mv1(const icu4x::capi::FixedDecimal* self); - - bool icu4x_FixedDecimal_is_zero_mv1(const icu4x::capi::FixedDecimal* self); - - void icu4x_FixedDecimal_multiply_pow10_mv1(icu4x::capi::FixedDecimal* self, int16_t power); - - icu4x::capi::FixedDecimalSign icu4x_FixedDecimal_sign_mv1(const icu4x::capi::FixedDecimal* self); - - void icu4x_FixedDecimal_set_sign_mv1(icu4x::capi::FixedDecimal* self, icu4x::capi::FixedDecimalSign sign); - - void icu4x_FixedDecimal_apply_sign_display_mv1(icu4x::capi::FixedDecimal* self, icu4x::capi::FixedDecimalSignDisplay sign_display); - - void icu4x_FixedDecimal_trim_start_mv1(icu4x::capi::FixedDecimal* self); - - void icu4x_FixedDecimal_trim_end_mv1(icu4x::capi::FixedDecimal* self); - - void icu4x_FixedDecimal_pad_start_mv1(icu4x::capi::FixedDecimal* self, int16_t position); - - void icu4x_FixedDecimal_pad_end_mv1(icu4x::capi::FixedDecimal* self, int16_t position); - - void icu4x_FixedDecimal_set_max_position_mv1(icu4x::capi::FixedDecimal* self, int16_t position); - - void icu4x_FixedDecimal_round_mv1(icu4x::capi::FixedDecimal* self, int16_t position); - - void icu4x_FixedDecimal_ceil_mv1(icu4x::capi::FixedDecimal* self, int16_t position); - - void icu4x_FixedDecimal_expand_mv1(icu4x::capi::FixedDecimal* self, int16_t position); - - void icu4x_FixedDecimal_floor_mv1(icu4x::capi::FixedDecimal* self, int16_t position); - - void icu4x_FixedDecimal_trunc_mv1(icu4x::capi::FixedDecimal* self, int16_t position); - - void icu4x_FixedDecimal_round_with_mode_mv1(icu4x::capi::FixedDecimal* self, int16_t position, icu4x::capi::FixedDecimalRoundingMode mode); - - void icu4x_FixedDecimal_round_with_mode_and_increment_mv1(icu4x::capi::FixedDecimal* self, int16_t position, icu4x::capi::FixedDecimalRoundingMode mode, icu4x::capi::FixedDecimalRoundingIncrement increment); - - typedef struct icu4x_FixedDecimal_concatenate_end_mv1_result { bool is_ok;} icu4x_FixedDecimal_concatenate_end_mv1_result; - icu4x_FixedDecimal_concatenate_end_mv1_result icu4x_FixedDecimal_concatenate_end_mv1(icu4x::capi::FixedDecimal* self, icu4x::capi::FixedDecimal* other); - - void icu4x_FixedDecimal_to_string_mv1(const icu4x::capi::FixedDecimal* self, diplomat::capi::DiplomatWrite* write); - - - void icu4x_FixedDecimal_destroy_mv1(FixedDecimal* self); - - } // extern "C" -} // namespace capi -} // namespace - -inline std::unique_ptr icu4x::FixedDecimal::from(int32_t v) { - auto result = icu4x::capi::icu4x_FixedDecimal_from_int32_mv1(v); - return std::unique_ptr(icu4x::FixedDecimal::FromFFI(result)); -} - -inline std::unique_ptr icu4x::FixedDecimal::from(uint32_t v) { - auto result = icu4x::capi::icu4x_FixedDecimal_from_uint32_mv1(v); - return std::unique_ptr(icu4x::FixedDecimal::FromFFI(result)); -} - -inline std::unique_ptr icu4x::FixedDecimal::from(int64_t v) { - auto result = icu4x::capi::icu4x_FixedDecimal_from_int64_mv1(v); - return std::unique_ptr(icu4x::FixedDecimal::FromFFI(result)); -} - -inline std::unique_ptr icu4x::FixedDecimal::from(uint64_t v) { - auto result = icu4x::capi::icu4x_FixedDecimal_from_uint64_mv1(v); - return std::unique_ptr(icu4x::FixedDecimal::FromFFI(result)); -} - -inline diplomat::result, icu4x::FixedDecimalLimitError> icu4x::FixedDecimal::from_double_with_integer_precision(double f) { - auto result = icu4x::capi::icu4x_FixedDecimal_from_double_with_integer_precision_mv1(f); - return result.is_ok ? diplomat::result, icu4x::FixedDecimalLimitError>(diplomat::Ok>(std::unique_ptr(icu4x::FixedDecimal::FromFFI(result.ok)))) : diplomat::result, icu4x::FixedDecimalLimitError>(diplomat::Err(icu4x::FixedDecimalLimitError {})); -} - -inline diplomat::result, icu4x::FixedDecimalLimitError> icu4x::FixedDecimal::from_double_with_lower_magnitude(double f, int16_t magnitude) { - auto result = icu4x::capi::icu4x_FixedDecimal_from_double_with_lower_magnitude_mv1(f, - magnitude); - return result.is_ok ? diplomat::result, icu4x::FixedDecimalLimitError>(diplomat::Ok>(std::unique_ptr(icu4x::FixedDecimal::FromFFI(result.ok)))) : diplomat::result, icu4x::FixedDecimalLimitError>(diplomat::Err(icu4x::FixedDecimalLimitError {})); -} - -inline diplomat::result, icu4x::FixedDecimalLimitError> icu4x::FixedDecimal::from_double_with_significant_digits(double f, uint8_t digits) { - auto result = icu4x::capi::icu4x_FixedDecimal_from_double_with_significant_digits_mv1(f, - digits); - return result.is_ok ? diplomat::result, icu4x::FixedDecimalLimitError>(diplomat::Ok>(std::unique_ptr(icu4x::FixedDecimal::FromFFI(result.ok)))) : diplomat::result, icu4x::FixedDecimalLimitError>(diplomat::Err(icu4x::FixedDecimalLimitError {})); -} - -inline diplomat::result, icu4x::FixedDecimalLimitError> icu4x::FixedDecimal::from_double_with_round_trip_precision(double f) { - auto result = icu4x::capi::icu4x_FixedDecimal_from_double_with_round_trip_precision_mv1(f); - return result.is_ok ? diplomat::result, icu4x::FixedDecimalLimitError>(diplomat::Ok>(std::unique_ptr(icu4x::FixedDecimal::FromFFI(result.ok)))) : diplomat::result, icu4x::FixedDecimalLimitError>(diplomat::Err(icu4x::FixedDecimalLimitError {})); -} - -inline diplomat::result, icu4x::FixedDecimalParseError> icu4x::FixedDecimal::from_string(std::string_view v) { - auto result = icu4x::capi::icu4x_FixedDecimal_from_string_mv1({v.data(), v.size()}); - return result.is_ok ? diplomat::result, icu4x::FixedDecimalParseError>(diplomat::Ok>(std::unique_ptr(icu4x::FixedDecimal::FromFFI(result.ok)))) : diplomat::result, icu4x::FixedDecimalParseError>(diplomat::Err(icu4x::FixedDecimalParseError::FromFFI(result.err))); -} - -inline uint8_t icu4x::FixedDecimal::digit_at(int16_t magnitude) const { - auto result = icu4x::capi::icu4x_FixedDecimal_digit_at_mv1(this->AsFFI(), - magnitude); - return result; -} - -inline int16_t icu4x::FixedDecimal::magnitude_start() const { - auto result = icu4x::capi::icu4x_FixedDecimal_magnitude_start_mv1(this->AsFFI()); - return result; -} - -inline int16_t icu4x::FixedDecimal::magnitude_end() const { - auto result = icu4x::capi::icu4x_FixedDecimal_magnitude_end_mv1(this->AsFFI()); - return result; -} - -inline int16_t icu4x::FixedDecimal::nonzero_magnitude_start() const { - auto result = icu4x::capi::icu4x_FixedDecimal_nonzero_magnitude_start_mv1(this->AsFFI()); - return result; -} - -inline int16_t icu4x::FixedDecimal::nonzero_magnitude_end() const { - auto result = icu4x::capi::icu4x_FixedDecimal_nonzero_magnitude_end_mv1(this->AsFFI()); - return result; -} - -inline bool icu4x::FixedDecimal::is_zero() const { - auto result = icu4x::capi::icu4x_FixedDecimal_is_zero_mv1(this->AsFFI()); - return result; -} - -inline void icu4x::FixedDecimal::multiply_pow10(int16_t power) { - icu4x::capi::icu4x_FixedDecimal_multiply_pow10_mv1(this->AsFFI(), - power); -} - -inline icu4x::FixedDecimalSign icu4x::FixedDecimal::sign() const { - auto result = icu4x::capi::icu4x_FixedDecimal_sign_mv1(this->AsFFI()); - return icu4x::FixedDecimalSign::FromFFI(result); -} - -inline void icu4x::FixedDecimal::set_sign(icu4x::FixedDecimalSign sign) { - icu4x::capi::icu4x_FixedDecimal_set_sign_mv1(this->AsFFI(), - sign.AsFFI()); -} - -inline void icu4x::FixedDecimal::apply_sign_display(icu4x::FixedDecimalSignDisplay sign_display) { - icu4x::capi::icu4x_FixedDecimal_apply_sign_display_mv1(this->AsFFI(), - sign_display.AsFFI()); -} - -inline void icu4x::FixedDecimal::trim_start() { - icu4x::capi::icu4x_FixedDecimal_trim_start_mv1(this->AsFFI()); -} - -inline void icu4x::FixedDecimal::trim_end() { - icu4x::capi::icu4x_FixedDecimal_trim_end_mv1(this->AsFFI()); -} - -inline void icu4x::FixedDecimal::pad_start(int16_t position) { - icu4x::capi::icu4x_FixedDecimal_pad_start_mv1(this->AsFFI(), - position); -} - -inline void icu4x::FixedDecimal::pad_end(int16_t position) { - icu4x::capi::icu4x_FixedDecimal_pad_end_mv1(this->AsFFI(), - position); -} - -inline void icu4x::FixedDecimal::set_max_position(int16_t position) { - icu4x::capi::icu4x_FixedDecimal_set_max_position_mv1(this->AsFFI(), - position); -} - -inline void icu4x::FixedDecimal::round(int16_t position) { - icu4x::capi::icu4x_FixedDecimal_round_mv1(this->AsFFI(), - position); -} - -inline void icu4x::FixedDecimal::ceil(int16_t position) { - icu4x::capi::icu4x_FixedDecimal_ceil_mv1(this->AsFFI(), - position); -} - -inline void icu4x::FixedDecimal::expand(int16_t position) { - icu4x::capi::icu4x_FixedDecimal_expand_mv1(this->AsFFI(), - position); -} - -inline void icu4x::FixedDecimal::floor(int16_t position) { - icu4x::capi::icu4x_FixedDecimal_floor_mv1(this->AsFFI(), - position); -} - -inline void icu4x::FixedDecimal::trunc(int16_t position) { - icu4x::capi::icu4x_FixedDecimal_trunc_mv1(this->AsFFI(), - position); -} - -inline void icu4x::FixedDecimal::round_with_mode(int16_t position, icu4x::FixedDecimalRoundingMode mode) { - icu4x::capi::icu4x_FixedDecimal_round_with_mode_mv1(this->AsFFI(), - position, - mode.AsFFI()); -} - -inline void icu4x::FixedDecimal::round_with_mode_and_increment(int16_t position, icu4x::FixedDecimalRoundingMode mode, icu4x::FixedDecimalRoundingIncrement increment) { - icu4x::capi::icu4x_FixedDecimal_round_with_mode_and_increment_mv1(this->AsFFI(), - position, - mode.AsFFI(), - increment.AsFFI()); -} - -inline diplomat::result icu4x::FixedDecimal::concatenate_end(icu4x::FixedDecimal& other) { - auto result = icu4x::capi::icu4x_FixedDecimal_concatenate_end_mv1(this->AsFFI(), - other.AsFFI()); - return result.is_ok ? diplomat::result(diplomat::Ok()) : diplomat::result(diplomat::Err()); -} - -inline std::string icu4x::FixedDecimal::to_string() const { - std::string output; - diplomat::capi::DiplomatWrite write = diplomat::WriteFromString(output); - icu4x::capi::icu4x_FixedDecimal_to_string_mv1(this->AsFFI(), - &write); - return output; -} - -inline const icu4x::capi::FixedDecimal* icu4x::FixedDecimal::AsFFI() const { - return reinterpret_cast(this); -} - -inline icu4x::capi::FixedDecimal* icu4x::FixedDecimal::AsFFI() { - return reinterpret_cast(this); -} - -inline const icu4x::FixedDecimal* icu4x::FixedDecimal::FromFFI(const icu4x::capi::FixedDecimal* ptr) { - return reinterpret_cast(ptr); -} - -inline icu4x::FixedDecimal* icu4x::FixedDecimal::FromFFI(icu4x::capi::FixedDecimal* ptr) { - return reinterpret_cast(ptr); -} - -inline void icu4x::FixedDecimal::operator delete(void* ptr) { - icu4x::capi::icu4x_FixedDecimal_destroy_mv1(reinterpret_cast(ptr)); -} - - -#endif // icu4x_FixedDecimal_HPP diff --git a/ffi/capi/bindings/cpp/icu4x/FixedDecimalFormatter.d.hpp b/ffi/capi/bindings/cpp/icu4x/FixedDecimalFormatter.d.hpp index 96d3aa811a9..fdf52709a21 100644 --- a/ffi/capi/bindings/cpp/icu4x/FixedDecimalFormatter.d.hpp +++ b/ffi/capi/bindings/cpp/icu4x/FixedDecimalFormatter.d.hpp @@ -12,12 +12,12 @@ namespace icu4x { namespace capi { struct DataProvider; } class DataProvider; -namespace capi { struct FixedDecimal; } -class FixedDecimal; namespace capi { struct FixedDecimalFormatter; } class FixedDecimalFormatter; namespace capi { struct Locale; } class Locale; +namespace capi { struct SignedFixedDecimal; } +class SignedFixedDecimal; class DataError; class FixedDecimalGroupingStrategy; } @@ -37,7 +37,7 @@ class FixedDecimalFormatter { inline static diplomat::result, icu4x::DataError> create_with_manual_data(std::string_view plus_sign_prefix, std::string_view plus_sign_suffix, std::string_view minus_sign_prefix, std::string_view minus_sign_suffix, std::string_view decimal_separator, std::string_view grouping_separator, uint8_t primary_group_size, uint8_t secondary_group_size, uint8_t min_group_size, diplomat::span digits, std::optional grouping_strategy); - inline std::string format(const icu4x::FixedDecimal& value) const; + inline std::string format(const icu4x::SignedFixedDecimal& value) const; inline const icu4x::capi::FixedDecimalFormatter* AsFFI() const; inline icu4x::capi::FixedDecimalFormatter* AsFFI(); diff --git a/ffi/capi/bindings/cpp/icu4x/FixedDecimalFormatter.hpp b/ffi/capi/bindings/cpp/icu4x/FixedDecimalFormatter.hpp index e9ff7ac94a9..3e6038427eb 100644 --- a/ffi/capi/bindings/cpp/icu4x/FixedDecimalFormatter.hpp +++ b/ffi/capi/bindings/cpp/icu4x/FixedDecimalFormatter.hpp @@ -12,9 +12,9 @@ #include "../diplomat_runtime.hpp" #include "DataError.hpp" #include "DataProvider.hpp" -#include "FixedDecimal.hpp" #include "FixedDecimalGroupingStrategy.hpp" #include "Locale.hpp" +#include "SignedFixedDecimal.hpp" namespace icu4x { @@ -27,7 +27,7 @@ namespace capi { typedef struct icu4x_FixedDecimalFormatter_create_with_manual_data_mv1_result {union {icu4x::capi::FixedDecimalFormatter* ok; icu4x::capi::DataError err;}; bool is_ok;} icu4x_FixedDecimalFormatter_create_with_manual_data_mv1_result; icu4x_FixedDecimalFormatter_create_with_manual_data_mv1_result icu4x_FixedDecimalFormatter_create_with_manual_data_mv1(diplomat::capi::DiplomatStringView plus_sign_prefix, diplomat::capi::DiplomatStringView plus_sign_suffix, diplomat::capi::DiplomatStringView minus_sign_prefix, diplomat::capi::DiplomatStringView minus_sign_suffix, diplomat::capi::DiplomatStringView decimal_separator, diplomat::capi::DiplomatStringView grouping_separator, uint8_t primary_group_size, uint8_t secondary_group_size, uint8_t min_group_size, diplomat::capi::DiplomatCharView digits, icu4x::capi::FixedDecimalGroupingStrategy_option grouping_strategy); - void icu4x_FixedDecimalFormatter_format_mv1(const icu4x::capi::FixedDecimalFormatter* self, const icu4x::capi::FixedDecimal* value, diplomat::capi::DiplomatWrite* write); + void icu4x_FixedDecimalFormatter_format_mv1(const icu4x::capi::FixedDecimalFormatter* self, const icu4x::capi::SignedFixedDecimal* value, diplomat::capi::DiplomatWrite* write); void icu4x_FixedDecimalFormatter_destroy_mv1(FixedDecimalFormatter* self); @@ -58,7 +58,7 @@ inline diplomat::result, icu4x::Da return result.is_ok ? diplomat::result, icu4x::DataError>(diplomat::Ok>(std::unique_ptr(icu4x::FixedDecimalFormatter::FromFFI(result.ok)))) : diplomat::result, icu4x::DataError>(diplomat::Err(icu4x::DataError::FromFFI(result.err))); } -inline std::string icu4x::FixedDecimalFormatter::format(const icu4x::FixedDecimal& value) const { +inline std::string icu4x::FixedDecimalFormatter::format(const icu4x::SignedFixedDecimal& value) const { std::string output; diplomat::capi::DiplomatWrite write = diplomat::WriteFromString(output); icu4x::capi::icu4x_FixedDecimalFormatter_format_mv1(this->AsFFI(), diff --git a/ffi/capi/bindings/cpp/icu4x/FixedDecimalRoundingMode.d.hpp b/ffi/capi/bindings/cpp/icu4x/FixedDecimalRoundingMode.d.hpp deleted file mode 100644 index 6c6cf2f26e4..00000000000 --- a/ffi/capi/bindings/cpp/icu4x/FixedDecimalRoundingMode.d.hpp +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef icu4x_FixedDecimalRoundingMode_D_HPP -#define icu4x_FixedDecimalRoundingMode_D_HPP - -#include -#include -#include -#include -#include -#include -#include "../diplomat_runtime.hpp" - - -namespace icu4x { -namespace capi { - enum FixedDecimalRoundingMode { - FixedDecimalRoundingMode_Ceil = 0, - FixedDecimalRoundingMode_Expand = 1, - FixedDecimalRoundingMode_Floor = 2, - FixedDecimalRoundingMode_Trunc = 3, - FixedDecimalRoundingMode_HalfCeil = 4, - FixedDecimalRoundingMode_HalfExpand = 5, - FixedDecimalRoundingMode_HalfFloor = 6, - FixedDecimalRoundingMode_HalfTrunc = 7, - FixedDecimalRoundingMode_HalfEven = 8, - }; - - typedef struct FixedDecimalRoundingMode_option {union { FixedDecimalRoundingMode ok; }; bool is_ok; } FixedDecimalRoundingMode_option; -} // namespace capi -} // namespace - -namespace icu4x { -class FixedDecimalRoundingMode { -public: - enum Value { - Ceil = 0, - Expand = 1, - Floor = 2, - Trunc = 3, - HalfCeil = 4, - HalfExpand = 5, - HalfFloor = 6, - HalfTrunc = 7, - HalfEven = 8, - }; - - FixedDecimalRoundingMode() = default; - // Implicit conversions between enum and ::Value - constexpr FixedDecimalRoundingMode(Value v) : value(v) {} - constexpr operator Value() const { return value; } - // Prevent usage as boolean value - explicit operator bool() const = delete; - - inline icu4x::capi::FixedDecimalRoundingMode AsFFI() const; - inline static icu4x::FixedDecimalRoundingMode FromFFI(icu4x::capi::FixedDecimalRoundingMode c_enum); -private: - Value value; -}; - -} // namespace -#endif // icu4x_FixedDecimalRoundingMode_D_HPP diff --git a/ffi/capi/bindings/cpp/icu4x/FixedDecimalRoundingMode.hpp b/ffi/capi/bindings/cpp/icu4x/FixedDecimalRoundingMode.hpp deleted file mode 100644 index 962bafc3048..00000000000 --- a/ffi/capi/bindings/cpp/icu4x/FixedDecimalRoundingMode.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef icu4x_FixedDecimalRoundingMode_HPP -#define icu4x_FixedDecimalRoundingMode_HPP - -#include "FixedDecimalRoundingMode.d.hpp" - -#include -#include -#include -#include -#include -#include -#include "../diplomat_runtime.hpp" - - -namespace icu4x { -namespace capi { - extern "C" { - - - } // extern "C" -} // namespace capi -} // namespace - -inline icu4x::capi::FixedDecimalRoundingMode icu4x::FixedDecimalRoundingMode::AsFFI() const { - return static_cast(value); -} - -inline icu4x::FixedDecimalRoundingMode icu4x::FixedDecimalRoundingMode::FromFFI(icu4x::capi::FixedDecimalRoundingMode c_enum) { - switch (c_enum) { - case icu4x::capi::FixedDecimalRoundingMode_Ceil: - case icu4x::capi::FixedDecimalRoundingMode_Expand: - case icu4x::capi::FixedDecimalRoundingMode_Floor: - case icu4x::capi::FixedDecimalRoundingMode_Trunc: - case icu4x::capi::FixedDecimalRoundingMode_HalfCeil: - case icu4x::capi::FixedDecimalRoundingMode_HalfExpand: - case icu4x::capi::FixedDecimalRoundingMode_HalfFloor: - case icu4x::capi::FixedDecimalRoundingMode_HalfTrunc: - case icu4x::capi::FixedDecimalRoundingMode_HalfEven: - return static_cast(c_enum); - default: - abort(); - } -} -#endif // icu4x_FixedDecimalRoundingMode_HPP diff --git a/ffi/capi/bindings/cpp/icu4x/FixedDecimalSignedRoundingMode.d.hpp b/ffi/capi/bindings/cpp/icu4x/FixedDecimalSignedRoundingMode.d.hpp new file mode 100644 index 00000000000..fee54ad2735 --- /dev/null +++ b/ffi/capi/bindings/cpp/icu4x/FixedDecimalSignedRoundingMode.d.hpp @@ -0,0 +1,60 @@ +#ifndef icu4x_FixedDecimalSignedRoundingMode_D_HPP +#define icu4x_FixedDecimalSignedRoundingMode_D_HPP + +#include +#include +#include +#include +#include +#include +#include "../diplomat_runtime.hpp" + + +namespace icu4x { +namespace capi { + enum FixedDecimalSignedRoundingMode { + FixedDecimalSignedRoundingMode_Expand = 0, + FixedDecimalSignedRoundingMode_Trunc = 1, + FixedDecimalSignedRoundingMode_HalfExpand = 2, + FixedDecimalSignedRoundingMode_HalfTrunc = 3, + FixedDecimalSignedRoundingMode_HalfEven = 4, + FixedDecimalSignedRoundingMode_Ceil = 5, + FixedDecimalSignedRoundingMode_Floor = 6, + FixedDecimalSignedRoundingMode_HalfCeil = 7, + FixedDecimalSignedRoundingMode_HalfFloor = 8, + }; + + typedef struct FixedDecimalSignedRoundingMode_option {union { FixedDecimalSignedRoundingMode ok; }; bool is_ok; } FixedDecimalSignedRoundingMode_option; +} // namespace capi +} // namespace + +namespace icu4x { +class FixedDecimalSignedRoundingMode { +public: + enum Value { + Expand = 0, + Trunc = 1, + HalfExpand = 2, + HalfTrunc = 3, + HalfEven = 4, + Ceil = 5, + Floor = 6, + HalfCeil = 7, + HalfFloor = 8, + }; + + FixedDecimalSignedRoundingMode() = default; + // Implicit conversions between enum and ::Value + constexpr FixedDecimalSignedRoundingMode(Value v) : value(v) {} + constexpr operator Value() const { return value; } + // Prevent usage as boolean value + explicit operator bool() const = delete; + + inline icu4x::capi::FixedDecimalSignedRoundingMode AsFFI() const; + inline static icu4x::FixedDecimalSignedRoundingMode FromFFI(icu4x::capi::FixedDecimalSignedRoundingMode c_enum); +private: + Value value; +}; + +} // namespace +#endif // icu4x_FixedDecimalSignedRoundingMode_D_HPP diff --git a/ffi/capi/bindings/cpp/icu4x/FixedDecimalSignedRoundingMode.hpp b/ffi/capi/bindings/cpp/icu4x/FixedDecimalSignedRoundingMode.hpp new file mode 100644 index 00000000000..0d4c1b93037 --- /dev/null +++ b/ffi/capi/bindings/cpp/icu4x/FixedDecimalSignedRoundingMode.hpp @@ -0,0 +1,44 @@ +#ifndef icu4x_FixedDecimalSignedRoundingMode_HPP +#define icu4x_FixedDecimalSignedRoundingMode_HPP + +#include "FixedDecimalSignedRoundingMode.d.hpp" + +#include +#include +#include +#include +#include +#include +#include "../diplomat_runtime.hpp" + + +namespace icu4x { +namespace capi { + extern "C" { + + + } // extern "C" +} // namespace capi +} // namespace + +inline icu4x::capi::FixedDecimalSignedRoundingMode icu4x::FixedDecimalSignedRoundingMode::AsFFI() const { + return static_cast(value); +} + +inline icu4x::FixedDecimalSignedRoundingMode icu4x::FixedDecimalSignedRoundingMode::FromFFI(icu4x::capi::FixedDecimalSignedRoundingMode c_enum) { + switch (c_enum) { + case icu4x::capi::FixedDecimalSignedRoundingMode_Expand: + case icu4x::capi::FixedDecimalSignedRoundingMode_Trunc: + case icu4x::capi::FixedDecimalSignedRoundingMode_HalfExpand: + case icu4x::capi::FixedDecimalSignedRoundingMode_HalfTrunc: + case icu4x::capi::FixedDecimalSignedRoundingMode_HalfEven: + case icu4x::capi::FixedDecimalSignedRoundingMode_Ceil: + case icu4x::capi::FixedDecimalSignedRoundingMode_Floor: + case icu4x::capi::FixedDecimalSignedRoundingMode_HalfCeil: + case icu4x::capi::FixedDecimalSignedRoundingMode_HalfFloor: + return static_cast(c_enum); + default: + abort(); + } +} +#endif // icu4x_FixedDecimalSignedRoundingMode_HPP diff --git a/ffi/capi/bindings/cpp/icu4x/PluralOperands.d.hpp b/ffi/capi/bindings/cpp/icu4x/PluralOperands.d.hpp index 27ec9275592..f9b2bbd7fc4 100644 --- a/ffi/capi/bindings/cpp/icu4x/PluralOperands.d.hpp +++ b/ffi/capi/bindings/cpp/icu4x/PluralOperands.d.hpp @@ -10,10 +10,10 @@ #include "../diplomat_runtime.hpp" namespace icu4x { -namespace capi { struct FixedDecimal; } -class FixedDecimal; namespace capi { struct PluralOperands; } class PluralOperands; +namespace capi { struct SignedFixedDecimal; } +class SignedFixedDecimal; class FixedDecimalParseError; } @@ -30,7 +30,7 @@ class PluralOperands { inline static diplomat::result, icu4x::FixedDecimalParseError> from_string(std::string_view s); - inline static std::unique_ptr from_fixed_decimal(const icu4x::FixedDecimal& x); + inline static std::unique_ptr from_fixed_decimal(const icu4x::SignedFixedDecimal& x); inline const icu4x::capi::PluralOperands* AsFFI() const; inline icu4x::capi::PluralOperands* AsFFI(); diff --git a/ffi/capi/bindings/cpp/icu4x/PluralOperands.hpp b/ffi/capi/bindings/cpp/icu4x/PluralOperands.hpp index 0bf6c9b0a9e..548d42f6e4a 100644 --- a/ffi/capi/bindings/cpp/icu4x/PluralOperands.hpp +++ b/ffi/capi/bindings/cpp/icu4x/PluralOperands.hpp @@ -10,8 +10,8 @@ #include #include #include "../diplomat_runtime.hpp" -#include "FixedDecimal.hpp" #include "FixedDecimalParseError.hpp" +#include "SignedFixedDecimal.hpp" namespace icu4x { @@ -21,7 +21,7 @@ namespace capi { typedef struct icu4x_PluralOperands_from_string_mv1_result {union {icu4x::capi::PluralOperands* ok; icu4x::capi::FixedDecimalParseError err;}; bool is_ok;} icu4x_PluralOperands_from_string_mv1_result; icu4x_PluralOperands_from_string_mv1_result icu4x_PluralOperands_from_string_mv1(diplomat::capi::DiplomatStringView s); - icu4x::capi::PluralOperands* icu4x_PluralOperands_from_fixed_decimal_mv1(const icu4x::capi::FixedDecimal* x); + icu4x::capi::PluralOperands* icu4x_PluralOperands_from_fixed_decimal_mv1(const icu4x::capi::SignedFixedDecimal* x); void icu4x_PluralOperands_destroy_mv1(PluralOperands* self); @@ -35,7 +35,7 @@ inline diplomat::result, icu4x::FixedDeci return result.is_ok ? diplomat::result, icu4x::FixedDecimalParseError>(diplomat::Ok>(std::unique_ptr(icu4x::PluralOperands::FromFFI(result.ok)))) : diplomat::result, icu4x::FixedDecimalParseError>(diplomat::Err(icu4x::FixedDecimalParseError::FromFFI(result.err))); } -inline std::unique_ptr icu4x::PluralOperands::from_fixed_decimal(const icu4x::FixedDecimal& x) { +inline std::unique_ptr icu4x::PluralOperands::from_fixed_decimal(const icu4x::SignedFixedDecimal& x) { auto result = icu4x::capi::icu4x_PluralOperands_from_fixed_decimal_mv1(x.AsFFI()); return std::unique_ptr(icu4x::PluralOperands::FromFFI(result)); } diff --git a/ffi/capi/bindings/cpp/icu4x/SignedFixedDecimal.d.hpp b/ffi/capi/bindings/cpp/icu4x/SignedFixedDecimal.d.hpp new file mode 100644 index 00000000000..8b4adb670a0 --- /dev/null +++ b/ffi/capi/bindings/cpp/icu4x/SignedFixedDecimal.d.hpp @@ -0,0 +1,115 @@ +#ifndef icu4x_SignedFixedDecimal_D_HPP +#define icu4x_SignedFixedDecimal_D_HPP + +#include +#include +#include +#include +#include +#include +#include "../diplomat_runtime.hpp" + +namespace icu4x { +namespace capi { struct SignedFixedDecimal; } +class SignedFixedDecimal; +struct FixedDecimalLimitError; +class FixedDecimalParseError; +class FixedDecimalRoundingIncrement; +class FixedDecimalSign; +class FixedDecimalSignDisplay; +class FixedDecimalSignedRoundingMode; +} + + +namespace icu4x { +namespace capi { + struct SignedFixedDecimal; +} // namespace capi +} // namespace + +namespace icu4x { +class SignedFixedDecimal { +public: + + inline static std::unique_ptr from(int32_t v); + + inline static std::unique_ptr from(uint32_t v); + + inline static std::unique_ptr from(int64_t v); + + inline static std::unique_ptr from(uint64_t v); + + inline static diplomat::result, icu4x::FixedDecimalLimitError> from_double_with_integer_precision(double f); + + inline static diplomat::result, icu4x::FixedDecimalLimitError> from_double_with_lower_magnitude(double f, int16_t magnitude); + + inline static diplomat::result, icu4x::FixedDecimalLimitError> from_double_with_significant_digits(double f, uint8_t digits); + + inline static diplomat::result, icu4x::FixedDecimalLimitError> from_double_with_round_trip_precision(double f); + + inline static diplomat::result, icu4x::FixedDecimalParseError> from_string(std::string_view v); + + inline uint8_t digit_at(int16_t magnitude) const; + + inline int16_t magnitude_start() const; + + inline int16_t magnitude_end() const; + + inline int16_t nonzero_magnitude_start() const; + + inline int16_t nonzero_magnitude_end() const; + + inline bool is_zero() const; + + inline void multiply_pow10(int16_t power); + + inline icu4x::FixedDecimalSign sign() const; + + inline void set_sign(icu4x::FixedDecimalSign sign); + + inline void apply_sign_display(icu4x::FixedDecimalSignDisplay sign_display); + + inline void trim_start(); + + inline void trim_end(); + + inline void pad_start(int16_t position); + + inline void pad_end(int16_t position); + + inline void set_max_position(int16_t position); + + inline void round(int16_t position); + + inline void ceil(int16_t position); + + inline void expand(int16_t position); + + inline void floor(int16_t position); + + inline void trunc(int16_t position); + + inline void round_with_mode(int16_t position, icu4x::FixedDecimalSignedRoundingMode mode); + + inline void round_with_mode_and_increment(int16_t position, icu4x::FixedDecimalSignedRoundingMode mode, icu4x::FixedDecimalRoundingIncrement increment); + + inline diplomat::result concatenate_end(icu4x::SignedFixedDecimal& other); + + inline std::string to_string() const; + + inline const icu4x::capi::SignedFixedDecimal* AsFFI() const; + inline icu4x::capi::SignedFixedDecimal* AsFFI(); + inline static const icu4x::SignedFixedDecimal* FromFFI(const icu4x::capi::SignedFixedDecimal* ptr); + inline static icu4x::SignedFixedDecimal* FromFFI(icu4x::capi::SignedFixedDecimal* ptr); + inline static void operator delete(void* ptr); +private: + SignedFixedDecimal() = delete; + SignedFixedDecimal(const icu4x::SignedFixedDecimal&) = delete; + SignedFixedDecimal(icu4x::SignedFixedDecimal&&) noexcept = delete; + SignedFixedDecimal operator=(const icu4x::SignedFixedDecimal&) = delete; + SignedFixedDecimal operator=(icu4x::SignedFixedDecimal&&) noexcept = delete; + static void operator delete[](void*, size_t) = delete; +}; + +} // namespace +#endif // icu4x_SignedFixedDecimal_D_HPP diff --git a/ffi/capi/bindings/cpp/icu4x/SignedFixedDecimal.hpp b/ffi/capi/bindings/cpp/icu4x/SignedFixedDecimal.hpp new file mode 100644 index 00000000000..524b5569bd5 --- /dev/null +++ b/ffi/capi/bindings/cpp/icu4x/SignedFixedDecimal.hpp @@ -0,0 +1,298 @@ +#ifndef icu4x_SignedFixedDecimal_HPP +#define icu4x_SignedFixedDecimal_HPP + +#include "SignedFixedDecimal.d.hpp" + +#include +#include +#include +#include +#include +#include +#include "../diplomat_runtime.hpp" +#include "FixedDecimalLimitError.hpp" +#include "FixedDecimalParseError.hpp" +#include "FixedDecimalRoundingIncrement.hpp" +#include "FixedDecimalSign.hpp" +#include "FixedDecimalSignDisplay.hpp" +#include "FixedDecimalSignedRoundingMode.hpp" + + +namespace icu4x { +namespace capi { + extern "C" { + + icu4x::capi::SignedFixedDecimal* icu4x_SignedFixedDecimal_from_int32_mv1(int32_t v); + + icu4x::capi::SignedFixedDecimal* icu4x_SignedFixedDecimal_from_uint32_mv1(uint32_t v); + + icu4x::capi::SignedFixedDecimal* icu4x_SignedFixedDecimal_from_int64_mv1(int64_t v); + + icu4x::capi::SignedFixedDecimal* icu4x_SignedFixedDecimal_from_uint64_mv1(uint64_t v); + + typedef struct icu4x_SignedFixedDecimal_from_double_with_integer_precision_mv1_result {union {icu4x::capi::SignedFixedDecimal* ok; }; bool is_ok;} icu4x_SignedFixedDecimal_from_double_with_integer_precision_mv1_result; + icu4x_SignedFixedDecimal_from_double_with_integer_precision_mv1_result icu4x_SignedFixedDecimal_from_double_with_integer_precision_mv1(double f); + + typedef struct icu4x_SignedFixedDecimal_from_double_with_lower_magnitude_mv1_result {union {icu4x::capi::SignedFixedDecimal* ok; }; bool is_ok;} icu4x_SignedFixedDecimal_from_double_with_lower_magnitude_mv1_result; + icu4x_SignedFixedDecimal_from_double_with_lower_magnitude_mv1_result icu4x_SignedFixedDecimal_from_double_with_lower_magnitude_mv1(double f, int16_t magnitude); + + typedef struct icu4x_SignedFixedDecimal_from_double_with_significant_digits_mv1_result {union {icu4x::capi::SignedFixedDecimal* ok; }; bool is_ok;} icu4x_SignedFixedDecimal_from_double_with_significant_digits_mv1_result; + icu4x_SignedFixedDecimal_from_double_with_significant_digits_mv1_result icu4x_SignedFixedDecimal_from_double_with_significant_digits_mv1(double f, uint8_t digits); + + typedef struct icu4x_SignedFixedDecimal_from_double_with_round_trip_precision_mv1_result {union {icu4x::capi::SignedFixedDecimal* ok; }; bool is_ok;} icu4x_SignedFixedDecimal_from_double_with_round_trip_precision_mv1_result; + icu4x_SignedFixedDecimal_from_double_with_round_trip_precision_mv1_result icu4x_SignedFixedDecimal_from_double_with_round_trip_precision_mv1(double f); + + typedef struct icu4x_SignedFixedDecimal_from_string_mv1_result {union {icu4x::capi::SignedFixedDecimal* ok; icu4x::capi::FixedDecimalParseError err;}; bool is_ok;} icu4x_SignedFixedDecimal_from_string_mv1_result; + icu4x_SignedFixedDecimal_from_string_mv1_result icu4x_SignedFixedDecimal_from_string_mv1(diplomat::capi::DiplomatStringView v); + + uint8_t icu4x_SignedFixedDecimal_digit_at_mv1(const icu4x::capi::SignedFixedDecimal* self, int16_t magnitude); + + int16_t icu4x_SignedFixedDecimal_magnitude_start_mv1(const icu4x::capi::SignedFixedDecimal* self); + + int16_t icu4x_SignedFixedDecimal_magnitude_end_mv1(const icu4x::capi::SignedFixedDecimal* self); + + int16_t icu4x_SignedFixedDecimal_nonzero_magnitude_start_mv1(const icu4x::capi::SignedFixedDecimal* self); + + int16_t icu4x_SignedFixedDecimal_nonzero_magnitude_end_mv1(const icu4x::capi::SignedFixedDecimal* self); + + bool icu4x_SignedFixedDecimal_is_zero_mv1(const icu4x::capi::SignedFixedDecimal* self); + + void icu4x_SignedFixedDecimal_multiply_pow10_mv1(icu4x::capi::SignedFixedDecimal* self, int16_t power); + + icu4x::capi::FixedDecimalSign icu4x_SignedFixedDecimal_sign_mv1(const icu4x::capi::SignedFixedDecimal* self); + + void icu4x_SignedFixedDecimal_set_sign_mv1(icu4x::capi::SignedFixedDecimal* self, icu4x::capi::FixedDecimalSign sign); + + void icu4x_SignedFixedDecimal_apply_sign_display_mv1(icu4x::capi::SignedFixedDecimal* self, icu4x::capi::FixedDecimalSignDisplay sign_display); + + void icu4x_SignedFixedDecimal_trim_start_mv1(icu4x::capi::SignedFixedDecimal* self); + + void icu4x_SignedFixedDecimal_trim_end_mv1(icu4x::capi::SignedFixedDecimal* self); + + void icu4x_SignedFixedDecimal_pad_start_mv1(icu4x::capi::SignedFixedDecimal* self, int16_t position); + + void icu4x_SignedFixedDecimal_pad_end_mv1(icu4x::capi::SignedFixedDecimal* self, int16_t position); + + void icu4x_SignedFixedDecimal_set_max_position_mv1(icu4x::capi::SignedFixedDecimal* self, int16_t position); + + void icu4x_SignedFixedDecimal_round_mv1(icu4x::capi::SignedFixedDecimal* self, int16_t position); + + void icu4x_SignedFixedDecimal_ceil_mv1(icu4x::capi::SignedFixedDecimal* self, int16_t position); + + void icu4x_SignedFixedDecimal_expand_mv1(icu4x::capi::SignedFixedDecimal* self, int16_t position); + + void icu4x_SignedFixedDecimal_floor_mv1(icu4x::capi::SignedFixedDecimal* self, int16_t position); + + void icu4x_SignedFixedDecimal_trunc_mv1(icu4x::capi::SignedFixedDecimal* self, int16_t position); + + void icu4x_SignedFixedDecimal_round_with_mode_mv1(icu4x::capi::SignedFixedDecimal* self, int16_t position, icu4x::capi::FixedDecimalSignedRoundingMode mode); + + void icu4x_SignedFixedDecimal_round_with_mode_and_increment_mv1(icu4x::capi::SignedFixedDecimal* self, int16_t position, icu4x::capi::FixedDecimalSignedRoundingMode mode, icu4x::capi::FixedDecimalRoundingIncrement increment); + + typedef struct icu4x_SignedFixedDecimal_concatenate_end_mv1_result { bool is_ok;} icu4x_SignedFixedDecimal_concatenate_end_mv1_result; + icu4x_SignedFixedDecimal_concatenate_end_mv1_result icu4x_SignedFixedDecimal_concatenate_end_mv1(icu4x::capi::SignedFixedDecimal* self, icu4x::capi::SignedFixedDecimal* other); + + void icu4x_SignedFixedDecimal_to_string_mv1(const icu4x::capi::SignedFixedDecimal* self, diplomat::capi::DiplomatWrite* write); + + + void icu4x_SignedFixedDecimal_destroy_mv1(SignedFixedDecimal* self); + + } // extern "C" +} // namespace capi +} // namespace + +inline std::unique_ptr icu4x::SignedFixedDecimal::from(int32_t v) { + auto result = icu4x::capi::icu4x_SignedFixedDecimal_from_int32_mv1(v); + return std::unique_ptr(icu4x::SignedFixedDecimal::FromFFI(result)); +} + +inline std::unique_ptr icu4x::SignedFixedDecimal::from(uint32_t v) { + auto result = icu4x::capi::icu4x_SignedFixedDecimal_from_uint32_mv1(v); + return std::unique_ptr(icu4x::SignedFixedDecimal::FromFFI(result)); +} + +inline std::unique_ptr icu4x::SignedFixedDecimal::from(int64_t v) { + auto result = icu4x::capi::icu4x_SignedFixedDecimal_from_int64_mv1(v); + return std::unique_ptr(icu4x::SignedFixedDecimal::FromFFI(result)); +} + +inline std::unique_ptr icu4x::SignedFixedDecimal::from(uint64_t v) { + auto result = icu4x::capi::icu4x_SignedFixedDecimal_from_uint64_mv1(v); + return std::unique_ptr(icu4x::SignedFixedDecimal::FromFFI(result)); +} + +inline diplomat::result, icu4x::FixedDecimalLimitError> icu4x::SignedFixedDecimal::from_double_with_integer_precision(double f) { + auto result = icu4x::capi::icu4x_SignedFixedDecimal_from_double_with_integer_precision_mv1(f); + return result.is_ok ? diplomat::result, icu4x::FixedDecimalLimitError>(diplomat::Ok>(std::unique_ptr(icu4x::SignedFixedDecimal::FromFFI(result.ok)))) : diplomat::result, icu4x::FixedDecimalLimitError>(diplomat::Err(icu4x::FixedDecimalLimitError {})); +} + +inline diplomat::result, icu4x::FixedDecimalLimitError> icu4x::SignedFixedDecimal::from_double_with_lower_magnitude(double f, int16_t magnitude) { + auto result = icu4x::capi::icu4x_SignedFixedDecimal_from_double_with_lower_magnitude_mv1(f, + magnitude); + return result.is_ok ? diplomat::result, icu4x::FixedDecimalLimitError>(diplomat::Ok>(std::unique_ptr(icu4x::SignedFixedDecimal::FromFFI(result.ok)))) : diplomat::result, icu4x::FixedDecimalLimitError>(diplomat::Err(icu4x::FixedDecimalLimitError {})); +} + +inline diplomat::result, icu4x::FixedDecimalLimitError> icu4x::SignedFixedDecimal::from_double_with_significant_digits(double f, uint8_t digits) { + auto result = icu4x::capi::icu4x_SignedFixedDecimal_from_double_with_significant_digits_mv1(f, + digits); + return result.is_ok ? diplomat::result, icu4x::FixedDecimalLimitError>(diplomat::Ok>(std::unique_ptr(icu4x::SignedFixedDecimal::FromFFI(result.ok)))) : diplomat::result, icu4x::FixedDecimalLimitError>(diplomat::Err(icu4x::FixedDecimalLimitError {})); +} + +inline diplomat::result, icu4x::FixedDecimalLimitError> icu4x::SignedFixedDecimal::from_double_with_round_trip_precision(double f) { + auto result = icu4x::capi::icu4x_SignedFixedDecimal_from_double_with_round_trip_precision_mv1(f); + return result.is_ok ? diplomat::result, icu4x::FixedDecimalLimitError>(diplomat::Ok>(std::unique_ptr(icu4x::SignedFixedDecimal::FromFFI(result.ok)))) : diplomat::result, icu4x::FixedDecimalLimitError>(diplomat::Err(icu4x::FixedDecimalLimitError {})); +} + +inline diplomat::result, icu4x::FixedDecimalParseError> icu4x::SignedFixedDecimal::from_string(std::string_view v) { + auto result = icu4x::capi::icu4x_SignedFixedDecimal_from_string_mv1({v.data(), v.size()}); + return result.is_ok ? diplomat::result, icu4x::FixedDecimalParseError>(diplomat::Ok>(std::unique_ptr(icu4x::SignedFixedDecimal::FromFFI(result.ok)))) : diplomat::result, icu4x::FixedDecimalParseError>(diplomat::Err(icu4x::FixedDecimalParseError::FromFFI(result.err))); +} + +inline uint8_t icu4x::SignedFixedDecimal::digit_at(int16_t magnitude) const { + auto result = icu4x::capi::icu4x_SignedFixedDecimal_digit_at_mv1(this->AsFFI(), + magnitude); + return result; +} + +inline int16_t icu4x::SignedFixedDecimal::magnitude_start() const { + auto result = icu4x::capi::icu4x_SignedFixedDecimal_magnitude_start_mv1(this->AsFFI()); + return result; +} + +inline int16_t icu4x::SignedFixedDecimal::magnitude_end() const { + auto result = icu4x::capi::icu4x_SignedFixedDecimal_magnitude_end_mv1(this->AsFFI()); + return result; +} + +inline int16_t icu4x::SignedFixedDecimal::nonzero_magnitude_start() const { + auto result = icu4x::capi::icu4x_SignedFixedDecimal_nonzero_magnitude_start_mv1(this->AsFFI()); + return result; +} + +inline int16_t icu4x::SignedFixedDecimal::nonzero_magnitude_end() const { + auto result = icu4x::capi::icu4x_SignedFixedDecimal_nonzero_magnitude_end_mv1(this->AsFFI()); + return result; +} + +inline bool icu4x::SignedFixedDecimal::is_zero() const { + auto result = icu4x::capi::icu4x_SignedFixedDecimal_is_zero_mv1(this->AsFFI()); + return result; +} + +inline void icu4x::SignedFixedDecimal::multiply_pow10(int16_t power) { + icu4x::capi::icu4x_SignedFixedDecimal_multiply_pow10_mv1(this->AsFFI(), + power); +} + +inline icu4x::FixedDecimalSign icu4x::SignedFixedDecimal::sign() const { + auto result = icu4x::capi::icu4x_SignedFixedDecimal_sign_mv1(this->AsFFI()); + return icu4x::FixedDecimalSign::FromFFI(result); +} + +inline void icu4x::SignedFixedDecimal::set_sign(icu4x::FixedDecimalSign sign) { + icu4x::capi::icu4x_SignedFixedDecimal_set_sign_mv1(this->AsFFI(), + sign.AsFFI()); +} + +inline void icu4x::SignedFixedDecimal::apply_sign_display(icu4x::FixedDecimalSignDisplay sign_display) { + icu4x::capi::icu4x_SignedFixedDecimal_apply_sign_display_mv1(this->AsFFI(), + sign_display.AsFFI()); +} + +inline void icu4x::SignedFixedDecimal::trim_start() { + icu4x::capi::icu4x_SignedFixedDecimal_trim_start_mv1(this->AsFFI()); +} + +inline void icu4x::SignedFixedDecimal::trim_end() { + icu4x::capi::icu4x_SignedFixedDecimal_trim_end_mv1(this->AsFFI()); +} + +inline void icu4x::SignedFixedDecimal::pad_start(int16_t position) { + icu4x::capi::icu4x_SignedFixedDecimal_pad_start_mv1(this->AsFFI(), + position); +} + +inline void icu4x::SignedFixedDecimal::pad_end(int16_t position) { + icu4x::capi::icu4x_SignedFixedDecimal_pad_end_mv1(this->AsFFI(), + position); +} + +inline void icu4x::SignedFixedDecimal::set_max_position(int16_t position) { + icu4x::capi::icu4x_SignedFixedDecimal_set_max_position_mv1(this->AsFFI(), + position); +} + +inline void icu4x::SignedFixedDecimal::round(int16_t position) { + icu4x::capi::icu4x_SignedFixedDecimal_round_mv1(this->AsFFI(), + position); +} + +inline void icu4x::SignedFixedDecimal::ceil(int16_t position) { + icu4x::capi::icu4x_SignedFixedDecimal_ceil_mv1(this->AsFFI(), + position); +} + +inline void icu4x::SignedFixedDecimal::expand(int16_t position) { + icu4x::capi::icu4x_SignedFixedDecimal_expand_mv1(this->AsFFI(), + position); +} + +inline void icu4x::SignedFixedDecimal::floor(int16_t position) { + icu4x::capi::icu4x_SignedFixedDecimal_floor_mv1(this->AsFFI(), + position); +} + +inline void icu4x::SignedFixedDecimal::trunc(int16_t position) { + icu4x::capi::icu4x_SignedFixedDecimal_trunc_mv1(this->AsFFI(), + position); +} + +inline void icu4x::SignedFixedDecimal::round_with_mode(int16_t position, icu4x::FixedDecimalSignedRoundingMode mode) { + icu4x::capi::icu4x_SignedFixedDecimal_round_with_mode_mv1(this->AsFFI(), + position, + mode.AsFFI()); +} + +inline void icu4x::SignedFixedDecimal::round_with_mode_and_increment(int16_t position, icu4x::FixedDecimalSignedRoundingMode mode, icu4x::FixedDecimalRoundingIncrement increment) { + icu4x::capi::icu4x_SignedFixedDecimal_round_with_mode_and_increment_mv1(this->AsFFI(), + position, + mode.AsFFI(), + increment.AsFFI()); +} + +inline diplomat::result icu4x::SignedFixedDecimal::concatenate_end(icu4x::SignedFixedDecimal& other) { + auto result = icu4x::capi::icu4x_SignedFixedDecimal_concatenate_end_mv1(this->AsFFI(), + other.AsFFI()); + return result.is_ok ? diplomat::result(diplomat::Ok()) : diplomat::result(diplomat::Err()); +} + +inline std::string icu4x::SignedFixedDecimal::to_string() const { + std::string output; + diplomat::capi::DiplomatWrite write = diplomat::WriteFromString(output); + icu4x::capi::icu4x_SignedFixedDecimal_to_string_mv1(this->AsFFI(), + &write); + return output; +} + +inline const icu4x::capi::SignedFixedDecimal* icu4x::SignedFixedDecimal::AsFFI() const { + return reinterpret_cast(this); +} + +inline icu4x::capi::SignedFixedDecimal* icu4x::SignedFixedDecimal::AsFFI() { + return reinterpret_cast(this); +} + +inline const icu4x::SignedFixedDecimal* icu4x::SignedFixedDecimal::FromFFI(const icu4x::capi::SignedFixedDecimal* ptr) { + return reinterpret_cast(ptr); +} + +inline icu4x::SignedFixedDecimal* icu4x::SignedFixedDecimal::FromFFI(icu4x::capi::SignedFixedDecimal* ptr) { + return reinterpret_cast(ptr); +} + +inline void icu4x::SignedFixedDecimal::operator delete(void* ptr) { + icu4x::capi::icu4x_SignedFixedDecimal_destroy_mv1(reinterpret_cast(ptr)); +} + + +#endif // icu4x_SignedFixedDecimal_HPP diff --git a/ffi/capi/bindings/dart/FixedDecimal.g.dart b/ffi/capi/bindings/dart/FixedDecimal.g.dart deleted file mode 100644 index ab9b3376fd2..00000000000 --- a/ffi/capi/bindings/dart/FixedDecimal.g.dart +++ /dev/null @@ -1,397 +0,0 @@ -// generated by diplomat-tool - -part of 'lib.g.dart'; - -/// See the [Rust documentation for `FixedDecimal`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html) for more information. -final class FixedDecimal implements ffi.Finalizable { - final ffi.Pointer _ffi; - - // These are "used" in the sense that they keep dependencies alive - // ignore: unused_field - final core.List _selfEdge; - - // This takes in a list of lifetime edges (including for &self borrows) - // corresponding to data this may borrow from. These should be flat arrays containing - // references to objects, and this object will hold on to them to keep them alive and - // maintain borrow validity. - FixedDecimal._fromFfi(this._ffi, this._selfEdge) { - if (_selfEdge.isEmpty) { - _finalizer.attach(this, _ffi.cast()); - } - } - - static final _finalizer = ffi.NativeFinalizer(ffi.Native.addressOf(_icu4x_FixedDecimal_destroy_mv1)); - - /// Construct an [`FixedDecimal`] from an integer. - /// - /// See the [Rust documentation for `FixedDecimal`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html) for more information. - factory FixedDecimal.fromInt(int v) { - final result = _icu4x_FixedDecimal_from_int64_mv1(v); - return FixedDecimal._fromFfi(result, []); - } - - /// Construct an [`FixedDecimal`] from an float, with a given power of 10 for the lower magnitude - /// - /// See the [Rust documentation for `try_from_f64`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.try_from_f64) for more information. - /// - /// See the [Rust documentation for `FloatPrecision`](https://docs.rs/fixed_decimal/latest/fixed_decimal/enum.FloatPrecision.html) for more information. - /// - /// Throws [FixedDecimalLimitError] on failure. - factory FixedDecimal.fromDoubleWithLowerMagnitude(double f, int magnitude) { - final result = _icu4x_FixedDecimal_from_double_with_lower_magnitude_mv1(f, magnitude); - if (!result.isOk) { - throw FixedDecimalLimitError(); - } - return FixedDecimal._fromFfi(result.union.ok, []); - } - - /// Construct an [`FixedDecimal`] from an float, for a given number of significant digits - /// - /// See the [Rust documentation for `try_from_f64`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.try_from_f64) for more information. - /// - /// See the [Rust documentation for `FloatPrecision`](https://docs.rs/fixed_decimal/latest/fixed_decimal/enum.FloatPrecision.html) for more information. - /// - /// Throws [FixedDecimalLimitError] on failure. - factory FixedDecimal.fromDoubleWithSignificantDigits(double f, int digits) { - final result = _icu4x_FixedDecimal_from_double_with_significant_digits_mv1(f, digits); - if (!result.isOk) { - throw FixedDecimalLimitError(); - } - return FixedDecimal._fromFfi(result.union.ok, []); - } - - /// Construct an [`FixedDecimal`] from an float, with enough digits to recover - /// the original floating point in IEEE 754 without needing trailing zeros - /// - /// See the [Rust documentation for `try_from_f64`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.try_from_f64) for more information. - /// - /// See the [Rust documentation for `FloatPrecision`](https://docs.rs/fixed_decimal/latest/fixed_decimal/enum.FloatPrecision.html) for more information. - /// - /// Throws [FixedDecimalLimitError] on failure. - factory FixedDecimal.fromDoubleWithRoundTripPrecision(double f) { - final result = _icu4x_FixedDecimal_from_double_with_round_trip_precision_mv1(f); - if (!result.isOk) { - throw FixedDecimalLimitError(); - } - return FixedDecimal._fromFfi(result.union.ok, []); - } - - /// Construct an [`FixedDecimal`] from a string. - /// - /// See the [Rust documentation for `try_from_str`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.try_from_str) for more information. - /// - /// Throws [FixedDecimalParseError] on failure. - factory FixedDecimal.fromString(String v) { - final temp = _FinalizedArena(); - final result = _icu4x_FixedDecimal_from_string_mv1(v._utf8AllocIn(temp.arena)); - if (!result.isOk) { - throw FixedDecimalParseError.values[result.union.err]; - } - return FixedDecimal._fromFfi(result.union.ok, []); - } - - /// See the [Rust documentation for `digit_at`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.digit_at) for more information. - int digitAt(int magnitude) { - final result = _icu4x_FixedDecimal_digit_at_mv1(_ffi, magnitude); - return result; - } - - /// See the [Rust documentation for `magnitude_range`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.magnitude_range) for more information. - int get magnitudeStart { - final result = _icu4x_FixedDecimal_magnitude_start_mv1(_ffi); - return result; - } - - /// See the [Rust documentation for `magnitude_range`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.magnitude_range) for more information. - int get magnitudeEnd { - final result = _icu4x_FixedDecimal_magnitude_end_mv1(_ffi); - return result; - } - - /// See the [Rust documentation for `nonzero_magnitude_start`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.nonzero_magnitude_start) for more information. - int get nonzeroMagnitudeStart { - final result = _icu4x_FixedDecimal_nonzero_magnitude_start_mv1(_ffi); - return result; - } - - /// See the [Rust documentation for `nonzero_magnitude_end`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.nonzero_magnitude_end) for more information. - int get nonzeroMagnitudeEnd { - final result = _icu4x_FixedDecimal_nonzero_magnitude_end_mv1(_ffi); - return result; - } - - /// See the [Rust documentation for `is_zero`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.is_zero) for more information. - bool get isZero { - final result = _icu4x_FixedDecimal_is_zero_mv1(_ffi); - return result; - } - - /// Multiply the [`FixedDecimal`] by a given power of ten. - /// - /// See the [Rust documentation for `multiply_pow10`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.multiply_pow10) for more information. - void multiplyPow10(int power) { - _icu4x_FixedDecimal_multiply_pow10_mv1(_ffi, power); - } - - /// See the [Rust documentation for `sign`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.sign) for more information. - FixedDecimalSign get sign { - final result = _icu4x_FixedDecimal_sign_mv1(_ffi); - return FixedDecimalSign.values[result]; - } - - /// Set the sign of the [`FixedDecimal`]. - /// - /// See the [Rust documentation for `set_sign`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.set_sign) for more information. - set sign(FixedDecimalSign sign) { - _icu4x_FixedDecimal_set_sign_mv1(_ffi, sign.index); - } - - /// See the [Rust documentation for `apply_sign_display`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.apply_sign_display) for more information. - void applySignDisplay(FixedDecimalSignDisplay signDisplay) { - _icu4x_FixedDecimal_apply_sign_display_mv1(_ffi, signDisplay.index); - } - - /// See the [Rust documentation for `trim_start`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.trim_start) for more information. - void trimStart() { - _icu4x_FixedDecimal_trim_start_mv1(_ffi); - } - - /// See the [Rust documentation for `trim_end`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.trim_end) for more information. - void trimEnd() { - _icu4x_FixedDecimal_trim_end_mv1(_ffi); - } - - /// Zero-pad the [`FixedDecimal`] on the left to a particular position - /// - /// See the [Rust documentation for `pad_start`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.pad_start) for more information. - void padStart(int position) { - _icu4x_FixedDecimal_pad_start_mv1(_ffi, position); - } - - /// Zero-pad the [`FixedDecimal`] on the right to a particular position - /// - /// See the [Rust documentation for `pad_end`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.pad_end) for more information. - void padEnd(int position) { - _icu4x_FixedDecimal_pad_end_mv1(_ffi, position); - } - - /// Truncate the [`FixedDecimal`] on the left to a particular position, deleting digits if necessary. This is useful for, e.g. abbreviating years - /// ("2022" -> "22") - /// - /// See the [Rust documentation for `set_max_position`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.set_max_position) for more information. - void setMaxPosition(int position) { - _icu4x_FixedDecimal_set_max_position_mv1(_ffi, position); - } - - /// Round the number at a particular digit position. - /// - /// This uses half to even rounding, which resolves ties by selecting the nearest - /// even integer to the original value. - /// - /// See the [Rust documentation for `round`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.round) for more information. - void round(int position) { - _icu4x_FixedDecimal_round_mv1(_ffi, position); - } - - /// See the [Rust documentation for `ceil`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.ceil) for more information. - void ceil(int position) { - _icu4x_FixedDecimal_ceil_mv1(_ffi, position); - } - - /// See the [Rust documentation for `expand`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.expand) for more information. - void expand(int position) { - _icu4x_FixedDecimal_expand_mv1(_ffi, position); - } - - /// See the [Rust documentation for `floor`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.floor) for more information. - void floor(int position) { - _icu4x_FixedDecimal_floor_mv1(_ffi, position); - } - - /// See the [Rust documentation for `trunc`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.trunc) for more information. - void trunc(int position) { - _icu4x_FixedDecimal_trunc_mv1(_ffi, position); - } - - /// See the [Rust documentation for `round_with_mode`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.round_with_mode) for more information. - void roundWithMode(int position, FixedDecimalRoundingMode mode) { - _icu4x_FixedDecimal_round_with_mode_mv1(_ffi, position, mode.index); - } - - /// See the [Rust documentation for `round_with_mode_and_increment`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.round_with_mode_and_increment) for more information. - void roundWithModeAndIncrement(int position, FixedDecimalRoundingMode mode, FixedDecimalRoundingIncrement increment) { - _icu4x_FixedDecimal_round_with_mode_and_increment_mv1(_ffi, position, mode.index, increment.index); - } - - /// Concatenates `other` to the end of `self`. - /// - /// If successful, `other` will be set to 0 and a successful status is returned. - /// - /// If not successful, `other` will be unchanged and an error is returned. - /// - /// See the [Rust documentation for `concatenate_end`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.concatenate_end) for more information. - bool concatenateEnd(FixedDecimal other) { - final result = _icu4x_FixedDecimal_concatenate_end_mv1(_ffi, other._ffi); - return result.isOk; - } - - /// Format the [`FixedDecimal`] as a string. - /// - /// See the [Rust documentation for `write_to`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.write_to) for more information. - @core.override - String toString() { - final write = _Write(); - _icu4x_FixedDecimal_to_string_mv1(_ffi, write._ffi); - return write.finalize(); - } -} - -@meta.RecordUse() -@ffi.Native)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_destroy_mv1') -// ignore: non_constant_identifier_names -external void _icu4x_FixedDecimal_destroy_mv1(ffi.Pointer self); - -@meta.RecordUse() -@ffi.Native Function(ffi.Int64)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_from_int64_mv1') -// ignore: non_constant_identifier_names -external ffi.Pointer _icu4x_FixedDecimal_from_int64_mv1(int v); - -@meta.RecordUse() -@ffi.Native<_ResultOpaqueFixedDecimalLimitErrorFfi Function(ffi.Double, ffi.Int16)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_from_double_with_lower_magnitude_mv1') -// ignore: non_constant_identifier_names -external _ResultOpaqueFixedDecimalLimitErrorFfi _icu4x_FixedDecimal_from_double_with_lower_magnitude_mv1(double f, int magnitude); - -@meta.RecordUse() -@ffi.Native<_ResultOpaqueFixedDecimalLimitErrorFfi Function(ffi.Double, ffi.Uint8)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_from_double_with_significant_digits_mv1') -// ignore: non_constant_identifier_names -external _ResultOpaqueFixedDecimalLimitErrorFfi _icu4x_FixedDecimal_from_double_with_significant_digits_mv1(double f, int digits); - -@meta.RecordUse() -@ffi.Native<_ResultOpaqueFixedDecimalLimitErrorFfi Function(ffi.Double)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_from_double_with_round_trip_precision_mv1') -// ignore: non_constant_identifier_names -external _ResultOpaqueFixedDecimalLimitErrorFfi _icu4x_FixedDecimal_from_double_with_round_trip_precision_mv1(double f); - -@meta.RecordUse() -@ffi.Native<_ResultOpaqueInt32 Function(_SliceUtf8)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_from_string_mv1') -// ignore: non_constant_identifier_names -external _ResultOpaqueInt32 _icu4x_FixedDecimal_from_string_mv1(_SliceUtf8 v); - -@meta.RecordUse() -@ffi.Native, ffi.Int16)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_digit_at_mv1') -// ignore: non_constant_identifier_names -external int _icu4x_FixedDecimal_digit_at_mv1(ffi.Pointer self, int magnitude); - -@meta.RecordUse() -@ffi.Native)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_magnitude_start_mv1') -// ignore: non_constant_identifier_names -external int _icu4x_FixedDecimal_magnitude_start_mv1(ffi.Pointer self); - -@meta.RecordUse() -@ffi.Native)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_magnitude_end_mv1') -// ignore: non_constant_identifier_names -external int _icu4x_FixedDecimal_magnitude_end_mv1(ffi.Pointer self); - -@meta.RecordUse() -@ffi.Native)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_nonzero_magnitude_start_mv1') -// ignore: non_constant_identifier_names -external int _icu4x_FixedDecimal_nonzero_magnitude_start_mv1(ffi.Pointer self); - -@meta.RecordUse() -@ffi.Native)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_nonzero_magnitude_end_mv1') -// ignore: non_constant_identifier_names -external int _icu4x_FixedDecimal_nonzero_magnitude_end_mv1(ffi.Pointer self); - -@meta.RecordUse() -@ffi.Native)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_is_zero_mv1') -// ignore: non_constant_identifier_names -external bool _icu4x_FixedDecimal_is_zero_mv1(ffi.Pointer self); - -@meta.RecordUse() -@ffi.Native, ffi.Int16)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_multiply_pow10_mv1') -// ignore: non_constant_identifier_names -external void _icu4x_FixedDecimal_multiply_pow10_mv1(ffi.Pointer self, int power); - -@meta.RecordUse() -@ffi.Native)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_sign_mv1') -// ignore: non_constant_identifier_names -external int _icu4x_FixedDecimal_sign_mv1(ffi.Pointer self); - -@meta.RecordUse() -@ffi.Native, ffi.Int32)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_set_sign_mv1') -// ignore: non_constant_identifier_names -external void _icu4x_FixedDecimal_set_sign_mv1(ffi.Pointer self, int sign); - -@meta.RecordUse() -@ffi.Native, ffi.Int32)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_apply_sign_display_mv1') -// ignore: non_constant_identifier_names -external void _icu4x_FixedDecimal_apply_sign_display_mv1(ffi.Pointer self, int signDisplay); - -@meta.RecordUse() -@ffi.Native)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_trim_start_mv1') -// ignore: non_constant_identifier_names -external void _icu4x_FixedDecimal_trim_start_mv1(ffi.Pointer self); - -@meta.RecordUse() -@ffi.Native)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_trim_end_mv1') -// ignore: non_constant_identifier_names -external void _icu4x_FixedDecimal_trim_end_mv1(ffi.Pointer self); - -@meta.RecordUse() -@ffi.Native, ffi.Int16)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_pad_start_mv1') -// ignore: non_constant_identifier_names -external void _icu4x_FixedDecimal_pad_start_mv1(ffi.Pointer self, int position); - -@meta.RecordUse() -@ffi.Native, ffi.Int16)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_pad_end_mv1') -// ignore: non_constant_identifier_names -external void _icu4x_FixedDecimal_pad_end_mv1(ffi.Pointer self, int position); - -@meta.RecordUse() -@ffi.Native, ffi.Int16)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_set_max_position_mv1') -// ignore: non_constant_identifier_names -external void _icu4x_FixedDecimal_set_max_position_mv1(ffi.Pointer self, int position); - -@meta.RecordUse() -@ffi.Native, ffi.Int16)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_round_mv1') -// ignore: non_constant_identifier_names -external void _icu4x_FixedDecimal_round_mv1(ffi.Pointer self, int position); - -@meta.RecordUse() -@ffi.Native, ffi.Int16)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_ceil_mv1') -// ignore: non_constant_identifier_names -external void _icu4x_FixedDecimal_ceil_mv1(ffi.Pointer self, int position); - -@meta.RecordUse() -@ffi.Native, ffi.Int16)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_expand_mv1') -// ignore: non_constant_identifier_names -external void _icu4x_FixedDecimal_expand_mv1(ffi.Pointer self, int position); - -@meta.RecordUse() -@ffi.Native, ffi.Int16)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_floor_mv1') -// ignore: non_constant_identifier_names -external void _icu4x_FixedDecimal_floor_mv1(ffi.Pointer self, int position); - -@meta.RecordUse() -@ffi.Native, ffi.Int16)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_trunc_mv1') -// ignore: non_constant_identifier_names -external void _icu4x_FixedDecimal_trunc_mv1(ffi.Pointer self, int position); - -@meta.RecordUse() -@ffi.Native, ffi.Int16, ffi.Int32)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_round_with_mode_mv1') -// ignore: non_constant_identifier_names -external void _icu4x_FixedDecimal_round_with_mode_mv1(ffi.Pointer self, int position, int mode); - -@meta.RecordUse() -@ffi.Native, ffi.Int16, ffi.Int32, ffi.Int32)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_round_with_mode_and_increment_mv1') -// ignore: non_constant_identifier_names -external void _icu4x_FixedDecimal_round_with_mode_and_increment_mv1(ffi.Pointer self, int position, int mode, int increment); - -@meta.RecordUse() -@ffi.Native<_ResultVoidVoid Function(ffi.Pointer, ffi.Pointer)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_concatenate_end_mv1') -// ignore: non_constant_identifier_names -external _ResultVoidVoid _icu4x_FixedDecimal_concatenate_end_mv1(ffi.Pointer self, ffi.Pointer other); - -@meta.RecordUse() -@ffi.Native, ffi.Pointer)>(isLeaf: true, symbol: 'icu4x_FixedDecimal_to_string_mv1') -// ignore: non_constant_identifier_names -external void _icu4x_FixedDecimal_to_string_mv1(ffi.Pointer self, ffi.Pointer write); diff --git a/ffi/capi/bindings/dart/FixedDecimalFormatter.g.dart b/ffi/capi/bindings/dart/FixedDecimalFormatter.g.dart index 00687fa5279..7de8a5bd62c 100644 --- a/ffi/capi/bindings/dart/FixedDecimalFormatter.g.dart +++ b/ffi/capi/bindings/dart/FixedDecimalFormatter.g.dart @@ -2,7 +2,7 @@ part of 'lib.g.dart'; -/// An ICU4X Fixed Decimal Format object, capable of formatting a [`FixedDecimal`] as a string. +/// An ICU4X Fixed Decimal Format object, capable of formatting a [`SignedFixedDecimal`] as a string. /// /// See the [Rust documentation for `FixedDecimalFormatter`](https://docs.rs/icu/latest/icu/decimal/struct.FixedDecimalFormatter.html) for more information. final class FixedDecimalFormatter implements ffi.Finalizable { @@ -51,10 +51,10 @@ final class FixedDecimalFormatter implements ffi.Finalizable { return FixedDecimalFormatter._fromFfi(result.union.ok, []); } - /// Formats a [`FixedDecimal`] to a string. + /// Formats a [`SignedFixedDecimal`] to a string. /// /// See the [Rust documentation for `format`](https://docs.rs/icu/latest/icu/decimal/struct.FixedDecimalFormatter.html#method.format) for more information. - String format(FixedDecimal value) { + String format(SignedFixedDecimal value) { final write = _Write(); _icu4x_FixedDecimalFormatter_format_mv1(_ffi, value._ffi, write._ffi); return write.finalize(); diff --git a/ffi/capi/bindings/dart/FixedDecimalRoundingMode.g.dart b/ffi/capi/bindings/dart/FixedDecimalRoundingMode.g.dart deleted file mode 100644 index 3b91090534a..00000000000 --- a/ffi/capi/bindings/dart/FixedDecimalRoundingMode.g.dart +++ /dev/null @@ -1,26 +0,0 @@ -// generated by diplomat-tool - -part of 'lib.g.dart'; - -/// Mode used in a rounding operation. -/// -/// See the [Rust documentation for `RoundingMode`](https://docs.rs/fixed_decimal/latest/fixed_decimal/enum.RoundingMode.html) for more information. -enum FixedDecimalRoundingMode { - ceil, - - expand, - - floor, - - trunc, - - halfCeil, - - halfExpand, - - halfFloor, - - halfTrunc, - - halfEven; -} diff --git a/ffi/capi/bindings/dart/FixedDecimalSignedRoundingMode.g.dart b/ffi/capi/bindings/dart/FixedDecimalSignedRoundingMode.g.dart new file mode 100644 index 00000000000..d4679c09f89 --- /dev/null +++ b/ffi/capi/bindings/dart/FixedDecimalSignedRoundingMode.g.dart @@ -0,0 +1,26 @@ +// generated by diplomat-tool + +part of 'lib.g.dart'; + +/// Mode used in a rounding operation for signed numbers. +/// +/// See the [Rust documentation for `SignedRoundingMode`](https://docs.rs/fixed_decimal/latest/fixed_decimal/enum.SignedRoundingMode.html) for more information. +enum FixedDecimalSignedRoundingMode { + expand, + + trunc, + + halfExpand, + + halfTrunc, + + halfEven, + + ceil, + + floor, + + halfCeil, + + halfFloor; +} diff --git a/ffi/capi/bindings/dart/PluralOperands.g.dart b/ffi/capi/bindings/dart/PluralOperands.g.dart index 58eb6b5e456..4f55ae93eb3 100644 --- a/ffi/capi/bindings/dart/PluralOperands.g.dart +++ b/ffi/capi/bindings/dart/PluralOperands.g.dart @@ -39,7 +39,7 @@ final class PluralOperands implements ffi.Finalizable { /// Construct from a FixedDecimal /// /// Retains at most 18 digits each from the integer and fraction parts. - factory PluralOperands.fromFixedDecimal(FixedDecimal x) { + factory PluralOperands.fromFixedDecimal(SignedFixedDecimal x) { final result = _icu4x_PluralOperands_from_fixed_decimal_mv1(x._ffi); return PluralOperands._fromFfi(result, []); } diff --git a/ffi/capi/bindings/dart/SignedFixedDecimal.g.dart b/ffi/capi/bindings/dart/SignedFixedDecimal.g.dart new file mode 100644 index 00000000000..ef5017554b0 --- /dev/null +++ b/ffi/capi/bindings/dart/SignedFixedDecimal.g.dart @@ -0,0 +1,397 @@ +// generated by diplomat-tool + +part of 'lib.g.dart'; + +/// See the [Rust documentation for `FixedDecimal`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html) for more information. +final class SignedFixedDecimal implements ffi.Finalizable { + final ffi.Pointer _ffi; + + // These are "used" in the sense that they keep dependencies alive + // ignore: unused_field + final core.List _selfEdge; + + // This takes in a list of lifetime edges (including for &self borrows) + // corresponding to data this may borrow from. These should be flat arrays containing + // references to objects, and this object will hold on to them to keep them alive and + // maintain borrow validity. + SignedFixedDecimal._fromFfi(this._ffi, this._selfEdge) { + if (_selfEdge.isEmpty) { + _finalizer.attach(this, _ffi.cast()); + } + } + + static final _finalizer = ffi.NativeFinalizer(ffi.Native.addressOf(_icu4x_SignedFixedDecimal_destroy_mv1)); + + /// Construct an [`SignedFixedDecimal`] from an integer. + /// + /// See the [Rust documentation for `FixedDecimal`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html) for more information. + factory SignedFixedDecimal.fromInt(int v) { + final result = _icu4x_SignedFixedDecimal_from_int64_mv1(v); + return SignedFixedDecimal._fromFfi(result, []); + } + + /// Construct an [`SignedFixedDecimal`] from an float, with a given power of 10 for the lower magnitude + /// + /// See the [Rust documentation for `try_from_f64`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.try_from_f64) for more information. + /// + /// See the [Rust documentation for `FloatPrecision`](https://docs.rs/fixed_decimal/latest/fixed_decimal/enum.FloatPrecision.html) for more information. + /// + /// Throws [FixedDecimalLimitError] on failure. + factory SignedFixedDecimal.fromDoubleWithLowerMagnitude(double f, int magnitude) { + final result = _icu4x_SignedFixedDecimal_from_double_with_lower_magnitude_mv1(f, magnitude); + if (!result.isOk) { + throw FixedDecimalLimitError(); + } + return SignedFixedDecimal._fromFfi(result.union.ok, []); + } + + /// Construct an [`SignedFixedDecimal`] from an float, for a given number of significant digits + /// + /// See the [Rust documentation for `try_from_f64`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.try_from_f64) for more information. + /// + /// See the [Rust documentation for `FloatPrecision`](https://docs.rs/fixed_decimal/latest/fixed_decimal/enum.FloatPrecision.html) for more information. + /// + /// Throws [FixedDecimalLimitError] on failure. + factory SignedFixedDecimal.fromDoubleWithSignificantDigits(double f, int digits) { + final result = _icu4x_SignedFixedDecimal_from_double_with_significant_digits_mv1(f, digits); + if (!result.isOk) { + throw FixedDecimalLimitError(); + } + return SignedFixedDecimal._fromFfi(result.union.ok, []); + } + + /// Construct an [`SignedFixedDecimal`] from an float, with enough digits to recover + /// the original floating point in IEEE 754 without needing trailing zeros + /// + /// See the [Rust documentation for `try_from_f64`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.SignedFixedDecimal.html#method.try_from_f64) for more information. + /// + /// See the [Rust documentation for `FloatPrecision`](https://docs.rs/fixed_decimal/latest/fixed_decimal/enum.FloatPrecision.html) for more information. + /// + /// Throws [FixedDecimalLimitError] on failure. + factory SignedFixedDecimal.fromDoubleWithRoundTripPrecision(double f) { + final result = _icu4x_SignedFixedDecimal_from_double_with_round_trip_precision_mv1(f); + if (!result.isOk) { + throw FixedDecimalLimitError(); + } + return SignedFixedDecimal._fromFfi(result.union.ok, []); + } + + /// Construct an [`SignedFixedDecimal`] from a string. + /// + /// See the [Rust documentation for `try_from_str`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.SignedFixedDecimal.html#method.try_from_str) for more information. + /// + /// Throws [FixedDecimalParseError] on failure. + factory SignedFixedDecimal.fromString(String v) { + final temp = _FinalizedArena(); + final result = _icu4x_SignedFixedDecimal_from_string_mv1(v._utf8AllocIn(temp.arena)); + if (!result.isOk) { + throw FixedDecimalParseError.values[result.union.err]; + } + return SignedFixedDecimal._fromFfi(result.union.ok, []); + } + + /// See the [Rust documentation for `digit_at`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.UnsignedFixedDecimal.html#method.digit_at) for more information. + int digitAt(int magnitude) { + final result = _icu4x_SignedFixedDecimal_digit_at_mv1(_ffi, magnitude); + return result; + } + + /// See the [Rust documentation for `magnitude_range`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.UnsignedFixedDecimal.html#method.magnitude_range) for more information. + int get magnitudeStart { + final result = _icu4x_SignedFixedDecimal_magnitude_start_mv1(_ffi); + return result; + } + + /// See the [Rust documentation for `magnitude_range`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.UnsignedFixedDecimal.html#method.magnitude_range) for more information. + int get magnitudeEnd { + final result = _icu4x_SignedFixedDecimal_magnitude_end_mv1(_ffi); + return result; + } + + /// See the [Rust documentation for `nonzero_magnitude_start`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.UnsignedFixedDecimal.html#method.nonzero_magnitude_start) for more information. + int get nonzeroMagnitudeStart { + final result = _icu4x_SignedFixedDecimal_nonzero_magnitude_start_mv1(_ffi); + return result; + } + + /// See the [Rust documentation for `nonzero_magnitude_end`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.UnsignedFixedDecimal.html#method.nonzero_magnitude_end) for more information. + int get nonzeroMagnitudeEnd { + final result = _icu4x_SignedFixedDecimal_nonzero_magnitude_end_mv1(_ffi); + return result; + } + + /// See the [Rust documentation for `is_zero`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.UnsignedFixedDecimal.html#method.is_zero) for more information. + bool get isZero { + final result = _icu4x_SignedFixedDecimal_is_zero_mv1(_ffi); + return result; + } + + /// Multiply the [`SignedFixedDecimal`] by a given power of ten. + /// + /// See the [Rust documentation for `multiply_pow10`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.SignedFixedDecimal.html#method.multiply_pow10) for more information. + void multiplyPow10(int power) { + _icu4x_SignedFixedDecimal_multiply_pow10_mv1(_ffi, power); + } + + /// See the [Rust documentation for `sign`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.SignedFixedDecimal.html#method.sign) for more information. + FixedDecimalSign get sign { + final result = _icu4x_SignedFixedDecimal_sign_mv1(_ffi); + return FixedDecimalSign.values[result]; + } + + /// Set the sign of the [`SignedFixedDecimal`]. + /// + /// See the [Rust documentation for `set_sign`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.SignedFixedDecimal.html#method.set_sign) for more information. + set sign(FixedDecimalSign sign) { + _icu4x_SignedFixedDecimal_set_sign_mv1(_ffi, sign.index); + } + + /// See the [Rust documentation for `apply_sign_display`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.SignedFixedDecimal.html#method.apply_sign_display) for more information. + void applySignDisplay(FixedDecimalSignDisplay signDisplay) { + _icu4x_SignedFixedDecimal_apply_sign_display_mv1(_ffi, signDisplay.index); + } + + /// See the [Rust documentation for `trim_start`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.trim_start) for more information. + void trimStart() { + _icu4x_SignedFixedDecimal_trim_start_mv1(_ffi); + } + + /// See the [Rust documentation for `trim_end`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.trim_end) for more information. + void trimEnd() { + _icu4x_SignedFixedDecimal_trim_end_mv1(_ffi); + } + + /// Zero-pad the [`SignedFixedDecimal`] on the left to a particular position + /// + /// See the [Rust documentation for `pad_start`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.pad_start) for more information. + void padStart(int position) { + _icu4x_SignedFixedDecimal_pad_start_mv1(_ffi, position); + } + + /// Zero-pad the [`SignedFixedDecimal`] on the right to a particular position + /// + /// See the [Rust documentation for `pad_end`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.pad_end) for more information. + void padEnd(int position) { + _icu4x_SignedFixedDecimal_pad_end_mv1(_ffi, position); + } + + /// Truncate the [`SignedFixedDecimal`] on the left to a particular position, deleting digits if necessary. This is useful for, e.g. abbreviating years + /// ("2022" -> "22") + /// + /// See the [Rust documentation for `set_max_position`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.set_max_position) for more information. + void setMaxPosition(int position) { + _icu4x_SignedFixedDecimal_set_max_position_mv1(_ffi, position); + } + + /// Round the number at a particular digit position. + /// + /// This uses half to even rounding, which resolves ties by selecting the nearest + /// even integer to the original value. + /// + /// See the [Rust documentation for `round`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.SignedFixedDecimal.html#method.round) for more information. + void round(int position) { + _icu4x_SignedFixedDecimal_round_mv1(_ffi, position); + } + + /// See the [Rust documentation for `ceil`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.SignedFixedDecimal.html#method.ceil) for more information. + void ceil(int position) { + _icu4x_SignedFixedDecimal_ceil_mv1(_ffi, position); + } + + /// See the [Rust documentation for `expand`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.SignedFixedDecimal.html#method.expand) for more information. + void expand(int position) { + _icu4x_SignedFixedDecimal_expand_mv1(_ffi, position); + } + + /// See the [Rust documentation for `floor`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.SignedFixedDecimal.html#method.floor) for more information. + void floor(int position) { + _icu4x_SignedFixedDecimal_floor_mv1(_ffi, position); + } + + /// See the [Rust documentation for `trunc`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.SignedFixedDecimal.html#method.trunc) for more information. + void trunc(int position) { + _icu4x_SignedFixedDecimal_trunc_mv1(_ffi, position); + } + + /// See the [Rust documentation for `round_with_mode`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.SignedFixedDecimal.html#method.round_with_mode) for more information. + void roundWithMode(int position, FixedDecimalSignedRoundingMode mode) { + _icu4x_SignedFixedDecimal_round_with_mode_mv1(_ffi, position, mode.index); + } + + /// See the [Rust documentation for `round_with_mode_and_increment`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.round_with_mode_and_increment) for more information. + void roundWithModeAndIncrement(int position, FixedDecimalSignedRoundingMode mode, FixedDecimalRoundingIncrement increment) { + _icu4x_SignedFixedDecimal_round_with_mode_and_increment_mv1(_ffi, position, mode.index, increment.index); + } + + /// Concatenates `other` to the end of `self`. + /// + /// If successful, `other` will be set to 0 and a successful status is returned. + /// + /// If not successful, `other` will be unchanged and an error is returned. + /// + /// See the [Rust documentation for `concatenate_end`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.concatenate_end) for more information. + bool concatenateEnd(SignedFixedDecimal other) { + final result = _icu4x_SignedFixedDecimal_concatenate_end_mv1(_ffi, other._ffi); + return result.isOk; + } + + /// Format the [`SignedFixedDecimal`] as a string. + /// + /// See the [Rust documentation for `write_to`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.write_to) for more information. + @core.override + String toString() { + final write = _Write(); + _icu4x_SignedFixedDecimal_to_string_mv1(_ffi, write._ffi); + return write.finalize(); + } +} + +@meta.RecordUse() +@ffi.Native)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_destroy_mv1') +// ignore: non_constant_identifier_names +external void _icu4x_SignedFixedDecimal_destroy_mv1(ffi.Pointer self); + +@meta.RecordUse() +@ffi.Native Function(ffi.Int64)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_from_int64_mv1') +// ignore: non_constant_identifier_names +external ffi.Pointer _icu4x_SignedFixedDecimal_from_int64_mv1(int v); + +@meta.RecordUse() +@ffi.Native<_ResultOpaqueFixedDecimalLimitErrorFfi Function(ffi.Double, ffi.Int16)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_from_double_with_lower_magnitude_mv1') +// ignore: non_constant_identifier_names +external _ResultOpaqueFixedDecimalLimitErrorFfi _icu4x_SignedFixedDecimal_from_double_with_lower_magnitude_mv1(double f, int magnitude); + +@meta.RecordUse() +@ffi.Native<_ResultOpaqueFixedDecimalLimitErrorFfi Function(ffi.Double, ffi.Uint8)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_from_double_with_significant_digits_mv1') +// ignore: non_constant_identifier_names +external _ResultOpaqueFixedDecimalLimitErrorFfi _icu4x_SignedFixedDecimal_from_double_with_significant_digits_mv1(double f, int digits); + +@meta.RecordUse() +@ffi.Native<_ResultOpaqueFixedDecimalLimitErrorFfi Function(ffi.Double)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_from_double_with_round_trip_precision_mv1') +// ignore: non_constant_identifier_names +external _ResultOpaqueFixedDecimalLimitErrorFfi _icu4x_SignedFixedDecimal_from_double_with_round_trip_precision_mv1(double f); + +@meta.RecordUse() +@ffi.Native<_ResultOpaqueInt32 Function(_SliceUtf8)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_from_string_mv1') +// ignore: non_constant_identifier_names +external _ResultOpaqueInt32 _icu4x_SignedFixedDecimal_from_string_mv1(_SliceUtf8 v); + +@meta.RecordUse() +@ffi.Native, ffi.Int16)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_digit_at_mv1') +// ignore: non_constant_identifier_names +external int _icu4x_SignedFixedDecimal_digit_at_mv1(ffi.Pointer self, int magnitude); + +@meta.RecordUse() +@ffi.Native)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_magnitude_start_mv1') +// ignore: non_constant_identifier_names +external int _icu4x_SignedFixedDecimal_magnitude_start_mv1(ffi.Pointer self); + +@meta.RecordUse() +@ffi.Native)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_magnitude_end_mv1') +// ignore: non_constant_identifier_names +external int _icu4x_SignedFixedDecimal_magnitude_end_mv1(ffi.Pointer self); + +@meta.RecordUse() +@ffi.Native)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_nonzero_magnitude_start_mv1') +// ignore: non_constant_identifier_names +external int _icu4x_SignedFixedDecimal_nonzero_magnitude_start_mv1(ffi.Pointer self); + +@meta.RecordUse() +@ffi.Native)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_nonzero_magnitude_end_mv1') +// ignore: non_constant_identifier_names +external int _icu4x_SignedFixedDecimal_nonzero_magnitude_end_mv1(ffi.Pointer self); + +@meta.RecordUse() +@ffi.Native)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_is_zero_mv1') +// ignore: non_constant_identifier_names +external bool _icu4x_SignedFixedDecimal_is_zero_mv1(ffi.Pointer self); + +@meta.RecordUse() +@ffi.Native, ffi.Int16)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_multiply_pow10_mv1') +// ignore: non_constant_identifier_names +external void _icu4x_SignedFixedDecimal_multiply_pow10_mv1(ffi.Pointer self, int power); + +@meta.RecordUse() +@ffi.Native)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_sign_mv1') +// ignore: non_constant_identifier_names +external int _icu4x_SignedFixedDecimal_sign_mv1(ffi.Pointer self); + +@meta.RecordUse() +@ffi.Native, ffi.Int32)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_set_sign_mv1') +// ignore: non_constant_identifier_names +external void _icu4x_SignedFixedDecimal_set_sign_mv1(ffi.Pointer self, int sign); + +@meta.RecordUse() +@ffi.Native, ffi.Int32)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_apply_sign_display_mv1') +// ignore: non_constant_identifier_names +external void _icu4x_SignedFixedDecimal_apply_sign_display_mv1(ffi.Pointer self, int signDisplay); + +@meta.RecordUse() +@ffi.Native)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_trim_start_mv1') +// ignore: non_constant_identifier_names +external void _icu4x_SignedFixedDecimal_trim_start_mv1(ffi.Pointer self); + +@meta.RecordUse() +@ffi.Native)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_trim_end_mv1') +// ignore: non_constant_identifier_names +external void _icu4x_SignedFixedDecimal_trim_end_mv1(ffi.Pointer self); + +@meta.RecordUse() +@ffi.Native, ffi.Int16)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_pad_start_mv1') +// ignore: non_constant_identifier_names +external void _icu4x_SignedFixedDecimal_pad_start_mv1(ffi.Pointer self, int position); + +@meta.RecordUse() +@ffi.Native, ffi.Int16)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_pad_end_mv1') +// ignore: non_constant_identifier_names +external void _icu4x_SignedFixedDecimal_pad_end_mv1(ffi.Pointer self, int position); + +@meta.RecordUse() +@ffi.Native, ffi.Int16)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_set_max_position_mv1') +// ignore: non_constant_identifier_names +external void _icu4x_SignedFixedDecimal_set_max_position_mv1(ffi.Pointer self, int position); + +@meta.RecordUse() +@ffi.Native, ffi.Int16)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_round_mv1') +// ignore: non_constant_identifier_names +external void _icu4x_SignedFixedDecimal_round_mv1(ffi.Pointer self, int position); + +@meta.RecordUse() +@ffi.Native, ffi.Int16)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_ceil_mv1') +// ignore: non_constant_identifier_names +external void _icu4x_SignedFixedDecimal_ceil_mv1(ffi.Pointer self, int position); + +@meta.RecordUse() +@ffi.Native, ffi.Int16)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_expand_mv1') +// ignore: non_constant_identifier_names +external void _icu4x_SignedFixedDecimal_expand_mv1(ffi.Pointer self, int position); + +@meta.RecordUse() +@ffi.Native, ffi.Int16)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_floor_mv1') +// ignore: non_constant_identifier_names +external void _icu4x_SignedFixedDecimal_floor_mv1(ffi.Pointer self, int position); + +@meta.RecordUse() +@ffi.Native, ffi.Int16)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_trunc_mv1') +// ignore: non_constant_identifier_names +external void _icu4x_SignedFixedDecimal_trunc_mv1(ffi.Pointer self, int position); + +@meta.RecordUse() +@ffi.Native, ffi.Int16, ffi.Int32)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_round_with_mode_mv1') +// ignore: non_constant_identifier_names +external void _icu4x_SignedFixedDecimal_round_with_mode_mv1(ffi.Pointer self, int position, int mode); + +@meta.RecordUse() +@ffi.Native, ffi.Int16, ffi.Int32, ffi.Int32)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_round_with_mode_and_increment_mv1') +// ignore: non_constant_identifier_names +external void _icu4x_SignedFixedDecimal_round_with_mode_and_increment_mv1(ffi.Pointer self, int position, int mode, int increment); + +@meta.RecordUse() +@ffi.Native<_ResultVoidVoid Function(ffi.Pointer, ffi.Pointer)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_concatenate_end_mv1') +// ignore: non_constant_identifier_names +external _ResultVoidVoid _icu4x_SignedFixedDecimal_concatenate_end_mv1(ffi.Pointer self, ffi.Pointer other); + +@meta.RecordUse() +@ffi.Native, ffi.Pointer)>(isLeaf: true, symbol: 'icu4x_SignedFixedDecimal_to_string_mv1') +// ignore: non_constant_identifier_names +external void _icu4x_SignedFixedDecimal_to_string_mv1(ffi.Pointer self, ffi.Pointer write); diff --git a/ffi/capi/bindings/dart/lib.g.dart b/ffi/capi/bindings/dart/lib.g.dart index 9dbda99fbed..1af6ac53a21 100644 --- a/ffi/capi/bindings/dart/lib.g.dart +++ b/ffi/capi/bindings/dart/lib.g.dart @@ -59,15 +59,14 @@ part 'DisplayNamesStyle.g.dart'; part 'EastAsianWidth.g.dart'; part 'EmojiSetData.g.dart'; part 'ExemplarCharacters.g.dart'; -part 'FixedDecimal.g.dart'; part 'FixedDecimalFormatter.g.dart'; part 'FixedDecimalGroupingStrategy.g.dart'; part 'FixedDecimalLimitError.g.dart'; part 'FixedDecimalParseError.g.dart'; part 'FixedDecimalRoundingIncrement.g.dart'; -part 'FixedDecimalRoundingMode.g.dart'; part 'FixedDecimalSign.g.dart'; part 'FixedDecimalSignDisplay.g.dart'; +part 'FixedDecimalSignedRoundingMode.g.dart'; part 'GeneralCategory.g.dart'; part 'GeneralCategoryNameToMaskMapper.g.dart'; part 'GraphemeClusterBreak.g.dart'; @@ -128,6 +127,7 @@ part 'SentenceBreakIteratorLatin1.g.dart'; part 'SentenceBreakIteratorUtf16.g.dart'; part 'SentenceBreakIteratorUtf8.g.dart'; part 'SentenceSegmenter.g.dart'; +part 'SignedFixedDecimal.g.dart'; part 'Time.g.dart'; part 'TimeFormatter.g.dart'; part 'TimeZoneIdMapper.g.dart'; diff --git a/ffi/capi/bindings/demo_gen/FixedDecimalFormatter.d.ts b/ffi/capi/bindings/demo_gen/FixedDecimalFormatter.d.ts index 34c4f859c76..22fbc2a2f56 100644 --- a/ffi/capi/bindings/demo_gen/FixedDecimalFormatter.d.ts +++ b/ffi/capi/bindings/demo_gen/FixedDecimalFormatter.d.ts @@ -1,5 +1,5 @@ import { DataProvider } from "icu4x" -import { FixedDecimal } from "icu4x" import { FixedDecimalFormatter } from "icu4x" import { Locale } from "icu4x" +import { SignedFixedDecimal } from "icu4x" export function format(name: string, groupingStrategy: FixedDecimalGroupingStrategy, f: number, magnitude: number); diff --git a/ffi/capi/bindings/demo_gen/FixedDecimalFormatter.mjs b/ffi/capi/bindings/demo_gen/FixedDecimalFormatter.mjs index 340fb900b38..d13642109d0 100644 --- a/ffi/capi/bindings/demo_gen/FixedDecimalFormatter.mjs +++ b/ffi/capi/bindings/demo_gen/FixedDecimalFormatter.mjs @@ -1,7 +1,7 @@ import { DataProvider } from "icu4x" -import { FixedDecimal } from "icu4x" import { FixedDecimalFormatter } from "icu4x" import { Locale } from "icu4x" +import { SignedFixedDecimal } from "icu4x" export function format() { var terminusArgs = arguments; return (function (...args) { return args[0].format(...args.slice(1)) }).apply( @@ -24,7 +24,7 @@ export function format() { terminusArgs[1] ] ), - FixedDecimal.fromNumberWithLowerMagnitude.apply( + SignedFixedDecimal.fromNumberWithLowerMagnitude.apply( null, [ terminusArgs[2], diff --git a/ffi/capi/bindings/demo_gen/FixedDecimal.d.ts b/ffi/capi/bindings/demo_gen/SignedFixedDecimal.d.ts similarity index 56% rename from ffi/capi/bindings/demo_gen/FixedDecimal.d.ts rename to ffi/capi/bindings/demo_gen/SignedFixedDecimal.d.ts index 47e2213750b..e0555d0114e 100644 --- a/ffi/capi/bindings/demo_gen/FixedDecimal.d.ts +++ b/ffi/capi/bindings/demo_gen/SignedFixedDecimal.d.ts @@ -1,2 +1,2 @@ -import { FixedDecimal } from "icu4x" +import { SignedFixedDecimal } from "icu4x" export function toString(f: number, magnitude: number); diff --git a/ffi/capi/bindings/demo_gen/FixedDecimal.mjs b/ffi/capi/bindings/demo_gen/SignedFixedDecimal.mjs similarity index 75% rename from ffi/capi/bindings/demo_gen/FixedDecimal.mjs rename to ffi/capi/bindings/demo_gen/SignedFixedDecimal.mjs index 870b8559089..4a2970a48e5 100644 --- a/ffi/capi/bindings/demo_gen/FixedDecimal.mjs +++ b/ffi/capi/bindings/demo_gen/SignedFixedDecimal.mjs @@ -1,10 +1,10 @@ -import { FixedDecimal } from "icu4x" +import { SignedFixedDecimal } from "icu4x" export function toString() { var terminusArgs = arguments; return (function (...args) { return args[0].toString(...args.slice(1)) }).apply( null, [ - FixedDecimal.fromNumberWithLowerMagnitude.apply( + SignedFixedDecimal.fromNumberWithLowerMagnitude.apply( null, [ terminusArgs[0], diff --git a/ffi/capi/bindings/demo_gen/index.mjs b/ffi/capi/bindings/demo_gen/index.mjs index bcf46a5301b..39a9650f7da 100644 --- a/ffi/capi/bindings/demo_gen/index.mjs +++ b/ffi/capi/bindings/demo_gen/index.mjs @@ -19,8 +19,8 @@ import * as TimeFormatterDemo from "./TimeFormatter.mjs"; export * as TimeFormatterDemo from "./TimeFormatter.mjs"; import * as FixedDecimalFormatterDemo from "./FixedDecimalFormatter.mjs"; export * as FixedDecimalFormatterDemo from "./FixedDecimalFormatter.mjs"; -import * as FixedDecimalDemo from "./FixedDecimal.mjs"; -export * as FixedDecimalDemo from "./FixedDecimal.mjs"; +import * as SignedFixedDecimalDemo from "./SignedFixedDecimal.mjs"; +export * as SignedFixedDecimalDemo from "./SignedFixedDecimal.mjs"; import * as ListFormatterDemo from "./ListFormatter.mjs"; export * as ListFormatterDemo from "./ListFormatter.mjs"; import * as LocaleDemo from "./Locale.mjs"; @@ -1087,10 +1087,10 @@ let termini = Object.assign({ ] }, - "FixedDecimal.toString": { - func: FixedDecimalDemo.toString, + "SignedFixedDecimal.toString": { + func: SignedFixedDecimalDemo.toString, // For avoiding webpacking minifying issues: - funcName: "FixedDecimal.toString", + funcName: "SignedFixedDecimal.toString", parameters: [ { diff --git a/ffi/capi/bindings/js/FixedDecimalFormatter.d.ts b/ffi/capi/bindings/js/FixedDecimalFormatter.d.ts index 2c154a11499..6d121b04c6a 100644 --- a/ffi/capi/bindings/js/FixedDecimalFormatter.d.ts +++ b/ffi/capi/bindings/js/FixedDecimalFormatter.d.ts @@ -1,13 +1,13 @@ // generated by diplomat-tool import type { DataError } from "./DataError" import type { DataProvider } from "./DataProvider" -import type { FixedDecimal } from "./FixedDecimal" import type { FixedDecimalGroupingStrategy } from "./FixedDecimalGroupingStrategy" import type { Locale } from "./Locale" +import type { SignedFixedDecimal } from "./SignedFixedDecimal" import type { pointer, codepoint } from "./diplomat-runtime.d.ts"; -/** An ICU4X Fixed Decimal Format object, capable of formatting a [`FixedDecimal`] as a string. +/** An ICU4X Fixed Decimal Format object, capable of formatting a [`SignedFixedDecimal`] as a string. * *See the [Rust documentation for `FixedDecimalFormatter`](https://docs.rs/icu/latest/icu/decimal/struct.FixedDecimalFormatter.html) for more information. */ @@ -20,5 +20,5 @@ export class FixedDecimalFormatter { static createWithManualData(plusSignPrefix: string, plusSignSuffix: string, minusSignPrefix: string, minusSignSuffix: string, decimalSeparator: string, groupingSeparator: string, primaryGroupSize: number, secondaryGroupSize: number, minGroupSize: number, digits: Array, groupingStrategy: FixedDecimalGroupingStrategy | null): FixedDecimalFormatter; - format(value: FixedDecimal): string; + format(value: SignedFixedDecimal): string; } \ No newline at end of file diff --git a/ffi/capi/bindings/js/FixedDecimalFormatter.mjs b/ffi/capi/bindings/js/FixedDecimalFormatter.mjs index c2dbdcd31b5..9fd15ed1adc 100644 --- a/ffi/capi/bindings/js/FixedDecimalFormatter.mjs +++ b/ffi/capi/bindings/js/FixedDecimalFormatter.mjs @@ -1,14 +1,14 @@ // generated by diplomat-tool import { DataError } from "./DataError.mjs" import { DataProvider } from "./DataProvider.mjs" -import { FixedDecimal } from "./FixedDecimal.mjs" import { FixedDecimalGroupingStrategy } from "./FixedDecimalGroupingStrategy.mjs" import { Locale } from "./Locale.mjs" +import { SignedFixedDecimal } from "./SignedFixedDecimal.mjs" import wasm from "./diplomat-wasm.mjs"; import * as diplomatRuntime from "./diplomat-runtime.mjs"; -/** An ICU4X Fixed Decimal Format object, capable of formatting a [`FixedDecimal`] as a string. +/** An ICU4X Fixed Decimal Format object, capable of formatting a [`SignedFixedDecimal`] as a string. * *See the [Rust documentation for `FixedDecimalFormatter`](https://docs.rs/icu/latest/icu/decimal/struct.FixedDecimalFormatter.html) for more information. */ diff --git a/ffi/capi/bindings/js/FixedDecimalRoundingMode.d.ts b/ffi/capi/bindings/js/FixedDecimalRoundingMode.d.ts deleted file mode 100644 index 3b0c46eb051..00000000000 --- a/ffi/capi/bindings/js/FixedDecimalRoundingMode.d.ts +++ /dev/null @@ -1,25 +0,0 @@ -// generated by diplomat-tool -import type { pointer, codepoint } from "./diplomat-runtime.d.ts"; - -// Base enumerator definition -/** Mode used in a rounding operation. -* -*See the [Rust documentation for `RoundingMode`](https://docs.rs/fixed_decimal/latest/fixed_decimal/enum.RoundingMode.html) for more information. -*/ -export class FixedDecimalRoundingMode { - constructor(value : FixedDecimalRoundingMode | string); - - get value() : string; - - get ffiValue() : number; - - static Ceil : FixedDecimalRoundingMode; - static Expand : FixedDecimalRoundingMode; - static Floor : FixedDecimalRoundingMode; - static Trunc : FixedDecimalRoundingMode; - static HalfCeil : FixedDecimalRoundingMode; - static HalfExpand : FixedDecimalRoundingMode; - static HalfFloor : FixedDecimalRoundingMode; - static HalfTrunc : FixedDecimalRoundingMode; - static HalfEven : FixedDecimalRoundingMode; -} \ No newline at end of file diff --git a/ffi/capi/bindings/js/FixedDecimalRoundingMode.mjs b/ffi/capi/bindings/js/FixedDecimalRoundingMode.mjs deleted file mode 100644 index ac8ba70194e..00000000000 --- a/ffi/capi/bindings/js/FixedDecimalRoundingMode.mjs +++ /dev/null @@ -1,82 +0,0 @@ -// generated by diplomat-tool -import wasm from "./diplomat-wasm.mjs"; -import * as diplomatRuntime from "./diplomat-runtime.mjs"; - -// Base enumerator definition -/** Mode used in a rounding operation. -* -*See the [Rust documentation for `RoundingMode`](https://docs.rs/fixed_decimal/latest/fixed_decimal/enum.RoundingMode.html) for more information. -*/ -export class FixedDecimalRoundingMode { - #value = undefined; - - static #values = new Map([ - ["Ceil", 0], - ["Expand", 1], - ["Floor", 2], - ["Trunc", 3], - ["HalfCeil", 4], - ["HalfExpand", 5], - ["HalfFloor", 6], - ["HalfTrunc", 7], - ["HalfEven", 8] - ]); - - static getAllEntries() { - return FixedDecimalRoundingMode.#values.entries(); - } - - constructor(value) { - if (arguments.length > 1 && arguments[0] === diplomatRuntime.internalConstructor) { - // We pass in two internalConstructor arguments to create *new* - // instances of this type, otherwise the enums are treated as singletons. - if (arguments[1] === diplomatRuntime.internalConstructor ) { - this.#value = arguments[2]; - return; - } - return FixedDecimalRoundingMode.#objectValues[arguments[1]]; - } - - if (value instanceof FixedDecimalRoundingMode) { - return value; - } - - let intVal = FixedDecimalRoundingMode.#values.get(value); - - // Nullish check, checks for null or undefined - if (intVal == null) { - return FixedDecimalRoundingMode.#objectValues[intVal]; - } - - throw TypeError(value + " is not a FixedDecimalRoundingMode and does not correspond to any of its enumerator values."); - } - - get value() { - return [...FixedDecimalRoundingMode.#values.keys()][this.#value]; - } - - get ffiValue() { - return this.#value; - } - static #objectValues = [ - new FixedDecimalRoundingMode(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 0), - new FixedDecimalRoundingMode(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 1), - new FixedDecimalRoundingMode(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 2), - new FixedDecimalRoundingMode(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 3), - new FixedDecimalRoundingMode(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 4), - new FixedDecimalRoundingMode(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 5), - new FixedDecimalRoundingMode(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 6), - new FixedDecimalRoundingMode(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 7), - new FixedDecimalRoundingMode(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 8), - ]; - - static Ceil = FixedDecimalRoundingMode.#objectValues[0]; - static Expand = FixedDecimalRoundingMode.#objectValues[1]; - static Floor = FixedDecimalRoundingMode.#objectValues[2]; - static Trunc = FixedDecimalRoundingMode.#objectValues[3]; - static HalfCeil = FixedDecimalRoundingMode.#objectValues[4]; - static HalfExpand = FixedDecimalRoundingMode.#objectValues[5]; - static HalfFloor = FixedDecimalRoundingMode.#objectValues[6]; - static HalfTrunc = FixedDecimalRoundingMode.#objectValues[7]; - static HalfEven = FixedDecimalRoundingMode.#objectValues[8]; -} \ No newline at end of file diff --git a/ffi/capi/bindings/js/FixedDecimalSignedRoundingMode.d.ts b/ffi/capi/bindings/js/FixedDecimalSignedRoundingMode.d.ts new file mode 100644 index 00000000000..6a79aa50822 --- /dev/null +++ b/ffi/capi/bindings/js/FixedDecimalSignedRoundingMode.d.ts @@ -0,0 +1,25 @@ +// generated by diplomat-tool +import type { pointer, codepoint } from "./diplomat-runtime.d.ts"; + +// Base enumerator definition +/** Mode used in a rounding operation for signed numbers. +* +*See the [Rust documentation for `SignedRoundingMode`](https://docs.rs/fixed_decimal/latest/fixed_decimal/enum.SignedRoundingMode.html) for more information. +*/ +export class FixedDecimalSignedRoundingMode { + constructor(value : FixedDecimalSignedRoundingMode | string); + + get value() : string; + + get ffiValue() : number; + + static Expand : FixedDecimalSignedRoundingMode; + static Trunc : FixedDecimalSignedRoundingMode; + static HalfExpand : FixedDecimalSignedRoundingMode; + static HalfTrunc : FixedDecimalSignedRoundingMode; + static HalfEven : FixedDecimalSignedRoundingMode; + static Ceil : FixedDecimalSignedRoundingMode; + static Floor : FixedDecimalSignedRoundingMode; + static HalfCeil : FixedDecimalSignedRoundingMode; + static HalfFloor : FixedDecimalSignedRoundingMode; +} \ No newline at end of file diff --git a/ffi/capi/bindings/js/FixedDecimalSignedRoundingMode.mjs b/ffi/capi/bindings/js/FixedDecimalSignedRoundingMode.mjs new file mode 100644 index 00000000000..b03a3800813 --- /dev/null +++ b/ffi/capi/bindings/js/FixedDecimalSignedRoundingMode.mjs @@ -0,0 +1,82 @@ +// generated by diplomat-tool +import wasm from "./diplomat-wasm.mjs"; +import * as diplomatRuntime from "./diplomat-runtime.mjs"; + +// Base enumerator definition +/** Mode used in a rounding operation for signed numbers. +* +*See the [Rust documentation for `SignedRoundingMode`](https://docs.rs/fixed_decimal/latest/fixed_decimal/enum.SignedRoundingMode.html) for more information. +*/ +export class FixedDecimalSignedRoundingMode { + #value = undefined; + + static #values = new Map([ + ["Expand", 0], + ["Trunc", 1], + ["HalfExpand", 2], + ["HalfTrunc", 3], + ["HalfEven", 4], + ["Ceil", 5], + ["Floor", 6], + ["HalfCeil", 7], + ["HalfFloor", 8] + ]); + + static getAllEntries() { + return FixedDecimalSignedRoundingMode.#values.entries(); + } + + constructor(value) { + if (arguments.length > 1 && arguments[0] === diplomatRuntime.internalConstructor) { + // We pass in two internalConstructor arguments to create *new* + // instances of this type, otherwise the enums are treated as singletons. + if (arguments[1] === diplomatRuntime.internalConstructor ) { + this.#value = arguments[2]; + return; + } + return FixedDecimalSignedRoundingMode.#objectValues[arguments[1]]; + } + + if (value instanceof FixedDecimalSignedRoundingMode) { + return value; + } + + let intVal = FixedDecimalSignedRoundingMode.#values.get(value); + + // Nullish check, checks for null or undefined + if (intVal == null) { + return FixedDecimalSignedRoundingMode.#objectValues[intVal]; + } + + throw TypeError(value + " is not a FixedDecimalSignedRoundingMode and does not correspond to any of its enumerator values."); + } + + get value() { + return [...FixedDecimalSignedRoundingMode.#values.keys()][this.#value]; + } + + get ffiValue() { + return this.#value; + } + static #objectValues = [ + new FixedDecimalSignedRoundingMode(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 0), + new FixedDecimalSignedRoundingMode(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 1), + new FixedDecimalSignedRoundingMode(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 2), + new FixedDecimalSignedRoundingMode(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 3), + new FixedDecimalSignedRoundingMode(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 4), + new FixedDecimalSignedRoundingMode(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 5), + new FixedDecimalSignedRoundingMode(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 6), + new FixedDecimalSignedRoundingMode(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 7), + new FixedDecimalSignedRoundingMode(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 8), + ]; + + static Expand = FixedDecimalSignedRoundingMode.#objectValues[0]; + static Trunc = FixedDecimalSignedRoundingMode.#objectValues[1]; + static HalfExpand = FixedDecimalSignedRoundingMode.#objectValues[2]; + static HalfTrunc = FixedDecimalSignedRoundingMode.#objectValues[3]; + static HalfEven = FixedDecimalSignedRoundingMode.#objectValues[4]; + static Ceil = FixedDecimalSignedRoundingMode.#objectValues[5]; + static Floor = FixedDecimalSignedRoundingMode.#objectValues[6]; + static HalfCeil = FixedDecimalSignedRoundingMode.#objectValues[7]; + static HalfFloor = FixedDecimalSignedRoundingMode.#objectValues[8]; +} \ No newline at end of file diff --git a/ffi/capi/bindings/js/PluralOperands.d.ts b/ffi/capi/bindings/js/PluralOperands.d.ts index 5b1ff1a19c7..d51b443dcad 100644 --- a/ffi/capi/bindings/js/PluralOperands.d.ts +++ b/ffi/capi/bindings/js/PluralOperands.d.ts @@ -1,6 +1,6 @@ // generated by diplomat-tool -import type { FixedDecimal } from "./FixedDecimal" import type { FixedDecimalParseError } from "./FixedDecimalParseError" +import type { SignedFixedDecimal } from "./SignedFixedDecimal" import type { pointer, codepoint } from "./diplomat-runtime.d.ts"; @@ -13,5 +13,5 @@ export class PluralOperands { static fromString(s: string): PluralOperands; - static fromFixedDecimal(x: FixedDecimal): PluralOperands; + static fromFixedDecimal(x: SignedFixedDecimal): PluralOperands; } \ No newline at end of file diff --git a/ffi/capi/bindings/js/PluralOperands.mjs b/ffi/capi/bindings/js/PluralOperands.mjs index 66aa6d97b47..197711f38d5 100644 --- a/ffi/capi/bindings/js/PluralOperands.mjs +++ b/ffi/capi/bindings/js/PluralOperands.mjs @@ -1,6 +1,6 @@ // generated by diplomat-tool -import { FixedDecimal } from "./FixedDecimal.mjs" import { FixedDecimalParseError } from "./FixedDecimalParseError.mjs" +import { SignedFixedDecimal } from "./SignedFixedDecimal.mjs" import wasm from "./diplomat-wasm.mjs"; import * as diplomatRuntime from "./diplomat-runtime.mjs"; diff --git a/ffi/capi/bindings/js/FixedDecimal.d.ts b/ffi/capi/bindings/js/SignedFixedDecimal.d.ts similarity index 72% rename from ffi/capi/bindings/js/FixedDecimal.d.ts rename to ffi/capi/bindings/js/SignedFixedDecimal.d.ts index c6418e3a2de..1b48a4e4bb1 100644 --- a/ffi/capi/bindings/js/FixedDecimal.d.ts +++ b/ffi/capi/bindings/js/SignedFixedDecimal.d.ts @@ -2,30 +2,30 @@ import type { FixedDecimalLimitError } from "./FixedDecimalLimitError" import type { FixedDecimalParseError } from "./FixedDecimalParseError" import type { FixedDecimalRoundingIncrement } from "./FixedDecimalRoundingIncrement" -import type { FixedDecimalRoundingMode } from "./FixedDecimalRoundingMode" import type { FixedDecimalSign } from "./FixedDecimalSign" import type { FixedDecimalSignDisplay } from "./FixedDecimalSignDisplay" +import type { FixedDecimalSignedRoundingMode } from "./FixedDecimalSignedRoundingMode" import type { pointer, codepoint } from "./diplomat-runtime.d.ts"; /** See the [Rust documentation for `FixedDecimal`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html) for more information. */ -export class FixedDecimal { +export class SignedFixedDecimal { get ffiValue(): pointer; - static fromNumber(v: number): FixedDecimal; + static fromNumber(v: number): SignedFixedDecimal; - static fromBigInt(v: bigint): FixedDecimal; + static fromBigInt(v: bigint): SignedFixedDecimal; - static fromNumberWithLowerMagnitude(f: number, magnitude: number): FixedDecimal; + static fromNumberWithLowerMagnitude(f: number, magnitude: number): SignedFixedDecimal; - static fromNumberWithSignificantDigits(f: number, digits: number): FixedDecimal; + static fromNumberWithSignificantDigits(f: number, digits: number): SignedFixedDecimal; - static fromNumberWithRoundTripPrecision(f: number): FixedDecimal; + static fromNumberWithRoundTripPrecision(f: number): SignedFixedDecimal; - static fromString(v: string): FixedDecimal; + static fromString(v: string): SignedFixedDecimal; digitAt(magnitude: number): number; @@ -67,11 +67,11 @@ export class FixedDecimal { trunc(position: number): void; - roundWithMode(position: number, mode: FixedDecimalRoundingMode): void; + roundWithMode(position: number, mode: FixedDecimalSignedRoundingMode): void; - roundWithModeAndIncrement(position: number, mode: FixedDecimalRoundingMode, increment: FixedDecimalRoundingIncrement): void; + roundWithModeAndIncrement(position: number, mode: FixedDecimalSignedRoundingMode, increment: FixedDecimalRoundingIncrement): void; - concatenateEnd(other: FixedDecimal): boolean; + concatenateEnd(other: SignedFixedDecimal): boolean; toString(): string; } \ No newline at end of file diff --git a/ffi/capi/bindings/js/FixedDecimal.mjs b/ffi/capi/bindings/js/SignedFixedDecimal.mjs similarity index 58% rename from ffi/capi/bindings/js/FixedDecimal.mjs rename to ffi/capi/bindings/js/SignedFixedDecimal.mjs index 22a01c6a848..12b1ee9e4fb 100644 --- a/ffi/capi/bindings/js/FixedDecimal.mjs +++ b/ffi/capi/bindings/js/SignedFixedDecimal.mjs @@ -2,20 +2,20 @@ import { FixedDecimalLimitError } from "./FixedDecimalLimitError.mjs" import { FixedDecimalParseError } from "./FixedDecimalParseError.mjs" import { FixedDecimalRoundingIncrement } from "./FixedDecimalRoundingIncrement.mjs" -import { FixedDecimalRoundingMode } from "./FixedDecimalRoundingMode.mjs" import { FixedDecimalSign } from "./FixedDecimalSign.mjs" import { FixedDecimalSignDisplay } from "./FixedDecimalSignDisplay.mjs" +import { FixedDecimalSignedRoundingMode } from "./FixedDecimalSignedRoundingMode.mjs" import wasm from "./diplomat-wasm.mjs"; import * as diplomatRuntime from "./diplomat-runtime.mjs"; /** See the [Rust documentation for `FixedDecimal`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html) for more information. */ -const FixedDecimal_box_destroy_registry = new FinalizationRegistry((ptr) => { - wasm.icu4x_FixedDecimal_destroy_mv1(ptr); +const SignedFixedDecimal_box_destroy_registry = new FinalizationRegistry((ptr) => { + wasm.icu4x_SignedFixedDecimal_destroy_mv1(ptr); }); -export class FixedDecimal { +export class SignedFixedDecimal { // Internal ptr reference: #ptr = null; @@ -25,7 +25,7 @@ export class FixedDecimal { constructor(symbol, ptr, selfEdge) { if (symbol !== diplomatRuntime.internalConstructor) { - console.error("FixedDecimal is an Opaque type. You cannot call its constructor."); + console.error("SignedFixedDecimal is an Opaque type. You cannot call its constructor."); return; } @@ -34,7 +34,7 @@ export class FixedDecimal { // Are we being borrowed? If not, we can register. if (this.#selfEdge.length === 0) { - FixedDecimal_box_destroy_registry.register(this, this.#ptr); + SignedFixedDecimal_box_destroy_registry.register(this, this.#ptr); } } @@ -43,20 +43,20 @@ export class FixedDecimal { } static fromNumber(v) { - const result = wasm.icu4x_FixedDecimal_from_int32_mv1(v); + const result = wasm.icu4x_SignedFixedDecimal_from_int32_mv1(v); try { - return new FixedDecimal(diplomatRuntime.internalConstructor, result, []); + return new SignedFixedDecimal(diplomatRuntime.internalConstructor, result, []); } finally {} } static fromBigInt(v) { - const result = wasm.icu4x_FixedDecimal_from_int64_mv1(v); + const result = wasm.icu4x_SignedFixedDecimal_from_int64_mv1(v); try { - return new FixedDecimal(diplomatRuntime.internalConstructor, result, []); + return new SignedFixedDecimal(diplomatRuntime.internalConstructor, result, []); } finally {} @@ -65,14 +65,14 @@ export class FixedDecimal { static fromNumberWithLowerMagnitude(f, magnitude) { const diplomatReceive = new diplomatRuntime.DiplomatReceiveBuf(wasm, 5, 4, true); - const result = wasm.icu4x_FixedDecimal_from_double_with_lower_magnitude_mv1(diplomatReceive.buffer, f, magnitude); + const result = wasm.icu4x_SignedFixedDecimal_from_double_with_lower_magnitude_mv1(diplomatReceive.buffer, f, magnitude); try { if (!diplomatReceive.resultFlag) { const cause = new FixedDecimalLimitError(diplomatRuntime.internalConstructor); throw new globalThis.Error('FixedDecimalLimitError', { cause }); } - return new FixedDecimal(diplomatRuntime.internalConstructor, diplomatRuntime.ptrRead(wasm, diplomatReceive.buffer), []); + return new SignedFixedDecimal(diplomatRuntime.internalConstructor, diplomatRuntime.ptrRead(wasm, diplomatReceive.buffer), []); } finally { @@ -83,14 +83,14 @@ export class FixedDecimal { static fromNumberWithSignificantDigits(f, digits) { const diplomatReceive = new diplomatRuntime.DiplomatReceiveBuf(wasm, 5, 4, true); - const result = wasm.icu4x_FixedDecimal_from_double_with_significant_digits_mv1(diplomatReceive.buffer, f, digits); + const result = wasm.icu4x_SignedFixedDecimal_from_double_with_significant_digits_mv1(diplomatReceive.buffer, f, digits); try { if (!diplomatReceive.resultFlag) { const cause = new FixedDecimalLimitError(diplomatRuntime.internalConstructor); throw new globalThis.Error('FixedDecimalLimitError', { cause }); } - return new FixedDecimal(diplomatRuntime.internalConstructor, diplomatRuntime.ptrRead(wasm, diplomatReceive.buffer), []); + return new SignedFixedDecimal(diplomatRuntime.internalConstructor, diplomatRuntime.ptrRead(wasm, diplomatReceive.buffer), []); } finally { @@ -101,14 +101,14 @@ export class FixedDecimal { static fromNumberWithRoundTripPrecision(f) { const diplomatReceive = new diplomatRuntime.DiplomatReceiveBuf(wasm, 5, 4, true); - const result = wasm.icu4x_FixedDecimal_from_double_with_round_trip_precision_mv1(diplomatReceive.buffer, f); + const result = wasm.icu4x_SignedFixedDecimal_from_double_with_round_trip_precision_mv1(diplomatReceive.buffer, f); try { if (!diplomatReceive.resultFlag) { const cause = new FixedDecimalLimitError(diplomatRuntime.internalConstructor); throw new globalThis.Error('FixedDecimalLimitError', { cause }); } - return new FixedDecimal(diplomatRuntime.internalConstructor, diplomatRuntime.ptrRead(wasm, diplomatReceive.buffer), []); + return new SignedFixedDecimal(diplomatRuntime.internalConstructor, diplomatRuntime.ptrRead(wasm, diplomatReceive.buffer), []); } finally { @@ -123,14 +123,14 @@ export class FixedDecimal { const diplomatReceive = new diplomatRuntime.DiplomatReceiveBuf(wasm, 5, 4, true); - const result = wasm.icu4x_FixedDecimal_from_string_mv1(diplomatReceive.buffer, ...vSlice.splat()); + const result = wasm.icu4x_SignedFixedDecimal_from_string_mv1(diplomatReceive.buffer, ...vSlice.splat()); try { if (!diplomatReceive.resultFlag) { const cause = new FixedDecimalParseError(diplomatRuntime.internalConstructor, diplomatRuntime.enumDiscriminant(wasm, diplomatReceive.buffer)); throw new globalThis.Error('FixedDecimalParseError: ' + cause.value, { cause }); } - return new FixedDecimal(diplomatRuntime.internalConstructor, diplomatRuntime.ptrRead(wasm, diplomatReceive.buffer), []); + return new SignedFixedDecimal(diplomatRuntime.internalConstructor, diplomatRuntime.ptrRead(wasm, diplomatReceive.buffer), []); } finally { @@ -141,7 +141,7 @@ export class FixedDecimal { } digitAt(magnitude) { - const result = wasm.icu4x_FixedDecimal_digit_at_mv1(this.ffiValue, magnitude); + const result = wasm.icu4x_SignedFixedDecimal_digit_at_mv1(this.ffiValue, magnitude); try { return result; @@ -151,7 +151,7 @@ export class FixedDecimal { } get magnitudeStart() { - const result = wasm.icu4x_FixedDecimal_magnitude_start_mv1(this.ffiValue); + const result = wasm.icu4x_SignedFixedDecimal_magnitude_start_mv1(this.ffiValue); try { return result; @@ -161,7 +161,7 @@ export class FixedDecimal { } get magnitudeEnd() { - const result = wasm.icu4x_FixedDecimal_magnitude_end_mv1(this.ffiValue); + const result = wasm.icu4x_SignedFixedDecimal_magnitude_end_mv1(this.ffiValue); try { return result; @@ -171,7 +171,7 @@ export class FixedDecimal { } get nonzeroMagnitudeStart() { - const result = wasm.icu4x_FixedDecimal_nonzero_magnitude_start_mv1(this.ffiValue); + const result = wasm.icu4x_SignedFixedDecimal_nonzero_magnitude_start_mv1(this.ffiValue); try { return result; @@ -181,7 +181,7 @@ export class FixedDecimal { } get nonzeroMagnitudeEnd() { - const result = wasm.icu4x_FixedDecimal_nonzero_magnitude_end_mv1(this.ffiValue); + const result = wasm.icu4x_SignedFixedDecimal_nonzero_magnitude_end_mv1(this.ffiValue); try { return result; @@ -191,7 +191,7 @@ export class FixedDecimal { } get isZero() { - const result = wasm.icu4x_FixedDecimal_is_zero_mv1(this.ffiValue); + const result = wasm.icu4x_SignedFixedDecimal_is_zero_mv1(this.ffiValue); try { return result; @@ -200,7 +200,7 @@ export class FixedDecimal { finally {} } - multiplyPow10(power) {wasm.icu4x_FixedDecimal_multiply_pow10_mv1(this.ffiValue, power); + multiplyPow10(power) {wasm.icu4x_SignedFixedDecimal_multiply_pow10_mv1(this.ffiValue, power); try {} @@ -208,7 +208,7 @@ export class FixedDecimal { } get sign() { - const result = wasm.icu4x_FixedDecimal_sign_mv1(this.ffiValue); + const result = wasm.icu4x_SignedFixedDecimal_sign_mv1(this.ffiValue); try { return new FixedDecimalSign(diplomatRuntime.internalConstructor, result); @@ -217,98 +217,98 @@ export class FixedDecimal { finally {} } - set sign(sign) {wasm.icu4x_FixedDecimal_set_sign_mv1(this.ffiValue, sign.ffiValue); + set sign(sign) {wasm.icu4x_SignedFixedDecimal_set_sign_mv1(this.ffiValue, sign.ffiValue); try {} finally {} } - applySignDisplay(signDisplay) {wasm.icu4x_FixedDecimal_apply_sign_display_mv1(this.ffiValue, signDisplay.ffiValue); + applySignDisplay(signDisplay) {wasm.icu4x_SignedFixedDecimal_apply_sign_display_mv1(this.ffiValue, signDisplay.ffiValue); try {} finally {} } - trimStart() {wasm.icu4x_FixedDecimal_trim_start_mv1(this.ffiValue); + trimStart() {wasm.icu4x_SignedFixedDecimal_trim_start_mv1(this.ffiValue); try {} finally {} } - trimEnd() {wasm.icu4x_FixedDecimal_trim_end_mv1(this.ffiValue); + trimEnd() {wasm.icu4x_SignedFixedDecimal_trim_end_mv1(this.ffiValue); try {} finally {} } - padStart(position) {wasm.icu4x_FixedDecimal_pad_start_mv1(this.ffiValue, position); + padStart(position) {wasm.icu4x_SignedFixedDecimal_pad_start_mv1(this.ffiValue, position); try {} finally {} } - padEnd(position) {wasm.icu4x_FixedDecimal_pad_end_mv1(this.ffiValue, position); + padEnd(position) {wasm.icu4x_SignedFixedDecimal_pad_end_mv1(this.ffiValue, position); try {} finally {} } - setMaxPosition(position) {wasm.icu4x_FixedDecimal_set_max_position_mv1(this.ffiValue, position); + setMaxPosition(position) {wasm.icu4x_SignedFixedDecimal_set_max_position_mv1(this.ffiValue, position); try {} finally {} } - round(position) {wasm.icu4x_FixedDecimal_round_mv1(this.ffiValue, position); + round(position) {wasm.icu4x_SignedFixedDecimal_round_mv1(this.ffiValue, position); try {} finally {} } - ceil(position) {wasm.icu4x_FixedDecimal_ceil_mv1(this.ffiValue, position); + ceil(position) {wasm.icu4x_SignedFixedDecimal_ceil_mv1(this.ffiValue, position); try {} finally {} } - expand(position) {wasm.icu4x_FixedDecimal_expand_mv1(this.ffiValue, position); + expand(position) {wasm.icu4x_SignedFixedDecimal_expand_mv1(this.ffiValue, position); try {} finally {} } - floor(position) {wasm.icu4x_FixedDecimal_floor_mv1(this.ffiValue, position); + floor(position) {wasm.icu4x_SignedFixedDecimal_floor_mv1(this.ffiValue, position); try {} finally {} } - trunc(position) {wasm.icu4x_FixedDecimal_trunc_mv1(this.ffiValue, position); + trunc(position) {wasm.icu4x_SignedFixedDecimal_trunc_mv1(this.ffiValue, position); try {} finally {} } - roundWithMode(position, mode) {wasm.icu4x_FixedDecimal_round_with_mode_mv1(this.ffiValue, position, mode.ffiValue); + roundWithMode(position, mode) {wasm.icu4x_SignedFixedDecimal_round_with_mode_mv1(this.ffiValue, position, mode.ffiValue); try {} finally {} } - roundWithModeAndIncrement(position, mode, increment) {wasm.icu4x_FixedDecimal_round_with_mode_and_increment_mv1(this.ffiValue, position, mode.ffiValue, increment.ffiValue); + roundWithModeAndIncrement(position, mode, increment) {wasm.icu4x_SignedFixedDecimal_round_with_mode_and_increment_mv1(this.ffiValue, position, mode.ffiValue, increment.ffiValue); try {} @@ -316,7 +316,7 @@ export class FixedDecimal { } concatenateEnd(other) { - const result = wasm.icu4x_FixedDecimal_concatenate_end_mv1(this.ffiValue, other.ffiValue); + const result = wasm.icu4x_SignedFixedDecimal_concatenate_end_mv1(this.ffiValue, other.ffiValue); try { return result === 1; @@ -327,7 +327,7 @@ export class FixedDecimal { toString() { const write = new diplomatRuntime.DiplomatWriteBuf(wasm); - wasm.icu4x_FixedDecimal_to_string_mv1(this.ffiValue, write.buffer); + wasm.icu4x_SignedFixedDecimal_to_string_mv1(this.ffiValue, write.buffer); try { return write.readString8(); diff --git a/ffi/capi/bindings/js/index.d.ts b/ffi/capi/bindings/js/index.d.ts index af785e7dc13..7056a1aaa7c 100644 --- a/ffi/capi/bindings/js/index.d.ts +++ b/ffi/capi/bindings/js/index.d.ts @@ -80,7 +80,7 @@ export { LocaleFallbacker } from "./LocaleFallbacker" export { LocaleFallbackerWithConfig } from "./LocaleFallbackerWithConfig" -export { FixedDecimal } from "./FixedDecimal" +export { SignedFixedDecimal } from "./SignedFixedDecimal" export { ListFormatter } from "./ListFormatter" @@ -236,12 +236,12 @@ export { LocaleFallbackPriority } from "./LocaleFallbackPriority" export { FixedDecimalRoundingIncrement } from "./FixedDecimalRoundingIncrement" -export { FixedDecimalRoundingMode } from "./FixedDecimalRoundingMode" - export { FixedDecimalSign } from "./FixedDecimalSign" export { FixedDecimalSignDisplay } from "./FixedDecimalSignDisplay" +export { FixedDecimalSignedRoundingMode } from "./FixedDecimalSignedRoundingMode" + export { ListLength } from "./ListLength" export { TransformResult } from "./TransformResult" diff --git a/ffi/capi/bindings/js/index.mjs b/ffi/capi/bindings/js/index.mjs index 19dc52bedca..97f778cc189 100644 --- a/ffi/capi/bindings/js/index.mjs +++ b/ffi/capi/bindings/js/index.mjs @@ -78,7 +78,7 @@ export { LocaleFallbacker } from "./LocaleFallbacker.mjs" export { LocaleFallbackerWithConfig } from "./LocaleFallbackerWithConfig.mjs" -export { FixedDecimal } from "./FixedDecimal.mjs" +export { SignedFixedDecimal } from "./SignedFixedDecimal.mjs" export { ListFormatter } from "./ListFormatter.mjs" @@ -234,12 +234,12 @@ export { LocaleFallbackPriority } from "./LocaleFallbackPriority.mjs" export { FixedDecimalRoundingIncrement } from "./FixedDecimalRoundingIncrement.mjs" -export { FixedDecimalRoundingMode } from "./FixedDecimalRoundingMode.mjs" - export { FixedDecimalSign } from "./FixedDecimalSign.mjs" export { FixedDecimalSignDisplay } from "./FixedDecimalSignDisplay.mjs" +export { FixedDecimalSignedRoundingMode } from "./FixedDecimalSignedRoundingMode.mjs" + export { ListLength } from "./ListLength.mjs" export { TransformResult } from "./TransformResult.mjs" diff --git a/ffi/capi/src/decimal.rs b/ffi/capi/src/decimal.rs index 08946c8cd6d..da182232a20 100644 --- a/ffi/capi/src/decimal.rs +++ b/ffi/capi/src/decimal.rs @@ -9,7 +9,7 @@ pub mod ffi { use alloc::boxed::Box; use crate::{ - errors::ffi::DataError, fixed_decimal::ffi::FixedDecimal, locale_core::ffi::Locale, + errors::ffi::DataError, fixed_decimal::ffi::SignedFixedDecimal, locale_core::ffi::Locale, provider::ffi::DataProvider, }; use icu_decimal::{options::FixedDecimalFormatterOptions, FixedDecimalFormatterPreferences}; @@ -17,7 +17,7 @@ pub mod ffi { use writeable::Writeable; #[diplomat::opaque] - /// An ICU4X Fixed Decimal Format object, capable of formatting a [`FixedDecimal`] as a string. + /// An ICU4X Fixed Decimal Format object, capable of formatting a [`SignedFixedDecimal`] as a string. #[diplomat::rust_link(icu::decimal::FixedDecimalFormatter, Struct)] #[diplomat::rust_link(icu::datetime::FormattedFixedDecimal, Struct, hidden)] pub struct FixedDecimalFormatter(pub icu_decimal::FixedDecimalFormatter); @@ -139,7 +139,7 @@ pub mod ffi { ))) } - /// Formats a [`FixedDecimal`] to a string. + /// Formats a [`SignedFixedDecimal`] to a string. #[diplomat::rust_link(icu::decimal::FixedDecimalFormatter::format, FnInStruct)] #[diplomat::rust_link( icu::decimal::FixedDecimalFormatter::format_to_string, @@ -149,7 +149,11 @@ pub mod ffi { #[diplomat::rust_link(icu::decimal::FormattedFixedDecimal, Struct, hidden)] #[diplomat::rust_link(icu::decimal::FormattedFixedDecimal::write_to, FnInStruct, hidden)] #[diplomat::rust_link(icu::decimal::FormattedFixedDecimal::to_string, FnInStruct, hidden)] - pub fn format(&self, value: &FixedDecimal, write: &mut diplomat_runtime::DiplomatWrite) { + pub fn format( + &self, + value: &SignedFixedDecimal, + write: &mut diplomat_runtime::DiplomatWrite, + ) { let _infallible = self.0.format(&value.0).write_to(write); } } diff --git a/ffi/capi/src/fixed_decimal.rs b/ffi/capi/src/fixed_decimal.rs index c29c22c0e49..93c2b18c517 100644 --- a/ffi/capi/src/fixed_decimal.rs +++ b/ffi/capi/src/fixed_decimal.rs @@ -2,6 +2,8 @@ // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). +use ffi::FixedDecimalSignedRoundingMode; + #[diplomat::bridge] #[diplomat::abi_rename = "icu4x_{0}_mv1"] #[diplomat::attr(auto, namespace = "icu4x")] @@ -14,7 +16,7 @@ pub mod ffi { #[diplomat::opaque] #[diplomat::rust_link(fixed_decimal::FixedDecimal, Struct)] - pub struct FixedDecimal(pub fixed_decimal::FixedDecimal); + pub struct SignedFixedDecimal(pub fixed_decimal::SignedFixedDecimal); /// The sign of a FixedDecimal, as shown in formatting. #[diplomat::rust_link(fixed_decimal::Sign, Enum)] @@ -49,62 +51,69 @@ pub mod ffi { MultiplesOf25, } - /// Mode used in a rounding operation. - #[diplomat::rust_link(fixed_decimal::RoundingMode, Enum)] - #[diplomat::enum_convert(fixed_decimal::RoundingMode, needs_wildcard)] - pub enum FixedDecimalRoundingMode { - Ceil, + /// Mode used in a rounding operation for signed numbers. + #[diplomat::rust_link(fixed_decimal::SignedRoundingMode, Enum)] + pub enum FixedDecimalSignedRoundingMode { Expand, - Floor, Trunc, - HalfCeil, HalfExpand, - HalfFloor, HalfTrunc, HalfEven, + Ceil, + Floor, + HalfCeil, + HalfFloor, } - impl FixedDecimal { - /// Construct an [`FixedDecimal`] from an integer. + impl SignedFixedDecimal { + /// Construct an [`SignedFixedDecimal`] from an integer. #[diplomat::rust_link(fixed_decimal::FixedDecimal, Struct)] #[diplomat::attr(dart, disable)] #[diplomat::attr(js, rename = "from_number")] #[diplomat::attr(supports = method_overloading, rename = "from")] #[diplomat::attr(supports = fallible_constructors, named_constructor)] - pub fn from_int32(v: i32) -> Box { - Box::new(FixedDecimal(fixed_decimal::FixedDecimal::from(v))) + pub fn from_int32(v: i32) -> Box { + Box::new(SignedFixedDecimal(fixed_decimal::SignedFixedDecimal::from( + v, + ))) } - /// Construct an [`FixedDecimal`] from an integer. + /// Construct an [`SignedFixedDecimal`] from an integer. #[diplomat::rust_link(fixed_decimal::FixedDecimal, Struct)] #[diplomat::attr(dart, disable)] #[diplomat::attr(js, disable)] #[diplomat::attr(supports = method_overloading, rename = "from")] #[diplomat::attr(supports = fallible_constructors, named_constructor)] - pub fn from_uint32(v: u32) -> Box { - Box::new(FixedDecimal(fixed_decimal::FixedDecimal::from(v))) + pub fn from_uint32(v: u32) -> Box { + Box::new(SignedFixedDecimal(fixed_decimal::SignedFixedDecimal::from( + v, + ))) } - /// Construct an [`FixedDecimal`] from an integer. + /// Construct an [`SignedFixedDecimal`] from an integer. #[diplomat::rust_link(fixed_decimal::FixedDecimal, Struct)] #[diplomat::attr(dart, rename = "from_int")] #[diplomat::attr(js, rename = "from_big_int")] #[diplomat::attr(supports = method_overloading, rename = "from")] #[diplomat::attr(supports = fallible_constructors, named_constructor)] - pub fn from_int64(v: i64) -> Box { - Box::new(FixedDecimal(fixed_decimal::FixedDecimal::from(v))) + pub fn from_int64(v: i64) -> Box { + Box::new(SignedFixedDecimal(fixed_decimal::SignedFixedDecimal::from( + v, + ))) } - /// Construct an [`FixedDecimal`] from an integer. + /// Construct an [`SignedFixedDecimal`] from an integer. #[diplomat::rust_link(fixed_decimal::FixedDecimal, Struct)] #[diplomat::attr(any(dart, js), disable)] #[diplomat::attr(supports = method_overloading, rename = "from")] #[diplomat::attr(supports = fallible_constructors, named_constructor)] - pub fn from_uint64(v: u64) -> Box { - Box::new(FixedDecimal(fixed_decimal::FixedDecimal::from(v))) + pub fn from_uint64(v: u64) -> Box { + Box::new(SignedFixedDecimal(fixed_decimal::SignedFixedDecimal::from( + v, + ))) } - /// Construct an [`FixedDecimal`] from an integer-valued float + /// Construct an [`SignedFixedDecimal`] from an integer-valued float #[diplomat::rust_link(fixed_decimal::FixedDecimal::try_from_f64, FnInStruct)] #[diplomat::rust_link(fixed_decimal::FloatPrecision, Enum)] #[diplomat::rust_link(fixed_decimal::DoublePrecision, Enum, hidden)] @@ -112,14 +121,14 @@ pub mod ffi { #[diplomat::attr(supports = fallible_constructors, named_constructor)] pub fn from_double_with_integer_precision( f: f64, - ) -> Result, FixedDecimalLimitError> { + ) -> Result, FixedDecimalLimitError> { let precision = fixed_decimal::DoublePrecision::Integer; - Ok(Box::new(FixedDecimal( - fixed_decimal::FixedDecimal::try_from_f64(f, precision)?, + Ok(Box::new(SignedFixedDecimal( + fixed_decimal::SignedFixedDecimal::try_from_f64(f, precision)?, ))) } - /// Construct an [`FixedDecimal`] from an float, with a given power of 10 for the lower magnitude + /// Construct an [`SignedFixedDecimal`] from an float, with a given power of 10 for the lower magnitude #[diplomat::rust_link(fixed_decimal::FixedDecimal::try_from_f64, FnInStruct)] #[diplomat::rust_link(fixed_decimal::FloatPrecision, Enum)] #[diplomat::rust_link(fixed_decimal::DoublePrecision, Enum, hidden)] @@ -129,14 +138,14 @@ pub mod ffi { pub fn from_double_with_lower_magnitude( f: f64, magnitude: i16, - ) -> Result, FixedDecimalLimitError> { + ) -> Result, FixedDecimalLimitError> { let precision = fixed_decimal::DoublePrecision::Magnitude(magnitude); - Ok(Box::new(FixedDecimal( - fixed_decimal::FixedDecimal::try_from_f64(f, precision)?, + Ok(Box::new(SignedFixedDecimal( + fixed_decimal::SignedFixedDecimal::try_from_f64(f, precision)?, ))) } - /// Construct an [`FixedDecimal`] from an float, for a given number of significant digits + /// Construct an [`SignedFixedDecimal`] from an float, for a given number of significant digits #[diplomat::rust_link(fixed_decimal::FixedDecimal::try_from_f64, FnInStruct)] #[diplomat::rust_link(fixed_decimal::FloatPrecision, Enum)] #[diplomat::rust_link(fixed_decimal::DoublePrecision, Enum, hidden)] @@ -145,98 +154,114 @@ pub mod ffi { pub fn from_double_with_significant_digits( f: f64, digits: u8, - ) -> Result, FixedDecimalLimitError> { + ) -> Result, FixedDecimalLimitError> { let precision = fixed_decimal::DoublePrecision::SignificantDigits(digits); - Ok(Box::new(FixedDecimal( - fixed_decimal::FixedDecimal::try_from_f64(f, precision)?, + Ok(Box::new(SignedFixedDecimal( + fixed_decimal::SignedFixedDecimal::try_from_f64(f, precision)?, ))) } - /// Construct an [`FixedDecimal`] from an float, with enough digits to recover + /// Construct an [`SignedFixedDecimal`] from an float, with enough digits to recover /// the original floating point in IEEE 754 without needing trailing zeros - #[diplomat::rust_link(fixed_decimal::FixedDecimal::try_from_f64, FnInStruct)] + #[diplomat::rust_link(fixed_decimal::SignedFixedDecimal::try_from_f64, FnInStruct)] #[diplomat::rust_link(fixed_decimal::FloatPrecision, Enum)] #[diplomat::rust_link(fixed_decimal::DoublePrecision, Enum, hidden)] #[diplomat::attr(js, rename = "from_number_with_round_trip_precision")] #[diplomat::attr(supports = fallible_constructors, named_constructor)] pub fn from_double_with_round_trip_precision( f: f64, - ) -> Result, FixedDecimalLimitError> { + ) -> Result, FixedDecimalLimitError> { let precision = fixed_decimal::DoublePrecision::RoundTrip; - Ok(Box::new(FixedDecimal( - fixed_decimal::FixedDecimal::try_from_f64(f, precision)?, + Ok(Box::new(SignedFixedDecimal( + fixed_decimal::SignedFixedDecimal::try_from_f64(f, precision)?, ))) } - /// Construct an [`FixedDecimal`] from a string. - #[diplomat::rust_link(fixed_decimal::FixedDecimal::try_from_str, FnInStruct)] - #[diplomat::rust_link(fixed_decimal::FixedDecimal::try_from_utf8, FnInStruct, hidden)] - #[diplomat::rust_link(fixed_decimal::FixedDecimal::from_str, FnInStruct, hidden)] + /// Construct an [`SignedFixedDecimal`] from a string. + #[diplomat::rust_link(fixed_decimal::SignedFixedDecimal::try_from_str, FnInStruct)] + #[diplomat::rust_link(fixed_decimal::SignedFixedDecimal::try_from_utf8, FnInStruct, hidden)] + #[diplomat::rust_link(fixed_decimal::SignedFixedDecimal::from_str, FnInStruct, hidden)] #[diplomat::attr(supports = fallible_constructors, named_constructor)] - pub fn from_string(v: &DiplomatStr) -> Result, FixedDecimalParseError> { - Ok(Box::new(FixedDecimal( - fixed_decimal::FixedDecimal::try_from_utf8(v)?, + pub fn from_string( + v: &DiplomatStr, + ) -> Result, FixedDecimalParseError> { + Ok(Box::new(SignedFixedDecimal( + fixed_decimal::SignedFixedDecimal::try_from_utf8(v)?, ))) } - #[diplomat::rust_link(fixed_decimal::FixedDecimal::digit_at, FnInStruct)] + #[diplomat::rust_link(fixed_decimal::UnsignedFixedDecimal::digit_at, FnInStruct)] pub fn digit_at(&self, magnitude: i16) -> u8 { - self.0.digit_at(magnitude) + self.0.absolute.digit_at(magnitude) } - #[diplomat::rust_link(fixed_decimal::FixedDecimal::magnitude_range, FnInStruct)] + #[diplomat::rust_link(fixed_decimal::UnsignedFixedDecimal::magnitude_range, FnInStruct)] #[diplomat::attr(auto, getter)] pub fn magnitude_start(&self) -> i16 { - *self.0.magnitude_range().start() + *self.0.absolute.magnitude_range().start() } - #[diplomat::rust_link(fixed_decimal::FixedDecimal::magnitude_range, FnInStruct)] + #[diplomat::rust_link(fixed_decimal::UnsignedFixedDecimal::magnitude_range, FnInStruct)] #[diplomat::attr(auto, getter)] pub fn magnitude_end(&self) -> i16 { - *self.0.magnitude_range().end() + *self.0.absolute.magnitude_range().end() } - #[diplomat::rust_link(fixed_decimal::FixedDecimal::nonzero_magnitude_start, FnInStruct)] + #[diplomat::rust_link( + fixed_decimal::UnsignedFixedDecimal::nonzero_magnitude_start, + FnInStruct + )] #[diplomat::attr(auto, getter)] pub fn nonzero_magnitude_start(&self) -> i16 { - self.0.nonzero_magnitude_start() + self.0.absolute.nonzero_magnitude_start() } - #[diplomat::rust_link(fixed_decimal::FixedDecimal::nonzero_magnitude_end, FnInStruct)] + #[diplomat::rust_link( + fixed_decimal::UnsignedFixedDecimal::nonzero_magnitude_end, + FnInStruct + )] #[diplomat::attr(auto, getter)] pub fn nonzero_magnitude_end(&self) -> i16 { - self.0.nonzero_magnitude_end() + self.0.absolute.nonzero_magnitude_end() } - #[diplomat::rust_link(fixed_decimal::FixedDecimal::is_zero, FnInStruct)] + #[diplomat::rust_link(fixed_decimal::UnsignedFixedDecimal::is_zero, FnInStruct)] #[diplomat::attr(auto, getter)] pub fn is_zero(&self) -> bool { - self.0.is_zero() + self.0.absolute.is_zero() } - /// Multiply the [`FixedDecimal`] by a given power of ten. - #[diplomat::rust_link(fixed_decimal::FixedDecimal::multiply_pow10, FnInStruct)] - #[diplomat::rust_link(fixed_decimal::FixedDecimal::multiplied_pow10, FnInStruct, hidden)] + /// Multiply the [`SignedFixedDecimal`] by a given power of ten. + #[diplomat::rust_link(fixed_decimal::SignedFixedDecimal::multiply_pow10, FnInStruct)] + #[diplomat::rust_link( + fixed_decimal::SignedFixedDecimal::multiplied_pow10, + FnInStruct, + hidden + )] pub fn multiply_pow10(&mut self, power: i16) { self.0.multiply_pow10(power) } - #[diplomat::rust_link(fixed_decimal::FixedDecimal::sign, FnInStruct)] + #[diplomat::rust_link(fixed_decimal::SignedFixedDecimal::sign, FnInStruct)] #[diplomat::attr(auto, getter)] pub fn sign(&self) -> FixedDecimalSign { self.0.sign().into() } - /// Set the sign of the [`FixedDecimal`]. - #[diplomat::rust_link(fixed_decimal::FixedDecimal::set_sign, FnInStruct)] - #[diplomat::rust_link(fixed_decimal::FixedDecimal::with_sign, FnInStruct, hidden)] + /// Set the sign of the [`SignedFixedDecimal`]. + #[diplomat::rust_link(fixed_decimal::SignedFixedDecimal::set_sign, FnInStruct)] + #[diplomat::rust_link(fixed_decimal::SignedFixedDecimal::with_sign, FnInStruct, hidden)] #[diplomat::attr(auto, setter = "sign")] pub fn set_sign(&mut self, sign: FixedDecimalSign) { self.0.set_sign(sign.into()) } - #[diplomat::rust_link(fixed_decimal::FixedDecimal::apply_sign_display, FnInStruct)] - #[diplomat::rust_link(fixed_decimal::FixedDecimal::with_sign_display, FnInStruct, hidden)] + #[diplomat::rust_link(fixed_decimal::SignedFixedDecimal::apply_sign_display, FnInStruct)] + #[diplomat::rust_link( + fixed_decimal::SignedFixedDecimal::with_sign_display, + FnInStruct, + hidden + )] pub fn apply_sign_display(&mut self, sign_display: FixedDecimalSignDisplay) { self.0.apply_sign_display(sign_display.into()) } @@ -244,74 +269,78 @@ pub mod ffi { #[diplomat::rust_link(fixed_decimal::FixedDecimal::trim_start, FnInStruct)] #[diplomat::rust_link(fixed_decimal::FixedDecimal::trimmed_start, FnInStruct, hidden)] pub fn trim_start(&mut self) { - self.0.trim_start() + self.0.absolute.trim_start() } #[diplomat::rust_link(fixed_decimal::FixedDecimal::trim_end, FnInStruct)] #[diplomat::rust_link(fixed_decimal::FixedDecimal::trimmed_end, FnInStruct, hidden)] pub fn trim_end(&mut self) { - self.0.trim_end() + self.0.absolute.trim_end() } - /// Zero-pad the [`FixedDecimal`] on the left to a particular position + /// Zero-pad the [`SignedFixedDecimal`] on the left to a particular position #[diplomat::rust_link(fixed_decimal::FixedDecimal::pad_start, FnInStruct)] #[diplomat::rust_link(fixed_decimal::FixedDecimal::padded_start, FnInStruct, hidden)] pub fn pad_start(&mut self, position: i16) { - self.0.pad_start(position) + self.0.absolute.pad_start(position) } - /// Zero-pad the [`FixedDecimal`] on the right to a particular position + /// Zero-pad the [`SignedFixedDecimal`] on the right to a particular position #[diplomat::rust_link(fixed_decimal::FixedDecimal::pad_end, FnInStruct)] #[diplomat::rust_link(fixed_decimal::FixedDecimal::padded_end, FnInStruct, hidden)] pub fn pad_end(&mut self, position: i16) { - self.0.pad_end(position) + self.0.absolute.pad_end(position) } - /// Truncate the [`FixedDecimal`] on the left to a particular position, deleting digits if necessary. This is useful for, e.g. abbreviating years + /// Truncate the [`SignedFixedDecimal`] on the left to a particular position, deleting digits if necessary. This is useful for, e.g. abbreviating years /// ("2022" -> "22") #[diplomat::rust_link(fixed_decimal::FixedDecimal::set_max_position, FnInStruct)] #[diplomat::rust_link(fixed_decimal::FixedDecimal::with_max_position, FnInStruct, hidden)] pub fn set_max_position(&mut self, position: i16) { - self.0.set_max_position(position) + self.0.absolute.set_max_position(position) } /// Round the number at a particular digit position. /// /// This uses half to even rounding, which resolves ties by selecting the nearest /// even integer to the original value. - #[diplomat::rust_link(fixed_decimal::FixedDecimal::round, FnInStruct)] - #[diplomat::rust_link(fixed_decimal::FixedDecimal::rounded, FnInStruct, hidden)] + #[diplomat::rust_link(fixed_decimal::SignedFixedDecimal::round, FnInStruct)] + #[diplomat::rust_link(fixed_decimal::SignedFixedDecimal::rounded, FnInStruct, hidden)] pub fn round(&mut self, position: i16) { self.0.round(position) } - #[diplomat::rust_link(fixed_decimal::FixedDecimal::ceil, FnInStruct)] - #[diplomat::rust_link(fixed_decimal::FixedDecimal::ceiled, FnInStruct, hidden)] + #[diplomat::rust_link(fixed_decimal::SignedFixedDecimal::ceil, FnInStruct)] + #[diplomat::rust_link(fixed_decimal::SignedFixedDecimal::ceiled, FnInStruct, hidden)] pub fn ceil(&mut self, position: i16) { self.0.ceil(position) } - #[diplomat::rust_link(fixed_decimal::FixedDecimal::expand, FnInStruct)] - #[diplomat::rust_link(fixed_decimal::FixedDecimal::expanded, FnInStruct, hidden)] + #[diplomat::rust_link(fixed_decimal::SignedFixedDecimal::expand, FnInStruct)] + #[diplomat::rust_link(fixed_decimal::SignedFixedDecimal::expanded, FnInStruct, hidden)] pub fn expand(&mut self, position: i16) { self.0.expand(position) } - #[diplomat::rust_link(fixed_decimal::FixedDecimal::floor, FnInStruct)] - #[diplomat::rust_link(fixed_decimal::FixedDecimal::floored, FnInStruct, hidden)] + #[diplomat::rust_link(fixed_decimal::SignedFixedDecimal::floor, FnInStruct)] + #[diplomat::rust_link(fixed_decimal::SignedFixedDecimal::floored, FnInStruct, hidden)] pub fn floor(&mut self, position: i16) { self.0.floor(position) } - #[diplomat::rust_link(fixed_decimal::FixedDecimal::trunc, FnInStruct)] - #[diplomat::rust_link(fixed_decimal::FixedDecimal::trunced, FnInStruct, hidden)] + #[diplomat::rust_link(fixed_decimal::SignedFixedDecimal::trunc, FnInStruct)] + #[diplomat::rust_link(fixed_decimal::SignedFixedDecimal::trunced, FnInStruct, hidden)] pub fn trunc(&mut self, position: i16) { self.0.trunc(position) } - #[diplomat::rust_link(fixed_decimal::FixedDecimal::round_with_mode, FnInStruct)] - #[diplomat::rust_link(fixed_decimal::FixedDecimal::rounded_with_mode, FnInStruct, hidden)] - pub fn round_with_mode(&mut self, position: i16, mode: FixedDecimalRoundingMode) { + #[diplomat::rust_link(fixed_decimal::SignedFixedDecimal::round_with_mode, FnInStruct)] + #[diplomat::rust_link( + fixed_decimal::SignedFixedDecimal::rounded_with_mode, + FnInStruct, + hidden + )] + pub fn round_with_mode(&mut self, position: i16, mode: FixedDecimalSignedRoundingMode) { self.0.round_with_mode(position, mode.into()) } @@ -327,7 +356,7 @@ pub mod ffi { pub fn round_with_mode_and_increment( &mut self, position: i16, - mode: FixedDecimalRoundingMode, + mode: FixedDecimalSignedRoundingMode, increment: FixedDecimalRoundingIncrement, ) { self.0 @@ -341,14 +370,14 @@ pub mod ffi { /// If not successful, `other` will be unchanged and an error is returned. #[diplomat::rust_link(fixed_decimal::FixedDecimal::concatenate_end, FnInStruct)] #[diplomat::rust_link(fixed_decimal::FixedDecimal::concatenated_end, FnInStruct, hidden)] - pub fn concatenate_end(&mut self, other: &mut FixedDecimal) -> Result<(), ()> { + pub fn concatenate_end(&mut self, other: &mut SignedFixedDecimal) -> Result<(), ()> { let x = core::mem::take(&mut other.0); - self.0.concatenate_end(x).map_err(|y| { - other.0 = y; + self.0.absolute.concatenate_end(x.absolute).map_err(|y| { + other.0.absolute = y; }) } - /// Format the [`FixedDecimal`] as a string. + /// Format the [`SignedFixedDecimal`] as a string. #[diplomat::rust_link(fixed_decimal::FixedDecimal::write_to, FnInStruct)] #[diplomat::rust_link(fixed_decimal::FixedDecimal::to_string, FnInStruct, hidden)] #[diplomat::attr(auto, stringifier)] @@ -357,3 +386,37 @@ pub mod ffi { } } } + +impl From for fixed_decimal::SignedRoundingMode { + fn from(mode: FixedDecimalSignedRoundingMode) -> Self { + match mode { + FixedDecimalSignedRoundingMode::Expand => fixed_decimal::SignedRoundingMode::Unsigned( + fixed_decimal::UnsignedRoundingMode::Expand, + ), + FixedDecimalSignedRoundingMode::Trunc => fixed_decimal::SignedRoundingMode::Unsigned( + fixed_decimal::UnsignedRoundingMode::Trunc, + ), + FixedDecimalSignedRoundingMode::HalfExpand => { + fixed_decimal::SignedRoundingMode::Unsigned( + fixed_decimal::UnsignedRoundingMode::HalfExpand, + ) + } + FixedDecimalSignedRoundingMode::HalfTrunc => { + fixed_decimal::SignedRoundingMode::Unsigned( + fixed_decimal::UnsignedRoundingMode::HalfTrunc, + ) + } + FixedDecimalSignedRoundingMode::HalfEven => { + fixed_decimal::SignedRoundingMode::Unsigned( + fixed_decimal::UnsignedRoundingMode::HalfEven, + ) + } + FixedDecimalSignedRoundingMode::Ceil => fixed_decimal::SignedRoundingMode::Ceil, + FixedDecimalSignedRoundingMode::Floor => fixed_decimal::SignedRoundingMode::Floor, + FixedDecimalSignedRoundingMode::HalfCeil => fixed_decimal::SignedRoundingMode::HalfCeil, + FixedDecimalSignedRoundingMode::HalfFloor => { + fixed_decimal::SignedRoundingMode::HalfFloor + } + } + } +} diff --git a/ffi/capi/src/pluralrules.rs b/ffi/capi/src/pluralrules.rs index 90d688090a2..9452473c218 100644 --- a/ffi/capi/src/pluralrules.rs +++ b/ffi/capi/src/pluralrules.rs @@ -101,7 +101,7 @@ pub mod ffi { #[diplomat::attr(supports = fallible_constructors, named_constructor)] pub fn from_string(s: &DiplomatStr) -> Result, FixedDecimalParseError> { Ok(Box::new(PluralOperands(icu_plurals::PluralOperands::from( - &fixed_decimal::FixedDecimal::try_from_utf8(s)?, + &fixed_decimal::SignedFixedDecimal::try_from_utf8(s)?, )))) } @@ -110,7 +110,7 @@ pub mod ffi { /// Retains at most 18 digits each from the integer and fraction parts. #[cfg(feature = "decimal")] #[diplomat::attr(supports = fallible_constructors, named_constructor)] - pub fn from_fixed_decimal(x: &crate::fixed_decimal::ffi::FixedDecimal) -> Box { + pub fn from_fixed_decimal(x: &crate::fixed_decimal::ffi::SignedFixedDecimal) -> Box { Box::new(Self((&x.0).into())) } } diff --git a/ffi/capi/tests/missing_apis.txt b/ffi/capi/tests/missing_apis.txt index 24ac126fd14..c69b515bfce 100644 --- a/ffi/capi/tests/missing_apis.txt +++ b/ffi/capi/tests/missing_apis.txt @@ -14,6 +14,64 @@ # Please check in with @Manishearth, @robertbastian, or @sffc if you have questions +fixed_decimal::Signed#Struct +fixed_decimal::Signed::apply_sign_display#FnInStruct +fixed_decimal::Signed::ceil#FnInStruct +fixed_decimal::Signed::ceiled#FnInStruct +fixed_decimal::Signed::expand#FnInStruct +fixed_decimal::Signed::expanded#FnInStruct +fixed_decimal::Signed::floor#FnInStruct +fixed_decimal::Signed::floored#FnInStruct +fixed_decimal::Signed::new#FnInStruct +fixed_decimal::Signed::round#FnInStruct +fixed_decimal::Signed::round_with_mode#FnInStruct +fixed_decimal::Signed::round_with_mode_and_increment#FnInStruct +fixed_decimal::Signed::rounded#FnInStruct +fixed_decimal::Signed::rounded_with_mode#FnInStruct +fixed_decimal::Signed::rounded_with_mode_and_increment#FnInStruct +fixed_decimal::Signed::set_sign#FnInStruct +fixed_decimal::Signed::sign#FnInStruct +fixed_decimal::Signed::to_string#FnInStruct +fixed_decimal::Signed::trunc#FnInStruct +fixed_decimal::Signed::trunced#FnInStruct +fixed_decimal::Signed::try_from_f64#FnInStruct +fixed_decimal::Signed::try_from_str#FnInStruct +fixed_decimal::Signed::try_from_utf8#FnInStruct +fixed_decimal::Signed::with_sign#FnInStruct +fixed_decimal::Signed::with_sign_display#FnInStruct +fixed_decimal::SignedFixedDecimal#Typedef +fixed_decimal::UnsignedFixedDecimal#Struct +fixed_decimal::UnsignedFixedDecimal::concatenate_end#FnInStruct +fixed_decimal::UnsignedFixedDecimal::concatenated_end#FnInStruct +fixed_decimal::UnsignedFixedDecimal::expand#FnInStruct +fixed_decimal::UnsignedFixedDecimal::expanded#FnInStruct +fixed_decimal::UnsignedFixedDecimal::from_str#FnInStruct +fixed_decimal::UnsignedFixedDecimal::multiplied_pow10#FnInStruct +fixed_decimal::UnsignedFixedDecimal::multiply_pow10#FnInStruct +fixed_decimal::UnsignedFixedDecimal::pad_end#FnInStruct +fixed_decimal::UnsignedFixedDecimal::pad_start#FnInStruct +fixed_decimal::UnsignedFixedDecimal::padded_end#FnInStruct +fixed_decimal::UnsignedFixedDecimal::padded_start#FnInStruct +fixed_decimal::UnsignedFixedDecimal::round#FnInStruct +fixed_decimal::UnsignedFixedDecimal::round_with_mode#FnInStruct +fixed_decimal::UnsignedFixedDecimal::round_with_mode_and_increment#FnInStruct +fixed_decimal::UnsignedFixedDecimal::rounded#FnInStruct +fixed_decimal::UnsignedFixedDecimal::rounded_with_mode#FnInStruct +fixed_decimal::UnsignedFixedDecimal::rounded_with_mode_and_increment#FnInStruct +fixed_decimal::UnsignedFixedDecimal::set_max_position#FnInStruct +fixed_decimal::UnsignedFixedDecimal::to_string#FnInStruct +fixed_decimal::UnsignedFixedDecimal::trim_end#FnInStruct +fixed_decimal::UnsignedFixedDecimal::trim_start#FnInStruct +fixed_decimal::UnsignedFixedDecimal::trimmed_end#FnInStruct +fixed_decimal::UnsignedFixedDecimal::trimmed_start#FnInStruct +fixed_decimal::UnsignedFixedDecimal::trunc#FnInStruct +fixed_decimal::UnsignedFixedDecimal::trunced#FnInStruct +fixed_decimal::UnsignedFixedDecimal::try_from_f64#FnInStruct +fixed_decimal::UnsignedFixedDecimal::try_from_str#FnInStruct +fixed_decimal::UnsignedFixedDecimal::try_from_utf8#FnInStruct +fixed_decimal::UnsignedFixedDecimal::with_max_position#FnInStruct +fixed_decimal::UnsignedFixedDecimal::write_to#FnInStruct +fixed_decimal::UnsignedRoundingMode#Enum icu::calendar::types::YearAmbiguity#Enum icu::calendar::types::YearInfo::year_ambiguity#FnInStruct icu::collator::CollatorPreferences::extend#FnInStruct diff --git a/ffi/dart/test/icu_test.dart b/ffi/dart/test/icu_test.dart index bd90474a1e8..d2e4809b353 100644 --- a/ffi/dart/test/icu_test.dart +++ b/ffi/dart/test/icu_test.dart @@ -4,8 +4,8 @@ import 'package:test/test.dart'; void main() { Logger.initSimpleLogger(); - test('FixedDecimal.toString', () { - final x = FixedDecimal.fromDoubleWithLowerMagnitude(1.49403, -7); + test('SignedFixedDecimal.toString', () { + final x = SignedFixedDecimal.fromDoubleWithLowerMagnitude(1.49403, -7); expect(x.toString(), '1.4940300'); }); diff --git a/ffi/ecma402/src/pluralrules.rs b/ffi/ecma402/src/pluralrules.rs index 64ca7eda5ba..447e13a28e1 100644 --- a/ffi/ecma402/src/pluralrules.rs +++ b/ffi/ecma402/src/pluralrules.rs @@ -10,7 +10,7 @@ pub(crate) mod internal { use core::str::FromStr; use ecma402_traits::pluralrules::options::Type; use ecma402_traits::pluralrules::Options; - use fixed_decimal::FixedDecimal; + use fixed_decimal::SignedFixedDecimal; use icu::plurals::{PluralCategory, PluralOperands, PluralRuleType}; use std::cmp::{max, min}; @@ -113,7 +113,7 @@ pub(crate) mod internal { dbg!("n={}", n); let nstr = fixed_format(n, &opts); #[allow(clippy::unwrap_used)] // TODO(#1668) Clippy exceptions need docs or fixing. - let ret = PluralOperands::from(&FixedDecimal::from_str(&nstr).unwrap()); + let ret = PluralOperands::from(&SignedFixedDecimal::from_str(&nstr).unwrap()); dbg!("ret={:?}\n---\n", &ret); ret } diff --git a/ffi/npm/test/data-providers.mjs b/ffi/npm/test/data-providers.mjs index 4a6831feb8d..fc41d7c3ff4 100644 --- a/ffi/npm/test/data-providers.mjs +++ b/ffi/npm/test/data-providers.mjs @@ -4,7 +4,7 @@ import test from 'ava'; -import { FixedDecimal, Locale, DataProvider, FixedDecimalFormatter, FixedDecimalGroupingStrategy } from 'icu4x'; +import { SignedFixedDecimal, Locale, DataProvider, FixedDecimalFormatter, FixedDecimalGroupingStrategy } from 'icu4x'; test('use createCompiled to format a simple decimal', async t => { const locale = Locale.fromString('bn'); @@ -12,7 +12,7 @@ test('use createCompiled to format a simple decimal', async t => { const format = FixedDecimalFormatter.createWithGroupingStrategy(provider, locale, FixedDecimalGroupingStrategy.Auto); - const decimal = FixedDecimal.fromNumber(1234); + const decimal = SignedFixedDecimal.fromNumber(1234); decimal.multiplyPow10(-2); t.is(format.format(decimal), '১২.৩৪'); diff --git a/ffi/npm/test/fixed-decimal-format.mjs b/ffi/npm/test/fixed-decimal-format.mjs index 68f23e7f0ab..2a41c0cb921 100644 --- a/ffi/npm/test/fixed-decimal-format.mjs +++ b/ffi/npm/test/fixed-decimal-format.mjs @@ -4,27 +4,27 @@ import test from 'ava'; -import { FixedDecimal, Locale, DataProvider, FixedDecimalFormatter, FixedDecimalSign, FixedDecimalGroupingStrategy } from 'icu4x'; +import { SignedFixedDecimal, Locale, DataProvider, FixedDecimalFormatter, FixedDecimalSign, FixedDecimalGroupingStrategy } from 'icu4x'; const locale = Locale.fromString('bn'); const provider = DataProvider.compiled(); const format = FixedDecimalFormatter.createWithGroupingStrategy(provider, locale, FixedDecimalGroupingStrategy.Auto); test('format a simple decimal', t => { - const decimal = FixedDecimal.fromNumber(1234); + const decimal = SignedFixedDecimal.fromNumber(1234); decimal.multiplyPow10(-2); t.is(format.format(decimal), '১২.৩৪'); }); test('format a long decimal', t => { - const decimal = FixedDecimal.fromNumber(1000007); + const decimal = SignedFixedDecimal.fromNumber(1000007); t.is(format.format(decimal), '১০,০০,০০৭'); }); test('format a negated, scaled decimal', t => { - const decimal = FixedDecimal.fromNumber(1000007); + const decimal = SignedFixedDecimal.fromNumber(1000007); decimal.multiplyPow10(2); decimal.sign = FixedDecimalSign.Negative; diff --git a/ffi/npm/test/fixed-decimal.mjs b/ffi/npm/test/fixed-decimal.mjs index 984188c9de7..5514abf4ddb 100644 --- a/ffi/npm/test/fixed-decimal.mjs +++ b/ffi/npm/test/fixed-decimal.mjs @@ -4,23 +4,23 @@ import test from 'ava'; -import { FixedDecimal, FixedDecimalSign } from 'icu4x'; +import { SignedFixedDecimal, FixedDecimalSign } from 'icu4x'; test('convert a simple decimal to a string', t => { - const decimal = FixedDecimal.fromBigInt(1234n); + const decimal = SignedFixedDecimal.fromBigInt(1234n); t.is(decimal.toString(), '1234'); }); test('multiply a decimal by a power of 10', t => { - const decimal = FixedDecimal.fromNumber(1234); + const decimal = SignedFixedDecimal.fromNumber(1234); decimal.multiplyPow10(-2); t.is(decimal.toString(), '12.34'); }); test('negate a decimal', t => { - const decimal = FixedDecimal.fromNumber(1234); + const decimal = SignedFixedDecimal.fromNumber(1234); decimal.sign = FixedDecimalSign.Negative; t.is(decimal.toString(), '-1234'); diff --git a/tutorials/c-tiny/fixeddecimal/test.c b/tutorials/c-tiny/fixeddecimal/test.c index 670ef8616d3..72e9188bc56 100644 --- a/tutorials/c-tiny/fixeddecimal/test.c +++ b/tutorials/c-tiny/fixeddecimal/test.c @@ -4,7 +4,7 @@ #include "DataProvider.h" #include "Locale.h" -#include "FixedDecimal.h" +#include "SignedFixedDecimal.h" #include "FixedDecimalFormatter.h" #include #include @@ -26,8 +26,8 @@ int main(int argc, char *argv[]) { } DataProvider* provider = icu4x_DataProvider_compiled_mv1(); - FixedDecimal* decimal = icu4x_FixedDecimal_from_uint64_mv1(1000007); - icu4x_FixedDecimal_round_mv1(decimal, 0); + SignedFixedDecimal* decimal = icu4x_SignedFixedDecimal_from_uint64_mv1(1000007); + icu4x_SignedFixedDecimal_round_mv1(decimal, 0); FixedDecimalGroupingStrategy_option o = {.ok = FixedDecimalGroupingStrategy_Auto, .is_ok = true}; @@ -55,7 +55,7 @@ int main(int argc, char *argv[]) { return 1; } - icu4x_FixedDecimal_destroy_mv1(decimal); + icu4x_SignedFixedDecimal_destroy_mv1(decimal); icu4x_FixedDecimalFormatter_destroy_mv1(fdf); icu4x_Locale_destroy_mv1(locale); icu4x_DataProvider_destroy_mv1(provider); diff --git a/tutorials/c/fixeddecimal.c b/tutorials/c/fixeddecimal.c index 89a4d7a90d0..040309b2c32 100644 --- a/tutorials/c/fixeddecimal.c +++ b/tutorials/c/fixeddecimal.c @@ -4,7 +4,7 @@ #include "DataProvider.h" #include "Locale.h" -#include "FixedDecimal.h" +#include "SignedFixedDecimal.h" #include "FixedDecimalFormatter.h" #include "Logger.h" #include @@ -24,7 +24,7 @@ int main() { Locale* locale = locale_result.ok; DataProvider* provider = icu4x_DataProvider_compiled_mv1(); - FixedDecimal* decimal = icu4x_FixedDecimal_from_uint64_mv1(1000007); + SignedFixedDecimal* decimal = icu4x_SignedFixedDecimal_from_uint64_mv1(1000007); FixedDecimalGroupingStrategy_option o = {.ok = FixedDecimalGroupingStrategy_Auto, .is_ok = true}; @@ -52,9 +52,9 @@ int main() { return 1; } - icu4x_FixedDecimal_multiply_pow10_mv1(decimal, 2); + icu4x_SignedFixedDecimal_multiply_pow10_mv1(decimal, 2); - icu4x_FixedDecimal_set_sign_mv1(decimal, FixedDecimalSign_Negative); + icu4x_SignedFixedDecimal_set_sign_mv1(decimal, FixedDecimalSign_Negative); write = diplomat_simple_write(output, 40); @@ -71,14 +71,14 @@ int main() { return 1; } - icu4x_FixedDecimal_destroy_mv1(decimal); + icu4x_SignedFixedDecimal_destroy_mv1(decimal); struct DiplomatStringView fixed_decimal_str = { "1000007.070", 11 }; - icu4x_FixedDecimal_from_string_mv1_result fd_result = icu4x_FixedDecimal_from_string_mv1(fixed_decimal_str); + icu4x_SignedFixedDecimal_from_string_mv1_result fd_result = icu4x_SignedFixedDecimal_from_string_mv1(fixed_decimal_str); if (!fd_result.is_ok) { printf("Failed to create FixedDecimal from string.\n"); return 1; @@ -100,7 +100,7 @@ int main() { return 1; } - icu4x_FixedDecimal_destroy_mv1(decimal); + icu4x_SignedFixedDecimal_destroy_mv1(decimal); icu4x_FixedDecimalFormatter_destroy_mv1(fdf); icu4x_Locale_destroy_mv1(locale); icu4x_DataProvider_destroy_mv1(provider); diff --git a/tutorials/cpp/fixeddecimal.cpp b/tutorials/cpp/fixeddecimal.cpp index 5f84b0c4ec7..39e6a9a9696 100644 --- a/tutorials/cpp/fixeddecimal.cpp +++ b/tutorials/cpp/fixeddecimal.cpp @@ -18,7 +18,7 @@ int main() { std::unique_ptr fdf = FixedDecimalFormatter::create_with_grouping_strategy( *dp.get(), *locale.get(), FixedDecimalGroupingStrategy::Auto).ok().value(); - std::unique_ptr decimal = FixedDecimal::from(1000007); + std::unique_ptr decimal = SignedFixedDecimal::from(1000007); std::string out = fdf->format(*decimal.get()); std::cout << "Formatted value is " << out << std::endl; if (out != "১০,০০,০০৭") { @@ -35,7 +35,7 @@ int main() { return 1; } - decimal = FixedDecimal::from_double_with_round_trip_precision(100.01).ok().value(); + decimal = SignedFixedDecimal::from_double_with_round_trip_precision(100.01).ok().value(); out = fdf->format(*decimal.get()); std::cout << "Formatted float value is " << out << std::endl; if (out != "১০০.০১") { @@ -67,7 +67,7 @@ int main() { return 1; } - decimal = FixedDecimal::from_double_with_lower_magnitude(100.0006, -2).ok().value(); + decimal = SignedFixedDecimal::from_double_with_lower_magnitude(100.0006, -2).ok().value(); out = fdf->format(*decimal.get()); std::cout << "Formatted float value from precision 2 is " << out << std::endl; if (out != "১০০.০০") { @@ -75,7 +75,7 @@ int main() { return 1; } - decimal = FixedDecimal::from_double_with_significant_digits(100.0006, 5).ok().value(); + decimal = SignedFixedDecimal::from_double_with_significant_digits(100.0006, 5).ok().value(); out = fdf->format(*decimal.get()); std::cout << "Formatted float value with 5 digits is " << out << std::endl; if (out != "১০০.০০") { @@ -87,14 +87,14 @@ int main() { fdf = FixedDecimalFormatter::create_with_manual_data("+", "", "-", "", "/", "_", 4, 2, 4, digits, FixedDecimalGroupingStrategy::Auto).ok().value(); - decimal = FixedDecimal::from_double_with_round_trip_precision(123456.8901).ok().value(); + decimal = SignedFixedDecimal::from_double_with_round_trip_precision(123456.8901).ok().value(); out = fdf->format(*decimal.get()); std::cout << "Formatted float value for custom numeric system is " << out << std::endl; if (out != "bcdefg/ijab") { std::cout << "Output does not match expected output" << std::endl; return 1; } - decimal = FixedDecimal::from_double_with_round_trip_precision(123451234567.8901).ok().value(); + decimal = SignedFixedDecimal::from_double_with_round_trip_precision(123451234567.8901).ok().value(); out = fdf->format(*decimal.get()); std::cout << "Formatted float value for custom numeric system is " << out << std::endl; if (out != "bc_de_fb_cd_efgh/ijab") { @@ -107,7 +107,7 @@ int main() { fdf = FixedDecimalFormatter::create_with_grouping_strategy( *dp.get(), *locale.get(), FixedDecimalGroupingStrategy::Auto).ok().value(); - decimal = FixedDecimal::from_double_with_round_trip_precision(123456.8901).ok().value(); + decimal = SignedFixedDecimal::from_double_with_round_trip_precision(123456.8901).ok().value(); out = fdf->format(*decimal.get()); std::cout << "Formatted value is " << out << std::endl; if (out != "๑๒๓,๔๕๖.๘๙๐๑") { diff --git a/tutorials/js-tiny/Cargo.lock b/tutorials/js-tiny/Cargo.lock index ed327c2dc0d..3edb7528aed 100644 --- a/tutorials/js-tiny/Cargo.lock +++ b/tutorials/js-tiny/Cargo.lock @@ -47,7 +47,7 @@ dependencies = [ [[package]] name = "diplomat" version = "0.8.0" -source = "git+https://github.com/rust-diplomat/diplomat?rev=8744ac97162341f347b63131969ad736e1047f6d#8744ac97162341f347b63131969ad736e1047f6d" +source = "git+https://github.com/rust-diplomat/diplomat?rev=b49d63ec2a50a456b4b6e9d072d3650dca153ff8#b49d63ec2a50a456b4b6e9d072d3650dca153ff8" dependencies = [ "diplomat_core", "proc-macro2", @@ -58,7 +58,7 @@ dependencies = [ [[package]] name = "diplomat-runtime" version = "0.8.1" -source = "git+https://github.com/rust-diplomat/diplomat?rev=8744ac97162341f347b63131969ad736e1047f6d#8744ac97162341f347b63131969ad736e1047f6d" +source = "git+https://github.com/rust-diplomat/diplomat?rev=b49d63ec2a50a456b4b6e9d072d3650dca153ff8#b49d63ec2a50a456b4b6e9d072d3650dca153ff8" dependencies = [ "log", ] @@ -66,13 +66,13 @@ dependencies = [ [[package]] name = "diplomat_core" version = "0.8.0" -source = "git+https://github.com/rust-diplomat/diplomat?rev=8744ac97162341f347b63131969ad736e1047f6d#8744ac97162341f347b63131969ad736e1047f6d" +source = "git+https://github.com/rust-diplomat/diplomat?rev=b49d63ec2a50a456b4b6e9d072d3650dca153ff8#b49d63ec2a50a456b4b6e9d072d3650dca153ff8" dependencies = [ "proc-macro2", "quote", "serde", "smallvec", - "strck_ident", + "strck", "syn", ] @@ -95,7 +95,7 @@ checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "fixed_decimal" -version = "0.5.6" +version = "0.6.0-dev" dependencies = [ "displaydoc", "ryu", @@ -105,7 +105,7 @@ dependencies = [ [[package]] name = "icu_calendar" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "calendrical_calculations", "displaydoc", @@ -120,7 +120,7 @@ dependencies = [ [[package]] name = "icu_calendar_data" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "icu_locale", "icu_provider_baked", @@ -128,7 +128,7 @@ dependencies = [ [[package]] name = "icu_capi" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "diplomat", "diplomat-runtime", @@ -151,6 +151,7 @@ dependencies = [ "icu_segmenter", "icu_timezone", "log", + "potential_utf", "simple_logger", "tinystr", "unicode-bidi", @@ -159,7 +160,7 @@ dependencies = [ [[package]] name = "icu_casemap" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "displaydoc", "icu_casemap_data", @@ -167,24 +168,26 @@ dependencies = [ "icu_locale_core", "icu_properties", "icu_provider", + "potential_utf", "writeable", "zerovec", ] [[package]] name = "icu_casemap_data" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "icu_provider_baked", ] [[package]] name = "icu_collator" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "displaydoc", "icu_collator_data", "icu_collections", + "icu_locale_core", "icu_normalizer", "icu_properties", "icu_provider", @@ -196,7 +199,7 @@ dependencies = [ [[package]] name = "icu_collator_data" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "icu_locale", "icu_provider_baked", @@ -204,9 +207,10 @@ dependencies = [ [[package]] name = "icu_collections" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "displaydoc", + "potential_utf", "yoke", "zerofrom", "zerovec", @@ -214,7 +218,7 @@ dependencies = [ [[package]] name = "icu_datetime" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "displaydoc", "either", @@ -223,9 +227,12 @@ dependencies = [ "icu_datetime_data", "icu_decimal", "icu_locale_core", + "icu_pattern", "icu_plurals", "icu_provider", "icu_timezone", + "litemap", + "potential_utf", "smallvec", "tinystr", "writeable", @@ -234,7 +241,7 @@ dependencies = [ [[package]] name = "icu_datetime_data" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "icu_locale", "icu_provider_baked", @@ -242,7 +249,7 @@ dependencies = [ [[package]] name = "icu_decimal" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "displaydoc", "fixed_decimal", @@ -253,7 +260,7 @@ dependencies = [ [[package]] name = "icu_decimal_data" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "icu_locale", "icu_provider_baked", @@ -261,13 +268,15 @@ dependencies = [ [[package]] name = "icu_experimental" -version = "0.1.0" +version = "0.2.0-dev" dependencies = [ "displaydoc", + "either", "fixed_decimal", "icu_collections", "icu_decimal", "icu_experimental_data", + "icu_list", "icu_locale", "icu_locale_core", "icu_normalizer", @@ -279,6 +288,7 @@ dependencies = [ "num-bigint", "num-rational", "num-traits", + "potential_utf", "smallvec", "tinystr", "writeable", @@ -289,7 +299,7 @@ dependencies = [ [[package]] name = "icu_experimental_data" -version = "0.1.0" +version = "0.2.0-dev" dependencies = [ "icu_locale", "icu_provider_baked", @@ -297,7 +307,7 @@ dependencies = [ [[package]] name = "icu_list" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "displaydoc", "icu_list_data", @@ -308,7 +318,7 @@ dependencies = [ [[package]] name = "icu_list_data" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "icu_locale", "icu_provider_baked", @@ -316,19 +326,21 @@ dependencies = [ [[package]] name = "icu_locale" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "displaydoc", + "icu_collections", "icu_locale_core", "icu_locale_data", "icu_provider", + "potential_utf", "tinystr", "zerovec", ] [[package]] name = "icu_locale_core" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "displaydoc", "litemap", @@ -339,14 +351,14 @@ dependencies = [ [[package]] name = "icu_locale_data" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "icu_provider_baked", ] [[package]] name = "icu_normalizer" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "displaydoc", "icu_collections", @@ -362,25 +374,25 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "icu_provider_baked", ] [[package]] name = "icu_pattern" -version = "0.2.0" +version = "0.3.0-dev" dependencies = [ "displaydoc", "either", "writeable", "yoke", - "zerofrom", + "zerovec", ] [[package]] name = "icu_plurals" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "displaydoc", "fixed_decimal", @@ -391,7 +403,7 @@ dependencies = [ [[package]] name = "icu_plurals_data" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "icu_locale", "icu_provider_baked", @@ -399,28 +411,29 @@ dependencies = [ [[package]] name = "icu_properties" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "displaydoc", "icu_collections", + "icu_locale_core", "icu_properties_data", "icu_provider", - "tinystr", + "potential_utf", "unicode-bidi", + "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ - "icu_locale", "icu_provider_baked", ] [[package]] name = "icu_provider" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "displaydoc", "icu_locale_core", @@ -436,7 +449,7 @@ dependencies = [ [[package]] name = "icu_provider_adapters" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "icu_locale", "icu_provider", @@ -446,7 +459,7 @@ dependencies = [ [[package]] name = "icu_provider_baked" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "icu_provider", "writeable", @@ -455,7 +468,7 @@ dependencies = [ [[package]] name = "icu_provider_macros" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "proc-macro2", "quote", @@ -464,7 +477,7 @@ dependencies = [ [[package]] name = "icu_segmenter" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "core_maths", "displaydoc", @@ -472,13 +485,14 @@ dependencies = [ "icu_locale_core", "icu_provider", "icu_segmenter_data", + "potential_utf", "utf8_iter", "zerovec", ] [[package]] name = "icu_segmenter_data" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "icu_locale", "icu_provider_baked", @@ -486,8 +500,9 @@ dependencies = [ [[package]] name = "icu_timezone" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ + "calendrical_calculations", "displaydoc", "icu_calendar", "icu_provider", @@ -499,7 +514,7 @@ dependencies = [ [[package]] name = "icu_timezone_data" -version = "1.5.0" +version = "2.0.0-dev" dependencies = [ "icu_provider_baked", ] @@ -512,7 +527,7 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "ixdtf" -version = "0.2.0" +version = "0.3.0-dev" dependencies = [ "displaydoc", "utf8_iter", @@ -600,6 +615,15 @@ dependencies = [ "libc", ] +[[package]] +name = "potential_utf" +version = "0.1.0-dev" +dependencies = [ + "serde", + "writeable", + "zerovec", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -682,17 +706,10 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "strck" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be91090ded9d8f979d9fe921777342d37e769e0b6b7296843a7a38247240e917" - -[[package]] -name = "strck_ident" -version = "0.1.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1c3802b169b3858a44667f221c9a0b3136e6019936ea926fc97fbad8af77202" +checksum = "42316e70da376f3d113a68d138a60d8a9883c604fe97942721ec2068dab13a9f" dependencies = [ - "strck", "unicode-ident", ] @@ -753,7 +770,7 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.7.6" +version = "0.8.0-dev" dependencies = [ "displaydoc", "zerovec", @@ -864,14 +881,14 @@ checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" [[package]] name = "writeable" -version = "0.5.5" +version = "0.5.6-dev" dependencies = [ "either", ] [[package]] name = "yoke" -version = "0.7.4" +version = "0.7.5-dev" dependencies = [ "serde", "stable_deref_trait", @@ -908,7 +925,7 @@ dependencies = [ [[package]] name = "zerotrie" -version = "0.1.3" +version = "0.2.0-dev" dependencies = [ "displaydoc", "yoke", @@ -917,7 +934,7 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.10.4" +version = "0.11.0-dev" dependencies = [ "yoke", "zerofrom", @@ -926,7 +943,7 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.10.3" +version = "0.11.0-dev" dependencies = [ "proc-macro2", "quote", @@ -943,7 +960,7 @@ version = "1.0.4" [[patch.unused]] name = "databake" -version = "0.1.8" +version = "0.1.9-dev" [[patch.unused]] name = "databake-derive" @@ -955,15 +972,15 @@ version = "0.1.6" [[patch.unused]] name = "icu" -version = "1.5.0" +version = "2.0.0-dev" [[patch.unused]] name = "icu4x-datagen" -version = "1.5.0" +version = "2.0.0-dev" [[patch.unused]] name = "icu4x_ecma402" -version = "0.8.2" +version = "0.9.0-dev" [[patch.unused]] name = "icu_benchmark_macros" @@ -971,11 +988,11 @@ version = "0.0.0" [[patch.unused]] name = "icu_codepointtrie_builder" -version = "0.3.8" +version = "0.4.0-dev" [[patch.unused]] name = "icu_freertos" -version = "1.5.0" +version = "2.0.0-dev" [[patch.unused]] name = "icu_harfbuzz" @@ -983,24 +1000,24 @@ version = "0.2.0" [[patch.unused]] name = "icu_provider_blob" -version = "1.5.0" +version = "2.0.0-dev" [[patch.unused]] name = "icu_provider_export" -version = "1.5.0" +version = "2.0.0-dev" [[patch.unused]] name = "icu_provider_fs" -version = "1.5.0" +version = "2.0.0-dev" [[patch.unused]] name = "icu_provider_registry" -version = "1.5.0" +version = "2.0.0-dev" [[patch.unused]] name = "icu_provider_source" -version = "1.5.0" +version = "2.0.0-dev" [[patch.unused]] name = "tzif" -version = "0.2.3" +version = "0.3.0-dev" diff --git a/tutorials/js-tiny/ld.py b/tutorials/js-tiny/ld.py index 1a8d0b40acd..f01e450c878 100755 --- a/tutorials/js-tiny/ld.py +++ b/tutorials/js-tiny/ld.py @@ -9,9 +9,9 @@ SYMBOLS = [ "icu4x_DataProvider_compiled_mv1", "icu4x_DataProvider_destroy_mv1", - "icu4x_FixedDecimal_from_int32_mv1", - "icu4x_FixedDecimal_destroy_mv1", - "icu4x_FixedDecimal_multiply_pow10_mv1", + "icu4x_SignedFixedDecimal_from_int32_mv1", + "icu4x_SignedFixedDecimal_destroy_mv1", + "icu4x_SignedFixedDecimal_multiply_pow10_mv1", "icu4x_FixedDecimalFormatter_create_with_grouping_strategy_mv1", "icu4x_FixedDecimalFormatter_destroy_mv1", "icu4x_FixedDecimalFormatter_format_mv1", diff --git a/tutorials/js-tiny/tiny.mjs b/tutorials/js-tiny/tiny.mjs index 3989bd73159..3ff2849b69c 100644 --- a/tutorials/js-tiny/tiny.mjs +++ b/tutorials/js-tiny/tiny.mjs @@ -7,14 +7,14 @@ // See . delete globalThis.fetch; -import {Locale, DataProvider, FixedDecimalFormatter, FixedDecimal, FixedDecimalGroupingStrategy } from './lib/index.mjs'; +import {Locale, DataProvider, FixedDecimalFormatter, SignedFixedDecimal, FixedDecimalGroupingStrategy } from './lib/index.mjs'; const locale = Locale.fromString("bn"); const provider = DataProvider.compiled(); const format = FixedDecimalFormatter.createWithGroupingStrategy(provider, locale, FixedDecimalGroupingStrategy.Auto); -const decimal = FixedDecimal.fromNumber(1000007); +const decimal = SignedFixedDecimal.fromNumber(1000007); decimal.multiplyPow10(-2); const result = format.format(decimal); diff --git a/tutorials/npm/src/ts/fixed-decimal.ts b/tutorials/npm/src/ts/fixed-decimal.ts index 2cdbea0346d..7b2a9563020 100644 --- a/tutorials/npm/src/ts/fixed-decimal.ts +++ b/tutorials/npm/src/ts/fixed-decimal.ts @@ -1,4 +1,4 @@ -import { DataProvider, FixedDecimal, FixedDecimalFormatter, FixedDecimalGroupingStrategy, Locale } from "icu4x"; +import { DataProvider, SignedFixedDecimal, FixedDecimalFormatter, FixedDecimalGroupingStrategy, Locale } from "icu4x"; import { Result, Ok, result, unwrap } from './index'; export class FixedDecimalDemo { @@ -8,7 +8,7 @@ export class FixedDecimalDemo { #locale: Result; #groupingStrategy: FixedDecimalGroupingStrategy; #formatter: Result; - #fixedDecimal: Result | null; + #fixedDecimal: Result | null; constructor(displayFn: (formatted: string) => void, dataProvider: DataProvider) { this.#displayFn = displayFn; @@ -31,7 +31,7 @@ export class FixedDecimalDemo { } setFixedDecimal(digits: string): void { - this.#fixedDecimal = digits === "" ? null : result(() => FixedDecimal.fromString(digits)); + this.#fixedDecimal = digits === "" ? null : result(() => SignedFixedDecimal.fromString(digits)); this.#render(); } diff --git a/utils/fixed_decimal/Cargo.toml b/utils/fixed_decimal/Cargo.toml index 233e821314a..817716d842a 100644 --- a/utils/fixed_decimal/Cargo.toml +++ b/utils/fixed_decimal/Cargo.toml @@ -53,4 +53,4 @@ denylist = ["bench"] [[bench]] name = "fixed_decimal" -harness = false +harness = false \ No newline at end of file diff --git a/utils/fixed_decimal/README.md b/utils/fixed_decimal/README.md index 0da508e65cd..5bee2b28728 100644 --- a/utils/fixed_decimal/README.md +++ b/utils/fixed_decimal/README.md @@ -4,16 +4,16 @@ `fixed_decimal` is a utility crate of the [`ICU4X`] project. -It includes [`FixedDecimal`], a core API for representing numbers in a human-readable form -appropriate for formatting and plural rule selection. It is optimized for operations involving -the individual digits of a number. +This crate provides [`SignedFixedDecimal`] and [`UnsignedFixedDecimal`], essential APIs for representing numbers in a human-readable format. +These types are particularly useful for formatting and plural rule selection, and are optimized for operations on individual digits. ## Examples ```rust -use fixed_decimal::FixedDecimal; +use fixed_decimal::SignedFixedDecimal; -let dec = FixedDecimal::from(250).multiplied_pow10(-2); +let mut dec = SignedFixedDecimal::from(250); +dec.multiply_pow10(-2); assert_eq!("2.50", format!("{}", dec)); #[derive(Debug, PartialEq)] diff --git a/utils/fixed_decimal/benches/fixed_decimal.rs b/utils/fixed_decimal/benches/fixed_decimal.rs index ccc203756cb..1bc9f4bab64 100644 --- a/utils/fixed_decimal/benches/fixed_decimal.rs +++ b/utils/fixed_decimal/benches/fixed_decimal.rs @@ -9,8 +9,9 @@ use rand_pcg::Lcg64Xsh32; use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use fixed_decimal::FixedDecimal; +use fixed_decimal::SignedFixedDecimal; +// TODO: move to helpers.rs fn triangular_nums(range: f64) -> Vec { // Use Lcg64Xsh32, a small, fast PRNG. // Generate 1000 numbers between -range and +range, weighted around 0. @@ -22,6 +23,7 @@ fn triangular_nums(range: f64) -> Vec { .collect() } +// TODO: move to helpers.rs #[cfg(feature = "bench")] fn triangular_floats(range: f64) -> impl Iterator { // Use Lcg64Xsh32, a small, fast PRNG.s @@ -43,12 +45,12 @@ fn overview_bench(c: &mut Criterion) { // * Serialization of FixedDecimal to string nums.iter() .map(|v| black_box(*v)) - .map(FixedDecimal::from) + .map(SignedFixedDecimal::from) .count(); let fds: Vec<_> = values .iter() .map(black_box) - .map(|v| FixedDecimal::from_str(v).expect("Failed to parse")) + .map(|v| SignedFixedDecimal::from_str(v).expect("Failed to parse")) .collect(); fds.iter().map(black_box).map(|v| v.to_string()).count(); }); @@ -76,7 +78,7 @@ fn smaller_isize_benches(c: &mut Criterion) { #[allow(clippy::suspicious_map)] nums.iter() .map(|v| black_box(*v)) - .map(FixedDecimal::from) + .map(SignedFixedDecimal::from) .count() }); }); @@ -94,7 +96,7 @@ fn larger_isize_benches(c: &mut Criterion) { #[allow(clippy::suspicious_map)] nums.iter() .map(|v| black_box(*v)) - .map(FixedDecimal::from) + .map(SignedFixedDecimal::from) .count() }); }); @@ -106,8 +108,12 @@ fn to_string_benches(c: &mut Criterion) { use writeable::Writeable; let objects = [ - FixedDecimal::from(2250).multiplied_pow10(-2), - FixedDecimal::from(908070605040302010u128), + { + let mut fd = SignedFixedDecimal::from(2250); + fd.multiply_pow10(-2); + fd + }, + SignedFixedDecimal::from(908070605040302010u128), ]; { @@ -161,7 +167,7 @@ fn from_string_benches(c: &mut Criterion) { group.bench_with_input( BenchmarkId::from_parameter(object.to_string()), object, - |b, object| b.iter(|| FixedDecimal::from_str(object).unwrap()), + |b, object| b.iter(|| SignedFixedDecimal::from_str(object).unwrap()), ); } group.finish(); @@ -170,21 +176,36 @@ fn from_string_benches(c: &mut Criterion) { #[cfg(feature = "bench")] fn rounding_benches(c: &mut Criterion) { - use fixed_decimal::{FloatPrecision, RoundingMode}; - const ROUNDING_MODES: [(&str, RoundingMode); 9] = [ - ("ceil", RoundingMode::Ceil), - ("floor", RoundingMode::Floor), - ("expand", RoundingMode::Expand), - ("trunc", RoundingMode::Trunc), - ("half_ceil", RoundingMode::HalfCeil), - ("half_floor", RoundingMode::HalfFloor), - ("half_expand", RoundingMode::HalfExpand), - ("half_trunc", RoundingMode::HalfTrunc), - ("half_even", RoundingMode::HalfEven), + use fixed_decimal::{FloatPrecision, SignedRoundingMode, UnsignedRoundingMode}; + const ROUNDING_MODES: [(&str, SignedRoundingMode); 9] = [ + ("ceil", SignedRoundingMode::Ceil), + ("floor", SignedRoundingMode::Floor), + ( + "expand", + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + ), + ( + "trunc", + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Trunc), + ), + ("half_ceil", SignedRoundingMode::HalfCeil), + ("half_floor", SignedRoundingMode::HalfFloor), + ( + "half_expand", + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + ), + ( + "half_trunc", + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc), + ), + ( + "half_even", + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + ), ]; let nums: Vec<_> = triangular_floats(1e7) - .map(|f| FixedDecimal::try_from_f64(f, FloatPrecision::RoundTrip).unwrap()) + .map(|f| SignedFixedDecimal::try_from_f64(f, FloatPrecision::RoundTrip).unwrap()) .collect(); let mut group = c.benchmark_group("rounding"); @@ -195,7 +216,11 @@ fn rounding_benches(c: &mut Criterion) { nums.iter() .cloned() .map(|num| { - FixedDecimal::rounded_with_mode(black_box(num), offset, rounding_mode) + SignedFixedDecimal::rounded_with_mode( + black_box(num), + offset, + rounding_mode, + ) }) .for_each(|num| { black_box(num); diff --git a/utils/fixed_decimal/examples/permyriad.rs b/utils/fixed_decimal/examples/permyriad.rs index 83d9fd3210c..81b77ffd244 100644 --- a/utils/fixed_decimal/examples/permyriad.rs +++ b/utils/fixed_decimal/examples/permyriad.rs @@ -9,12 +9,16 @@ #![no_main] // https://github.com/unicode-org/icu4x/issues/395 icu_benchmark_macros::instrument!(); -use fixed_decimal::FixedDecimal; +use fixed_decimal::SignedFixedDecimal; use writeable::Writeable; fn main() { let monetary_int = 19_9500; - let fixed_decimal = FixedDecimal::from(monetary_int).multiplied_pow10(-4); + let fixed_decimal = { + let mut fixed_decimal = SignedFixedDecimal::from(monetary_int); + fixed_decimal.multiply_pow10(-4); + fixed_decimal + }; assert_eq!(fixed_decimal.write_to_string(), "19.9500"); } diff --git a/utils/fixed_decimal/src/compact.rs b/utils/fixed_decimal/src/compact.rs index ce97ecf9fbb..d1c0f142aa5 100644 --- a/utils/fixed_decimal/src/compact.rs +++ b/utils/fixed_decimal/src/compact.rs @@ -5,10 +5,10 @@ use core::fmt; use core::str::FromStr; -use crate::FixedDecimal; use crate::ParseError; +use crate::SignedFixedDecimal; -/// A struct containing a [`FixedDecimal`] significand together with an exponent, representing a +/// A struct containing a [`SignedFixedDecimal`] significand together with an exponent, representing a /// number written in compact notation (such as 1.2M). /// This represents a _source number_, as defined /// [in UTS #35](https://www.unicode.org/reports/tr35/tr35-numbers.html#Plural_rules_syntax). @@ -19,13 +19,13 @@ use crate::ParseError; /// nor a sign in the exponent, and behaves differently in pluralization. #[derive(Debug, Clone, PartialEq)] pub struct CompactDecimal { - significand: FixedDecimal, + significand: SignedFixedDecimal, exponent: u8, } impl CompactDecimal { /// Constructs a [`CompactDecimal`] from its significand and exponent. - pub fn from_significand_and_exponent(significand: FixedDecimal, exponent: u8) -> Self { + pub fn from_significand_and_exponent(significand: SignedFixedDecimal, exponent: u8) -> Self { Self { significand, exponent, @@ -35,32 +35,32 @@ impl CompactDecimal { /// Returns a reference to the significand of `self`. /// ``` /// # use fixed_decimal::CompactDecimal; - /// # use fixed_decimal::FixedDecimal; + /// # use fixed_decimal::SignedFixedDecimal; /// # use std::str::FromStr; /// # /// assert_eq!( /// CompactDecimal::from_str("+1.20c6").unwrap().significand(), - /// &FixedDecimal::from_str("+1.20").unwrap() + /// &SignedFixedDecimal::from_str("+1.20").unwrap() /// ); /// ``` - pub fn significand(&self) -> &FixedDecimal { + pub fn significand(&self) -> &SignedFixedDecimal { &self.significand } /// Returns the significand of `self`. /// ``` /// # use fixed_decimal::CompactDecimal; - /// # use fixed_decimal::FixedDecimal; + /// # use fixed_decimal::SignedFixedDecimal; /// # use std::str::FromStr; /// # /// assert_eq!( /// CompactDecimal::from_str("+1.20c6") /// .unwrap() /// .into_significand(), - /// FixedDecimal::from_str("+1.20").unwrap() + /// SignedFixedDecimal::from_str("+1.20").unwrap() /// ); /// ``` - pub fn into_significand(self) -> FixedDecimal { + pub fn into_significand(self) -> SignedFixedDecimal { self.significand } @@ -127,7 +127,8 @@ impl CompactDecimal { return Err(ParseError::Syntax); } let mut parts = code_units.split(|&c| c == b'c'); - let significand = FixedDecimal::try_from_utf8(parts.next().ok_or(ParseError::Syntax)?)?; + let significand = + SignedFixedDecimal::try_from_utf8(parts.next().ok_or(ParseError::Syntax)?)?; match parts.next() { None => Ok(CompactDecimal { significand, diff --git a/utils/fixed_decimal/src/decimal.rs b/utils/fixed_decimal/src/decimal.rs index 985f3e7e566..340e9c7442c 100644 --- a/utils/fixed_decimal/src/decimal.rs +++ b/utils/fixed_decimal/src/decimal.rs @@ -10,13 +10,12 @@ use core::fmt; use core::ops::RangeInclusive; use core::str::FromStr; -use crate::uint_iterator::IntIterator; - +use crate::{uint_iterator::IntIterator, IncrementLike, NoIncrement}; #[cfg(feature = "ryu")] -use crate::LimitError; -use crate::ParseError; +use crate::{FloatPrecision, LimitError}; +use crate::{ParseError, RoundingIncrement, UnsignedRoundingMode}; -// FixedDecimal assumes usize (digits.len()) is at least as big as a u16 +// UnsignedFixedDecimal assumes usize (digits.len()) is at least as big as a u16 #[cfg(not(any( target_pointer_width = "16", target_pointer_width = "32", @@ -28,19 +27,19 @@ compile_error!("The fixed_decimal crate only works if usizes are at least the si /// (power of 10). /// /// Supports a mantissa of non-zero digits and a number of leading and trailing -/// zeros, as well as an optional sign; used for formatting and plural selection. +/// zeros; used for formatting and plural selection. /// /// # Data Types /// -/// The following types can be converted to a `FixedDecimal`: +/// The following types can be converted to a [`UnsignedFixedDecimal`]: /// -/// - Integers, signed and unsigned +/// - Integers, unsigned /// - Strings representing an arbitrary-precision decimal /// - Floating point values (using the `ryu` feature) /// -/// To create a [`FixedDecimal`] with fraction digits, either create it from an integer and then -/// call [`FixedDecimal::multiplied_pow10`], create it from a string, or (when the `ryu` feature is -/// enabled) create it from a floating point value using [`FixedDecimal::try_from_f64`]. +/// To create a [`UnsignedFixedDecimal`] with fraction digits, either create it from an integer and then +/// call [`UnsignedFixedDecimal::multiplied_pow10`], create it from a string, or (when the `ryu` feature is +/// enabled) create it from a floating point value using [`UnsignedFixedDecimal::try_from_f64`]. /// /// # Magnitude and Position /// @@ -77,16 +76,16 @@ compile_error!("The fixed_decimal crate only works if usizes are at least the si /// # Examples /// /// ``` -/// use fixed_decimal::FixedDecimal; +/// use fixed_decimal::UnsignedFixedDecimal; /// -/// let mut dec = FixedDecimal::from(250); +/// let mut dec = UnsignedFixedDecimal::from(250u32); /// assert_eq!("250", dec.to_string()); /// /// dec.multiply_pow10(-2); /// assert_eq!("2.50", dec.to_string()); -/// ``` +/// ``````` #[derive(Debug, Clone, PartialEq)] -pub struct FixedDecimal { +pub struct UnsignedFixedDecimal { /// List of digits; digits\[0\] is the most significant. /// /// Invariants: @@ -115,86 +114,23 @@ pub struct FixedDecimal { /// - <= 0 /// - <= magnitude lower_magnitude: i16, - - /// The sign; note that a positive value may be represented by either - /// `Sign::Positive` (corresponding to a prefix +) or `Sign::None` - /// (corresponding to the absence of a prefix sign). - sign: Sign, -} - -/// A specification of the sign used when formatting a number. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -#[allow(clippy::exhaustive_enums)] -// There are only 3 sign values, and they correspond to the low-level data model of FixedDecimal and UTS 35. -pub enum Sign { - /// No sign (implicitly positive, e.g., 1729). - None, - /// A negative sign, e.g., -1729. - Negative, - /// An explicit positive sign, e.g., +1729. - Positive, -} - -/// Configuration for when to render the minus sign or plus sign. -#[non_exhaustive] -#[derive(Debug, Eq, PartialEq, Clone, Copy)] -pub enum SignDisplay { - /// Render the sign according to locale preferences. In most cases, this means a minus sign - /// will be shown on negative numbers, and no sign will be shown on positive numbers. - Auto, - - /// Do not display the sign. Positive and negative numbers are indistinguishable. - Never, - - /// Show a minus sign on negative numbers and a plus sign on positive numbers, including zero. - Always, - - /// Show a minus sign on negative numbers and a plus sign on positive numbers, except do not - /// show any sign on positive or negative zero. - ExceptZero, - - /// Show a minus sign on strictly negative numbers. Do not show a sign on positive numbers or - /// on positive or negative zero. - /// - /// This differs from [`Auto`](SignDisplay::Auto) in that it does not render a sign on negative zero. - Negative, } -impl Default for FixedDecimal { - /// Returns a `FixedDecimal` representing zero. +impl Default for UnsignedFixedDecimal { + /// Returns a [`UnsignedFixedDecimal`] representing zero. fn default() -> Self { Self { digits: SmallVec::new(), magnitude: 0, upper_magnitude: 0, lower_magnitude: 0, - sign: Sign::None, } } } -macro_rules! impl_from_signed_integer_type { - ($itype:ident, $utype: ident) => { - impl From<$itype> for FixedDecimal { - fn from(value: $itype) -> Self { - let int_iterator: IntIterator<$utype> = value.into(); - let sign = if int_iterator.is_negative { - Sign::Negative - } else { - Sign::None - }; - let mut result = Self::from_ascending(int_iterator) - .expect("All built-in integer types should fit"); - result.sign = sign; - result - } - } - }; -} - macro_rules! impl_from_unsigned_integer_type { ($utype: ident) => { - impl From<$utype> for FixedDecimal { + impl From<$utype> for UnsignedFixedDecimal { fn from(value: $utype) -> Self { let int_iterator: IntIterator<$utype> = value.into(); Self::from_ascending(int_iterator).expect("All built-in integer types should fit") @@ -203,13 +139,6 @@ macro_rules! impl_from_unsigned_integer_type { }; } -impl_from_signed_integer_type!(isize, usize); -impl_from_signed_integer_type!(i128, u128); -impl_from_signed_integer_type!(i64, u64); -impl_from_signed_integer_type!(i32, u32); -impl_from_signed_integer_type!(i16, u16); -impl_from_signed_integer_type!(i8, u8); - impl_from_unsigned_integer_type!(usize); impl_from_unsigned_integer_type!(u128); impl_from_unsigned_integer_type!(u64); @@ -217,145 +146,12 @@ impl_from_unsigned_integer_type!(u32); impl_from_unsigned_integer_type!(u16); impl_from_unsigned_integer_type!(u8); -/// 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, -} - -// 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; - const MULTIPLES_OF_2: Option; - const MULTIPLES_OF_5: Option; - const MULTIPLES_OF_25: Option; -} - -impl IncrementLike for RoundingIncrement { - const MULTIPLES_OF_1: Option = Some(Self::MultiplesOf1); - - const MULTIPLES_OF_2: Option = Some(Self::MultiplesOf2); - - const MULTIPLES_OF_5: Option = Some(Self::MultiplesOf5); - - const MULTIPLES_OF_25: Option = Some(Self::MultiplesOf25); -} - -impl IncrementLike for NoIncrement { - const MULTIPLES_OF_1: Option = Some(Self); - - const MULTIPLES_OF_2: Option = None; - - const MULTIPLES_OF_5: Option = None; - - const MULTIPLES_OF_25: Option = None; -} - -impl FixedDecimal { - /// Initialize a `FixedDecimal` with an iterator of digits in ascending +impl UnsignedFixedDecimal { + /// Initialize a [`UnsignedFixedDecimal`] with an iterator of digits in ascending /// order of magnitude, starting with the digit at magnitude 0. /// /// This method is not public; use `TryFrom::` instead. - fn from_ascending(digits_iter: T) -> Result + pub(crate) fn from_ascending(digits_iter: T) -> Result where T: Iterator, { @@ -409,9 +205,9 @@ impl FixedDecimal { /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::UnsignedFixedDecimal; /// - /// let dec = FixedDecimal::from(945); + /// let dec = UnsignedFixedDecimal::from(945u32); /// assert_eq!(0, dec.digit_at(-1)); /// assert_eq!(5, dec.digit_at(0)); /// assert_eq!(4, dec.digit_at(1)); @@ -632,9 +428,9 @@ impl FixedDecimal { /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::UnsignedFixedDecimal; /// - /// let dec: FixedDecimal = "012.340".parse().expect("valid syntax"); + /// let dec: UnsignedFixedDecimal = "012.340".parse().expect("valid syntax"); /// assert_eq!(-3..=2, dec.magnitude_range()); /// ``` pub const fn magnitude_range(&self) -> RangeInclusive { @@ -646,12 +442,12 @@ impl FixedDecimal { /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::UnsignedFixedDecimal; /// - /// let dec: FixedDecimal = "012.340".parse().expect("valid syntax"); + /// let dec: UnsignedFixedDecimal = "012.340".parse().expect("valid syntax"); /// assert_eq!(1, dec.nonzero_magnitude_start()); /// - /// assert_eq!(0, FixedDecimal::from(0).nonzero_magnitude_start()); + /// assert_eq!(0, UnsignedFixedDecimal::from(0u32).nonzero_magnitude_start()); /// ``` pub fn nonzero_magnitude_start(&self) -> i16 { self.magnitude @@ -662,12 +458,12 @@ impl FixedDecimal { /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::UnsignedFixedDecimal; /// - /// let dec: FixedDecimal = "012.340".parse().expect("valid syntax"); + /// let dec: UnsignedFixedDecimal = "012.340".parse().expect("valid syntax"); /// assert_eq!(-2, dec.nonzero_magnitude_end()); /// - /// assert_eq!(0, FixedDecimal::from(0).nonzero_magnitude_end()); + /// assert_eq!(0, UnsignedFixedDecimal::from(0u32).nonzero_magnitude_end()); /// ``` pub fn nonzero_magnitude_end(&self) -> i16 { if self.is_zero() { @@ -682,9 +478,9 @@ impl FixedDecimal { /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::UnsignedFixedDecimal; /// - /// let dec: FixedDecimal = "000.000".parse().expect("valid syntax"); + /// let dec: UnsignedFixedDecimal = "000.000".parse().expect("valid syntax"); /// assert!(dec.is_zero()); /// ``` #[inline] @@ -693,12 +489,11 @@ impl FixedDecimal { } /// Clears all the fields and sets the number to zero. - fn clear(&mut self) { + pub(crate) fn clear(&mut self) { self.upper_magnitude = 0; self.lower_magnitude = 0; self.magnitude = 0; self.digits.clear(); - self.sign = Sign::None; #[cfg(debug_assertions)] self.check_invariants(); @@ -714,9 +509,9 @@ impl FixedDecimal { /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::UnsignedFixedDecimal; /// - /// let mut dec = FixedDecimal::from(42); + /// let mut dec = UnsignedFixedDecimal::from(42u32); /// assert_eq!("42", dec.to_string()); /// /// dec.multiply_pow10(3); @@ -773,9 +568,9 @@ impl FixedDecimal { /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::UnsignedFixedDecimal; /// - /// let dec = FixedDecimal::from(42).multiplied_pow10(3); + /// let dec = UnsignedFixedDecimal::from(42u32).multiplied_pow10(3); /// assert_eq!("42000", dec.to_string()); /// ``` pub fn multiplied_pow10(mut self, delta: i16) -> Self { @@ -783,151 +578,14 @@ impl FixedDecimal { self } - /// Returns the sign of this number. - /// - /// # Examples - /// - /// ``` - /// use fixed_decimal::FixedDecimal; - /// use fixed_decimal::Sign; - /// # use std::str::FromStr; - /// - /// assert_eq!(FixedDecimal::from_str("1729").unwrap().sign(), Sign::None); - /// assert_eq!( - /// FixedDecimal::from_str("-1729").unwrap().sign(), - /// Sign::Negative - /// ); - /// assert_eq!( - /// FixedDecimal::from_str("+1729").unwrap().sign(), - /// Sign::Positive - /// ); - /// ``` - pub fn sign(&self) -> Sign { - self.sign - } - - /// Changes the sign of this number to the one given. - /// - /// # Examples - /// - /// ``` - /// use fixed_decimal::FixedDecimal; - /// use fixed_decimal::Sign; - /// - /// let mut dec = FixedDecimal::from(1729); - /// assert_eq!("1729", dec.to_string()); - /// - /// dec.set_sign(Sign::Negative); - /// assert_eq!("-1729", dec.to_string()); - /// - /// dec.set_sign(Sign::Positive); - /// assert_eq!("+1729", dec.to_string()); - /// - /// dec.set_sign(Sign::None); - /// assert_eq!("1729", dec.to_string()); - /// ``` - pub fn set_sign(&mut self, sign: Sign) { - self.sign = sign; - } - - /// Returns this number with the sign changed to the one given. - /// - /// # Examples - /// - /// ``` - /// use fixed_decimal::FixedDecimal; - /// use fixed_decimal::Sign; - /// - /// assert_eq!( - /// "+1729", - /// FixedDecimal::from(1729) - /// .with_sign(Sign::Positive) - /// .to_string() - /// ); - /// assert_eq!( - /// "1729", - /// FixedDecimal::from(-1729).with_sign(Sign::None).to_string() - /// ); - /// assert_eq!( - /// "-1729", - /// FixedDecimal::from(1729) - /// .with_sign(Sign::Negative) - /// .to_string() - /// ); - /// ``` - pub fn with_sign(mut self, sign: Sign) -> Self { - self.set_sign(sign); - self - } - - /// Sets the sign of this number according to the given sign display strategy. - /// - /// # Examples - /// ``` - /// use fixed_decimal::FixedDecimal; - /// use fixed_decimal::SignDisplay::*; - /// - /// let mut dec = FixedDecimal::from(1729); - /// assert_eq!("1729", dec.to_string()); - /// dec.apply_sign_display(Always); - /// assert_eq!("+1729", dec.to_string()); - /// ``` - pub fn apply_sign_display(&mut self, sign_display: SignDisplay) { - use Sign::*; - match sign_display { - SignDisplay::Auto => { - if self.sign != Negative { - self.sign = None - } - } - SignDisplay::Always => { - if self.sign != Negative { - self.sign = Positive - } - } - SignDisplay::Never => self.sign = None, - SignDisplay::ExceptZero => { - if self.is_zero() { - self.sign = None - } else if self.sign != Negative { - self.sign = Positive - } - } - SignDisplay::Negative => { - if self.sign != Negative || self.is_zero() { - self.sign = None - } - } - } - } - - /// Returns this number with its sign set according to the given sign display strategy. - /// - /// # Examples - /// ``` - /// use fixed_decimal::FixedDecimal; - /// use fixed_decimal::SignDisplay::*; - /// - /// assert_eq!( - /// "+1729", - /// FixedDecimal::from(1729) - /// .with_sign_display(ExceptZero) - /// .to_string() - /// ); - /// ``` - pub fn with_sign_display(mut self, sign_display: SignDisplay) -> Self { - self.apply_sign_display(sign_display); - self - } - /// Returns this number with its leading zeroes removed. /// /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::UnsignedFixedDecimal; /// - /// let dec = FixedDecimal::from(123400) + /// let dec = UnsignedFixedDecimal::from(123400u32) /// .multiplied_pow10(-4) /// .padded_start(4); /// assert_eq!("0012.3400", dec.to_string()); @@ -944,9 +602,9 @@ impl FixedDecimal { /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::UnsignedFixedDecimal; /// - /// let mut dec = FixedDecimal::from(123400) + /// let mut dec = UnsignedFixedDecimal::from(123400u32) /// .multiplied_pow10(-4) /// .padded_start(4); /// assert_eq!("0012.3400", dec.to_string()); @@ -955,11 +613,11 @@ impl FixedDecimal { /// assert_eq!("12.3400", dec.to_string()); /// ``` /// - /// There is no effect if the most significant digit has magnitude less than zero: + /// There is no effect if the most significant digit has magnitude less than zero /// /// ``` - /// # use fixed_decimal::FixedDecimal; - /// let mut dec = FixedDecimal::from(22).multiplied_pow10(-4); + /// # use fixed_decimal::UnsignedFixedDecimal; + /// let mut dec = UnsignedFixedDecimal::from(22u32).multiplied_pow10(-4); /// assert_eq!("0.0022", dec.to_string()); /// /// dec.trim_start(); @@ -976,9 +634,9 @@ impl FixedDecimal { /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::UnsignedFixedDecimal; /// - /// let dec = FixedDecimal::from(123400) + /// let dec = UnsignedFixedDecimal::from(123400u32) /// .multiplied_pow10(-4) /// .padded_start(4); /// assert_eq!("0012.3400", dec.to_string()); @@ -995,9 +653,9 @@ impl FixedDecimal { /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::UnsignedFixedDecimal; /// - /// let mut dec = FixedDecimal::from(123400) + /// let mut dec = UnsignedFixedDecimal::from(123400u32) /// .multiplied_pow10(-4) /// .padded_start(4); /// assert_eq!("0012.3400", dec.to_string()); @@ -1009,8 +667,8 @@ impl FixedDecimal { /// There is no effect if the least significant digit has magnitude more than zero: /// /// ``` - /// # use fixed_decimal::FixedDecimal; - /// let mut dec = FixedDecimal::from(2200); + /// # use fixed_decimal::UnsignedFixedDecimal; + /// let mut dec = UnsignedFixedDecimal::from(2200u32); /// assert_eq!("2200", dec.to_string()); /// /// dec.trim_end(); @@ -1026,14 +684,14 @@ impl FixedDecimal { /// /// Negative position numbers have no effect. /// - /// Also see [`FixedDecimal::with_max_position()`]. + /// Also see [`UnsignedFixedDecimal::with_max_position()`]. /// /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::UnsignedFixedDecimal; /// - /// let mut dec = FixedDecimal::from(42); + /// let mut dec = UnsignedFixedDecimal::from(42u32); /// assert_eq!("42", dec.to_string()); /// assert_eq!("0042", dec.clone().padded_start(4).to_string()); /// @@ -1052,14 +710,14 @@ impl FixedDecimal { /// /// Negative position numbers have no effect. /// - /// Also see [`FixedDecimal::set_max_position()`]. + /// Also see [`UnsignedFixedDecimal::set_max_position()`]. /// /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::UnsignedFixedDecimal; /// - /// let mut dec = FixedDecimal::from(42); + /// let mut dec = UnsignedFixedDecimal::from(42u32); /// assert_eq!("42", dec.to_string()); /// /// dec.pad_start(4); @@ -1093,15 +751,15 @@ impl FixedDecimal { /// /// Positive position numbers have no effect. /// - /// Also see [`FixedDecimal::trunced()`]. + /// Also see [`UnsignedFixedDecimal::trunced()`]. /// /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::UnsignedFixedDecimal; /// # use std::str::FromStr; /// - /// let mut dec = FixedDecimal::from_str("123.456").unwrap(); + /// let mut dec = UnsignedFixedDecimal::from_str("123.456").unwrap(); /// assert_eq!("123.456", dec.to_string()); /// /// assert_eq!("123.456", dec.clone().padded_end(-1).to_string()); @@ -1122,15 +780,15 @@ impl FixedDecimal { /// /// Positive position numbers have no effect. /// - /// Also see [`FixedDecimal::trunc()`]. + /// Also see [`UnsignedFixedDecimal::trunc()`]. /// /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::UnsignedFixedDecimal; /// # use std::str::FromStr; /// - /// let mut dec = FixedDecimal::from_str("123.456").unwrap(); + /// let mut dec = UnsignedFixedDecimal::from_str("123.456").unwrap(); /// assert_eq!("123.456", dec.to_string()); /// /// dec.pad_end(-2); @@ -1139,7 +797,7 @@ impl FixedDecimal { /// dec.pad_end(-6); /// assert_eq!("123.456000", dec.to_string()); /// - /// let mut dec = FixedDecimal::from_str("123.000").unwrap(); + /// let mut dec = UnsignedFixedDecimal::from_str("123.000").unwrap(); /// dec.pad_end(0); /// assert_eq!("123", dec.to_string()); /// @@ -1162,14 +820,14 @@ impl FixedDecimal { /// Returns this number with the leading significant digits truncated to a particular position, /// deleting digits if necessary. /// - /// Also see [`FixedDecimal::padded_start()`]. + /// Also see [`UnsignedFixedDecimal::padded_start()`]. /// /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::UnsignedFixedDecimal; /// - /// let mut dec = FixedDecimal::from(4235970).multiplied_pow10(-3); + /// let mut dec = UnsignedFixedDecimal::from(4235970u32).multiplied_pow10(-3); /// assert_eq!("4235.970", dec.to_string()); /// /// assert_eq!("04235.970", dec.clone().with_max_position(5).to_string()); @@ -1194,14 +852,14 @@ impl FixedDecimal { /// Truncates the leading significant digits of this number to a particular position, deleting /// digits if necessary. /// - /// Also see [`FixedDecimal::pad_start()`]. + /// Also see [`UnsignedFixedDecimal::pad_start()`]. /// /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::UnsignedFixedDecimal; /// - /// let mut dec = FixedDecimal::from(4235970).multiplied_pow10(-3); + /// let mut dec = UnsignedFixedDecimal::from(4235970u32).multiplied_pow10(-3); /// assert_eq!("4235.970", dec.to_string()); /// /// dec.set_max_position(5); @@ -1257,22 +915,19 @@ impl FixedDecimal { /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::UnsignedFixedDecimal; /// # use std::str::FromStr; /// - /// let mut dec = FixedDecimal::from_str("-1.5").unwrap(); - /// dec.round(0); - /// assert_eq!("-2", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("0.4").unwrap(); + /// let mut dec = UnsignedFixedDecimal::from_str("0.4").unwrap(); /// dec.round(0); /// assert_eq!("0", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("0.5").unwrap(); + /// let mut dec = UnsignedFixedDecimal::from_str("0.5").unwrap(); /// dec.round(0); /// assert_eq!("0", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("0.6").unwrap(); + /// let mut dec = UnsignedFixedDecimal::from_str("0.6").unwrap(); /// dec.round(0); /// assert_eq!("1", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("1.5").unwrap(); + /// let mut dec = UnsignedFixedDecimal::from_str("1.5").unwrap(); /// dec.round(0); /// assert_eq!("2", dec.to_string()); /// ``` @@ -1288,18 +943,16 @@ impl FixedDecimal { /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::UnsignedFixedDecimal; /// # use std::str::FromStr; /// - /// let mut dec = FixedDecimal::from_str("-1.5").unwrap(); - /// assert_eq!("-2", dec.rounded(0).to_string()); - /// let mut dec = FixedDecimal::from_str("0.4").unwrap(); + /// let mut dec = UnsignedFixedDecimal::from_str("0.4").unwrap(); /// assert_eq!("0", dec.rounded(0).to_string()); - /// let mut dec = FixedDecimal::from_str("0.5").unwrap(); + /// let mut dec = UnsignedFixedDecimal::from_str("0.5").unwrap(); /// assert_eq!("0", dec.rounded(0).to_string()); - /// let mut dec = FixedDecimal::from_str("0.6").unwrap(); + /// let mut dec = UnsignedFixedDecimal::from_str("0.6").unwrap(); /// assert_eq!("1", dec.rounded(0).to_string()); - /// let mut dec = FixedDecimal::from_str("1.5").unwrap(); + /// let mut dec = UnsignedFixedDecimal::from_str("1.5").unwrap(); /// assert_eq!("2", dec.rounded(0).to_string()); /// ``` pub fn rounded(mut self, position: i16) -> Self { @@ -1307,80 +960,24 @@ impl FixedDecimal { self } - /// Rounds this number towards positive infinity at a particular digit position. - /// - /// # Examples - /// - /// ``` - /// use fixed_decimal::FixedDecimal; - /// # use std::str::FromStr; - /// - /// let mut dec = FixedDecimal::from_str("-1.5").unwrap(); - /// dec.ceil(0); - /// assert_eq!("-1", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("0.4").unwrap(); - /// dec.ceil(0); - /// assert_eq!("1", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("0.5").unwrap(); - /// dec.ceil(0); - /// assert_eq!("1", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("0.6").unwrap(); - /// dec.ceil(0); - /// assert_eq!("1", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("1.5").unwrap(); - /// dec.ceil(0); - /// assert_eq!("2", dec.to_string()); - /// ``` - #[inline(never)] - pub fn ceil(&mut self, position: i16) { - self.ceil_to_increment_internal(position, NoIncrement); - } - - /// Returns this number rounded towards positive infinity at a particular digit position. - /// - /// # Examples - /// - /// ``` - /// use fixed_decimal::FixedDecimal; - /// # use std::str::FromStr; - /// - /// let dec = FixedDecimal::from_str("-1.5").unwrap(); - /// assert_eq!("-1", dec.ceiled(0).to_string()); - /// let dec = FixedDecimal::from_str("0.4").unwrap(); - /// assert_eq!("1", dec.ceiled(0).to_string()); - /// let dec = FixedDecimal::from_str("0.5").unwrap(); - /// assert_eq!("1", dec.ceiled(0).to_string()); - /// let dec = FixedDecimal::from_str("0.6").unwrap(); - /// assert_eq!("1", dec.ceiled(0).to_string()); - /// let dec = FixedDecimal::from_str("1.5").unwrap(); - /// assert_eq!("2", dec.ceiled(0).to_string()); - /// ``` - pub fn ceiled(mut self, position: i16) -> Self { - self.ceil(position); - self - } - /// Rounds this number away from zero at a particular digit position. /// /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::UnsignedFixedDecimal; /// # use std::str::FromStr; /// - /// let mut dec = FixedDecimal::from_str("-1.5").unwrap(); - /// dec.expand(0); - /// assert_eq!("-2", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("0.4").unwrap(); + /// let mut dec = UnsignedFixedDecimal::from_str("0.4").unwrap(); /// dec.expand(0); /// assert_eq!("1", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("0.5").unwrap(); + /// let mut dec = UnsignedFixedDecimal::from_str("0.5").unwrap(); /// dec.expand(0); /// assert_eq!("1", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("0.6").unwrap(); + /// let mut dec = UnsignedFixedDecimal::from_str("0.6").unwrap(); /// dec.expand(0); /// assert_eq!("1", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("1.5").unwrap(); + /// let mut dec = UnsignedFixedDecimal::from_str("1.5").unwrap(); /// dec.expand(0); /// assert_eq!("2", dec.to_string()); /// ``` @@ -1394,18 +991,16 @@ impl FixedDecimal { /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::UnsignedFixedDecimal; /// # use std::str::FromStr; /// - /// let dec = FixedDecimal::from_str("-1.5").unwrap(); - /// assert_eq!("-2", dec.expanded(0).to_string()); - /// let dec = FixedDecimal::from_str("0.4").unwrap(); + /// let dec = UnsignedFixedDecimal::from_str("0.4").unwrap(); /// assert_eq!("1", dec.expanded(0).to_string()); - /// let dec = FixedDecimal::from_str("0.5").unwrap(); + /// let dec = UnsignedFixedDecimal::from_str("0.5").unwrap(); /// assert_eq!("1", dec.expanded(0).to_string()); - /// let dec = FixedDecimal::from_str("0.6").unwrap(); + /// let dec = UnsignedFixedDecimal::from_str("0.6").unwrap(); /// assert_eq!("1", dec.expanded(0).to_string()); - /// let dec = FixedDecimal::from_str("1.5").unwrap(); + /// let dec = UnsignedFixedDecimal::from_str("1.5").unwrap(); /// assert_eq!("2", dec.expanded(0).to_string()); /// ``` pub fn expanded(mut self, position: i16) -> Self { @@ -1413,82 +1008,26 @@ impl FixedDecimal { self } - /// Rounds this number towards negative infinity at a particular digit position. - /// - /// # Examples - /// - /// ``` - /// use fixed_decimal::FixedDecimal; - /// # use std::str::FromStr; - /// - /// let mut dec = FixedDecimal::from_str("-1.5").unwrap(); - /// dec.floor(0); - /// assert_eq!("-2", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("0.4").unwrap(); - /// dec.floor(0); - /// assert_eq!("0", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("0.5").unwrap(); - /// dec.floor(0); - /// assert_eq!("0", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("0.6").unwrap(); - /// dec.floor(0); - /// assert_eq!("0", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("1.5").unwrap(); - /// dec.floor(0); - /// assert_eq!("1", dec.to_string()); - /// ``` - #[inline(never)] - pub fn floor(&mut self, position: i16) { - self.floor_to_increment_internal(position, NoIncrement); - } - - /// Returns this number rounded towards negative infinity at a particular digit position. - /// - /// # Examples - /// - /// ``` - /// use fixed_decimal::FixedDecimal; - /// # use std::str::FromStr; - /// - /// let dec = FixedDecimal::from_str("-1.5").unwrap(); - /// assert_eq!("-2", dec.floored(0).to_string()); - /// let dec = FixedDecimal::from_str("0.4").unwrap(); - /// assert_eq!("0", dec.floored(0).to_string()); - /// let dec = FixedDecimal::from_str("0.5").unwrap(); - /// assert_eq!("0", dec.floored(0).to_string()); - /// let dec = FixedDecimal::from_str("0.6").unwrap(); - /// assert_eq!("0", dec.floored(0).to_string()); - /// let dec = FixedDecimal::from_str("1.5").unwrap(); - /// assert_eq!("1", dec.floored(0).to_string()); - /// ``` - pub fn floored(mut self, position: i16) -> Self { - self.floor(position); - self - } - /// Rounds this number towards zero at a particular digit position. /// - /// Also see [`FixedDecimal::pad_end()`]. + /// Also see [`UnsignedFixedDecimal::pad_end()`]. /// /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::UnsignedFixedDecimal; /// # use std::str::FromStr; /// - /// let mut dec = FixedDecimal::from_str("-1.5").unwrap(); - /// dec.trunc(0); - /// assert_eq!("-1", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("0.4").unwrap(); + /// let mut dec = UnsignedFixedDecimal::from_str("0.4").unwrap(); /// dec.trunc(0); /// assert_eq!("0", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("0.5").unwrap(); + /// let mut dec = UnsignedFixedDecimal::from_str("0.5").unwrap(); /// dec.trunc(0); /// assert_eq!("0", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("0.6").unwrap(); + /// let mut dec = UnsignedFixedDecimal::from_str("0.6").unwrap(); /// dec.trunc(0); /// assert_eq!("0", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("1.5").unwrap(); + /// let mut dec = UnsignedFixedDecimal::from_str("1.5").unwrap(); /// dec.trunc(0); /// assert_eq!("1", dec.to_string()); /// ``` @@ -1499,23 +1038,21 @@ impl FixedDecimal { /// Returns this number rounded towards zero at a particular digit position. /// - /// Also see [`FixedDecimal::padded_end()`]. + /// Also see [`UnsignedFixedDecimal::padded_end()`]. /// /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::UnsignedFixedDecimal; /// # use std::str::FromStr; /// - /// let dec = FixedDecimal::from_str("-1.5").unwrap(); - /// assert_eq!("-1", dec.trunced(0).to_string()); - /// let dec = FixedDecimal::from_str("0.4").unwrap(); + /// let dec = UnsignedFixedDecimal::from_str("0.4").unwrap(); /// assert_eq!("0", dec.trunced(0).to_string()); - /// let dec = FixedDecimal::from_str("0.5").unwrap(); + /// let dec = UnsignedFixedDecimal::from_str("0.5").unwrap(); /// assert_eq!("0", dec.trunced(0).to_string()); - /// let dec = FixedDecimal::from_str("0.6").unwrap(); + /// let dec = UnsignedFixedDecimal::from_str("0.6").unwrap(); /// assert_eq!("0", dec.trunced(0).to_string()); - /// let dec = FixedDecimal::from_str("1.5").unwrap(); + /// let dec = UnsignedFixedDecimal::from_str("1.5").unwrap(); /// assert_eq!("1", dec.trunced(0).to_string()); /// ``` pub fn trunced(mut self, position: i16) -> Self { @@ -1528,38 +1065,31 @@ impl FixedDecimal { /// # Examples /// /// ``` - /// use fixed_decimal::{FixedDecimal, RoundingMode}; + /// use fixed_decimal::{UnsignedFixedDecimal, UnsignedRoundingMode}; /// # use std::str::FromStr; /// - /// let mut dec = FixedDecimal::from_str("-3.5").unwrap(); - /// dec.round_with_mode(0, RoundingMode::Floor); - /// assert_eq!("-4", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("-3.5").unwrap(); - /// dec.round_with_mode(0, RoundingMode::Ceil); - /// assert_eq!("-3", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("5.455").unwrap(); - /// dec.round_with_mode(-2, RoundingMode::HalfExpand); + /// let mut dec = UnsignedFixedDecimal::from_str("5.455").unwrap(); + /// dec.round_with_mode(-2, UnsignedRoundingMode::HalfExpand); /// assert_eq!("5.46", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("-7.235").unwrap(); - /// dec.round_with_mode(-2, RoundingMode::HalfTrunc); - /// assert_eq!("-7.23", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("9.75").unwrap(); - /// dec.round_with_mode(-1, RoundingMode::HalfEven); + /// let mut dec = UnsignedFixedDecimal::from_str("9.75").unwrap(); + /// dec.round_with_mode(-1, UnsignedRoundingMode::HalfEven); /// assert_eq!("9.8", dec.to_string()); /// ``` - pub fn round_with_mode(&mut self, position: i16, mode: RoundingMode) { + pub fn round_with_mode(&mut self, position: i16, mode: UnsignedRoundingMode) { match mode { - RoundingMode::Ceil => self.ceil_to_increment_internal(position, NoIncrement), - RoundingMode::Expand => self.expand_to_increment_internal(position, NoIncrement), - RoundingMode::Floor => self.floor_to_increment_internal(position, NoIncrement), - RoundingMode::Trunc => self.trunc_to_increment_internal(position, NoIncrement), - RoundingMode::HalfCeil => self.half_ceil_to_increment_internal(position, NoIncrement), - RoundingMode::HalfExpand => { + UnsignedRoundingMode::Expand => { + self.expand_to_increment_internal(position, NoIncrement) + } + UnsignedRoundingMode::Trunc => self.trunc_to_increment_internal(position, NoIncrement), + UnsignedRoundingMode::HalfExpand => { self.half_expand_to_increment_internal(position, NoIncrement) } - RoundingMode::HalfFloor => self.half_floor_to_increment_internal(position, NoIncrement), - RoundingMode::HalfTrunc => self.half_trunc_to_increment_internal(position, NoIncrement), - RoundingMode::HalfEven => self.half_even_to_increment_internal(position, NoIncrement), + UnsignedRoundingMode::HalfTrunc => { + self.half_trunc_to_increment_internal(position, NoIncrement) + } + UnsignedRoundingMode::HalfEven => { + self.half_even_to_increment_internal(position, NoIncrement) + } } } @@ -1568,39 +1098,23 @@ impl FixedDecimal { /// # Examples /// /// ``` - /// use fixed_decimal::{FixedDecimal, RoundingMode}; + /// use fixed_decimal::{UnsignedFixedDecimal, UnsignedRoundingMode}; /// # use std::str::FromStr; /// - /// let mut dec = FixedDecimal::from_str("-3.5").unwrap(); - /// assert_eq!( - /// "-4", - /// dec.rounded_with_mode(0, RoundingMode::Floor).to_string() - /// ); - /// let mut dec = FixedDecimal::from_str("-3.5").unwrap(); - /// assert_eq!( - /// "-3", - /// dec.rounded_with_mode(0, RoundingMode::Ceil).to_string() - /// ); - /// let mut dec = FixedDecimal::from_str("5.455").unwrap(); + /// let mut dec = UnsignedFixedDecimal::from_str("5.455").unwrap(); /// assert_eq!( /// "5.46", - /// dec.rounded_with_mode(-2, RoundingMode::HalfExpand) + /// dec.rounded_with_mode(-2, UnsignedRoundingMode::HalfExpand) /// .to_string() /// ); - /// let mut dec = FixedDecimal::from_str("-7.235").unwrap(); - /// assert_eq!( - /// "-7.23", - /// dec.rounded_with_mode(-2, RoundingMode::HalfTrunc) - /// .to_string() - /// ); - /// let mut dec = FixedDecimal::from_str("9.75").unwrap(); + /// let mut dec = UnsignedFixedDecimal::from_str("9.75").unwrap(); /// assert_eq!( /// "9.8", - /// dec.rounded_with_mode(-1, RoundingMode::HalfEven) + /// dec.rounded_with_mode(-1, UnsignedRoundingMode::HalfEven) /// .to_string() /// ); /// ``` - pub fn rounded_with_mode(mut self, position: i16, mode: RoundingMode) -> Self { + pub fn rounded_with_mode(mut self, position: i16, mode: UnsignedRoundingMode) -> Self { self.round_with_mode(position, mode); self } @@ -1610,41 +1124,21 @@ impl FixedDecimal { /// # Examples /// /// ``` - /// use fixed_decimal::{FixedDecimal, RoundingIncrement, RoundingMode}; + /// use fixed_decimal::{UnsignedFixedDecimal, RoundingIncrement, UnsignedRoundingMode}; /// # use std::str::FromStr; /// - /// let mut dec = FixedDecimal::from_str("-3.5").unwrap(); - /// dec.round_with_mode_and_increment( - /// 0, - /// RoundingMode::Floor, - /// RoundingIncrement::MultiplesOf1, - /// ); - /// assert_eq!("-4", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("-3.59").unwrap(); - /// dec.round_with_mode_and_increment( - /// -1, - /// RoundingMode::Ceil, - /// RoundingIncrement::MultiplesOf2, - /// ); - /// assert_eq!("-3.4", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("5.455").unwrap(); + /// let mut dec = UnsignedFixedDecimal::from_str("5.455").unwrap(); /// dec.round_with_mode_and_increment( /// -2, - /// RoundingMode::HalfExpand, + /// UnsignedRoundingMode::HalfExpand, /// RoundingIncrement::MultiplesOf5, /// ); /// assert_eq!("5.45", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("-7.235").unwrap(); - /// dec.round_with_mode_and_increment( - /// -2, - /// RoundingMode::HalfTrunc, - /// RoundingIncrement::MultiplesOf25, - /// ); - /// assert_eq!("-7.25", dec.to_string()); - /// let mut dec = FixedDecimal::from_str("9.75").unwrap(); + /// + /// let mut dec = UnsignedFixedDecimal::from_str("9.75").unwrap(); /// dec.round_with_mode_and_increment( /// -1, - /// RoundingMode::HalfEven, + /// UnsignedRoundingMode::HalfEven, /// RoundingIncrement::MultiplesOf5, /// ); /// assert_eq!("10.0", dec.to_string()); @@ -1652,19 +1146,21 @@ impl FixedDecimal { pub fn round_with_mode_and_increment( &mut self, position: i16, - mode: RoundingMode, + mode: UnsignedRoundingMode, increment: RoundingIncrement, ) { match mode { - RoundingMode::Ceil => self.ceil_to_increment_internal(position, increment), - RoundingMode::Expand => self.expand_to_increment_internal(position, increment), - RoundingMode::Floor => self.floor_to_increment_internal(position, increment), - RoundingMode::Trunc => self.trunc_to_increment_internal(position, increment), - RoundingMode::HalfCeil => self.half_ceil_to_increment_internal(position, increment), - RoundingMode::HalfExpand => self.half_expand_to_increment_internal(position, increment), - RoundingMode::HalfFloor => self.half_floor_to_increment_internal(position, increment), - RoundingMode::HalfTrunc => self.half_trunc_to_increment_internal(position, increment), - RoundingMode::HalfEven => self.half_even_to_increment_internal(position, increment), + UnsignedRoundingMode::Expand => self.expand_to_increment_internal(position, increment), + UnsignedRoundingMode::Trunc => self.trunc_to_increment_internal(position, increment), + UnsignedRoundingMode::HalfExpand => { + self.half_expand_to_increment_internal(position, increment) + } + UnsignedRoundingMode::HalfTrunc => { + self.half_trunc_to_increment_internal(position, increment) + } + UnsignedRoundingMode::HalfEven => { + self.half_even_to_increment_internal(position, increment) + } } } @@ -1673,55 +1169,26 @@ impl FixedDecimal { /// # Examples /// /// ``` - /// use fixed_decimal::{FixedDecimal, RoundingIncrement, RoundingMode}; + /// use fixed_decimal::{UnsignedFixedDecimal, RoundingIncrement, UnsignedRoundingMode}; /// # use std::str::FromStr; /// - /// let mut dec = FixedDecimal::from_str("-3.5").unwrap(); - /// assert_eq!( - /// "-4", - /// dec.rounded_with_mode_and_increment( - /// 0, - /// RoundingMode::Floor, - /// RoundingIncrement::MultiplesOf1 - /// ) - /// .to_string() - /// ); - /// let mut dec = FixedDecimal::from_str("-3.59").unwrap(); - /// assert_eq!( - /// "-3.4", - /// dec.rounded_with_mode_and_increment( - /// -1, - /// RoundingMode::Ceil, - /// RoundingIncrement::MultiplesOf2 - /// ) - /// .to_string() - /// ); - /// let mut dec = FixedDecimal::from_str("5.455").unwrap(); + /// let mut dec = UnsignedFixedDecimal::from_str("5.455").unwrap(); /// assert_eq!( /// "5.45", /// dec.rounded_with_mode_and_increment( /// -2, - /// RoundingMode::HalfExpand, + /// UnsignedRoundingMode::HalfExpand, /// RoundingIncrement::MultiplesOf5 /// ) /// .to_string() /// ); - /// let mut dec = FixedDecimal::from_str("-7.235").unwrap(); - /// assert_eq!( - /// "-7.25", - /// dec.rounded_with_mode_and_increment( - /// -2, - /// RoundingMode::HalfTrunc, - /// RoundingIncrement::MultiplesOf25 - /// ) - /// .to_string() - /// ); - /// let mut dec = FixedDecimal::from_str("9.75").unwrap(); + /// + /// let mut dec = UnsignedFixedDecimal::from_str("9.75").unwrap(); /// assert_eq!( /// "10.0", /// dec.rounded_with_mode_and_increment( /// -1, - /// RoundingMode::HalfEven, + /// UnsignedRoundingMode::HalfEven, /// RoundingIncrement::MultiplesOf5 /// ) /// .to_string() @@ -1730,29 +1197,20 @@ impl FixedDecimal { pub fn rounded_with_mode_and_increment( mut self, position: i16, - mode: RoundingMode, + mode: UnsignedRoundingMode, increment: RoundingIncrement, ) -> Self { self.round_with_mode_and_increment(position, mode, increment); self } - fn ceil_to_increment_internal(&mut self, position: i16, increment: R) { - if self.sign == Sign::Negative { - self.trunc_to_increment_internal(position, increment); - return; - } - - self.expand_to_increment_internal(position, increment); - } - - fn expand_to_increment_internal( + pub(crate) fn expand_to_increment_internal( &mut self, position: i16, inner_increment: R, ) { /// Modifies `number` to signal that an overflow happened. - fn overflow(number: &mut FixedDecimal) { + fn overflow(number: &mut UnsignedFixedDecimal) { // TODO(#2297): Decide on behavior here number.digits.clear(); number.magnitude = 0; @@ -1991,16 +1449,11 @@ impl FixedDecimal { self.check_invariants(); } - fn floor_to_increment_internal(&mut self, position: i16, increment: R) { - if self.sign == Sign::Negative { - self.expand_to_increment_internal(position, increment); - return; - } - - self.trunc_to_increment_internal(position, increment); - } - - fn trunc_to_increment_internal(&mut self, position: i16, inner_increment: R) { + pub(crate) fn trunc_to_increment_internal( + &mut self, + position: i16, + inner_increment: R, + ) { let increment = Some(inner_increment); // 1. Set upper and lower magnitude @@ -2123,16 +1576,11 @@ impl FixedDecimal { self.check_invariants(); } - fn half_ceil_to_increment_internal(&mut self, position: i16, increment: R) { - if self.sign == Sign::Negative { - self.half_trunc_to_increment_internal(position, increment); - return; - } - - self.half_expand_to_increment_internal(position, increment); - } - - fn half_even_to_increment_internal(&mut self, position: i16, increment: R) { + pub(crate) fn half_even_to_increment_internal( + &mut self, + position: i16, + increment: R, + ) { let should_expand = match self.half_increment_at_magnitude(position, increment) { Ordering::Greater => true, Ordering::Less => false, @@ -2185,7 +1633,11 @@ impl FixedDecimal { } } - fn half_expand_to_increment_internal(&mut self, position: i16, increment: R) { + pub(crate) fn half_expand_to_increment_internal( + &mut self, + position: i16, + increment: R, + ) { // 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; @@ -2197,16 +1649,11 @@ impl FixedDecimal { } } - fn half_floor_to_increment_internal(&mut self, position: i16, increment: R) { - if self.sign == Sign::Negative { - self.half_expand_to_increment_internal(position, increment); - return; - } - - self.half_trunc_to_increment_internal(position, increment); - } - - fn half_trunc_to_increment_internal(&mut self, position: i16, increment: R) { + pub(crate) fn half_trunc_to_increment_internal( + &mut self, + position: i16, + increment: R, + ) { // Only expand if the rounding position is strictly greater than the half increment. // At the half increment, `half_trunc` always truncates. let should_expand = @@ -2219,7 +1666,7 @@ impl FixedDecimal { } } - /// Concatenate another `FixedDecimal` into the end of this `FixedDecimal`. + /// Concatenate another [`UnsignedFixedDecimal`] into the end of this [`UnsignedFixedDecimal`]. /// /// All nonzero digits in `other` must have lower magnitude than nonzero digits in `self`. /// If the two decimals represent overlapping ranges of magnitudes, an `Err` is returned, @@ -2230,10 +1677,10 @@ impl FixedDecimal { /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::UnsignedFixedDecimal; /// - /// let integer = FixedDecimal::from(123); - /// let fraction = FixedDecimal::from(456).multiplied_pow10(-3); + /// let integer = UnsignedFixedDecimal::from(123u32); + /// let fraction = UnsignedFixedDecimal::from(456u32).multiplied_pow10(-3); /// /// let result = integer.concatenated_end(fraction).expect("nonoverlapping"); /// @@ -2241,15 +1688,15 @@ impl FixedDecimal { /// ``` pub fn concatenated_end( mut self, - other: FixedDecimal, - ) -> Result { + other: UnsignedFixedDecimal, + ) -> Result { match self.concatenate_end(other) { Ok(()) => Ok(self), Err(err) => Err((self, err)), } } - /// Concatenate another `FixedDecimal` into the end of this `FixedDecimal`. + /// Concatenate another [`UnsignedFixedDecimal`] into the end of this [`UnsignedFixedDecimal`]. /// /// All nonzero digits in `other` must have lower magnitude than nonzero digits in `self`. /// If the two decimals represent overlapping ranges of magnitudes, an `Err` is returned, @@ -2260,16 +1707,19 @@ impl FixedDecimal { /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::UnsignedFixedDecimal; /// - /// let mut integer = FixedDecimal::from(123); - /// let fraction = FixedDecimal::from(456).multiplied_pow10(-3); + /// let mut integer = UnsignedFixedDecimal::from(123u32); + /// let fraction = UnsignedFixedDecimal::from(456u32).multiplied_pow10(-3); /// /// integer.concatenate_end(fraction); /// /// assert_eq!("123.456", integer.to_string()); /// ``` - pub fn concatenate_end(&mut self, other: FixedDecimal) -> Result<(), FixedDecimal> { + pub fn concatenate_end( + &mut self, + other: UnsignedFixedDecimal, + ) -> Result<(), UnsignedFixedDecimal> { let self_right = self.nonzero_magnitude_end(); let other_left = other.nonzero_magnitude_start(); if self.is_zero() { @@ -2350,18 +1800,13 @@ impl FixedDecimal { /// # Examples /// /// ``` -/// # use fixed_decimal::FixedDecimal; +/// # use fixed_decimal::UnsignedFixedDecimal; /// # use writeable::assert_writeable_eq; /// # -/// assert_writeable_eq!(FixedDecimal::from(42), "42"); +/// assert_writeable_eq!(UnsignedFixedDecimal::from(42u32), "42"); /// ``` -impl writeable::Writeable for FixedDecimal { +impl writeable::Writeable for UnsignedFixedDecimal { fn write_to(&self, sink: &mut W) -> fmt::Result { - match self.sign { - Sign::Negative => sink.write_char('-')?, - Sign::Positive => sink.write_char('+')?, - Sign::None => (), - } for m in self.magnitude_range().rev() { if m == -1 { sink.write_char('.')?; @@ -2375,41 +1820,48 @@ impl writeable::Writeable for FixedDecimal { fn writeable_length_hint(&self) -> writeable::LengthHint { writeable::LengthHint::exact(1) + ((self.upper_magnitude as i32 - self.lower_magnitude as i32) as usize) - + (self.sign != Sign::None) as usize + (self.lower_magnitude < 0) as usize } } -writeable::impl_display_with_writeable!(FixedDecimal); +writeable::impl_display_with_writeable!(UnsignedFixedDecimal); -impl FixedDecimal { +impl UnsignedFixedDecimal { #[inline] - /// Parses a [`FixedDecimal`]. + /// Parses a [`UnsignedFixedDecimal`]. pub fn try_from_str(s: &str) -> Result { Self::try_from_utf8(s.as_bytes()) } + /// This function is used to parse a [`UnsignedFixedDecimal`] from a string without a sign. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::UnsignedFixedDecimal; + /// use fixed_decimal::ParseError; + /// + /// let decimal = UnsignedFixedDecimal::try_from_utf8(b"1234567890"); + /// assert_eq!(decimal, Ok(UnsignedFixedDecimal::from(1234567890u32))); + /// + /// // In case of adding `+`, the function will return an error. + /// let decimal = UnsignedFixedDecimal::try_from_utf8(b"+1234567890"); + /// assert_eq!(decimal, Err(ParseError::Syntax)); + /// + /// // In case of adding `-`, the function will return error + /// let decimal = UnsignedFixedDecimal::try_from_utf8(b"-1234567890"); + /// assert_eq!(decimal, Err(ParseError::Syntax)); + /// ``` pub fn try_from_utf8(input_str: &[u8]) -> Result { - // input_str: the input string - // no_sign_str: the input string when the sign is removed from it if input_str.is_empty() { return Err(ParseError::Syntax); } - #[allow(clippy::indexing_slicing)] // The string is not empty. - let sign = match input_str[0] { - b'-' => Sign::Negative, - b'+' => Sign::Positive, - _ => Sign::None, - }; - #[allow(clippy::indexing_slicing)] // The string is not empty. - let no_sign_str = if sign == Sign::None { - input_str - } else { - &input_str[1..] - }; - if no_sign_str.is_empty() { - return Err(ParseError::Syntax); - } + + // NOTE: this function assumes that the input string has no sign, this means if the string starts with `-` or `+`, it will be treated as a syntax error. + Self::try_from_no_sign_utf8(input_str) + } + + pub(crate) fn try_from_no_sign_utf8(no_sign_str: &[u8]) -> Result { // Compute length of each string once and store it, so if you use that multiple times, // you don't compute it multiple times // has_dot: shows if your input has dot in it @@ -2473,10 +1925,7 @@ impl FixedDecimal { } // defining the output dec here and set its sign - let mut dec = Self { - sign, - ..Default::default() - }; + let mut dec = Self::default(); // no_dot_str_len: shows length of the string after removing the dot let mut no_dot_str_len = no_exponent_str.len(); @@ -2588,48 +2037,16 @@ impl FixedDecimal { } } -impl FromStr for FixedDecimal { +impl FromStr for UnsignedFixedDecimal { type Err = ParseError; fn from_str(s: &str) -> Result { Self::try_from_str(s) } } -/// Specifies the precision of a floating point value when constructing a FixedDecimal. -/// -/// IEEE 754 is a representation of a point on the number line. On the other hand, FixedDecimal -/// specifies not only the point on the number line but also the precision of the number to a -/// specific power of 10. This enum augments a floating-point value with the additional -/// information required by FixedDecimal. -#[non_exhaustive] -#[cfg(feature = "ryu")] -#[derive(Debug, Clone, Copy)] -pub enum FloatPrecision { - /// Specify that the floating point number is integer-valued. - /// - /// If the floating point is not actually integer-valued, an error will be returned. - Integer, - - /// Specify that the floating point number is precise to a specific power of 10. - /// The number may be rounded or trailing zeros may be added as necessary. - Magnitude(i16), - - /// Specify that the floating point number is precise to a specific number of significant digits. - /// The number may be rounded or trailing zeros may be added as necessary. - /// - /// The number requested may not be zero - SignificantDigits(u8), - - /// Specify that the floating point number is precise to the maximum representable by IEEE. - /// - /// This results in a FixedDecimal having enough digits to recover the original floating point - /// value, with no trailing zeros. - RoundTrip, -} - #[cfg(feature = "ryu")] -impl FixedDecimal { - /// Constructs a [`FixedDecimal`] from an f64. +impl UnsignedFixedDecimal { + /// Constructs a [`UnsignedFixedDecimal`] from an f64. /// /// Since f64 values do not carry a notion of their precision, the second argument to this /// function specifies the type of precision associated with the f64. For more information, @@ -2641,39 +2058,27 @@ impl FixedDecimal { /// /// This function can be made available with the `"ryu"` Cargo feature. /// + /// NOTE: + /// Negative numbers are not supported. + /// /// ```rust - /// use fixed_decimal::{FixedDecimal, FloatPrecision}; + /// use fixed_decimal::{UnsignedFixedDecimal, FloatPrecision}; /// use writeable::assert_writeable_eq; /// /// let decimal = - /// FixedDecimal::try_from_f64(-5.1, FloatPrecision::Magnitude(-2)) - /// .expect("Finite quantity with limited precision"); - /// assert_writeable_eq!(decimal, "-5.10"); + /// UnsignedFixedDecimal::try_from_f64(-5.1, FloatPrecision::Magnitude(-2)) + /// .expect_err("Negative numbers are not supported"); /// /// let decimal = - /// FixedDecimal::try_from_f64(0.012345678, FloatPrecision::RoundTrip) + /// UnsignedFixedDecimal::try_from_f64(0.012345678, FloatPrecision::RoundTrip) /// .expect("Finite quantity"); /// assert_writeable_eq!(decimal, "0.012345678"); /// /// let decimal = - /// FixedDecimal::try_from_f64(12345678000., FloatPrecision::Integer) + /// UnsignedFixedDecimal::try_from_f64(12345678000., FloatPrecision::Integer) /// .expect("Finite, integer-valued quantity"); /// assert_writeable_eq!(decimal, "12345678000"); /// ``` - /// - /// Negative zero is supported. - /// - /// ```rust - /// use fixed_decimal::{FixedDecimal, FloatPrecision}; - /// use writeable::assert_writeable_eq; - /// - /// // IEEE 754 for floating point defines the sign bit separate - /// // from the mantissa and exponent, allowing for -0. - /// let negative_zero = - /// FixedDecimal::try_from_f64(-0.0, FloatPrecision::Integer) - /// .expect("Negative zero"); - /// assert_writeable_eq!(negative_zero, "-0"); - /// ``` pub fn try_from_f64(float: f64, precision: FloatPrecision) -> Result { let mut decimal = Self::new_from_f64_raw(float)?; let n_digits = decimal.digits.len(); @@ -2716,7 +2121,7 @@ impl FixedDecimal { /// Internal function for parsing directly from floats using ryū fn new_from_f64_raw(float: f64) -> Result { - if !float.is_finite() { + if !float.is_finite() || float.is_sign_negative() { return Err(LimitError); } // note: this does not heap allocate @@ -2903,7 +2308,7 @@ fn test_float() { ]; for case in &cases { - let dec = FixedDecimal::try_from_f64(case.input, case.precision).unwrap(); + let dec = UnsignedFixedDecimal::try_from_f64(case.input, case.precision).unwrap(); writeable::assert_writeable_eq!(dec, case.expected, "{:?}", case); } } @@ -2912,7 +2317,7 @@ fn test_float() { fn test_basic() { #[derive(Debug)] struct TestCase { - pub input: isize, + pub input: usize, pub delta: i16, pub expected: &'static str, } @@ -2987,29 +2392,9 @@ fn test_basic() { delta: 3, expected: "500000", }, - TestCase { - input: -123, - delta: 0, - expected: "-123", - }, - TestCase { - input: -123, - delta: -2, - expected: "-1.23", - }, - TestCase { - input: -123, - delta: -5, - expected: "-0.00123", - }, - TestCase { - input: -123, - delta: 3, - expected: "-123000", - }, ]; for cas in &cases { - let mut dec: FixedDecimal = cas.input.into(); + let mut dec: UnsignedFixedDecimal = cas.input.into(); // println!("{}", cas.input + 0.01); dec.multiply_pow10(cas.delta); writeable::assert_writeable_eq!(dec, cas.expected, "{:?}", cas); @@ -3028,12 +2413,7 @@ fn test_from_str() { } let cases = [ TestCase { - input_str: "-00123400", - output_str: None, - magnitudes: [7, 5, 2, 0], - }, - TestCase { - input_str: "+00123400", + input_str: "00123400", output_str: None, magnitudes: [7, 5, 2, 0], }, @@ -3042,36 +2422,16 @@ fn test_from_str() { output_str: None, magnitudes: [0, -2, -5, -7], }, - TestCase { - input_str: "-00.123400", - output_str: None, - magnitudes: [1, -1, -4, -6], - }, TestCase { input_str: "0012.3400", output_str: None, magnitudes: [3, 1, -2, -4], }, - TestCase { - input_str: "-0012340.0", - output_str: None, - magnitudes: [6, 4, 1, -1], - }, TestCase { input_str: "1234", output_str: None, magnitudes: [3, 3, 0, 0], }, - TestCase { - input_str: "0.000000001", - output_str: None, - magnitudes: [0, -9, -9, -9], - }, - TestCase { - input_str: "0.0000000010", - output_str: None, - magnitudes: [0, -9, -9, -10], - }, TestCase { input_str: "1000000", output_str: None, @@ -3097,36 +2457,16 @@ fn test_from_str() { output_str: None, magnitudes: [11, 9, -33, -36], }, - TestCase { - input_str: "-009223372000.003685477580898230948203840239384000", - output_str: None, - magnitudes: [11, 9, -33, -36], - }, TestCase { input_str: "0", output_str: None, magnitudes: [0, 0, 0, 0], }, - TestCase { - input_str: "-0", - output_str: None, - magnitudes: [0, 0, 0, 0], - }, - TestCase { - input_str: "+0", - output_str: None, - magnitudes: [0, 0, 0, 0], - }, TestCase { input_str: "000", output_str: None, magnitudes: [2, 0, 0, 0], }, - TestCase { - input_str: "-00.0", - output_str: None, - magnitudes: [1, 0, 0, -1], - }, // no leading 0 parsing TestCase { input_str: ".0123400", @@ -3138,14 +2478,10 @@ fn test_from_str() { output_str: Some("0.000000001"), magnitudes: [0, -9, -9, -9], }, - TestCase { - input_str: "-.123400", - output_str: Some("-0.123400"), - magnitudes: [0, -1, -4, -6], - }, ]; for cas in &cases { - let fd = FixedDecimal::from_str(cas.input_str).unwrap(); + println!("cas: {:?}", cas); + let fd = UnsignedFixedDecimal::from_str(cas.input_str).unwrap(); assert_eq!( fd.magnitude_range(), cas.magnitudes[3]..=cas.magnitudes[0], @@ -3155,6 +2491,13 @@ fn test_from_str() { assert_eq!(fd.nonzero_magnitude_end(), cas.magnitudes[2], "{cas:?}"); let input_str_roundtrip = fd.to_string(); let output_str = cas.output_str.unwrap_or(cas.input_str); + + // Check if the output string starts with a plus sign and remove it, + // because we do not show sign for unsigned fixed decimal + let output_str = match output_str.strip_prefix('+') { + Some(stripped) => stripped, + None => output_str, + }; assert_eq!(output_str, input_str_roundtrip, "{cas:?}"); } } @@ -3167,10 +2510,6 @@ fn test_from_str_scientific() { pub output: &'static str, } let cases = [ - TestCase { - input_str: "-5.4e10", - output: "-54000000000", - }, TestCase { input_str: "5.4e-2", output: "0.054", @@ -3179,57 +2518,44 @@ fn test_from_str_scientific() { input_str: "54.1e-2", output: "0.541", }, - TestCase { - input_str: "-541e-2", - output: "-5.41", - }, TestCase { input_str: "0.009E10", output: "90000000", }, - TestCase { - input_str: "-9000E-10", - output: "-0.0000009", - }, ]; for cas in &cases { - let input_str_roundtrip = FixedDecimal::from_str(cas.input_str).unwrap().to_string(); + let input_str_roundtrip = UnsignedFixedDecimal::from_str(cas.input_str) + .unwrap() + .to_string(); assert_eq!(cas.output, input_str_roundtrip); } } #[test] -fn test_isize_limits() { - for num in &[isize::MAX, isize::MIN] { - let dec: FixedDecimal = (*num).into(); +fn test_usize_limits() { + for num in &[usize::MAX, usize::MIN] { + let dec: UnsignedFixedDecimal = (*num).into(); let dec_str = dec.to_string(); assert_eq!(num.to_string(), dec_str); - assert_eq!(dec, FixedDecimal::from_str(&dec_str).unwrap()); + assert_eq!(dec, UnsignedFixedDecimal::from_str(&dec_str).unwrap()); writeable::assert_writeable_eq!(dec, dec_str); } } #[test] -fn test_ui128_limits() { - for num in &[i128::MAX, i128::MIN] { - let dec: FixedDecimal = (*num).into(); - let dec_str = dec.to_string(); - assert_eq!(num.to_string(), dec_str); - assert_eq!(dec, FixedDecimal::from_str(&dec_str).unwrap()); - writeable::assert_writeable_eq!(dec, dec_str); - } +fn test_u128_limits() { for num in &[u128::MAX, u128::MIN] { - let dec: FixedDecimal = (*num).into(); + let dec: UnsignedFixedDecimal = (*num).into(); let dec_str = dec.to_string(); assert_eq!(num.to_string(), dec_str); - assert_eq!(dec, FixedDecimal::from_str(&dec_str).unwrap()); + assert_eq!(dec, UnsignedFixedDecimal::from_str(&dec_str).unwrap()); writeable::assert_writeable_eq!(dec, dec_str); } } #[test] fn test_upper_magnitude_bounds() { - let mut dec: FixedDecimal = 98765.into(); + let mut dec: UnsignedFixedDecimal = 98765u32.into(); assert_eq!(dec.upper_magnitude, 4); dec.multiply_pow10(i16::MAX - 4); assert_eq!(dec.upper_magnitude, i16::MAX); @@ -3240,13 +2566,13 @@ fn test_upper_magnitude_bounds() { assert_ne!(dec, dec_backup, "Value should be unchanged on failure"); // Checking from_str for dec (which is valid) - let dec_roundtrip = FixedDecimal::from_str(&dec.to_string()).unwrap(); + let dec_roundtrip = UnsignedFixedDecimal::from_str(&dec.to_string()).unwrap(); assert_eq!(dec, dec_roundtrip); } #[test] fn test_lower_magnitude_bounds() { - let mut dec: FixedDecimal = 98765.into(); + let mut dec: UnsignedFixedDecimal = 98765u32.into(); assert_eq!(dec.lower_magnitude, 0); dec.multiply_pow10(i16::MIN); assert_eq!(dec.lower_magnitude, i16::MIN); @@ -3257,7 +2583,7 @@ fn test_lower_magnitude_bounds() { assert_ne!(dec, dec_backup); // Checking from_str for dec (which is valid) - let dec_roundtrip = FixedDecimal::from_str(&dec.to_string()).unwrap(); + let dec_roundtrip = UnsignedFixedDecimal::from_str(&dec.to_string()).unwrap(); assert_eq!(dec, dec_roundtrip); } @@ -3327,7 +2653,7 @@ fn test_zero_str_bounds() { input_str.push('.'); input_str.push_str(&format!("{:0fill$}", 0, fill = cas.zeros_after_dot)); } - match FixedDecimal::from_str(&input_str) { + match UnsignedFixedDecimal::from_str(&input_str) { Ok(dec) => { assert_eq!(cas.expected_err, None, "{cas:?}"); assert_eq!(input_str, dec.to_string(), "{cas:?}"); @@ -3347,6 +2673,14 @@ fn test_syntax_error() { pub expected_err: Option, } let cases = [ + TestCase { + input_str: "+1234567890", + expected_err: Some(ParseError::Syntax), + }, + TestCase { + input_str: "-1234567890", + expected_err: Some(ParseError::Syntax), + }, TestCase { input_str: "-12a34", expected_err: Some(ParseError::Syntax), @@ -3369,7 +2703,7 @@ fn test_syntax_error() { }, TestCase { input_str: "-0.00123400", - expected_err: None, + expected_err: Some(ParseError::Syntax), }, TestCase { input_str: "00123400.", @@ -3397,11 +2731,11 @@ fn test_syntax_error() { }, TestCase { input_str: "-1", - expected_err: None, + expected_err: Some(ParseError::Syntax), }, ]; for cas in &cases { - match FixedDecimal::from_str(cas.input_str) { + match UnsignedFixedDecimal::from_str(cas.input_str) { Ok(dec) => { assert_eq!(cas.expected_err, None, "{cas:?}"); assert_eq!(cas.input_str, dec.to_string(), "{cas:?}"); @@ -3415,129 +2749,22 @@ fn test_syntax_error() { #[test] fn test_pad() { - let mut dec = FixedDecimal::from_str("-0.42").unwrap(); - assert_eq!("-0.42", dec.to_string()); + let mut dec = UnsignedFixedDecimal::from_str("0.42").unwrap(); + assert_eq!("0.42", dec.to_string()); dec.pad_start(1); - assert_eq!("-0.42", dec.to_string()); + assert_eq!("0.42", dec.to_string()); dec.pad_start(4); - assert_eq!("-0000.42", dec.to_string()); + assert_eq!("0000.42", dec.to_string()); dec.pad_start(2); - assert_eq!("-00.42", dec.to_string()); -} - -#[test] -fn test_sign_display() { - use SignDisplay::*; - let positive_nonzero = FixedDecimal::from(163); - let negative_nonzero = FixedDecimal::from(-163); - let positive_zero = FixedDecimal::from(0); - let negative_zero = FixedDecimal::from(0).with_sign(Sign::Negative); - assert_eq!( - "163", - positive_nonzero.clone().with_sign_display(Auto).to_string() - ); - assert_eq!( - "-163", - negative_nonzero.clone().with_sign_display(Auto).to_string() - ); - assert_eq!( - "0", - positive_zero.clone().with_sign_display(Auto).to_string() - ); - assert_eq!( - "-0", - negative_zero.clone().with_sign_display(Auto).to_string() - ); - assert_eq!( - "+163", - positive_nonzero - .clone() - .with_sign_display(Always) - .to_string() - ); - assert_eq!( - "-163", - negative_nonzero - .clone() - .with_sign_display(Always) - .to_string() - ); - assert_eq!( - "+0", - positive_zero.clone().with_sign_display(Always).to_string() - ); - assert_eq!( - "-0", - negative_zero.clone().with_sign_display(Always).to_string() - ); - assert_eq!( - "163", - positive_nonzero - .clone() - .with_sign_display(Never) - .to_string() - ); - assert_eq!( - "163", - negative_nonzero - .clone() - .with_sign_display(Never) - .to_string() - ); - assert_eq!( - "0", - positive_zero.clone().with_sign_display(Never).to_string() - ); - assert_eq!( - "0", - negative_zero.clone().with_sign_display(Never).to_string() - ); - assert_eq!( - "+163", - positive_nonzero - .clone() - .with_sign_display(ExceptZero) - .to_string() - ); - assert_eq!( - "-163", - negative_nonzero - .clone() - .with_sign_display(ExceptZero) - .to_string() - ); - assert_eq!( - "0", - positive_zero - .clone() - .with_sign_display(ExceptZero) - .to_string() - ); - assert_eq!( - "0", - negative_zero - .clone() - .with_sign_display(ExceptZero) - .to_string() - ); - assert_eq!( - "163", - positive_nonzero.with_sign_display(Negative).to_string() - ); - assert_eq!( - "-163", - negative_nonzero.with_sign_display(Negative).to_string() - ); - assert_eq!("0", positive_zero.with_sign_display(Negative).to_string()); - assert_eq!("0", negative_zero.with_sign_display(Negative).to_string()); + assert_eq!("00.42", dec.to_string()); } #[test] fn test_set_max_position() { - let mut dec = FixedDecimal::from(1000); + let mut dec = UnsignedFixedDecimal::from(1000u32); assert_eq!("1000", dec.to_string()); dec.set_max_position(2); @@ -3549,7 +2776,7 @@ fn test_set_max_position() { dec.set_max_position(3); assert_eq!("000", dec.to_string()); - let mut dec = FixedDecimal::from_str("0.456").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("0.456").unwrap(); assert_eq!("0.456", dec.to_string()); dec.set_max_position(0); @@ -3567,14 +2794,14 @@ fn test_set_max_position() { dec.set_max_position(-4); assert_eq!("0.0000", dec.to_string()); - let mut dec = FixedDecimal::from_str("100.01").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("100.01").unwrap(); dec.set_max_position(1); assert_eq!("0.01", dec.to_string()); } #[test] fn test_pad_start_bounds() { - let mut dec = FixedDecimal::from_str("299792.458").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("299792.458").unwrap(); let max_integer_digits = i16::MAX as usize + 1; dec.pad_start(i16::MAX - 1); @@ -3592,7 +2819,7 @@ fn test_pad_start_bounds() { #[test] fn test_pad_end_bounds() { - let mut dec = FixedDecimal::from_str("299792.458").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("299792.458").unwrap(); let max_fractional_digits = -(i16::MIN as isize) as usize; dec.pad_end(i16::MIN + 1); @@ -3612,220 +2839,8 @@ fn test_pad_end_bounds() { fn test_rounding() { pub(crate) use std::str::FromStr; - // Test Ceil - let mut dec = FixedDecimal::from_str("3.234").unwrap(); - dec.ceil(0); - assert_eq!("4", dec.to_string()); - - let mut dec = FixedDecimal::from_str("2.222").unwrap(); - dec.ceil(-1); - assert_eq!("2.3", dec.to_string()); - - let mut dec = FixedDecimal::from_str("22.222").unwrap(); - dec.ceil(-2); - assert_eq!("22.23", dec.to_string()); - - let mut dec = FixedDecimal::from_str("99.999").unwrap(); - dec.ceil(-2); - assert_eq!("100.00", dec.to_string()); - - let mut dec = FixedDecimal::from_str("99.999").unwrap(); - dec.ceil(-5); - assert_eq!("99.99900", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); - dec.ceil(-5); - assert_eq!("-99.99900", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); - dec.ceil(-2); - assert_eq!("-99.99", dec.to_string()); - - let mut dec = FixedDecimal::from_str("99.999").unwrap(); - dec.ceil(4); - assert_eq!("10000", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); - dec.ceil(4); - assert_eq!("-0000", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0.009").unwrap(); - dec.ceil(-1); - assert_eq!("0.1", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-0.009").unwrap(); - dec.ceil(-1); - assert_eq!("-0.0", dec.to_string()); - - // Test Half Ceil - let mut dec = FixedDecimal::from_str("3.234").unwrap(); - dec.round_with_mode(0, RoundingMode::HalfCeil); - assert_eq!("3", dec.to_string()); - - let mut dec = FixedDecimal::from_str("3.534").unwrap(); - dec.round_with_mode(0, RoundingMode::HalfCeil); - assert_eq!("4", dec.to_string()); - - let mut dec = FixedDecimal::from_str("3.934").unwrap(); - dec.round_with_mode(0, RoundingMode::HalfCeil); - assert_eq!("4", dec.to_string()); - - let mut dec = FixedDecimal::from_str("2.222").unwrap(); - dec.round_with_mode(-1, RoundingMode::HalfCeil); - assert_eq!("2.2", dec.to_string()); - - let mut dec = FixedDecimal::from_str("2.44").unwrap(); - dec.round_with_mode(-1, RoundingMode::HalfCeil); - assert_eq!("2.4", dec.to_string()); - - let mut dec = FixedDecimal::from_str("2.45").unwrap(); - dec.round_with_mode(-1, RoundingMode::HalfCeil); - assert_eq!("2.5", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-2.44").unwrap(); - dec.round_with_mode(-1, RoundingMode::HalfCeil); - assert_eq!("-2.4", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-2.45").unwrap(); - dec.round_with_mode(-1, RoundingMode::HalfCeil); - assert_eq!("-2.4", dec.to_string()); - - let mut dec = FixedDecimal::from_str("22.222").unwrap(); - dec.round_with_mode(-2, RoundingMode::HalfCeil); - assert_eq!("22.22", dec.to_string()); - - let mut dec = FixedDecimal::from_str("99.999").unwrap(); - dec.round_with_mode(-2, RoundingMode::HalfCeil); - assert_eq!("100.00", dec.to_string()); - - let mut dec = FixedDecimal::from_str("99.999").unwrap(); - dec.round_with_mode(-5, RoundingMode::HalfCeil); - assert_eq!("99.99900", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); - dec.round_with_mode(-5, RoundingMode::HalfCeil); - assert_eq!("-99.99900", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); - dec.round_with_mode(-2, RoundingMode::HalfCeil); - assert_eq!("-100.00", dec.to_string()); - - let mut dec = FixedDecimal::from_str("99.999").unwrap(); - dec.round_with_mode(4, RoundingMode::HalfCeil); - assert_eq!("0000", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); - dec.round_with_mode(4, RoundingMode::HalfCeil); - assert_eq!("-0000", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0.009").unwrap(); - dec.round_with_mode(-1, RoundingMode::HalfCeil); - assert_eq!("0.0", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-0.009").unwrap(); - dec.round_with_mode(-1, RoundingMode::HalfCeil); - assert_eq!("-0.0", dec.to_string()); - - // Test Floor - let mut dec = FixedDecimal::from_str("3.234").unwrap(); - dec.floor(0); - assert_eq!("3", dec.to_string()); - - let mut dec = FixedDecimal::from_str("2.222").unwrap(); - dec.floor(-1); - assert_eq!("2.2", dec.to_string()); - - let mut dec = FixedDecimal::from_str("99.999").unwrap(); - dec.floor(-2); - assert_eq!("99.99", dec.to_string()); - - let mut dec = FixedDecimal::from_str("99.999").unwrap(); - dec.floor(-10); - assert_eq!("99.9990000000", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); - dec.floor(-10); - assert_eq!("-99.9990000000", dec.to_string()); - - let mut dec = FixedDecimal::from_str("99.999").unwrap(); - dec.floor(10); - assert_eq!("0000000000", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); - dec.floor(10); - assert_eq!("-10000000000", dec.to_string()); - - // Test Half Floor - let mut dec = FixedDecimal::from_str("3.234").unwrap(); - dec.round_with_mode(0, RoundingMode::HalfFloor); - assert_eq!("3", dec.to_string()); - - let mut dec = FixedDecimal::from_str("3.534").unwrap(); - dec.round_with_mode(0, RoundingMode::HalfFloor); - assert_eq!("4", dec.to_string()); - - let mut dec = FixedDecimal::from_str("3.934").unwrap(); - dec.round_with_mode(0, RoundingMode::HalfFloor); - assert_eq!("4", dec.to_string()); - - let mut dec = FixedDecimal::from_str("2.222").unwrap(); - dec.round_with_mode(-1, RoundingMode::HalfFloor); - assert_eq!("2.2", dec.to_string()); - - let mut dec = FixedDecimal::from_str("2.44").unwrap(); - dec.round_with_mode(-1, RoundingMode::HalfFloor); - assert_eq!("2.4", dec.to_string()); - - let mut dec = FixedDecimal::from_str("2.45").unwrap(); - dec.round_with_mode(-1, RoundingMode::HalfFloor); - assert_eq!("2.4", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-2.44").unwrap(); - dec.round_with_mode(-1, RoundingMode::HalfFloor); - assert_eq!("-2.4", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-2.45").unwrap(); - dec.round_with_mode(-1, RoundingMode::HalfFloor); - assert_eq!("-2.5", dec.to_string()); - - let mut dec = FixedDecimal::from_str("22.222").unwrap(); - dec.round_with_mode(-2, RoundingMode::HalfFloor); - assert_eq!("22.22", dec.to_string()); - - let mut dec = FixedDecimal::from_str("99.999").unwrap(); - dec.round_with_mode(-2, RoundingMode::HalfFloor); - assert_eq!("100.00", dec.to_string()); - - let mut dec = FixedDecimal::from_str("99.999").unwrap(); - dec.round_with_mode(-5, RoundingMode::HalfFloor); - assert_eq!("99.99900", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); - dec.round_with_mode(-5, RoundingMode::HalfFloor); - assert_eq!("-99.99900", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); - dec.round_with_mode(-2, RoundingMode::HalfFloor); - assert_eq!("-100.00", dec.to_string()); - - let mut dec = FixedDecimal::from_str("99.999").unwrap(); - dec.round_with_mode(4, RoundingMode::HalfFloor); - assert_eq!("0000", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); - dec.round_with_mode(4, RoundingMode::HalfFloor); - assert_eq!("-0000", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0.009").unwrap(); - dec.round_with_mode(-1, RoundingMode::HalfFloor); - assert_eq!("0.0", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-0.009").unwrap(); - dec.round_with_mode(-1, RoundingMode::HalfFloor); - assert_eq!("-0.0", dec.to_string()); - // Test Truncate Right - let mut dec = FixedDecimal::from(4235970).multiplied_pow10(-3); + let mut dec = UnsignedFixedDecimal::from(4235970u32).multiplied_pow10(-3); assert_eq!("4235.970", dec.to_string()); dec.trunc(-5); @@ -3846,20 +2861,16 @@ fn test_rounding() { dec.trunc(2); assert_eq!("00000", dec.to_string()); - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); - dec.trunc(-2); - assert_eq!("-99.99", dec.to_string()); - - let mut dec = FixedDecimal::from_str("1234.56").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("1234.56").unwrap(); dec.trunc(-1); assert_eq!("1234.5", dec.to_string()); - let mut dec = FixedDecimal::from_str("0.009").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("0.009").unwrap(); dec.trunc(-1); assert_eq!("0.0", dec.to_string()); // Test trunced - let dec = FixedDecimal::from(4235970).multiplied_pow10(-3); + let dec = UnsignedFixedDecimal::from(4235970u32).multiplied_pow10(-3); assert_eq!("4235.970", dec.to_string()); assert_eq!("4235.97000", dec.clone().trunced(-5).to_string()); @@ -3871,138 +2882,98 @@ fn test_rounding() { assert_eq!("00000", dec.trunced(5).to_string()); //Test expand - let mut dec = FixedDecimal::from_str("3.234").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("3.234").unwrap(); dec.expand(0); assert_eq!("4", dec.to_string()); - let mut dec = FixedDecimal::from_str("2.222").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("2.222").unwrap(); dec.expand(-1); assert_eq!("2.3", dec.to_string()); - let mut dec = FixedDecimal::from_str("22.222").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("22.222").unwrap(); dec.expand(-2); assert_eq!("22.23", dec.to_string()); - let mut dec = FixedDecimal::from_str("99.999").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("99.999").unwrap(); dec.expand(-2); assert_eq!("100.00", dec.to_string()); - let mut dec = FixedDecimal::from_str("99.999").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("99.999").unwrap(); dec.expand(-5); assert_eq!("99.99900", dec.to_string()); - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); - dec.expand(-5); - assert_eq!("-99.99900", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); - dec.expand(-2); - assert_eq!("-100.00", dec.to_string()); - - let mut dec = FixedDecimal::from_str("99.999").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("99.999").unwrap(); dec.expand(4); assert_eq!("10000", dec.to_string()); - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); - dec.expand(4); - assert_eq!("-10000", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0.009").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("0.009").unwrap(); dec.expand(-1); assert_eq!("0.1", dec.to_string()); - let mut dec = FixedDecimal::from_str("-0.009").unwrap(); - dec.expand(-1); - assert_eq!("-0.1", dec.to_string()); - - let mut dec = FixedDecimal::from_str("3.954").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("3.954").unwrap(); dec.expand(0); assert_eq!("4", dec.to_string()); // Test half_expand - let mut dec = FixedDecimal::from_str("3.234").unwrap(); - dec.round_with_mode(0, RoundingMode::HalfExpand); + let mut dec = UnsignedFixedDecimal::from_str("3.234").unwrap(); + dec.round_with_mode(0, UnsignedRoundingMode::HalfExpand); assert_eq!("3", dec.to_string()); - let mut dec = FixedDecimal::from_str("3.534").unwrap(); - dec.round_with_mode(0, RoundingMode::HalfExpand); + let mut dec = UnsignedFixedDecimal::from_str("3.534").unwrap(); + dec.round_with_mode(0, UnsignedRoundingMode::HalfExpand); assert_eq!("4", dec.to_string()); - let mut dec = FixedDecimal::from_str("3.934").unwrap(); - dec.round_with_mode(0, RoundingMode::HalfExpand); + let mut dec = UnsignedFixedDecimal::from_str("3.934").unwrap(); + dec.round_with_mode(0, UnsignedRoundingMode::HalfExpand); assert_eq!("4", dec.to_string()); - let mut dec = FixedDecimal::from_str("2.222").unwrap(); - dec.round_with_mode(-1, RoundingMode::HalfExpand); + let mut dec = UnsignedFixedDecimal::from_str("2.222").unwrap(); + dec.round_with_mode(-1, UnsignedRoundingMode::HalfExpand); assert_eq!("2.2", dec.to_string()); - let mut dec = FixedDecimal::from_str("2.44").unwrap(); - dec.round_with_mode(-1, RoundingMode::HalfExpand); + let mut dec = UnsignedFixedDecimal::from_str("2.44").unwrap(); + dec.round_with_mode(-1, UnsignedRoundingMode::HalfExpand); assert_eq!("2.4", dec.to_string()); - let mut dec = FixedDecimal::from_str("2.45").unwrap(); - dec.round_with_mode(-1, RoundingMode::HalfExpand); + let mut dec = UnsignedFixedDecimal::from_str("2.45").unwrap(); + dec.round_with_mode(-1, UnsignedRoundingMode::HalfExpand); assert_eq!("2.5", dec.to_string()); - let mut dec = FixedDecimal::from_str("-2.44").unwrap(); - dec.round_with_mode(-1, RoundingMode::HalfExpand); - assert_eq!("-2.4", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-2.45").unwrap(); - dec.round_with_mode(-1, RoundingMode::HalfExpand); - assert_eq!("-2.5", dec.to_string()); - - let mut dec = FixedDecimal::from_str("22.222").unwrap(); - dec.round_with_mode(-2, RoundingMode::HalfExpand); + let mut dec = UnsignedFixedDecimal::from_str("22.222").unwrap(); + dec.round_with_mode(-2, UnsignedRoundingMode::HalfExpand); assert_eq!("22.22", dec.to_string()); - let mut dec = FixedDecimal::from_str("99.999").unwrap(); - dec.round_with_mode(-2, RoundingMode::HalfExpand); + let mut dec = UnsignedFixedDecimal::from_str("99.999").unwrap(); + dec.round_with_mode(-2, UnsignedRoundingMode::HalfExpand); assert_eq!("100.00", dec.to_string()); - let mut dec = FixedDecimal::from_str("99.999").unwrap(); - dec.round_with_mode(-5, RoundingMode::HalfExpand); + let mut dec = UnsignedFixedDecimal::from_str("99.999").unwrap(); + dec.round_with_mode(-5, UnsignedRoundingMode::HalfExpand); assert_eq!("99.99900", dec.to_string()); - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); - dec.round_with_mode(-5, RoundingMode::HalfExpand); - assert_eq!("-99.99900", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); - dec.round_with_mode(-2, RoundingMode::HalfExpand); - assert_eq!("-100.00", dec.to_string()); - - let mut dec = FixedDecimal::from_str("99.999").unwrap(); - dec.round_with_mode(4, RoundingMode::HalfExpand); + let mut dec = UnsignedFixedDecimal::from_str("99.999").unwrap(); + dec.round_with_mode(4, UnsignedRoundingMode::HalfExpand); assert_eq!("0000", dec.to_string()); - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); - dec.round_with_mode(4, RoundingMode::HalfExpand); - assert_eq!("-0000", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0.009").unwrap(); - dec.round_with_mode(-1, RoundingMode::HalfExpand); + let mut dec = UnsignedFixedDecimal::from_str("0.009").unwrap(); + dec.round_with_mode(-1, UnsignedRoundingMode::HalfExpand); assert_eq!("0.0", dec.to_string()); - let mut dec = FixedDecimal::from_str("-0.009").unwrap(); - dec.round_with_mode(-1, RoundingMode::HalfExpand); - assert_eq!("-0.0", dec.to_string()); - // Test specific cases - let mut dec = FixedDecimal::from_str("1.108").unwrap(); - dec.round_with_mode(-2, RoundingMode::HalfEven); + let mut dec = UnsignedFixedDecimal::from_str("1.108").unwrap(); + dec.round_with_mode(-2, UnsignedRoundingMode::HalfEven); assert_eq!("1.11", dec.to_string()); - let mut dec = FixedDecimal::from_str("1.108").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("1.108").unwrap(); dec.expand(-2); assert_eq!("1.11", dec.to_string()); - let mut dec = FixedDecimal::from_str("1.108").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("1.108").unwrap(); dec.trunc(-2); assert_eq!("1.10", dec.to_string()); - let mut dec = FixedDecimal::from_str("2.78536913177").unwrap(); - dec.round_with_mode(-2, RoundingMode::HalfEven); + let mut dec = UnsignedFixedDecimal::from_str("2.78536913177").unwrap(); + dec.round_with_mode(-2, UnsignedRoundingMode::HalfEven); assert_eq!("2.79", dec.to_string()); } @@ -4107,8 +3078,8 @@ fn test_concatenate() { }, ]; for cas in &cases { - let fd1 = FixedDecimal::from_str(cas.input_1).unwrap(); - let fd2 = FixedDecimal::from_str(cas.input_2).unwrap(); + let fd1 = UnsignedFixedDecimal::from_str(cas.input_1).unwrap(); + let fd2 = UnsignedFixedDecimal::from_str(cas.input_2).unwrap(); match fd1.concatenated_end(fd2) { Ok(fd) => { assert_eq!(cas.expected, Some(fd.to_string().as_str()), "{cas:?}"); @@ -4123,1042 +3094,1106 @@ fn test_concatenate() { #[test] fn test_rounding_increment() { // Test Truncate Right - let mut dec = FixedDecimal::from(4235970).multiplied_pow10(-3); + let mut dec = UnsignedFixedDecimal::from(4235970u32).multiplied_pow10(-3); assert_eq!("4235.970", dec.to_string()); - dec.round_with_mode_and_increment(-2, RoundingMode::Trunc, RoundingIncrement::MultiplesOf2); + dec.round_with_mode_and_increment( + -2, + UnsignedRoundingMode::Trunc, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("4235.96", dec.to_string()); - dec.round_with_mode_and_increment(-1, RoundingMode::Trunc, RoundingIncrement::MultiplesOf5); + dec.round_with_mode_and_increment( + -1, + UnsignedRoundingMode::Trunc, + RoundingIncrement::MultiplesOf5, + ); assert_eq!("4235.5", dec.to_string()); - dec.round_with_mode_and_increment(0, RoundingMode::Trunc, RoundingIncrement::MultiplesOf25); + dec.round_with_mode_and_increment( + 0, + UnsignedRoundingMode::Trunc, + RoundingIncrement::MultiplesOf25, + ); assert_eq!("4225", dec.to_string()); - dec.round_with_mode_and_increment(5, RoundingMode::Trunc, RoundingIncrement::MultiplesOf5); + dec.round_with_mode_and_increment( + 5, + UnsignedRoundingMode::Trunc, + RoundingIncrement::MultiplesOf5, + ); assert_eq!("00000", dec.to_string()); - dec.round_with_mode_and_increment(2, RoundingMode::Trunc, RoundingIncrement::MultiplesOf2); + dec.round_with_mode_and_increment( + 2, + UnsignedRoundingMode::Trunc, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("00000", dec.to_string()); - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::Trunc, RoundingIncrement::MultiplesOf25); - assert_eq!("-99.75", dec.to_string()); - - let mut dec = FixedDecimal::from_str("1234.56").unwrap(); - dec.round_with_mode_and_increment(-1, RoundingMode::Trunc, RoundingIncrement::MultiplesOf2); + let mut dec = UnsignedFixedDecimal::from_str("1234.56").unwrap(); + dec.round_with_mode_and_increment( + -1, + UnsignedRoundingMode::Trunc, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("1234.4", dec.to_string()); - let mut dec = FixedDecimal::from_str("0.009").unwrap(); - dec.round_with_mode_and_increment(-1, RoundingMode::Trunc, RoundingIncrement::MultiplesOf5); + let mut dec = UnsignedFixedDecimal::from_str("0.009").unwrap(); + dec.round_with_mode_and_increment( + -1, + UnsignedRoundingMode::Trunc, + RoundingIncrement::MultiplesOf5, + ); assert_eq!("0.0", dec.to_string()); - let mut dec = FixedDecimal::from_str("0.60").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::Trunc, RoundingIncrement::MultiplesOf25); + let mut dec = UnsignedFixedDecimal::from_str("0.60").unwrap(); + dec.round_with_mode_and_increment( + -2, + UnsignedRoundingMode::Trunc, + RoundingIncrement::MultiplesOf25, + ); assert_eq!("0.50", dec.to_string()); - let mut dec = FixedDecimal::from_str("0.40").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::Trunc, RoundingIncrement::MultiplesOf25); + let mut dec = UnsignedFixedDecimal::from_str("0.40").unwrap(); + dec.round_with_mode_and_increment( + -2, + UnsignedRoundingMode::Trunc, + RoundingIncrement::MultiplesOf25, + ); assert_eq!("0.25", dec.to_string()); - let mut dec = FixedDecimal::from_str("0.7000000099").unwrap(); - dec.round_with_mode_and_increment(-3, RoundingMode::Trunc, RoundingIncrement::MultiplesOf2); + let mut dec = UnsignedFixedDecimal::from_str("0.7000000099").unwrap(); + dec.round_with_mode_and_increment( + -3, + UnsignedRoundingMode::Trunc, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("0.700", dec.to_string()); - let mut dec = FixedDecimal::from_str("5").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Trunc, RoundingIncrement::MultiplesOf25); + let mut dec = UnsignedFixedDecimal::from_str("5").unwrap(); + dec.round_with_mode_and_increment( + 0, + UnsignedRoundingMode::Trunc, + RoundingIncrement::MultiplesOf25, + ); assert_eq!("0", dec.to_string()); - let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MIN); + let mut dec = UnsignedFixedDecimal::from(7u32).multiplied_pow10(i16::MIN); dec.round_with_mode_and_increment( i16::MIN, - RoundingMode::Trunc, + UnsignedRoundingMode::Trunc, RoundingIncrement::MultiplesOf2, ); - assert_eq!(FixedDecimal::from(6).multiplied_pow10(i16::MIN), dec); + assert_eq!( + UnsignedFixedDecimal::from(6u32).multiplied_pow10(i16::MIN), + dec + ); - let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MIN); + let mut dec = UnsignedFixedDecimal::from(9u32).multiplied_pow10(i16::MIN); dec.round_with_mode_and_increment( i16::MIN, - RoundingMode::Trunc, + UnsignedRoundingMode::Trunc, RoundingIncrement::MultiplesOf5, ); - assert_eq!(FixedDecimal::from(5).multiplied_pow10(i16::MIN), dec); + assert_eq!( + UnsignedFixedDecimal::from(5u32).multiplied_pow10(i16::MIN), + dec + ); - let mut dec = FixedDecimal::from(70).multiplied_pow10(i16::MIN); + let mut dec = UnsignedFixedDecimal::from(70u32).multiplied_pow10(i16::MIN); dec.round_with_mode_and_increment( i16::MIN, - RoundingMode::Trunc, + UnsignedRoundingMode::Trunc, RoundingIncrement::MultiplesOf25, ); - assert_eq!(FixedDecimal::from(50).multiplied_pow10(i16::MIN), dec); + assert_eq!( + UnsignedFixedDecimal::from(50u32).multiplied_pow10(i16::MIN), + dec + ); - let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX); + let mut dec = UnsignedFixedDecimal::from(7u32).multiplied_pow10(i16::MAX); dec.round_with_mode_and_increment( i16::MAX, - RoundingMode::Trunc, + UnsignedRoundingMode::Trunc, RoundingIncrement::MultiplesOf2, ); - assert_eq!(FixedDecimal::from(6).multiplied_pow10(i16::MAX), dec); + assert_eq!( + UnsignedFixedDecimal::from(6u32).multiplied_pow10(i16::MAX), + dec + ); - let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX); + let mut dec = UnsignedFixedDecimal::from(7u32).multiplied_pow10(i16::MAX); dec.round_with_mode_and_increment( i16::MAX, - RoundingMode::Trunc, + UnsignedRoundingMode::Trunc, RoundingIncrement::MultiplesOf5, ); - assert_eq!(FixedDecimal::from(5).multiplied_pow10(i16::MAX), dec); + assert_eq!( + UnsignedFixedDecimal::from(5u32).multiplied_pow10(i16::MAX), + dec + ); - let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX); + let mut dec = UnsignedFixedDecimal::from(7u32).multiplied_pow10(i16::MAX); dec.round_with_mode_and_increment( i16::MAX, - RoundingMode::Trunc, + UnsignedRoundingMode::Trunc, RoundingIncrement::MultiplesOf25, ); - assert_eq!(FixedDecimal::from(0).multiplied_pow10(i16::MAX), dec); + assert_eq!( + UnsignedFixedDecimal::from(0u32).multiplied_pow10(i16::MAX), + dec + ); // Test Expand - let mut dec = FixedDecimal::from(4235970).multiplied_pow10(-3); + let mut dec = UnsignedFixedDecimal::from(4235970u32).multiplied_pow10(-3); assert_eq!("4235.970", dec.to_string()); - dec.round_with_mode_and_increment(-2, RoundingMode::Expand, RoundingIncrement::MultiplesOf2); + dec.round_with_mode_and_increment( + -2, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("4235.98", dec.to_string()); - dec.round_with_mode_and_increment(-1, RoundingMode::Expand, RoundingIncrement::MultiplesOf5); + dec.round_with_mode_and_increment( + -1, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf5, + ); assert_eq!("4236.0", dec.to_string()); - dec.round_with_mode_and_increment(0, RoundingMode::Expand, RoundingIncrement::MultiplesOf25); + dec.round_with_mode_and_increment( + 0, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf25, + ); assert_eq!("4250", dec.to_string()); - dec.round_with_mode_and_increment(5, RoundingMode::Expand, RoundingIncrement::MultiplesOf5); + dec.round_with_mode_and_increment( + 5, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf5, + ); assert_eq!("500000", dec.to_string()); - dec.round_with_mode_and_increment(2, RoundingMode::Expand, RoundingIncrement::MultiplesOf2); + dec.round_with_mode_and_increment( + 2, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("500000", dec.to_string()); - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::Expand, RoundingIncrement::MultiplesOf25); - assert_eq!("-100.00", dec.to_string()); - - let mut dec = FixedDecimal::from_str("1234.56").unwrap(); - dec.round_with_mode_and_increment(-1, RoundingMode::Expand, RoundingIncrement::MultiplesOf2); + let mut dec = UnsignedFixedDecimal::from_str("1234.56").unwrap(); + dec.round_with_mode_and_increment( + -1, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("1234.6", dec.to_string()); - let mut dec = FixedDecimal::from_str("0.009").unwrap(); - dec.round_with_mode_and_increment(-1, RoundingMode::Expand, RoundingIncrement::MultiplesOf5); + let mut dec = UnsignedFixedDecimal::from_str("0.009").unwrap(); + dec.round_with_mode_and_increment( + -1, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf5, + ); assert_eq!("0.5", dec.to_string()); - let mut dec = FixedDecimal::from_str("0.60").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::Expand, RoundingIncrement::MultiplesOf25); + let mut dec = UnsignedFixedDecimal::from_str("0.60").unwrap(); + dec.round_with_mode_and_increment( + -2, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf25, + ); assert_eq!("0.75", dec.to_string()); - let mut dec = FixedDecimal::from_str("0.40").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::Expand, RoundingIncrement::MultiplesOf25); + let mut dec = UnsignedFixedDecimal::from_str("0.40").unwrap(); + dec.round_with_mode_and_increment( + -2, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf25, + ); assert_eq!("0.50", dec.to_string()); - let mut dec = FixedDecimal::from_str("0.7000000099").unwrap(); - dec.round_with_mode_and_increment(-3, RoundingMode::Expand, RoundingIncrement::MultiplesOf2); + let mut dec = UnsignedFixedDecimal::from_str("0.7000000099").unwrap(); + dec.round_with_mode_and_increment( + -3, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("0.702", dec.to_string()); - let mut dec = FixedDecimal::from_str("5").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Expand, RoundingIncrement::MultiplesOf25); + let mut dec = UnsignedFixedDecimal::from_str("5").unwrap(); + dec.round_with_mode_and_increment( + 0, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf25, + ); assert_eq!("25", dec.to_string()); - let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MIN); + let mut dec = UnsignedFixedDecimal::from(7u32).multiplied_pow10(i16::MIN); dec.round_with_mode_and_increment( i16::MIN, - RoundingMode::Expand, + UnsignedRoundingMode::Expand, RoundingIncrement::MultiplesOf2, ); - assert_eq!(FixedDecimal::from(8).multiplied_pow10(i16::MIN), dec); + assert_eq!( + UnsignedFixedDecimal::from(8u32).multiplied_pow10(i16::MIN), + dec + ); - let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MIN); + let mut dec = UnsignedFixedDecimal::from(9u32).multiplied_pow10(i16::MIN); dec.round_with_mode_and_increment( i16::MIN, - RoundingMode::Expand, + UnsignedRoundingMode::Expand, RoundingIncrement::MultiplesOf5, ); - assert_eq!(FixedDecimal::from(10).multiplied_pow10(i16::MIN), dec); + assert_eq!( + UnsignedFixedDecimal::from(10u32).multiplied_pow10(i16::MIN), + dec + ); - let mut dec = FixedDecimal::from(70).multiplied_pow10(i16::MIN); + let mut dec = UnsignedFixedDecimal::from(70u32).multiplied_pow10(i16::MIN); dec.round_with_mode_and_increment( i16::MIN, - RoundingMode::Expand, + UnsignedRoundingMode::Expand, RoundingIncrement::MultiplesOf25, ); - assert_eq!(FixedDecimal::from(75).multiplied_pow10(i16::MIN), dec); + assert_eq!( + UnsignedFixedDecimal::from(75u32).multiplied_pow10(i16::MIN), + dec + ); - let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX); + let mut dec = UnsignedFixedDecimal::from(7u32).multiplied_pow10(i16::MAX); dec.round_with_mode_and_increment( i16::MAX, - RoundingMode::Expand, + UnsignedRoundingMode::Expand, RoundingIncrement::MultiplesOf2, ); - assert_eq!(FixedDecimal::from(8).multiplied_pow10(i16::MAX), dec); + assert_eq!( + UnsignedFixedDecimal::from(8u32).multiplied_pow10(i16::MAX), + dec + ); - let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX); + let mut dec = UnsignedFixedDecimal::from(7u32).multiplied_pow10(i16::MAX); dec.round_with_mode_and_increment( i16::MAX, - RoundingMode::Expand, + UnsignedRoundingMode::Expand, RoundingIncrement::MultiplesOf5, ); - assert_eq!(FixedDecimal::from(0).multiplied_pow10(i16::MAX), dec); + assert_eq!( + UnsignedFixedDecimal::from(0u32).multiplied_pow10(i16::MAX), + dec + ); - let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX); + let mut dec = UnsignedFixedDecimal::from(7u32).multiplied_pow10(i16::MAX); dec.round_with_mode_and_increment( i16::MAX, - RoundingMode::Expand, + UnsignedRoundingMode::Expand, RoundingIncrement::MultiplesOf25, ); - assert_eq!(FixedDecimal::from(0).multiplied_pow10(i16::MAX), dec); + assert_eq!( + UnsignedFixedDecimal::from(0u32).multiplied_pow10(i16::MAX), + dec + ); // Test Half Truncate Right - let mut dec = FixedDecimal::from(4235970).multiplied_pow10(-3); + let mut dec = UnsignedFixedDecimal::from(4235970u32).multiplied_pow10(-3); assert_eq!("4235.970", dec.to_string()); - dec.round_with_mode_and_increment(-2, RoundingMode::HalfTrunc, RoundingIncrement::MultiplesOf2); + dec.round_with_mode_and_increment( + -2, + UnsignedRoundingMode::HalfTrunc, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("4235.96", dec.to_string()); - dec.round_with_mode_and_increment(-1, RoundingMode::HalfTrunc, RoundingIncrement::MultiplesOf5); + dec.round_with_mode_and_increment( + -1, + UnsignedRoundingMode::HalfTrunc, + RoundingIncrement::MultiplesOf5, + ); assert_eq!("4236.0", dec.to_string()); - dec.round_with_mode_and_increment(0, RoundingMode::HalfTrunc, RoundingIncrement::MultiplesOf25); + dec.round_with_mode_and_increment( + 0, + UnsignedRoundingMode::HalfTrunc, + RoundingIncrement::MultiplesOf25, + ); assert_eq!("4225", dec.to_string()); - dec.round_with_mode_and_increment(5, RoundingMode::HalfTrunc, RoundingIncrement::MultiplesOf5); + dec.round_with_mode_and_increment( + 5, + UnsignedRoundingMode::HalfTrunc, + RoundingIncrement::MultiplesOf5, + ); assert_eq!("00000", dec.to_string()); - dec.round_with_mode_and_increment(2, RoundingMode::HalfTrunc, RoundingIncrement::MultiplesOf2); + dec.round_with_mode_and_increment( + 2, + UnsignedRoundingMode::HalfTrunc, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("00000", dec.to_string()); - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("1234.56").unwrap(); dec.round_with_mode_and_increment( - -2, - RoundingMode::HalfTrunc, - RoundingIncrement::MultiplesOf25, + -1, + UnsignedRoundingMode::HalfTrunc, + RoundingIncrement::MultiplesOf2, ); - assert_eq!("-100.00", dec.to_string()); - - let mut dec = FixedDecimal::from_str("1234.56").unwrap(); - dec.round_with_mode_and_increment(-1, RoundingMode::HalfTrunc, RoundingIncrement::MultiplesOf2); assert_eq!("1234.6", dec.to_string()); - let mut dec = FixedDecimal::from_str("0.009").unwrap(); - dec.round_with_mode_and_increment(-1, RoundingMode::HalfTrunc, RoundingIncrement::MultiplesOf5); + let mut dec = UnsignedFixedDecimal::from_str("0.009").unwrap(); + dec.round_with_mode_and_increment( + -1, + UnsignedRoundingMode::HalfTrunc, + RoundingIncrement::MultiplesOf5, + ); assert_eq!("0.0", dec.to_string()); - let mut dec = FixedDecimal::from_str("0.60").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("0.60").unwrap(); dec.round_with_mode_and_increment( -2, - RoundingMode::HalfTrunc, + UnsignedRoundingMode::HalfTrunc, RoundingIncrement::MultiplesOf25, ); assert_eq!("0.50", dec.to_string()); - let mut dec = FixedDecimal::from_str("0.40").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("0.40").unwrap(); dec.round_with_mode_and_increment( -2, - RoundingMode::HalfTrunc, + UnsignedRoundingMode::HalfTrunc, RoundingIncrement::MultiplesOf25, ); assert_eq!("0.50", dec.to_string()); - let mut dec = FixedDecimal::from_str("0.7000000099").unwrap(); - dec.round_with_mode_and_increment(-3, RoundingMode::HalfTrunc, RoundingIncrement::MultiplesOf2); + let mut dec = UnsignedFixedDecimal::from_str("0.7000000099").unwrap(); + dec.round_with_mode_and_increment( + -3, + UnsignedRoundingMode::HalfTrunc, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("0.700", dec.to_string()); - let mut dec = FixedDecimal::from_str("5").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::HalfTrunc, RoundingIncrement::MultiplesOf25); + let mut dec = UnsignedFixedDecimal::from_str("5").unwrap(); + dec.round_with_mode_and_increment( + 0, + UnsignedRoundingMode::HalfTrunc, + RoundingIncrement::MultiplesOf25, + ); assert_eq!("0", dec.to_string()); - let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MIN); + let mut dec = UnsignedFixedDecimal::from(7u32).multiplied_pow10(i16::MIN); dec.round_with_mode_and_increment( i16::MIN, - RoundingMode::HalfTrunc, + UnsignedRoundingMode::HalfTrunc, RoundingIncrement::MultiplesOf2, ); - assert_eq!(FixedDecimal::from(6).multiplied_pow10(i16::MIN), dec); + assert_eq!( + UnsignedFixedDecimal::from(6u32).multiplied_pow10(i16::MIN), + dec + ); - let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MIN); + let mut dec = UnsignedFixedDecimal::from(9u32).multiplied_pow10(i16::MIN); dec.round_with_mode_and_increment( i16::MIN, - RoundingMode::HalfTrunc, + UnsignedRoundingMode::HalfTrunc, RoundingIncrement::MultiplesOf5, ); - assert_eq!(FixedDecimal::from(10).multiplied_pow10(i16::MIN), dec); + assert_eq!( + UnsignedFixedDecimal::from(10u32).multiplied_pow10(i16::MIN), + dec + ); - let mut dec = FixedDecimal::from(70).multiplied_pow10(i16::MIN); + let mut dec = UnsignedFixedDecimal::from(70u32).multiplied_pow10(i16::MIN); dec.round_with_mode_and_increment( i16::MIN, - RoundingMode::HalfTrunc, + UnsignedRoundingMode::HalfTrunc, RoundingIncrement::MultiplesOf25, ); - assert_eq!(FixedDecimal::from(75).multiplied_pow10(i16::MIN), dec); + assert_eq!( + UnsignedFixedDecimal::from(75u32).multiplied_pow10(i16::MIN), + dec + ); - let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX); + let mut dec = UnsignedFixedDecimal::from(7u32).multiplied_pow10(i16::MAX); dec.round_with_mode_and_increment( i16::MAX, - RoundingMode::HalfTrunc, + UnsignedRoundingMode::HalfTrunc, RoundingIncrement::MultiplesOf2, ); - assert_eq!(FixedDecimal::from(6).multiplied_pow10(i16::MAX), dec); + assert_eq!( + UnsignedFixedDecimal::from(6u32).multiplied_pow10(i16::MAX), + dec + ); - let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX); + let mut dec = UnsignedFixedDecimal::from(7u32).multiplied_pow10(i16::MAX); dec.round_with_mode_and_increment( i16::MAX, - RoundingMode::HalfTrunc, + UnsignedRoundingMode::HalfTrunc, RoundingIncrement::MultiplesOf5, ); - assert_eq!(FixedDecimal::from(5).multiplied_pow10(i16::MAX), dec); + assert_eq!( + UnsignedFixedDecimal::from(5u32).multiplied_pow10(i16::MAX), + dec + ); - let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX); + let mut dec = UnsignedFixedDecimal::from(7u32).multiplied_pow10(i16::MAX); dec.round_with_mode_and_increment( i16::MAX, - RoundingMode::HalfTrunc, + UnsignedRoundingMode::HalfTrunc, RoundingIncrement::MultiplesOf25, ); - assert_eq!(FixedDecimal::from(0).multiplied_pow10(i16::MAX), dec); + assert_eq!( + UnsignedFixedDecimal::from(0u32).multiplied_pow10(i16::MAX), + dec + ); // Test Half Expand - let mut dec = FixedDecimal::from(4235970).multiplied_pow10(-3); + let mut dec = UnsignedFixedDecimal::from(4235970u32).multiplied_pow10(-3); assert_eq!("4235.970", dec.to_string()); dec.round_with_mode_and_increment( -2, - RoundingMode::HalfExpand, + UnsignedRoundingMode::HalfExpand, RoundingIncrement::MultiplesOf2, ); assert_eq!("4235.98", dec.to_string()); dec.round_with_mode_and_increment( -1, - RoundingMode::HalfExpand, + UnsignedRoundingMode::HalfExpand, RoundingIncrement::MultiplesOf5, ); assert_eq!("4236.0", dec.to_string()); dec.round_with_mode_and_increment( 0, - RoundingMode::HalfExpand, + UnsignedRoundingMode::HalfExpand, RoundingIncrement::MultiplesOf25, ); assert_eq!("4225", dec.to_string()); - dec.round_with_mode_and_increment(5, RoundingMode::HalfExpand, RoundingIncrement::MultiplesOf5); - assert_eq!("00000", dec.to_string()); - - dec.round_with_mode_and_increment(2, RoundingMode::HalfExpand, RoundingIncrement::MultiplesOf2); + dec.round_with_mode_and_increment( + 5, + UnsignedRoundingMode::HalfExpand, + RoundingIncrement::MultiplesOf5, + ); assert_eq!("00000", dec.to_string()); - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); dec.round_with_mode_and_increment( - -2, - RoundingMode::HalfExpand, - RoundingIncrement::MultiplesOf25, + 2, + UnsignedRoundingMode::HalfExpand, + RoundingIncrement::MultiplesOf2, ); - assert_eq!("-100.00", dec.to_string()); + assert_eq!("00000", dec.to_string()); - let mut dec = FixedDecimal::from_str("1234.56").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("1234.56").unwrap(); dec.round_with_mode_and_increment( -1, - RoundingMode::HalfExpand, + UnsignedRoundingMode::HalfExpand, RoundingIncrement::MultiplesOf2, ); assert_eq!("1234.6", dec.to_string()); - let mut dec = FixedDecimal::from_str("0.009").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("0.009").unwrap(); dec.round_with_mode_and_increment( -1, - RoundingMode::HalfExpand, + UnsignedRoundingMode::HalfExpand, RoundingIncrement::MultiplesOf5, ); assert_eq!("0.0", dec.to_string()); - let mut dec = FixedDecimal::from_str("0.60").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("0.60").unwrap(); dec.round_with_mode_and_increment( -2, - RoundingMode::HalfExpand, + UnsignedRoundingMode::HalfExpand, RoundingIncrement::MultiplesOf25, ); assert_eq!("0.50", dec.to_string()); - let mut dec = FixedDecimal::from_str("0.40").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("0.40").unwrap(); dec.round_with_mode_and_increment( -2, - RoundingMode::HalfExpand, + UnsignedRoundingMode::HalfExpand, RoundingIncrement::MultiplesOf25, ); assert_eq!("0.50", dec.to_string()); - let mut dec = FixedDecimal::from_str("0.7000000099").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("0.7000000099").unwrap(); dec.round_with_mode_and_increment( -3, - RoundingMode::HalfExpand, + UnsignedRoundingMode::HalfExpand, RoundingIncrement::MultiplesOf2, ); assert_eq!("0.700", dec.to_string()); - let mut dec = FixedDecimal::from_str("5").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("5").unwrap(); dec.round_with_mode_and_increment( 0, - RoundingMode::HalfExpand, + UnsignedRoundingMode::HalfExpand, RoundingIncrement::MultiplesOf25, ); assert_eq!("0", dec.to_string()); - let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MIN); + let mut dec = UnsignedFixedDecimal::from(7u32).multiplied_pow10(i16::MIN); dec.round_with_mode_and_increment( i16::MIN, - RoundingMode::HalfExpand, + UnsignedRoundingMode::HalfExpand, RoundingIncrement::MultiplesOf2, ); - assert_eq!(FixedDecimal::from(8).multiplied_pow10(i16::MIN), dec); + assert_eq!( + UnsignedFixedDecimal::from(8u32).multiplied_pow10(i16::MIN), + dec + ); - let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MIN); + let mut dec = UnsignedFixedDecimal::from(9u32).multiplied_pow10(i16::MIN); dec.round_with_mode_and_increment( i16::MIN, - RoundingMode::HalfExpand, + UnsignedRoundingMode::HalfExpand, RoundingIncrement::MultiplesOf5, ); - assert_eq!(FixedDecimal::from(10).multiplied_pow10(i16::MIN), dec); + assert_eq!( + UnsignedFixedDecimal::from(10u32).multiplied_pow10(i16::MIN), + dec + ); - let mut dec = FixedDecimal::from(70).multiplied_pow10(i16::MIN); + let mut dec = UnsignedFixedDecimal::from(70u32).multiplied_pow10(i16::MIN); dec.round_with_mode_and_increment( i16::MIN, - RoundingMode::HalfExpand, + UnsignedRoundingMode::HalfExpand, RoundingIncrement::MultiplesOf25, ); - assert_eq!(FixedDecimal::from(75).multiplied_pow10(i16::MIN), dec); + assert_eq!( + UnsignedFixedDecimal::from(75u32).multiplied_pow10(i16::MIN), + dec + ); - let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX); + let mut dec = UnsignedFixedDecimal::from(7u32).multiplied_pow10(i16::MAX); dec.round_with_mode_and_increment( i16::MAX, - RoundingMode::HalfExpand, + UnsignedRoundingMode::HalfExpand, RoundingIncrement::MultiplesOf2, ); - assert_eq!(FixedDecimal::from(8).multiplied_pow10(i16::MAX), dec); + assert_eq!( + UnsignedFixedDecimal::from(8u32).multiplied_pow10(i16::MAX), + dec + ); - // Test Ceil - let mut dec = FixedDecimal::from(4235970).multiplied_pow10(-3); + // Test Half Even + let mut dec = UnsignedFixedDecimal::from(4235970u32).multiplied_pow10(-3); assert_eq!("4235.970", dec.to_string()); - dec.round_with_mode_and_increment(-2, RoundingMode::Ceil, RoundingIncrement::MultiplesOf2); - assert_eq!("4235.98", dec.to_string()); - - dec.round_with_mode_and_increment(-1, RoundingMode::Ceil, RoundingIncrement::MultiplesOf5); - assert_eq!("4236.0", dec.to_string()); - - dec.round_with_mode_and_increment(0, RoundingMode::Ceil, RoundingIncrement::MultiplesOf25); - assert_eq!("4250", dec.to_string()); - - dec.round_with_mode_and_increment(5, RoundingMode::Ceil, RoundingIncrement::MultiplesOf5); - assert_eq!("500000", dec.to_string()); - - dec.round_with_mode_and_increment(2, RoundingMode::Ceil, RoundingIncrement::MultiplesOf2); - assert_eq!("500000", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::Ceil, RoundingIncrement::MultiplesOf25); - assert_eq!("-99.75", dec.to_string()); - - let mut dec = FixedDecimal::from_str("1234.56").unwrap(); - dec.round_with_mode_and_increment(-1, RoundingMode::Ceil, RoundingIncrement::MultiplesOf2); - assert_eq!("1234.6", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0.009").unwrap(); - dec.round_with_mode_and_increment(-1, RoundingMode::Ceil, RoundingIncrement::MultiplesOf5); - assert_eq!("0.5", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0.60").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::Ceil, RoundingIncrement::MultiplesOf25); - assert_eq!("0.75", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0.40").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::Ceil, RoundingIncrement::MultiplesOf25); - assert_eq!("0.50", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0.7000000099").unwrap(); - dec.round_with_mode_and_increment(-3, RoundingMode::Ceil, RoundingIncrement::MultiplesOf2); - assert_eq!("0.702", dec.to_string()); - - let mut dec = FixedDecimal::from_str("5").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Ceil, RoundingIncrement::MultiplesOf25); - assert_eq!("25", dec.to_string()); - - let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MIN); dec.round_with_mode_and_increment( - i16::MIN, - RoundingMode::Ceil, + -2, + UnsignedRoundingMode::HalfEven, RoundingIncrement::MultiplesOf2, ); - assert_eq!(FixedDecimal::from(8).multiplied_pow10(i16::MIN), dec); + assert_eq!("4235.96", dec.to_string()); - let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MIN); dec.round_with_mode_and_increment( - i16::MIN, - RoundingMode::Ceil, + -1, + UnsignedRoundingMode::HalfEven, RoundingIncrement::MultiplesOf5, ); - assert_eq!(FixedDecimal::from(10).multiplied_pow10(i16::MIN), dec); + assert_eq!("4236.0", dec.to_string()); - let mut dec = FixedDecimal::from(70).multiplied_pow10(i16::MIN); dec.round_with_mode_and_increment( - i16::MIN, - RoundingMode::Ceil, + 0, + UnsignedRoundingMode::HalfEven, RoundingIncrement::MultiplesOf25, ); - assert_eq!(FixedDecimal::from(75).multiplied_pow10(i16::MIN), dec); + assert_eq!("4225", dec.to_string()); - let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX); dec.round_with_mode_and_increment( - i16::MAX, - RoundingMode::Ceil, - RoundingIncrement::MultiplesOf2, + 5, + UnsignedRoundingMode::HalfEven, + RoundingIncrement::MultiplesOf5, ); - 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.round_with_mode_and_increment(-2, RoundingMode::HalfCeil, RoundingIncrement::MultiplesOf2); - assert_eq!("4235.98", dec.to_string()); - - dec.round_with_mode_and_increment(-1, RoundingMode::HalfCeil, RoundingIncrement::MultiplesOf5); - assert_eq!("4236.0", dec.to_string()); - - dec.round_with_mode_and_increment(0, RoundingMode::HalfCeil, RoundingIncrement::MultiplesOf25); - assert_eq!("4225", dec.to_string()); - - dec.round_with_mode_and_increment(5, RoundingMode::HalfCeil, RoundingIncrement::MultiplesOf5); assert_eq!("00000", dec.to_string()); - dec.round_with_mode_and_increment(2, RoundingMode::HalfCeil, RoundingIncrement::MultiplesOf2); + dec.round_with_mode_and_increment( + 2, + UnsignedRoundingMode::HalfEven, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("00000", dec.to_string()); - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::HalfCeil, RoundingIncrement::MultiplesOf25); - assert_eq!("-100.00", dec.to_string()); - - let mut dec = FixedDecimal::from_str("1234.56").unwrap(); - dec.round_with_mode_and_increment(-1, RoundingMode::HalfCeil, RoundingIncrement::MultiplesOf2); - assert_eq!("1234.6", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0.009").unwrap(); - dec.round_with_mode_and_increment(-1, RoundingMode::HalfCeil, RoundingIncrement::MultiplesOf5); - assert_eq!("0.0", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0.60").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::HalfCeil, RoundingIncrement::MultiplesOf25); - assert_eq!("0.50", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0.40").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::HalfCeil, RoundingIncrement::MultiplesOf25); - assert_eq!("0.50", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0.7000000099").unwrap(); - dec.round_with_mode_and_increment(-3, RoundingMode::HalfCeil, RoundingIncrement::MultiplesOf2); - assert_eq!("0.700", dec.to_string()); - - let mut dec = FixedDecimal::from_str("5").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::HalfCeil, RoundingIncrement::MultiplesOf25); - assert_eq!("0", dec.to_string()); - - let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MIN); + let mut dec = UnsignedFixedDecimal::from_str("1234.56").unwrap(); dec.round_with_mode_and_increment( - i16::MIN, - RoundingMode::HalfCeil, + -1, + UnsignedRoundingMode::HalfEven, RoundingIncrement::MultiplesOf2, ); - assert_eq!(FixedDecimal::from(8).multiplied_pow10(i16::MIN), dec); + assert_eq!("1234.6", dec.to_string()); - let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MIN); + let mut dec = UnsignedFixedDecimal::from_str("0.009").unwrap(); dec.round_with_mode_and_increment( - i16::MIN, - RoundingMode::HalfCeil, + -1, + UnsignedRoundingMode::HalfEven, RoundingIncrement::MultiplesOf5, ); - assert_eq!(FixedDecimal::from(10).multiplied_pow10(i16::MIN), dec); + assert_eq!("0.0", dec.to_string()); - let mut dec = FixedDecimal::from(70).multiplied_pow10(i16::MIN); + let mut dec = UnsignedFixedDecimal::from_str("0.60").unwrap(); dec.round_with_mode_and_increment( - i16::MIN, - RoundingMode::HalfCeil, + -2, + UnsignedRoundingMode::HalfEven, RoundingIncrement::MultiplesOf25, ); - assert_eq!(FixedDecimal::from(75).multiplied_pow10(i16::MIN), dec); + assert_eq!("0.50", dec.to_string()); - let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX); + let mut dec = UnsignedFixedDecimal::from_str("0.40").unwrap(); dec.round_with_mode_and_increment( - i16::MAX, - RoundingMode::HalfCeil, - RoundingIncrement::MultiplesOf2, + -2, + UnsignedRoundingMode::HalfEven, + RoundingIncrement::MultiplesOf25, ); - 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.round_with_mode_and_increment(-2, RoundingMode::Floor, RoundingIncrement::MultiplesOf2); - assert_eq!("4235.96", dec.to_string()); - - dec.round_with_mode_and_increment(-1, RoundingMode::Floor, RoundingIncrement::MultiplesOf5); - assert_eq!("4235.5", dec.to_string()); - - dec.round_with_mode_and_increment(0, RoundingMode::Floor, RoundingIncrement::MultiplesOf25); - assert_eq!("4225", dec.to_string()); - - dec.round_with_mode_and_increment(5, RoundingMode::Floor, RoundingIncrement::MultiplesOf5); - assert_eq!("00000", dec.to_string()); - - dec.round_with_mode_and_increment(2, RoundingMode::Floor, RoundingIncrement::MultiplesOf2); - assert_eq!("00000", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::Floor, RoundingIncrement::MultiplesOf25); - assert_eq!("-100.00", dec.to_string()); - - let mut dec = FixedDecimal::from_str("1234.56").unwrap(); - dec.round_with_mode_and_increment(-1, RoundingMode::Floor, RoundingIncrement::MultiplesOf2); - assert_eq!("1234.4", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0.009").unwrap(); - dec.round_with_mode_and_increment(-1, RoundingMode::Floor, RoundingIncrement::MultiplesOf5); - assert_eq!("0.0", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0.60").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::Floor, RoundingIncrement::MultiplesOf25); assert_eq!("0.50", dec.to_string()); - let mut dec = FixedDecimal::from_str("0.40").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::Floor, RoundingIncrement::MultiplesOf25); - assert_eq!("0.25", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0.7000000099").unwrap(); - dec.round_with_mode_and_increment(-3, RoundingMode::Floor, RoundingIncrement::MultiplesOf2); + let mut dec = UnsignedFixedDecimal::from_str("0.7000000099").unwrap(); + dec.round_with_mode_and_increment( + -3, + UnsignedRoundingMode::HalfEven, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("0.700", dec.to_string()); - let mut dec = FixedDecimal::from_str("5").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Floor, RoundingIncrement::MultiplesOf25); + let mut dec = UnsignedFixedDecimal::from_str("5").unwrap(); + dec.round_with_mode_and_increment( + 0, + UnsignedRoundingMode::HalfEven, + RoundingIncrement::MultiplesOf25, + ); assert_eq!("0", dec.to_string()); - let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MIN); + let mut dec = UnsignedFixedDecimal::from(7u32).multiplied_pow10(i16::MIN); dec.round_with_mode_and_increment( i16::MIN, - RoundingMode::Floor, + UnsignedRoundingMode::HalfEven, RoundingIncrement::MultiplesOf2, ); - assert_eq!(FixedDecimal::from(6).multiplied_pow10(i16::MIN), dec); + assert_eq!( + UnsignedFixedDecimal::from(8u32).multiplied_pow10(i16::MIN), + dec + ); - let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MIN); + let mut dec = UnsignedFixedDecimal::from(9u32).multiplied_pow10(i16::MIN); dec.round_with_mode_and_increment( i16::MIN, - RoundingMode::Floor, + UnsignedRoundingMode::HalfEven, RoundingIncrement::MultiplesOf5, ); - assert_eq!(FixedDecimal::from(5).multiplied_pow10(i16::MIN), dec); + assert_eq!( + UnsignedFixedDecimal::from(10u32).multiplied_pow10(i16::MIN), + dec + ); - let mut dec = FixedDecimal::from(70).multiplied_pow10(i16::MIN); + let mut dec = UnsignedFixedDecimal::from(70u32).multiplied_pow10(i16::MIN); dec.round_with_mode_and_increment( i16::MIN, - RoundingMode::Floor, + UnsignedRoundingMode::HalfEven, RoundingIncrement::MultiplesOf25, ); - assert_eq!(FixedDecimal::from(50).multiplied_pow10(i16::MIN), dec); + assert_eq!( + UnsignedFixedDecimal::from(75u32).multiplied_pow10(i16::MIN), + dec + ); - let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX); + let mut dec = UnsignedFixedDecimal::from(7u32).multiplied_pow10(i16::MAX); dec.round_with_mode_and_increment( i16::MAX, - RoundingMode::Floor, + UnsignedRoundingMode::HalfEven, RoundingIncrement::MultiplesOf2, ); - assert_eq!(FixedDecimal::from(6).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.round_with_mode_and_increment(-2, RoundingMode::HalfFloor, RoundingIncrement::MultiplesOf2); - assert_eq!("4235.96", dec.to_string()); - - dec.round_with_mode_and_increment(-1, RoundingMode::HalfFloor, RoundingIncrement::MultiplesOf5); - assert_eq!("4236.0", dec.to_string()); - - dec.round_with_mode_and_increment(0, RoundingMode::HalfFloor, RoundingIncrement::MultiplesOf25); - assert_eq!("4225", dec.to_string()); - - dec.round_with_mode_and_increment(5, RoundingMode::HalfFloor, RoundingIncrement::MultiplesOf5); - assert_eq!("00000", dec.to_string()); - - dec.round_with_mode_and_increment(2, RoundingMode::HalfFloor, RoundingIncrement::MultiplesOf2); - assert_eq!("00000", dec.to_string()); + assert_eq!( + UnsignedFixedDecimal::from(8u32).multiplied_pow10(i16::MAX), + dec + ); - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); + // Test specific cases + let mut dec = UnsignedFixedDecimal::from_str("1.108").unwrap(); dec.round_with_mode_and_increment( -2, - RoundingMode::HalfFloor, - RoundingIncrement::MultiplesOf25, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf2, ); - assert_eq!("-100.00", dec.to_string()); - - let mut dec = FixedDecimal::from_str("1234.56").unwrap(); - dec.round_with_mode_and_increment(-1, RoundingMode::HalfFloor, RoundingIncrement::MultiplesOf2); - assert_eq!("1234.6", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0.009").unwrap(); - dec.round_with_mode_and_increment(-1, RoundingMode::HalfFloor, RoundingIncrement::MultiplesOf5); - assert_eq!("0.0", dec.to_string()); + assert_eq!("1.12", dec.to_string()); - let mut dec = FixedDecimal::from_str("0.60").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("1.108").unwrap(); dec.round_with_mode_and_increment( -2, - RoundingMode::HalfFloor, - RoundingIncrement::MultiplesOf25, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf5, ); - assert_eq!("0.50", dec.to_string()); + assert_eq!("1.15", dec.to_string()); - let mut dec = FixedDecimal::from_str("0.40").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("1.108").unwrap(); dec.round_with_mode_and_increment( -2, - RoundingMode::HalfFloor, + UnsignedRoundingMode::Expand, RoundingIncrement::MultiplesOf25, ); - assert_eq!("0.50", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0.7000000099").unwrap(); - dec.round_with_mode_and_increment(-3, RoundingMode::HalfFloor, RoundingIncrement::MultiplesOf2); - assert_eq!("0.700", dec.to_string()); - - let mut dec = FixedDecimal::from_str("5").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::HalfFloor, RoundingIncrement::MultiplesOf25); - assert_eq!("0", dec.to_string()); + assert_eq!("1.25", dec.to_string()); - let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MIN); + let mut dec = UnsignedFixedDecimal::from(9u32).multiplied_pow10(i16::MAX - 1); dec.round_with_mode_and_increment( - i16::MIN, - RoundingMode::HalfFloor, - RoundingIncrement::MultiplesOf2, + i16::MAX - 1, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf25, ); - assert_eq!(FixedDecimal::from(6).multiplied_pow10(i16::MIN), dec); - - let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MIN); - dec.round_with_mode_and_increment( - i16::MIN, - RoundingMode::HalfFloor, - RoundingIncrement::MultiplesOf5, + assert_eq!( + UnsignedFixedDecimal::from(25u32).multiplied_pow10(i16::MAX - 1), + dec ); - assert_eq!(FixedDecimal::from(10).multiplied_pow10(i16::MIN), dec); - let mut dec = FixedDecimal::from(70).multiplied_pow10(i16::MIN); + let mut dec = UnsignedFixedDecimal::from(9u32).multiplied_pow10(i16::MAX); dec.round_with_mode_and_increment( - i16::MIN, - RoundingMode::HalfFloor, + i16::MAX, + UnsignedRoundingMode::Expand, RoundingIncrement::MultiplesOf25, ); - assert_eq!(FixedDecimal::from(75).multiplied_pow10(i16::MIN), dec); - - let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX); - dec.round_with_mode_and_increment( - i16::MAX, - RoundingMode::HalfFloor, - RoundingIncrement::MultiplesOf2, + assert_eq!( + UnsignedFixedDecimal::from(0u32).multiplied_pow10(i16::MAX), + dec ); - assert_eq!(FixedDecimal::from(6).multiplied_pow10(i16::MAX), dec); - - // Test Half Even - let mut dec = FixedDecimal::from(4235970).multiplied_pow10(-3); - assert_eq!("4235.970", dec.to_string()); - - dec.round_with_mode_and_increment(-2, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf2); - assert_eq!("4235.96", dec.to_string()); - - dec.round_with_mode_and_increment(-1, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf5); - assert_eq!("4236.0", dec.to_string()); - dec.round_with_mode_and_increment(0, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf25); - assert_eq!("4225", dec.to_string()); - - dec.round_with_mode_and_increment(5, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf5); - assert_eq!("00000", dec.to_string()); - - dec.round_with_mode_and_increment(2, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf2); - assert_eq!("00000", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-99.999").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf25); - assert_eq!("-100.00", dec.to_string()); - - let mut dec = FixedDecimal::from_str("1234.56").unwrap(); - dec.round_with_mode_and_increment(-1, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf2); - assert_eq!("1234.6", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0.009").unwrap(); - dec.round_with_mode_and_increment(-1, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf5); - assert_eq!("0.0", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0.60").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf25); - assert_eq!("0.50", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0.40").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf25); - assert_eq!("0.50", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0.7000000099").unwrap(); - dec.round_with_mode_and_increment(-3, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf2); - assert_eq!("0.700", dec.to_string()); - - let mut dec = FixedDecimal::from_str("5").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf25); - assert_eq!("0", dec.to_string()); - - let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MIN); + let mut dec = UnsignedFixedDecimal::from_str("0").unwrap(); dec.round_with_mode_and_increment( - i16::MIN, - RoundingMode::HalfEven, + 0, + UnsignedRoundingMode::Expand, RoundingIncrement::MultiplesOf2, ); - assert_eq!(FixedDecimal::from(8).multiplied_pow10(i16::MIN), dec); + assert_eq!("0", dec.to_string()); - let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MIN); + let mut dec = UnsignedFixedDecimal::from_str("0").unwrap(); dec.round_with_mode_and_increment( - i16::MIN, - RoundingMode::HalfEven, + 0, + UnsignedRoundingMode::Expand, RoundingIncrement::MultiplesOf5, ); - assert_eq!(FixedDecimal::from(10).multiplied_pow10(i16::MIN), dec); + assert_eq!("0", dec.to_string()); - let mut dec = FixedDecimal::from(70).multiplied_pow10(i16::MIN); + let mut dec = UnsignedFixedDecimal::from_str("0").unwrap(); dec.round_with_mode_and_increment( - i16::MIN, - RoundingMode::HalfEven, + 0, + UnsignedRoundingMode::Expand, RoundingIncrement::MultiplesOf25, ); - assert_eq!(FixedDecimal::from(75).multiplied_pow10(i16::MIN), dec); + assert_eq!("0", dec.to_string()); - let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX); + let mut dec = UnsignedFixedDecimal::from_str("0.1").unwrap(); dec.round_with_mode_and_increment( - i16::MAX, - RoundingMode::HalfEven, + 0, + UnsignedRoundingMode::Expand, RoundingIncrement::MultiplesOf2, ); - assert_eq!(FixedDecimal::from(8).multiplied_pow10(i16::MAX), dec); - - // Test specific cases - let mut dec = FixedDecimal::from_str("1.108").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::Expand, RoundingIncrement::MultiplesOf2); - assert_eq!("1.12", dec.to_string()); - - let mut dec = FixedDecimal::from_str("1.108").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::Expand, RoundingIncrement::MultiplesOf5); - assert_eq!("1.15", dec.to_string()); - - let mut dec = FixedDecimal::from_str("1.108").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::Expand, RoundingIncrement::MultiplesOf25); - assert_eq!("1.25", dec.to_string()); + assert_eq!("2", dec.to_string()); - let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MAX - 1); + let mut dec = UnsignedFixedDecimal::from_str("0.1").unwrap(); dec.round_with_mode_and_increment( - i16::MAX - 1, - RoundingMode::Expand, - RoundingIncrement::MultiplesOf25, + 0, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf5, ); - assert_eq!(FixedDecimal::from(25).multiplied_pow10(i16::MAX - 1), dec); + assert_eq!("5", dec.to_string()); - let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MAX); + let mut dec = UnsignedFixedDecimal::from_str("0.1").unwrap(); dec.round_with_mode_and_increment( - i16::MAX, - RoundingMode::Expand, + 0, + UnsignedRoundingMode::Expand, RoundingIncrement::MultiplesOf25, ); - assert_eq!(FixedDecimal::from(0).multiplied_pow10(i16::MAX), dec); - - let mut dec = FixedDecimal::from_str("0").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Expand, RoundingIncrement::MultiplesOf2); - assert_eq!("0", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Expand, RoundingIncrement::MultiplesOf5); - assert_eq!("0", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Expand, RoundingIncrement::MultiplesOf25); - assert_eq!("0", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0.1").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Expand, RoundingIncrement::MultiplesOf2); - assert_eq!("2", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0.1").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Expand, RoundingIncrement::MultiplesOf5); - assert_eq!("5", dec.to_string()); - - let mut dec = FixedDecimal::from_str("0.1").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Expand, RoundingIncrement::MultiplesOf25); assert_eq!("25", dec.to_string()); - let mut dec = FixedDecimal::from_str("1").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Expand, RoundingIncrement::MultiplesOf2); + let mut dec = UnsignedFixedDecimal::from_str("1").unwrap(); + dec.round_with_mode_and_increment( + 0, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("2", dec.to_string()); - let mut dec = FixedDecimal::from_str("1").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Expand, RoundingIncrement::MultiplesOf5); + let mut dec = UnsignedFixedDecimal::from_str("1").unwrap(); + dec.round_with_mode_and_increment( + 0, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf5, + ); assert_eq!("5", dec.to_string()); - let mut dec = FixedDecimal::from_str("1").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Expand, RoundingIncrement::MultiplesOf25); + let mut dec = UnsignedFixedDecimal::from_str("1").unwrap(); + dec.round_with_mode_and_increment( + 0, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf25, + ); assert_eq!("25", dec.to_string()); - let mut dec = FixedDecimal::from_str("2").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Expand, RoundingIncrement::MultiplesOf2); + let mut dec = UnsignedFixedDecimal::from_str("2").unwrap(); + dec.round_with_mode_and_increment( + 0, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("2", dec.to_string()); - let mut dec = FixedDecimal::from_str("2").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Expand, RoundingIncrement::MultiplesOf5); + let mut dec = UnsignedFixedDecimal::from_str("2").unwrap(); + dec.round_with_mode_and_increment( + 0, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf5, + ); assert_eq!("5", dec.to_string()); - let mut dec = FixedDecimal::from_str("2.1").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Expand, RoundingIncrement::MultiplesOf2); + let mut dec = UnsignedFixedDecimal::from_str("2.1").unwrap(); + dec.round_with_mode_and_increment( + 0, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("4", dec.to_string()); - let mut dec = FixedDecimal::from_str("2.1").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Expand, RoundingIncrement::MultiplesOf5); + let mut dec = UnsignedFixedDecimal::from_str("2.1").unwrap(); + dec.round_with_mode_and_increment( + 0, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf5, + ); assert_eq!("5", dec.to_string()); - let mut dec = FixedDecimal::from_str("4").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Expand, RoundingIncrement::MultiplesOf2); + let mut dec = UnsignedFixedDecimal::from_str("4").unwrap(); + dec.round_with_mode_and_increment( + 0, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("4", dec.to_string()); - let mut dec = FixedDecimal::from_str("4").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Expand, RoundingIncrement::MultiplesOf5); + let mut dec = UnsignedFixedDecimal::from_str("4").unwrap(); + dec.round_with_mode_and_increment( + 0, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf5, + ); assert_eq!("5", dec.to_string()); - let mut dec = FixedDecimal::from_str("4.1").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Expand, RoundingIncrement::MultiplesOf2); + let mut dec = UnsignedFixedDecimal::from_str("4.1").unwrap(); + dec.round_with_mode_and_increment( + 0, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("6", dec.to_string()); - let mut dec = FixedDecimal::from_str("4.1").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Expand, RoundingIncrement::MultiplesOf5); + let mut dec = UnsignedFixedDecimal::from_str("4.1").unwrap(); + dec.round_with_mode_and_increment( + 0, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf5, + ); assert_eq!("5", dec.to_string()); - let mut dec = FixedDecimal::from_str("5").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Expand, RoundingIncrement::MultiplesOf2); + let mut dec = UnsignedFixedDecimal::from_str("5").unwrap(); + dec.round_with_mode_and_increment( + 0, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("6", dec.to_string()); - let mut dec = FixedDecimal::from_str("5").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Expand, RoundingIncrement::MultiplesOf5); + let mut dec = UnsignedFixedDecimal::from_str("5").unwrap(); + dec.round_with_mode_and_increment( + 0, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf5, + ); assert_eq!("5", dec.to_string()); - let mut dec = FixedDecimal::from_str("5.1").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Expand, RoundingIncrement::MultiplesOf2); + let mut dec = UnsignedFixedDecimal::from_str("5.1").unwrap(); + dec.round_with_mode_and_increment( + 0, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("6", dec.to_string()); - let mut dec = FixedDecimal::from_str("5.1").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Expand, RoundingIncrement::MultiplesOf5); + let mut dec = UnsignedFixedDecimal::from_str("5.1").unwrap(); + dec.round_with_mode_and_increment( + 0, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf5, + ); assert_eq!("10", dec.to_string()); - let mut dec = FixedDecimal::from_str("6").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Expand, RoundingIncrement::MultiplesOf2); + let mut dec = UnsignedFixedDecimal::from_str("6").unwrap(); + dec.round_with_mode_and_increment( + 0, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("6", dec.to_string()); - let mut dec = FixedDecimal::from_str("6").unwrap(); - dec.round_with_mode_and_increment(0, RoundingMode::Expand, RoundingIncrement::MultiplesOf5); + let mut dec = UnsignedFixedDecimal::from_str("6").unwrap(); + dec.round_with_mode_and_increment( + 0, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf5, + ); assert_eq!("10", dec.to_string()); - let mut dec = FixedDecimal::from_str("0.50").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::Expand, RoundingIncrement::MultiplesOf25); + let mut dec = UnsignedFixedDecimal::from_str("0.50").unwrap(); + dec.round_with_mode_and_increment( + -2, + UnsignedRoundingMode::Expand, + RoundingIncrement::MultiplesOf25, + ); assert_eq!("0.50", dec.to_string()); - let mut dec = FixedDecimal::from_str("1.1025").unwrap(); - dec.round_with_mode_and_increment(-3, RoundingMode::HalfTrunc, RoundingIncrement::MultiplesOf5); + let mut dec = UnsignedFixedDecimal::from_str("1.1025").unwrap(); + dec.round_with_mode_and_increment( + -3, + UnsignedRoundingMode::HalfTrunc, + RoundingIncrement::MultiplesOf5, + ); assert_eq!("1.100", dec.to_string()); - let mut dec = FixedDecimal::from_str("1.10125").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("1.10125").unwrap(); dec.round_with_mode_and_increment( -4, - RoundingMode::HalfExpand, + UnsignedRoundingMode::HalfExpand, RoundingIncrement::MultiplesOf25, ); assert_eq!("1.1025", dec.to_string()); - let mut dec = FixedDecimal::from_str("-1.25").unwrap(); - dec.round_with_mode_and_increment(-1, RoundingMode::HalfCeil, RoundingIncrement::MultiplesOf5); - assert_eq!("-1.0", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-1.251").unwrap(); - dec.round_with_mode_and_increment(-1, RoundingMode::HalfCeil, RoundingIncrement::MultiplesOf5); - assert_eq!("-1.5", dec.to_string()); - - let mut dec = FixedDecimal::from_str("-1.125").unwrap(); + let mut dec = UnsignedFixedDecimal::from_str("2.71").unwrap(); dec.round_with_mode_and_increment( -2, - RoundingMode::HalfFloor, - RoundingIncrement::MultiplesOf25, + UnsignedRoundingMode::HalfEven, + RoundingIncrement::MultiplesOf2, ); - assert_eq!("-1.25", dec.to_string()); - - let mut dec = FixedDecimal::from_str("2.71").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf2); assert_eq!("2.72", dec.to_string()); - let mut dec = FixedDecimal::from_str("2.73").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf2); + let mut dec = UnsignedFixedDecimal::from_str("2.73").unwrap(); + dec.round_with_mode_and_increment( + -2, + UnsignedRoundingMode::HalfEven, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("2.72", dec.to_string()); - let mut dec = FixedDecimal::from_str("2.75").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf2); + let mut dec = UnsignedFixedDecimal::from_str("2.75").unwrap(); + dec.round_with_mode_and_increment( + -2, + UnsignedRoundingMode::HalfEven, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("2.76", dec.to_string()); - let mut dec = FixedDecimal::from_str("2.77").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf2); + let mut dec = UnsignedFixedDecimal::from_str("2.77").unwrap(); + dec.round_with_mode_and_increment( + -2, + UnsignedRoundingMode::HalfEven, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("2.76", dec.to_string()); - let mut dec = FixedDecimal::from_str("2.79").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf2); + let mut dec = UnsignedFixedDecimal::from_str("2.79").unwrap(); + dec.round_with_mode_and_increment( + -2, + UnsignedRoundingMode::HalfEven, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("2.80", dec.to_string()); - let mut dec = FixedDecimal::from_str("2.41").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf2); + let mut dec = UnsignedFixedDecimal::from_str("2.41").unwrap(); + dec.round_with_mode_and_increment( + -2, + UnsignedRoundingMode::HalfEven, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("2.40", dec.to_string()); - let mut dec = FixedDecimal::from_str("2.43").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf2); + let mut dec = UnsignedFixedDecimal::from_str("2.43").unwrap(); + dec.round_with_mode_and_increment( + -2, + UnsignedRoundingMode::HalfEven, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("2.44", dec.to_string()); - let mut dec = FixedDecimal::from_str("2.45").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf2); + let mut dec = UnsignedFixedDecimal::from_str("2.45").unwrap(); + dec.round_with_mode_and_increment( + -2, + UnsignedRoundingMode::HalfEven, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("2.44", dec.to_string()); - let mut dec = FixedDecimal::from_str("2.47").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf2); + let mut dec = UnsignedFixedDecimal::from_str("2.47").unwrap(); + dec.round_with_mode_and_increment( + -2, + UnsignedRoundingMode::HalfEven, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("2.48", dec.to_string()); - let mut dec = FixedDecimal::from_str("2.49").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf2); + let mut dec = UnsignedFixedDecimal::from_str("2.49").unwrap(); + dec.round_with_mode_and_increment( + -2, + UnsignedRoundingMode::HalfEven, + RoundingIncrement::MultiplesOf2, + ); assert_eq!("2.48", dec.to_string()); - let mut dec = FixedDecimal::from_str("2.725").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf5); + let mut dec = UnsignedFixedDecimal::from_str("2.725").unwrap(); + dec.round_with_mode_and_increment( + -2, + UnsignedRoundingMode::HalfEven, + RoundingIncrement::MultiplesOf5, + ); assert_eq!("2.70", dec.to_string()); - let mut dec = FixedDecimal::from_str("2.775").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf5); + let mut dec = UnsignedFixedDecimal::from_str("2.775").unwrap(); + dec.round_with_mode_and_increment( + -2, + UnsignedRoundingMode::HalfEven, + RoundingIncrement::MultiplesOf5, + ); assert_eq!("2.80", dec.to_string()); - let mut dec = FixedDecimal::from_str("2.875").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf25); + let mut dec = UnsignedFixedDecimal::from_str("2.875").unwrap(); + dec.round_with_mode_and_increment( + -2, + UnsignedRoundingMode::HalfEven, + RoundingIncrement::MultiplesOf25, + ); assert_eq!("3.00", dec.to_string()); - let mut dec = FixedDecimal::from_str("2.375").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf25); + let mut dec = UnsignedFixedDecimal::from_str("2.375").unwrap(); + dec.round_with_mode_and_increment( + -2, + UnsignedRoundingMode::HalfEven, + RoundingIncrement::MultiplesOf25, + ); assert_eq!("2.50", dec.to_string()); - let mut dec = FixedDecimal::from_str("2.125").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf25); + let mut dec = UnsignedFixedDecimal::from_str("2.125").unwrap(); + dec.round_with_mode_and_increment( + -2, + UnsignedRoundingMode::HalfEven, + RoundingIncrement::MultiplesOf25, + ); assert_eq!("2.00", dec.to_string()); - let mut dec = FixedDecimal::from_str("2.625").unwrap(); - dec.round_with_mode_and_increment(-2, RoundingMode::HalfEven, RoundingIncrement::MultiplesOf25); + let mut dec = UnsignedFixedDecimal::from_str("2.625").unwrap(); + dec.round_with_mode_and_increment( + -2, + UnsignedRoundingMode::HalfEven, + RoundingIncrement::MultiplesOf25, + ); assert_eq!("2.50", dec.to_string()); } diff --git a/utils/fixed_decimal/src/integer.rs b/utils/fixed_decimal/src/integer.rs index 98870d12dc3..4ffdd2a712c 100644 --- a/utils/fixed_decimal/src/integer.rs +++ b/utils/fixed_decimal/src/integer.rs @@ -7,42 +7,42 @@ use core::fmt; use core::str::FromStr; -use crate::FixedDecimal; use crate::LimitError; use crate::ParseError; +use crate::SignedFixedDecimal; -/// A [`FixedInteger`] is a [`FixedDecimal`] with no fractional part. +/// A [`FixedInteger`] is a [`SignedFixedDecimal`] with no fractional part. /// /// /// # Examples /// /// ``` /// # use std::str::FromStr; -/// use fixed_decimal::FixedDecimal; +/// use fixed_decimal::SignedFixedDecimal; /// use fixed_decimal::FixedInteger; /// use fixed_decimal::LimitError; /// /// assert_eq!( -/// FixedDecimal::from(FixedInteger::from(5)), -/// FixedDecimal::from(5) +/// SignedFixedDecimal::from(FixedInteger::from(5)), +/// SignedFixedDecimal::from(5) /// ); /// assert_eq!( -/// FixedInteger::try_from(FixedDecimal::from(5)), +/// FixedInteger::try_from(SignedFixedDecimal::from(5)), /// Ok(FixedInteger::from(5)) /// ); /// assert_eq!( -/// FixedInteger::try_from(FixedDecimal::from_str("05").unwrap()), +/// FixedInteger::try_from(SignedFixedDecimal::from_str("05").unwrap()), /// Ok(FixedInteger::from_str("05").unwrap()) /// ); /// assert_eq!( -/// FixedInteger::try_from(FixedDecimal::from_str("5.0").unwrap()), +/// FixedInteger::try_from(SignedFixedDecimal::from_str("5.0").unwrap()), /// Err(LimitError) /// ); /// ``` #[derive(Debug, Clone, PartialEq, Default)] -pub struct FixedInteger(FixedDecimal); +pub struct FixedInteger(SignedFixedDecimal); -impl From for FixedDecimal { +impl From for SignedFixedDecimal { fn from(value: FixedInteger) -> Self { value.0 } @@ -52,7 +52,7 @@ macro_rules! impl_fixed_integer_from_integer_type { ($type:ident) => { impl From<$type> for FixedInteger { fn from(value: $type) -> Self { - FixedInteger(FixedDecimal::from(value)) + FixedInteger(SignedFixedDecimal::from(value)) } } }; @@ -77,13 +77,13 @@ impl writeable::Writeable for FixedInteger { } } -impl TryFrom for FixedInteger { +impl TryFrom for FixedInteger { type Error = LimitError; - fn try_from(value: FixedDecimal) -> Result { - if value.magnitude_range().start() != &0 { + fn try_from(signed_fd: SignedFixedDecimal) -> Result { + if signed_fd.absolute.magnitude_range().start() != &0 { Err(LimitError) } else { - Ok(FixedInteger(value)) + Ok(FixedInteger(signed_fd)) } } } @@ -95,7 +95,7 @@ impl FixedInteger { } pub fn try_from_utf8(code_units: &[u8]) -> Result { - FixedInteger::try_from(FixedDecimal::try_from_utf8(code_units)?) + FixedInteger::try_from(SignedFixedDecimal::try_from_utf8(code_units)?) .map_err(|LimitError| ParseError::Limit) } } diff --git a/utils/fixed_decimal/src/lib.rs b/utils/fixed_decimal/src/lib.rs index d7c3a958abd..ae70deafc57 100644 --- a/utils/fixed_decimal/src/lib.rs +++ b/utils/fixed_decimal/src/lib.rs @@ -4,16 +4,16 @@ //! `fixed_decimal` is a utility crate of the [`ICU4X`] project. //! -//! It includes [`FixedDecimal`], a core API for representing numbers in a human-readable form -//! appropriate for formatting and plural rule selection. It is optimized for operations involving -//! the individual digits of a number. +//! This crate provides [`SignedFixedDecimal`] and [`UnsignedFixedDecimal`], essential APIs for representing numbers in a human-readable format. +//! These types are particularly useful for formatting and plural rule selection, and are optimized for operations on individual digits. //! //! # Examples //! //! ``` -//! use fixed_decimal::FixedDecimal; +//! use fixed_decimal::SignedFixedDecimal; //! -//! let dec = FixedDecimal::from(250).multiplied_pow10(-2); +//! let mut dec = SignedFixedDecimal::from(250); +//! dec.multiply_pow10(-2); //! assert_eq!("2.50", format!("{}", dec)); //! //! #[derive(Debug, PartialEq)] @@ -55,42 +55,54 @@ mod compact; mod decimal; mod integer; mod ops; +mod rounding; mod scientific; +mod signed_decimal; mod uint_iterator; +mod variations; #[cfg(feature = "ryu")] -pub use decimal::FloatPrecision; +pub use rounding::FloatPrecision; +// use variations::Signed; +// use variations::WithInfinity; +// use variations::WithNaN; #[cfg(feature = "ryu")] #[doc(no_inline)] pub use FloatPrecision as DoublePrecision; pub use compact::CompactDecimal; -pub use decimal::FixedDecimal; -pub use decimal::RoundingIncrement; -pub use decimal::RoundingMode; -pub use decimal::Sign; -pub use decimal::SignDisplay; +pub use decimal::UnsignedFixedDecimal; use displaydoc::Display; pub use integer::FixedInteger; +pub use rounding::RoundingIncrement; +pub use rounding::SignedRoundingMode; +pub use rounding::UnsignedRoundingMode; pub use scientific::ScientificDecimal; +pub use signed_decimal::SignedFixedDecimal; +pub use variations::Sign; +pub use variations::SignDisplay; +pub use variations::Signed; -/// The magnitude or number of digits exceeds the limit of the [`FixedDecimal`]. +pub(crate) use rounding::IncrementLike; +pub(crate) use rounding::NoIncrement; + +/// The magnitude or number of digits exceeds the limit of the [`UnsignedFixedDecimal`] or [`SignedFixedDecimal`]. /// /// The highest /// magnitude of the most significant digit is [`i16::MAX`], and the lowest magnitude of the /// least significant digit is [`i16::MIN`]. /// -/// This error is also returned when constructing a [`FixedInteger`] from a [`FixedDecimal`] with a +/// This error is also returned when constructing a [`FixedInteger`] from a [`SignedFixedDecimal`] with a /// fractional part. /// /// # Examples /// /// ``` -/// use fixed_decimal::FixedDecimal; +/// use fixed_decimal::SignedFixedDecimal; /// use fixed_decimal::LimitError; /// -/// let mut dec1 = FixedDecimal::from(123); +/// let mut dec1 = SignedFixedDecimal::from(123); /// dec1.multiply_pow10(i16::MAX); /// assert!(dec1.is_zero()); /// ``` @@ -119,3 +131,8 @@ pub enum ParseError { #[cfg(feature = "std")] impl std::error::Error for ParseError {} + +// TODO(#5065): implement these while `WithCompactExponent` and `WithScientificExponent` are implemented. +// pub type FixedDecimalOrInfinity = WithInfinity; +// pub type SignedFixedDecimalOrInfinity = Signed; +// pub type SignedFixedDecimalOrInfinityOrNan = WithNaN; diff --git a/utils/fixed_decimal/src/rounding.rs b/utils/fixed_decimal/src/rounding.rs new file mode 100644 index 00000000000..3ce02590abd --- /dev/null +++ b/utils/fixed_decimal/src/rounding.rs @@ -0,0 +1,174 @@ +// 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)] +pub(crate) struct NoIncrement; + +pub(crate) trait IncrementLike: Copy + Sized + PartialEq { + const MULTIPLES_OF_1: Option; + const MULTIPLES_OF_2: Option; + const MULTIPLES_OF_5: Option; + const MULTIPLES_OF_25: Option; +} + +impl IncrementLike for RoundingIncrement { + const MULTIPLES_OF_1: Option = Some(Self::MultiplesOf1); + + const MULTIPLES_OF_2: Option = Some(Self::MultiplesOf2); + + const MULTIPLES_OF_5: Option = Some(Self::MultiplesOf5); + + const MULTIPLES_OF_25: Option = Some(Self::MultiplesOf25); +} + +impl IncrementLike for NoIncrement { + const MULTIPLES_OF_1: Option = Some(Self); + + const MULTIPLES_OF_2: Option = None; + + const MULTIPLES_OF_5: Option = None; + + const MULTIPLES_OF_25: Option = None; +} + +/// Mode used in a unsigned rounding operations. +/// +/// # Comparative table of all the rounding modes, including the signed and unsigned ones. +/// +/// | 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 | " | +/// +/// NOTE: +/// - Ceil, Floor, HalfCeil and HalfFloor are part of the [`SignedRoundingMode`] enum. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +#[non_exhaustive] +pub enum UnsignedRoundingMode { + Expand, + Trunc, + HalfExpand, + HalfTrunc, + HalfEven, +} + +/// Mode used in a signed rounding operations. +/// +/// NOTE: +/// - You can find the comparative table of all the rounding modes in the [`UnsignedRoundingMode`] documentation. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +#[non_exhaustive] +pub enum SignedRoundingMode { + Unsigned(UnsignedRoundingMode), + Ceil, + Floor, + HalfCeil, + HalfFloor, +} + +/// Increment used in a rounding operation. +/// +/// Forces a rounding operation to round to only multiples of the specified increment. +/// +/// # Example +/// +/// ``` +/// use fixed_decimal::{SignedFixedDecimal, RoundingIncrement, SignedRoundingMode, UnsignedRoundingMode}; +/// use writeable::assert_writeable_eq; +/// # use std::str::FromStr; +/// let dec = SignedFixedDecimal::from_str("-7.266").unwrap(); +/// let mode = SignedRoundingMode::Unsigned(UnsignedRoundingMode::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, +} + +/// Specifies the precision of a floating point value when constructing a FixedDecimal. +/// +/// IEEE 754 is a representation of a point on the number line. On the other hand, FixedDecimal +/// specifies not only the point on the number line but also the precision of the number to a +/// specific power of 10. This enum augments a floating-point value with the additional +/// information required by FixedDecimal. +#[non_exhaustive] +#[cfg(feature = "ryu")] +#[derive(Debug, Clone, Copy)] +pub enum FloatPrecision { + /// Specify that the floating point number is integer-valued. + /// + /// If the floating point is not actually integer-valued, an error will be returned. + Integer, + + /// Specify that the floating point number is precise to a specific power of 10. + /// The number may be rounded or trailing zeros may be added as necessary. + Magnitude(i16), + + /// Specify that the floating point number is precise to a specific number of significant digits. + /// The number may be rounded or trailing zeros may be added as necessary. + /// + /// The number requested may not be zero + SignificantDigits(u8), + + /// Specify that the floating point number is precise to the maximum representable by IEEE. + /// + /// This results in a FixedDecimal having enough digits to recover the original floating point + /// value, with no trailing zeros. + RoundTrip, +} diff --git a/utils/fixed_decimal/src/scientific.rs b/utils/fixed_decimal/src/scientific.rs index efe53fcebf7..cdaf9fa627f 100644 --- a/utils/fixed_decimal/src/scientific.rs +++ b/utils/fixed_decimal/src/scientific.rs @@ -5,23 +5,23 @@ use core::fmt; use core::str::FromStr; -use crate::FixedDecimal; use crate::FixedInteger; use crate::ParseError; +use crate::SignedFixedDecimal; -/// A struct containing a [`FixedDecimal`] significand together with an exponent, representing a +/// A struct containing a [`SignedFixedDecimal`] significand together with an exponent, representing a /// number written in scientific notation, such as 1.729×10³. /// /// This structure represents any 0s shown in the significand and exponent, /// and an optional sign for both the significand and the exponent. #[derive(Debug, Clone, PartialEq)] pub struct ScientificDecimal { - significand: FixedDecimal, + significand: SignedFixedDecimal, exponent: FixedInteger, } impl ScientificDecimal { - pub fn from(significand: FixedDecimal, exponent: FixedInteger) -> Self { + pub fn from(significand: SignedFixedDecimal, exponent: FixedInteger) -> Self { ScientificDecimal { significand, exponent, @@ -35,7 +35,7 @@ impl ScientificDecimal { /// # Examples /// /// ``` -/// # use fixed_decimal::FixedDecimal; +/// # use fixed_decimal::SignedFixedDecimal; /// # use fixed_decimal::FixedInteger; /// # use fixed_decimal::ScientificDecimal; /// # use std::str::FromStr; @@ -43,14 +43,18 @@ impl ScientificDecimal { /// # /// assert_writeable_eq!( /// ScientificDecimal::from( -/// FixedDecimal::from(1729).multiplied_pow10(-3), +/// { +/// let mut dec = SignedFixedDecimal::from(1729u32); +/// dec.multiply_pow10(-3); +/// dec +/// }, /// FixedInteger::from(3) /// ), /// "1.729e3" /// ); /// assert_writeable_eq!( /// ScientificDecimal::from( -/// FixedDecimal::from_str("+1.729").unwrap(), +/// SignedFixedDecimal::from_str("+1.729").unwrap(), /// FixedInteger::from_str("+03").unwrap() /// ), /// "+1.729e+03" @@ -90,7 +94,7 @@ impl ScientificDecimal { return Err(ParseError::Syntax); } Ok(ScientificDecimal::from( - FixedDecimal::try_from_utf8(significand)?, + SignedFixedDecimal::try_from_utf8(significand)?, FixedInteger::try_from_utf8(exponent)?, )) } diff --git a/utils/fixed_decimal/src/signed_decimal.rs b/utils/fixed_decimal/src/signed_decimal.rs new file mode 100644 index 00000000000..b340f2672f3 --- /dev/null +++ b/utils/fixed_decimal/src/signed_decimal.rs @@ -0,0 +1,3977 @@ +// 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 ). + +use core::fmt; +use core::ops::{Deref, DerefMut}; +use core::str::FromStr; + +use crate::uint_iterator::IntIterator; +use crate::{variations::Signed, UnsignedFixedDecimal}; +#[cfg(feature = "ryu")] +use crate::{FloatPrecision, LimitError}; +use crate::{ + IncrementLike, NoIncrement, ParseError, RoundingIncrement, Sign, SignDisplay, + SignedRoundingMode, UnsignedRoundingMode, +}; + +/// A Type containing a [`UnsignedFixedDecimal`] and a [`Sign`] to represent a signed decimal number. +/// +/// Supports a mantissa of non-zero digits and a number of leading and trailing +/// zeros, as well as an optional sign; used for formatting and plural selection. +/// +/// # Data Types +/// +/// The following types can be converted to a `SignedFixedDecimal`: +/// +/// - Integers, signed and unsigned +/// - Strings representing an arbitrary-precision decimal +/// - Floating point values (using the `ryu` feature) +/// +/// To create a [`SignedFixedDecimal`] with fractional digits, you have several options: +/// - Create it from an integer and then call [`UnsignedFixedDecimal::multiply_pow10`] (you can also call `multiply_pow10` directly on the [`SignedFixedDecimal`]). +/// - Create it from a string. +/// - When the `ryu` feature is enabled, create it from a floating point value using [`SignedFixedDecimal::try_from_f64`]. +/// +/// # Examples +/// +/// ``` +/// use fixed_decimal::SignedFixedDecimal; +/// +/// let mut dec = SignedFixedDecimal::from(250); +/// assert_eq!("250", dec.to_string()); +/// +/// dec.multiply_pow10(-2); +/// assert_eq!("2.50", dec.to_string()); +/// ``` +pub type SignedFixedDecimal = Signed; + +impl SignedFixedDecimal { + pub fn new(sign: Sign, absolute: UnsignedFixedDecimal) -> Self { + SignedFixedDecimal { sign, absolute } + } + + #[inline] + /// Parses a [`SignedFixedDecimal`]. + pub fn try_from_str(s: &str) -> Result { + Self::try_from_utf8(s.as_bytes()) + } + + pub fn try_from_utf8(input_str: &[u8]) -> Result { + // input_str: the input string + // no_sign_str: the input string when the sign is removed from it + if input_str.is_empty() { + return Err(ParseError::Syntax); + } + #[allow(clippy::indexing_slicing)] // The string is not empty. + let sign = match input_str[0] { + b'-' => Sign::Negative, + b'+' => Sign::Positive, + _ => Sign::None, + }; + #[allow(clippy::indexing_slicing)] // The string is not empty. + let no_sign_str = if sign == Sign::None { + input_str + } else { + &input_str[1..] + }; + if no_sign_str.is_empty() { + return Err(ParseError::Syntax); + } + + let unsigned_decimal = UnsignedFixedDecimal::try_from_no_sign_utf8(no_sign_str)?; + Ok(Self { + sign, + absolute: unsigned_decimal, + }) + } + + // TODO: Shall we add this method to `Signed`? + /// Sets the sign of this number according to the given sign display strategy. + /// + /// # Examples + /// ``` + /// use fixed_decimal::SignedFixedDecimal; + /// use fixed_decimal::SignDisplay::*; + /// + /// let mut dec = SignedFixedDecimal::from(1729); + /// assert_eq!("1729", dec.to_string()); + /// dec.apply_sign_display(Always); + /// assert_eq!("+1729", dec.to_string()); + /// ``` + pub fn apply_sign_display(&mut self, sign_display: SignDisplay) { + use Sign::*; + match sign_display { + SignDisplay::Auto => { + if self.sign != Negative { + self.sign = None + } + } + SignDisplay::Always => { + if self.sign != Negative { + self.sign = Positive + } + } + SignDisplay::Never => self.sign = None, + SignDisplay::ExceptZero => { + if self.absolute.is_zero() { + self.sign = None + } else if self.sign != Negative { + self.sign = Positive + } + } + SignDisplay::Negative => { + if self.sign != Negative || self.absolute.is_zero() { + self.sign = None + } + } + } + } + + // TODO: Shall we add this method to `Signed`? + /// Returns this number with its sign set according to the given sign display strategy. + /// + /// # Examples + /// ``` + /// use fixed_decimal::SignedFixedDecimal; + /// use fixed_decimal::SignDisplay::*; + /// + /// assert_eq!( + /// "+1729", + /// SignedFixedDecimal::from(1729) + /// .with_sign_display(ExceptZero) + /// .to_string() + /// ); + /// ``` + pub fn with_sign_display(mut self, sign_display: SignDisplay) -> Self { + self.apply_sign_display(sign_display); + self + } +} + +impl FromStr for SignedFixedDecimal { + type Err = ParseError; + fn from_str(s: &str) -> Result { + Self::try_from_str(s) + } +} + +macro_rules! impl_from_signed_integer_type { + ($itype:ident, $utype: ident) => { + impl From<$itype> for SignedFixedDecimal { + fn from(value: $itype) -> Self { + let int_iterator: IntIterator<$utype> = value.into(); + let sign = if int_iterator.is_negative { + Sign::Negative + } else { + Sign::None + }; + let value = UnsignedFixedDecimal::from_ascending(int_iterator) + .expect("All built-in integer types should fit"); + SignedFixedDecimal { + sign, + absolute: value, + } + } + } + }; +} + +impl_from_signed_integer_type!(isize, usize); +impl_from_signed_integer_type!(i128, u128); +impl_from_signed_integer_type!(i64, u64); +impl_from_signed_integer_type!(i32, u32); +impl_from_signed_integer_type!(i16, u16); +impl_from_signed_integer_type!(i8, u8); + +macro_rules! impl_from_unsigned_integer_type { + ($utype: ident) => { + impl From<$utype> for SignedFixedDecimal { + fn from(value: $utype) -> Self { + let int_iterator: IntIterator<$utype> = value.into(); + Self { + sign: Sign::None, + absolute: UnsignedFixedDecimal::from_ascending(int_iterator) + .expect("All built-in integer types should fit"), + } + } + } + }; +} + +impl_from_unsigned_integer_type!(usize); +impl_from_unsigned_integer_type!(u128); +impl_from_unsigned_integer_type!(u64); +impl_from_unsigned_integer_type!(u32); +impl_from_unsigned_integer_type!(u16); +impl_from_unsigned_integer_type!(u8); + +#[cfg(feature = "ryu")] +impl SignedFixedDecimal { + /// Constructs a [`SignedFixedDecimal`] from an f64. + /// + /// Since f64 values do not carry a notion of their precision, the second argument to this + /// function specifies the type of precision associated with the f64. For more information, + /// see [`FloatPrecision`]. + /// + /// This function uses `ryu`, which is an efficient double-to-string algorithm, but other + /// implementations may yield higher performance; for more details, see + /// [icu4x#166](https://github.com/unicode-org/icu4x/issues/166). + /// + /// This function can be made available with the `"ryu"` Cargo feature. + /// + /// ```rust + /// use fixed_decimal::{SignedFixedDecimal, FloatPrecision}; + /// use writeable::assert_writeable_eq; + /// + /// let decimal = + /// SignedFixedDecimal::try_from_f64(-5.1, FloatPrecision::Magnitude(-2)) + /// .expect("Finite quantity with limited precision"); + /// assert_writeable_eq!(decimal, "-5.10"); + /// + /// let decimal = + /// SignedFixedDecimal::try_from_f64(0.012345678, FloatPrecision::RoundTrip) + /// .expect("Finite quantity"); + /// assert_writeable_eq!(decimal, "0.012345678"); + /// + /// let decimal = + /// SignedFixedDecimal::try_from_f64(12345678000., FloatPrecision::Integer) + /// .expect("Finite, integer-valued quantity"); + /// assert_writeable_eq!(decimal, "12345678000"); + /// ``` + /// + /// Negative zero is supported. + /// + /// ```rust + /// use fixed_decimal::{SignedFixedDecimal, FloatPrecision}; + /// use writeable::assert_writeable_eq; + /// + /// // IEEE 754 for floating point defines the sign bit separate + /// // from the mantissa and exponent, allowing for -0. + /// let negative_zero = + /// SignedFixedDecimal::try_from_f64(-0.0, FloatPrecision::Integer) + /// .expect("Negative zero"); + /// assert_writeable_eq!(negative_zero, "-0"); + /// ``` + pub fn try_from_f64(float: f64, precision: FloatPrecision) -> Result { + match float.is_sign_negative() { + true => Ok(SignedFixedDecimal { + sign: Sign::Negative, + absolute: UnsignedFixedDecimal::try_from_f64(-float, precision)?, + }), + false => Ok(SignedFixedDecimal { + sign: Sign::None, + absolute: UnsignedFixedDecimal::try_from_f64(float, precision)?, + }), + } + } +} + +impl Deref for SignedFixedDecimal { + type Target = UnsignedFixedDecimal; + fn deref(&self) -> &Self::Target { + &self.absolute + } +} + +impl DerefMut for SignedFixedDecimal { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.absolute + } +} + +/// All the rounding and rounding related logic is implmented in this implmentation block. +impl SignedFixedDecimal { + /// Rounds this number at a particular digit position. + /// + /// This uses half to even rounding, which rounds to the nearest integer and resolves ties by + /// selecting the nearest even integer to the original value. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::SignedFixedDecimal; + /// # use std::str::FromStr; + /// + /// let mut dec = SignedFixedDecimal::from_str("-1.5").unwrap(); + /// dec.round(0); + /// assert_eq!("-2", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("0.4").unwrap(); + /// dec.round(0); + /// assert_eq!("0", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("0.5").unwrap(); + /// dec.round(0); + /// assert_eq!("0", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("0.6").unwrap(); + /// dec.round(0); + /// assert_eq!("1", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("1.5").unwrap(); + /// dec.round(0); + /// assert_eq!("2", dec.to_string()); + /// ``` + pub fn round(&mut self, position: i16) { + self.half_even_to_increment_internal(position, NoIncrement) + } + + /// Returns this number rounded at a particular digit position. + /// + /// This uses half to even rounding by default, which rounds to the nearest integer and + /// resolves ties by selecting the nearest even integer to the original value. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::SignedFixedDecimal; + /// # use std::str::FromStr; + /// + /// let mut dec = SignedFixedDecimal::from_str("-1.5").unwrap(); + /// assert_eq!("-2", dec.rounded(0).to_string()); + /// let mut dec = SignedFixedDecimal::from_str("0.4").unwrap(); + /// assert_eq!("0", dec.rounded(0).to_string()); + /// let mut dec = SignedFixedDecimal::from_str("0.5").unwrap(); + /// assert_eq!("0", dec.rounded(0).to_string()); + /// let mut dec = SignedFixedDecimal::from_str("0.6").unwrap(); + /// assert_eq!("1", dec.rounded(0).to_string()); + /// let mut dec = SignedFixedDecimal::from_str("1.5").unwrap(); + /// assert_eq!("2", dec.rounded(0).to_string()); + /// ``` + pub fn rounded(mut self, position: i16) -> Self { + self.round(position); + self + } + + /// Rounds this number towards positive infinity at a particular digit position. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::SignedFixedDecimal; + /// # use std::str::FromStr; + /// + /// let mut dec = SignedFixedDecimal::from_str("-1.5").unwrap(); + /// dec.ceil(0); + /// assert_eq!("-1", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("0.4").unwrap(); + /// dec.ceil(0); + /// assert_eq!("1", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("0.5").unwrap(); + /// dec.ceil(0); + /// assert_eq!("1", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("0.6").unwrap(); + /// dec.ceil(0); + /// assert_eq!("1", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("1.5").unwrap(); + /// dec.ceil(0); + /// assert_eq!("2", dec.to_string()); + /// ``` + #[inline(never)] + pub fn ceil(&mut self, position: i16) { + self.ceil_to_increment_internal(position, NoIncrement); + } + + /// Returns this number rounded towards positive infinity at a particular digit position. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::SignedFixedDecimal; + /// # use std::str::FromStr; + /// + /// let dec = SignedFixedDecimal::from_str("-1.5").unwrap(); + /// assert_eq!("-1", dec.ceiled(0).to_string()); + /// let dec = SignedFixedDecimal::from_str("0.4").unwrap(); + /// assert_eq!("1", dec.ceiled(0).to_string()); + /// let dec = SignedFixedDecimal::from_str("0.5").unwrap(); + /// assert_eq!("1", dec.ceiled(0).to_string()); + /// let dec = SignedFixedDecimal::from_str("0.6").unwrap(); + /// assert_eq!("1", dec.ceiled(0).to_string()); + /// let dec = SignedFixedDecimal::from_str("1.5").unwrap(); + /// assert_eq!("2", dec.ceiled(0).to_string()); + /// ``` + pub fn ceiled(mut self, position: i16) -> Self { + self.ceil(position); + self + } + + /// Rounds this number away from zero at a particular digit position. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::SignedFixedDecimal; + /// # use std::str::FromStr; + /// + /// let mut dec = SignedFixedDecimal::from_str("-1.5").unwrap(); + /// dec.expand(0); + /// assert_eq!("-2", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("0.4").unwrap(); + /// dec.expand(0); + /// assert_eq!("1", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("0.5").unwrap(); + /// dec.expand(0); + /// assert_eq!("1", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("0.6").unwrap(); + /// dec.expand(0); + /// assert_eq!("1", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("1.5").unwrap(); + /// dec.expand(0); + /// assert_eq!("2", dec.to_string()); + /// ``` + #[inline(never)] + pub fn expand(&mut self, position: i16) { + self.expand_to_increment_internal(position, NoIncrement) + } + + /// Returns this number rounded away from zero at a particular digit position. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::SignedFixedDecimal; + /// # use std::str::FromStr; + /// + /// let dec = SignedFixedDecimal::from_str("-1.5").unwrap(); + /// assert_eq!("-2", dec.expanded(0).to_string()); + /// let dec = SignedFixedDecimal::from_str("0.4").unwrap(); + /// assert_eq!("1", dec.expanded(0).to_string()); + /// let dec = SignedFixedDecimal::from_str("0.5").unwrap(); + /// assert_eq!("1", dec.expanded(0).to_string()); + /// let dec = SignedFixedDecimal::from_str("0.6").unwrap(); + /// assert_eq!("1", dec.expanded(0).to_string()); + /// let dec = SignedFixedDecimal::from_str("1.5").unwrap(); + /// assert_eq!("2", dec.expanded(0).to_string()); + /// ``` + pub fn expanded(mut self, position: i16) -> Self { + self.expand(position); + self + } + + /// Rounds this number towards negative infinity at a particular digit position. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::SignedFixedDecimal; + /// # use std::str::FromStr; + /// + /// let mut dec = SignedFixedDecimal::from_str("-1.5").unwrap(); + /// dec.floor(0); + /// assert_eq!("-2", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("0.4").unwrap(); + /// dec.floor(0); + /// assert_eq!("0", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("0.5").unwrap(); + /// dec.floor(0); + /// assert_eq!("0", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("0.6").unwrap(); + /// dec.floor(0); + /// assert_eq!("0", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("1.5").unwrap(); + /// dec.floor(0); + /// assert_eq!("1", dec.to_string()); + /// ``` + #[inline(never)] + pub fn floor(&mut self, position: i16) { + self.floor_to_increment_internal(position, NoIncrement); + } + + /// Returns this number rounded towards negative infinity at a particular digit position. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::SignedFixedDecimal; + /// # use std::str::FromStr; + /// + /// let dec = SignedFixedDecimal::from_str("-1.5").unwrap(); + /// assert_eq!("-2", dec.floored(0).to_string()); + /// let dec = SignedFixedDecimal::from_str("0.4").unwrap(); + /// assert_eq!("0", dec.floored(0).to_string()); + /// let dec = SignedFixedDecimal::from_str("0.5").unwrap(); + /// assert_eq!("0", dec.floored(0).to_string()); + /// let dec = SignedFixedDecimal::from_str("0.6").unwrap(); + /// assert_eq!("0", dec.floored(0).to_string()); + /// let dec = SignedFixedDecimal::from_str("1.5").unwrap(); + /// assert_eq!("1", dec.floored(0).to_string()); + /// ``` + pub fn floored(mut self, position: i16) -> Self { + self.floor(position); + self + } + + /// Rounds this number towards zero at a particular digit position. + /// + /// Also see [`UnsignedFixedDecimal::pad_end()`]. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::SignedFixedDecimal; + /// # use std::str::FromStr; + /// + /// let mut dec = SignedFixedDecimal::from_str("-1.5").unwrap(); + /// dec.trunc(0); + /// assert_eq!("-1", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("0.4").unwrap(); + /// dec.trunc(0); + /// assert_eq!("0", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("0.5").unwrap(); + /// dec.trunc(0); + /// assert_eq!("0", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("0.6").unwrap(); + /// dec.trunc(0); + /// assert_eq!("0", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("1.5").unwrap(); + /// dec.trunc(0); + /// assert_eq!("1", dec.to_string()); + /// ``` + #[inline(never)] + pub fn trunc(&mut self, position: i16) { + self.trunc_to_increment_internal(position, NoIncrement) + } + + /// Returns this number rounded towards zero at a particular digit position. + /// + /// Also see [`UnsignedFixedDecimal::padded_end()`]. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::SignedFixedDecimal; + /// # use std::str::FromStr; + /// + /// let dec = SignedFixedDecimal::from_str("-1.5").unwrap(); + /// assert_eq!("-1", dec.trunced(0).to_string()); + /// let dec = SignedFixedDecimal::from_str("0.4").unwrap(); + /// assert_eq!("0", dec.trunced(0).to_string()); + /// let dec = SignedFixedDecimal::from_str("0.5").unwrap(); + /// assert_eq!("0", dec.trunced(0).to_string()); + /// let dec = SignedFixedDecimal::from_str("0.6").unwrap(); + /// assert_eq!("0", dec.trunced(0).to_string()); + /// let dec = SignedFixedDecimal::from_str("1.5").unwrap(); + /// assert_eq!("1", dec.trunced(0).to_string()); + /// ``` + pub fn trunced(mut self, position: i16) -> Self { + self.trunc(position); + self + } + + /// Rounds this number at a particular digit position, using the specified rounding mode. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::{SignedFixedDecimal, SignedRoundingMode, UnsignedRoundingMode}; + /// # use std::str::FromStr; + /// + /// let mut dec = SignedFixedDecimal::from_str("-3.5").unwrap(); + /// dec.round_with_mode(0, SignedRoundingMode::Floor); + /// assert_eq!("-4", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("-3.5").unwrap(); + /// dec.round_with_mode(0, SignedRoundingMode::Ceil); + /// assert_eq!("-3", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("5.455").unwrap(); + /// dec.round_with_mode(-2, SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand)); + /// assert_eq!("5.46", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("-7.235").unwrap(); + /// dec.round_with_mode(-2, SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc)); + /// assert_eq!("-7.23", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("9.75").unwrap(); + /// dec.round_with_mode(-1, SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven)); + /// assert_eq!("9.8", dec.to_string()); + /// ``` + pub fn round_with_mode(&mut self, position: i16, mode: SignedRoundingMode) { + match mode { + SignedRoundingMode::Ceil => self.ceil_to_increment_internal(position, NoIncrement), + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand) => { + self.expand_to_increment_internal(position, NoIncrement) + } + SignedRoundingMode::Floor => self.floor_to_increment_internal(position, NoIncrement), + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Trunc) => { + self.trunc_to_increment_internal(position, NoIncrement) + } + SignedRoundingMode::HalfCeil => { + self.half_ceil_to_increment_internal(position, NoIncrement) + } + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand) => { + self.half_expand_to_increment_internal(position, NoIncrement) + } + SignedRoundingMode::HalfFloor => { + self.half_floor_to_increment_internal(position, NoIncrement) + } + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc) => { + self.half_trunc_to_increment_internal(position, NoIncrement) + } + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven) => { + self.half_even_to_increment_internal(position, NoIncrement) + } + } + } + + /// Returns this number rounded at a particular digit position, using the specified rounding mode. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::{SignedFixedDecimal, SignedRoundingMode, UnsignedRoundingMode}; + /// # use std::str::FromStr; + /// + /// let mut dec = SignedFixedDecimal::from_str("-3.5").unwrap(); + /// assert_eq!( + /// "-4", + /// dec.rounded_with_mode(0, SignedRoundingMode::Floor).to_string() + /// ); + /// let mut dec = SignedFixedDecimal::from_str("-3.5").unwrap(); + /// assert_eq!( + /// "-3", + /// dec.rounded_with_mode(0, SignedRoundingMode::Ceil).to_string() + /// ); + /// let mut dec = SignedFixedDecimal::from_str("5.455").unwrap(); + /// assert_eq!( + /// "5.46", + /// dec.rounded_with_mode(-2, SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand)) + /// .to_string() + /// ); + /// let mut dec = SignedFixedDecimal::from_str("-7.235").unwrap(); + /// assert_eq!( + /// "-7.23", + /// dec.rounded_with_mode(-2, SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc)) + /// .to_string() + /// ); + /// let mut dec = SignedFixedDecimal::from_str("9.75").unwrap(); + /// assert_eq!( + /// "9.8", + /// dec.rounded_with_mode(-1, SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven)) + /// .to_string() + /// ); + /// ``` + pub fn rounded_with_mode(mut self, position: i16, mode: SignedRoundingMode) -> Self { + self.round_with_mode(position, mode); + self + } + + /// Rounds this number at a particular digit position and increment, using the specified rounding mode. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::{SignedFixedDecimal, RoundingIncrement, SignedRoundingMode, UnsignedRoundingMode}; + /// # use std::str::FromStr; + /// + /// let mut dec = SignedFixedDecimal::from_str("-3.5").unwrap(); + /// dec.round_with_mode_and_increment( + /// 0, + /// SignedRoundingMode::Floor, + /// RoundingIncrement::MultiplesOf1, + /// ); + /// assert_eq!("-4", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("-3.59").unwrap(); + /// dec.round_with_mode_and_increment( + /// -1, + /// SignedRoundingMode::Ceil, + /// RoundingIncrement::MultiplesOf2, + /// ); + /// assert_eq!("-3.4", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("5.455").unwrap(); + /// dec.round_with_mode_and_increment( + /// -2, + /// SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + /// RoundingIncrement::MultiplesOf5, + /// ); + /// assert_eq!("5.45", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("-7.235").unwrap(); + /// dec.round_with_mode_and_increment( + /// -2, + /// SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc), + /// RoundingIncrement::MultiplesOf25, + /// ); + /// assert_eq!("-7.25", dec.to_string()); + /// let mut dec = SignedFixedDecimal::from_str("9.75").unwrap(); + /// dec.round_with_mode_and_increment( + /// -1, + /// SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + /// RoundingIncrement::MultiplesOf5, + /// ); + /// assert_eq!("10.0", dec.to_string()); + /// ``` + pub fn round_with_mode_and_increment( + &mut self, + position: i16, + mode: SignedRoundingMode, + increment: RoundingIncrement, + ) { + match mode { + SignedRoundingMode::Ceil => self.ceil_to_increment_internal(position, increment), + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand) => { + self.expand_to_increment_internal(position, increment) + } + SignedRoundingMode::Floor => self.floor_to_increment_internal(position, increment), + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Trunc) => { + self.trunc_to_increment_internal(position, increment) + } + SignedRoundingMode::HalfCeil => { + self.half_ceil_to_increment_internal(position, increment) + } + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand) => { + self.half_expand_to_increment_internal(position, increment) + } + SignedRoundingMode::HalfFloor => { + self.half_floor_to_increment_internal(position, increment) + } + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc) => { + self.half_trunc_to_increment_internal(position, increment) + } + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven) => { + self.half_even_to_increment_internal(position, increment) + } + } + } + + /// Returns this number rounded at a particular digit position and increment, using the specified rounding mode. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::{SignedFixedDecimal, RoundingIncrement, SignedRoundingMode, UnsignedRoundingMode}; + /// # use std::str::FromStr; + /// + /// let mut dec = SignedFixedDecimal::from_str("-3.5").unwrap(); + /// assert_eq!( + /// "-4", + /// dec.rounded_with_mode_and_increment( + /// 0, + /// SignedRoundingMode::Floor, + /// RoundingIncrement::MultiplesOf1 + /// ) + /// .to_string() + /// ); + /// let mut dec = SignedFixedDecimal::from_str("-3.59").unwrap(); + /// assert_eq!( + /// "-3.4", + /// dec.rounded_with_mode_and_increment( + /// -1, + /// SignedRoundingMode::Ceil, + /// RoundingIncrement::MultiplesOf2 + /// ) + /// .to_string() + /// ); + /// let mut dec = SignedFixedDecimal::from_str("5.455").unwrap(); + /// assert_eq!( + /// "5.45", + /// dec.rounded_with_mode_and_increment( + /// -2, + /// SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + /// RoundingIncrement::MultiplesOf5 + /// ) + /// .to_string() + /// ); + /// let mut dec = SignedFixedDecimal::from_str("-7.235").unwrap(); + /// assert_eq!( + /// "-7.25", + /// dec.rounded_with_mode_and_increment( + /// -2, + /// SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc), + /// RoundingIncrement::MultiplesOf25 + /// ) + /// .to_string() + /// ); + /// let mut dec = SignedFixedDecimal::from_str("9.75").unwrap(); + /// assert_eq!( + /// "10.0", + /// dec.rounded_with_mode_and_increment( + /// -1, + /// SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + /// RoundingIncrement::MultiplesOf5 + /// ) + /// .to_string() + /// ); + /// ``` + pub fn rounded_with_mode_and_increment( + mut self, + position: i16, + mode: SignedRoundingMode, + increment: RoundingIncrement, + ) -> Self { + self.round_with_mode_and_increment(position, mode, increment); + self + } + + fn ceil_to_increment_internal(&mut self, position: i16, increment: R) { + if self.sign == Sign::Negative { + self.trunc_to_increment_internal(position, increment); + return; + } + + self.expand_to_increment_internal(position, increment); + } + + fn half_ceil_to_increment_internal(&mut self, position: i16, increment: R) { + if self.sign == Sign::Negative { + self.half_trunc_to_increment_internal(position, increment); + return; + } + + self.half_expand_to_increment_internal(position, increment); + } + + fn floor_to_increment_internal(&mut self, position: i16, increment: R) { + if self.sign == Sign::Negative { + self.expand_to_increment_internal(position, increment); + return; + } + + self.trunc_to_increment_internal(position, increment); + } + + fn half_floor_to_increment_internal(&mut self, position: i16, increment: R) { + if self.sign == Sign::Negative { + self.half_expand_to_increment_internal(position, increment); + return; + } + + self.half_trunc_to_increment_internal(position, increment); + } +} + +/// Render the [`SignedFixedDecimal`] as a string of ASCII digits with a possible decimal point. +/// +/// # Examples +/// +/// ``` +/// # use fixed_decimal::SignedFixedDecimal; +/// # use writeable::assert_writeable_eq; +/// # +/// assert_writeable_eq!(SignedFixedDecimal::from(42), "42"); +/// ``` +impl writeable::Writeable for SignedFixedDecimal { + fn write_to(&self, sink: &mut W) -> fmt::Result { + match self.sign { + Sign::Negative => sink.write_char('-')?, + Sign::Positive => sink.write_char('+')?, + Sign::None => (), + } + for m in self.absolute.magnitude_range().rev() { + if m == -1 { + sink.write_char('.')?; + } + let d = self.absolute.digit_at(m); + sink.write_char((b'0' + d) as char)?; + } + Ok(()) + } + + fn writeable_length_hint(&self) -> writeable::LengthHint { + self.absolute.writeable_length_hint() + (self.sign != Sign::None) as usize + } +} + +writeable::impl_display_with_writeable!(SignedFixedDecimal); + +#[test] +fn test_basic() { + #[derive(Debug)] + struct TestCase { + pub input: isize, + pub delta: i16, + pub expected: &'static str, + } + let cases = [ + TestCase { + input: 51423, + delta: 0, + expected: "51423", + }, + TestCase { + input: 51423, + delta: -2, + expected: "514.23", + }, + TestCase { + input: 51423, + delta: -5, + expected: "0.51423", + }, + TestCase { + input: 51423, + delta: -8, + expected: "0.00051423", + }, + TestCase { + input: 51423, + delta: 3, + expected: "51423000", + }, + TestCase { + input: 0, + delta: 0, + expected: "0", + }, + TestCase { + input: 0, + delta: -2, + expected: "0.00", + }, + TestCase { + input: 0, + delta: 3, + expected: "0000", + }, + TestCase { + input: 500, + delta: 0, + expected: "500", + }, + TestCase { + input: 500, + delta: -1, + expected: "50.0", + }, + TestCase { + input: 500, + delta: -2, + expected: "5.00", + }, + TestCase { + input: 500, + delta: -3, + expected: "0.500", + }, + TestCase { + input: 500, + delta: -4, + expected: "0.0500", + }, + TestCase { + input: 500, + delta: 3, + expected: "500000", + }, + TestCase { + input: -123, + delta: 0, + expected: "-123", + }, + TestCase { + input: -123, + delta: -2, + expected: "-1.23", + }, + TestCase { + input: -123, + delta: -5, + expected: "-0.00123", + }, + TestCase { + input: -123, + delta: 3, + expected: "-123000", + }, + ]; + for cas in &cases { + let mut dec: SignedFixedDecimal = cas.input.into(); + // println!("{}", cas.input + 0.01); + dec.absolute.multiply_pow10(cas.delta); + writeable::assert_writeable_eq!(dec, cas.expected, "{:?}", cas); + } +} + +#[test] +fn test_from_str() { + #[derive(Debug)] + struct TestCase { + pub input_str: &'static str, + /// The output str, `None` for roundtrip + pub output_str: Option<&'static str>, + /// [upper magnitude, upper nonzero magnitude, lower nonzero magnitude, lower magnitude] + pub magnitudes: [i16; 4], + } + let cases = [ + TestCase { + input_str: "-00123400", + output_str: None, + magnitudes: [7, 5, 2, 0], + }, + TestCase { + input_str: "+00123400", + output_str: None, + magnitudes: [7, 5, 2, 0], + }, + TestCase { + input_str: "0.0123400", + output_str: None, + magnitudes: [0, -2, -5, -7], + }, + TestCase { + input_str: "-00.123400", + output_str: None, + magnitudes: [1, -1, -4, -6], + }, + TestCase { + input_str: "0012.3400", + output_str: None, + magnitudes: [3, 1, -2, -4], + }, + TestCase { + input_str: "-0012340.0", + output_str: None, + magnitudes: [6, 4, 1, -1], + }, + TestCase { + input_str: "1234", + output_str: None, + magnitudes: [3, 3, 0, 0], + }, + TestCase { + input_str: "0.000000001", + output_str: None, + magnitudes: [0, -9, -9, -9], + }, + TestCase { + input_str: "0.0000000010", + output_str: None, + magnitudes: [0, -9, -9, -10], + }, + TestCase { + input_str: "1000000", + output_str: None, + magnitudes: [6, 6, 6, 0], + }, + TestCase { + input_str: "10000001", + output_str: None, + magnitudes: [7, 7, 0, 0], + }, + TestCase { + input_str: "123", + output_str: None, + magnitudes: [2, 2, 0, 0], + }, + TestCase { + input_str: "922337203685477580898230948203840239384.9823094820384023938423424", + output_str: None, + magnitudes: [38, 38, -25, -25], + }, + TestCase { + input_str: "009223372000.003685477580898230948203840239384000", + output_str: None, + magnitudes: [11, 9, -33, -36], + }, + TestCase { + input_str: "-009223372000.003685477580898230948203840239384000", + output_str: None, + magnitudes: [11, 9, -33, -36], + }, + TestCase { + input_str: "0", + output_str: None, + magnitudes: [0, 0, 0, 0], + }, + TestCase { + input_str: "-0", + output_str: None, + magnitudes: [0, 0, 0, 0], + }, + TestCase { + input_str: "+0", + output_str: None, + magnitudes: [0, 0, 0, 0], + }, + TestCase { + input_str: "000", + output_str: None, + magnitudes: [2, 0, 0, 0], + }, + TestCase { + input_str: "-00.0", + output_str: None, + magnitudes: [1, 0, 0, -1], + }, + // no leading 0 parsing + TestCase { + input_str: ".0123400", + output_str: Some("0.0123400"), + magnitudes: [0, -2, -5, -7], + }, + TestCase { + input_str: ".000000001", + output_str: Some("0.000000001"), + magnitudes: [0, -9, -9, -9], + }, + TestCase { + input_str: "-.123400", + output_str: Some("-0.123400"), + magnitudes: [0, -1, -4, -6], + }, + ]; + for cas in &cases { + let fd = SignedFixedDecimal::from_str(cas.input_str).unwrap(); + assert_eq!( + fd.absolute.magnitude_range(), + cas.magnitudes[3]..=cas.magnitudes[0], + "{cas:?}" + ); + assert_eq!( + fd.absolute.nonzero_magnitude_start(), + cas.magnitudes[1], + "{cas:?}" + ); + assert_eq!( + fd.absolute.nonzero_magnitude_end(), + cas.magnitudes[2], + "{cas:?}" + ); + let input_str_roundtrip = fd.to_string(); + let output_str = cas.output_str.unwrap_or(cas.input_str); + assert_eq!(output_str, input_str_roundtrip, "{cas:?}"); + } +} + +#[test] +fn test_from_str_scientific() { + #[derive(Debug)] + struct TestCase { + pub input_str: &'static str, + pub output: &'static str, + } + let cases = [ + TestCase { + input_str: "-5.4e10", + output: "-54000000000", + }, + TestCase { + input_str: "5.4e-2", + output: "0.054", + }, + TestCase { + input_str: "54.1e-2", + output: "0.541", + }, + TestCase { + input_str: "-541e-2", + output: "-5.41", + }, + TestCase { + input_str: "0.009E10", + output: "90000000", + }, + TestCase { + input_str: "-9000E-10", + output: "-0.0000009", + }, + ]; + for cas in &cases { + let input_str_roundtrip = SignedFixedDecimal::from_str(cas.input_str) + .unwrap() + .to_string(); + assert_eq!(cas.output, input_str_roundtrip); + } +} + +#[test] +fn test_isize_limits() { + for num in &[isize::MAX, isize::MIN] { + let dec: SignedFixedDecimal = (*num).into(); + let dec_str = dec.to_string(); + assert_eq!(num.to_string(), dec_str); + assert_eq!(dec, SignedFixedDecimal::from_str(&dec_str).unwrap()); + writeable::assert_writeable_eq!(dec, dec_str); + } +} + +#[test] +fn test_ui128_limits() { + for num in &[i128::MAX, i128::MIN] { + let dec: SignedFixedDecimal = (*num).into(); + let dec_str = dec.to_string(); + assert_eq!(num.to_string(), dec_str); + assert_eq!(dec, SignedFixedDecimal::from_str(&dec_str).unwrap()); + writeable::assert_writeable_eq!(dec, dec_str); + } + for num in &[u128::MAX, u128::MIN] { + let dec: SignedFixedDecimal = (*num).into(); + let dec_str = dec.to_string(); + assert_eq!(num.to_string(), dec_str); + assert_eq!(dec, SignedFixedDecimal::from_str(&dec_str).unwrap()); + writeable::assert_writeable_eq!(dec, dec_str); + } +} + +#[test] +fn test_zero_str_bounds() { + #[derive(Debug)] + struct TestCase { + pub zeros_before_dot: usize, + pub zeros_after_dot: usize, + pub expected_err: Option, + } + let cases = [ + TestCase { + zeros_before_dot: i16::MAX as usize + 1, + zeros_after_dot: 0, + expected_err: None, + }, + TestCase { + zeros_before_dot: i16::MAX as usize, + zeros_after_dot: 0, + expected_err: None, + }, + TestCase { + zeros_before_dot: i16::MAX as usize + 2, + zeros_after_dot: 0, + expected_err: Some(ParseError::Limit), + }, + TestCase { + zeros_before_dot: 0, + zeros_after_dot: i16::MAX as usize + 2, + expected_err: Some(ParseError::Limit), + }, + TestCase { + zeros_before_dot: i16::MAX as usize + 1, + zeros_after_dot: i16::MAX as usize + 1, + expected_err: None, + }, + TestCase { + zeros_before_dot: i16::MAX as usize + 2, + zeros_after_dot: i16::MAX as usize + 1, + expected_err: Some(ParseError::Limit), + }, + TestCase { + zeros_before_dot: i16::MAX as usize + 1, + zeros_after_dot: i16::MAX as usize + 2, + expected_err: Some(ParseError::Limit), + }, + TestCase { + zeros_before_dot: i16::MAX as usize, + zeros_after_dot: i16::MAX as usize + 2, + expected_err: Some(ParseError::Limit), + }, + TestCase { + zeros_before_dot: i16::MAX as usize, + zeros_after_dot: i16::MAX as usize, + expected_err: None, + }, + TestCase { + zeros_before_dot: i16::MAX as usize + 1, + zeros_after_dot: i16::MAX as usize, + expected_err: None, + }, + ]; + for cas in &cases { + let mut input_str = format!("{:0fill$}", 0, fill = cas.zeros_before_dot); + if cas.zeros_after_dot > 0 { + input_str.push('.'); + input_str.push_str(&format!("{:0fill$}", 0, fill = cas.zeros_after_dot)); + } + match SignedFixedDecimal::from_str(&input_str) { + Ok(dec) => { + assert_eq!(cas.expected_err, None, "{cas:?}"); + assert_eq!(input_str, dec.to_string(), "{cas:?}"); + } + Err(err) => { + assert_eq!(cas.expected_err, Some(err), "{cas:?}"); + } + } + } +} + +#[test] +fn test_syntax_error() { + #[derive(Debug)] + struct TestCase { + pub input_str: &'static str, + pub expected_err: Option, + } + let cases = [ + TestCase { + input_str: "-12a34", + expected_err: Some(ParseError::Syntax), + }, + TestCase { + input_str: "0.0123√400", + expected_err: Some(ParseError::Syntax), + }, + TestCase { + input_str: "0.012.3400", + expected_err: Some(ParseError::Syntax), + }, + TestCase { + input_str: "-0-0123400", + expected_err: Some(ParseError::Syntax), + }, + TestCase { + input_str: "0-0123400", + expected_err: Some(ParseError::Syntax), + }, + TestCase { + input_str: "-0.00123400", + expected_err: None, + }, + TestCase { + input_str: "00123400.", + expected_err: Some(ParseError::Syntax), + }, + TestCase { + input_str: "00123400.0", + expected_err: None, + }, + TestCase { + input_str: "123_456", + expected_err: Some(ParseError::Syntax), + }, + TestCase { + input_str: "", + expected_err: Some(ParseError::Syntax), + }, + TestCase { + input_str: "-", + expected_err: Some(ParseError::Syntax), + }, + TestCase { + input_str: "+", + expected_err: Some(ParseError::Syntax), + }, + TestCase { + input_str: "-1", + expected_err: None, + }, + ]; + for cas in &cases { + match SignedFixedDecimal::from_str(cas.input_str) { + Ok(dec) => { + assert_eq!(cas.expected_err, None, "{cas:?}"); + assert_eq!(cas.input_str, dec.to_string(), "{cas:?}"); + } + Err(err) => { + assert_eq!(cas.expected_err, Some(err), "{cas:?}"); + } + } + } +} + +#[test] +fn test_pad() { + let mut dec = SignedFixedDecimal::from_str("-0.42").unwrap(); + assert_eq!("-0.42", dec.to_string()); + + dec.absolute.pad_start(1); + assert_eq!("-0.42", dec.to_string()); + + dec.absolute.pad_start(4); + assert_eq!("-0000.42", dec.to_string()); + + dec.absolute.pad_start(2); + assert_eq!("-00.42", dec.to_string()); +} + +#[test] +fn test_sign_display() { + use SignDisplay::*; + let positive_nonzero = SignedFixedDecimal::from(163u32); + let negative_nonzero = SignedFixedDecimal::from(-163); + let positive_zero = SignedFixedDecimal::from(0u32); + let negative_zero = SignedFixedDecimal::from(0u32).with_sign(Sign::Negative); + assert_eq!( + "163", + positive_nonzero.clone().with_sign_display(Auto).to_string() + ); + assert_eq!( + "-163", + negative_nonzero.clone().with_sign_display(Auto).to_string() + ); + assert_eq!( + "0", + positive_zero.clone().with_sign_display(Auto).to_string() + ); + assert_eq!( + "-0", + negative_zero.clone().with_sign_display(Auto).to_string() + ); + assert_eq!( + "+163", + positive_nonzero + .clone() + .with_sign_display(Always) + .to_string() + ); + assert_eq!( + "-163", + negative_nonzero + .clone() + .with_sign_display(Always) + .to_string() + ); + assert_eq!( + "+0", + positive_zero.clone().with_sign_display(Always).to_string() + ); + assert_eq!( + "-0", + negative_zero.clone().with_sign_display(Always).to_string() + ); + assert_eq!( + "163", + positive_nonzero + .clone() + .with_sign_display(Never) + .to_string() + ); + assert_eq!( + "163", + negative_nonzero + .clone() + .with_sign_display(Never) + .to_string() + ); + assert_eq!( + "0", + positive_zero.clone().with_sign_display(Never).to_string() + ); + assert_eq!( + "0", + negative_zero.clone().with_sign_display(Never).to_string() + ); + assert_eq!( + "+163", + positive_nonzero + .clone() + .with_sign_display(ExceptZero) + .to_string() + ); + assert_eq!( + "-163", + negative_nonzero + .clone() + .with_sign_display(ExceptZero) + .to_string() + ); + assert_eq!( + "0", + positive_zero + .clone() + .with_sign_display(ExceptZero) + .to_string() + ); + assert_eq!( + "0", + negative_zero + .clone() + .with_sign_display(ExceptZero) + .to_string() + ); + assert_eq!( + "163", + positive_nonzero.with_sign_display(Negative).to_string() + ); + assert_eq!( + "-163", + negative_nonzero.with_sign_display(Negative).to_string() + ); + assert_eq!("0", positive_zero.with_sign_display(Negative).to_string()); + assert_eq!("0", negative_zero.with_sign_display(Negative).to_string()); +} + +#[test] +fn test_set_max_position() { + let mut dec = SignedFixedDecimal::from(1000u32); + assert_eq!("1000", dec.to_string()); + + dec.absolute.set_max_position(2); + assert_eq!("00", dec.to_string()); + + dec.absolute.set_max_position(0); + assert_eq!("0", dec.to_string()); + + dec.absolute.set_max_position(3); + assert_eq!("000", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.456").unwrap(); + assert_eq!("0.456", dec.to_string()); + + dec.absolute.set_max_position(0); + assert_eq!("0.456", dec.to_string()); + + dec.absolute.set_max_position(-1); + assert_eq!("0.056", dec.to_string()); + + dec.absolute.set_max_position(-2); + assert_eq!("0.006", dec.to_string()); + + dec.absolute.set_max_position(-3); + assert_eq!("0.000", dec.to_string()); + + dec.absolute.set_max_position(-4); + assert_eq!("0.0000", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("100.01").unwrap(); + dec.absolute.set_max_position(1); + assert_eq!("0.01", dec.to_string()); +} + +#[test] +fn test_pad_start_bounds() { + let mut dec = SignedFixedDecimal::from_str("299792.458").unwrap(); + let max_integer_digits = i16::MAX as usize + 1; + + dec.absolute.pad_start(i16::MAX - 1); + assert_eq!( + max_integer_digits - 2, + dec.to_string().split_once('.').unwrap().0.len() + ); + + dec.absolute.pad_start(i16::MAX); + assert_eq!( + max_integer_digits - 1, + dec.to_string().split_once('.').unwrap().0.len() + ); +} + +#[test] +fn test_pad_end_bounds() { + let mut dec = SignedFixedDecimal::from_str("299792.458").unwrap(); + let max_fractional_digits = -(i16::MIN as isize) as usize; + + dec.absolute.pad_end(i16::MIN + 1); + assert_eq!( + max_fractional_digits - 1, + dec.to_string().split_once('.').unwrap().1.len() + ); + + dec.absolute.pad_end(i16::MIN); + assert_eq!( + max_fractional_digits, + dec.to_string().split_once('.').unwrap().1.len() + ); +} + +#[test] +fn test_rounding() { + pub(crate) use std::str::FromStr; + + // Test Ceil + let mut dec = SignedFixedDecimal::from_str("3.234").unwrap(); + dec.ceil(0); + assert_eq!("4", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.222").unwrap(); + dec.ceil(-1); + assert_eq!("2.3", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("22.222").unwrap(); + dec.ceil(-2); + assert_eq!("22.23", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("99.999").unwrap(); + dec.ceil(-2); + assert_eq!("100.00", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("99.999").unwrap(); + dec.ceil(-5); + assert_eq!("99.99900", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.ceil(-5); + assert_eq!("-99.99900", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.ceil(-2); + assert_eq!("-99.99", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("99.999").unwrap(); + dec.ceil(4); + assert_eq!("10000", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.ceil(4); + assert_eq!("-0000", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.009").unwrap(); + dec.ceil(-1); + assert_eq!("0.1", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-0.009").unwrap(); + dec.ceil(-1); + assert_eq!("-0.0", dec.to_string()); + + // Test Half Ceil + let mut dec = SignedFixedDecimal::from_str("3.234").unwrap(); + dec.round_with_mode(0, SignedRoundingMode::HalfCeil); + assert_eq!("3", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("3.534").unwrap(); + dec.round_with_mode(0, SignedRoundingMode::HalfCeil); + assert_eq!("4", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("3.934").unwrap(); + dec.round_with_mode(0, SignedRoundingMode::HalfCeil); + assert_eq!("4", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.222").unwrap(); + dec.round_with_mode(-1, SignedRoundingMode::HalfCeil); + assert_eq!("2.2", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.44").unwrap(); + dec.round_with_mode(-1, SignedRoundingMode::HalfCeil); + assert_eq!("2.4", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.45").unwrap(); + dec.round_with_mode(-1, SignedRoundingMode::HalfCeil); + assert_eq!("2.5", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-2.44").unwrap(); + dec.round_with_mode(-1, SignedRoundingMode::HalfCeil); + assert_eq!("-2.4", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-2.45").unwrap(); + dec.round_with_mode(-1, SignedRoundingMode::HalfCeil); + assert_eq!("-2.4", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("22.222").unwrap(); + dec.round_with_mode(-2, SignedRoundingMode::HalfCeil); + assert_eq!("22.22", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("99.999").unwrap(); + dec.round_with_mode(-2, SignedRoundingMode::HalfCeil); + assert_eq!("100.00", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("99.999").unwrap(); + dec.round_with_mode(-5, SignedRoundingMode::HalfCeil); + assert_eq!("99.99900", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.round_with_mode(-5, SignedRoundingMode::HalfCeil); + assert_eq!("-99.99900", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.round_with_mode(-2, SignedRoundingMode::HalfCeil); + assert_eq!("-100.00", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("99.999").unwrap(); + dec.round_with_mode(4, SignedRoundingMode::HalfCeil); + assert_eq!("0000", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.round_with_mode(4, SignedRoundingMode::HalfCeil); + assert_eq!("-0000", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.009").unwrap(); + dec.round_with_mode(-1, SignedRoundingMode::HalfCeil); + assert_eq!("0.0", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-0.009").unwrap(); + dec.round_with_mode(-1, SignedRoundingMode::HalfCeil); + assert_eq!("-0.0", dec.to_string()); + + // Test Floor + let mut dec = SignedFixedDecimal::from_str("3.234").unwrap(); + dec.floor(0); + assert_eq!("3", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.222").unwrap(); + dec.floor(-1); + assert_eq!("2.2", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("99.999").unwrap(); + dec.floor(-2); + assert_eq!("99.99", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("99.999").unwrap(); + dec.floor(-10); + assert_eq!("99.9990000000", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.floor(-10); + assert_eq!("-99.9990000000", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("99.999").unwrap(); + dec.floor(10); + assert_eq!("0000000000", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.floor(10); + assert_eq!("-10000000000", dec.to_string()); + + // Test Half Floor + let mut dec = SignedFixedDecimal::from_str("3.234").unwrap(); + dec.round_with_mode(0, SignedRoundingMode::HalfFloor); + assert_eq!("3", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("3.534").unwrap(); + dec.round_with_mode(0, SignedRoundingMode::HalfFloor); + assert_eq!("4", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("3.934").unwrap(); + dec.round_with_mode(0, SignedRoundingMode::HalfFloor); + assert_eq!("4", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.222").unwrap(); + dec.round_with_mode(-1, SignedRoundingMode::HalfFloor); + assert_eq!("2.2", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.44").unwrap(); + dec.round_with_mode(-1, SignedRoundingMode::HalfFloor); + assert_eq!("2.4", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.45").unwrap(); + dec.round_with_mode(-1, SignedRoundingMode::HalfFloor); + assert_eq!("2.4", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-2.44").unwrap(); + dec.round_with_mode(-1, SignedRoundingMode::HalfFloor); + assert_eq!("-2.4", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-2.45").unwrap(); + dec.round_with_mode(-1, SignedRoundingMode::HalfFloor); + assert_eq!("-2.5", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("22.222").unwrap(); + dec.round_with_mode(-2, SignedRoundingMode::HalfFloor); + assert_eq!("22.22", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("99.999").unwrap(); + dec.round_with_mode(-2, SignedRoundingMode::HalfFloor); + assert_eq!("100.00", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("99.999").unwrap(); + dec.round_with_mode(-5, SignedRoundingMode::HalfFloor); + assert_eq!("99.99900", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.round_with_mode(-5, SignedRoundingMode::HalfFloor); + assert_eq!("-99.99900", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.round_with_mode(-2, SignedRoundingMode::HalfFloor); + assert_eq!("-100.00", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("99.999").unwrap(); + dec.round_with_mode(4, SignedRoundingMode::HalfFloor); + assert_eq!("0000", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.round_with_mode(4, SignedRoundingMode::HalfFloor); + assert_eq!("-0000", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.009").unwrap(); + dec.round_with_mode(-1, SignedRoundingMode::HalfFloor); + assert_eq!("0.0", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-0.009").unwrap(); + dec.round_with_mode(-1, SignedRoundingMode::HalfFloor); + assert_eq!("-0.0", dec.to_string()); + + // Test Truncate Right + let mut dec = SignedFixedDecimal::from(4235970u32); + dec.multiply_pow10(-3); + assert_eq!("4235.970", dec.to_string()); + + dec.trunc(-5); + assert_eq!("4235.97000", dec.to_string()); + + dec.trunc(-1); + assert_eq!("4235.9", dec.to_string()); + + dec.trunc(0); + assert_eq!("4235", dec.to_string()); + + dec.trunc(1); + assert_eq!("4230", dec.to_string()); + + dec.trunc(5); + assert_eq!("00000", dec.to_string()); + + dec.trunc(2); + assert_eq!("00000", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.trunc(-2); + assert_eq!("-99.99", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("1234.56").unwrap(); + dec.trunc(-1); + assert_eq!("1234.5", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.009").unwrap(); + dec.trunc(-1); + assert_eq!("0.0", dec.to_string()); + + // Test trunced + let mut dec = SignedFixedDecimal::from(4235970u32); + dec.multiply_pow10(-3); + assert_eq!("4235.970", dec.to_string()); + + assert_eq!("4235.97000", dec.clone().trunced(-5).to_string()); + + assert_eq!("4230", dec.clone().trunced(1).to_string()); + + assert_eq!("4200", dec.clone().trunced(2).to_string()); + + assert_eq!("00000", dec.trunced(5).to_string()); + + //Test expand + let mut dec = SignedFixedDecimal::from_str("3.234").unwrap(); + dec.expand(0); + assert_eq!("4", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.222").unwrap(); + dec.expand(-1); + assert_eq!("2.3", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("22.222").unwrap(); + dec.expand(-2); + assert_eq!("22.23", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("99.999").unwrap(); + dec.expand(-2); + assert_eq!("100.00", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("99.999").unwrap(); + dec.expand(-5); + assert_eq!("99.99900", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.expand(-5); + assert_eq!("-99.99900", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.expand(-2); + assert_eq!("-100.00", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("99.999").unwrap(); + dec.expand(4); + assert_eq!("10000", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.expand(4); + assert_eq!("-10000", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.009").unwrap(); + dec.expand(-1); + assert_eq!("0.1", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-0.009").unwrap(); + dec.expand(-1); + assert_eq!("-0.1", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("3.954").unwrap(); + dec.expand(0); + assert_eq!("4", dec.to_string()); + + // Test half_expand + let mut dec = SignedFixedDecimal::from_str("3.234").unwrap(); + dec.round_with_mode( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + ); + assert_eq!("3", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("3.534").unwrap(); + dec.round_with_mode( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + ); + assert_eq!("4", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("3.934").unwrap(); + dec.round_with_mode( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + ); + assert_eq!("4", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.222").unwrap(); + dec.round_with_mode( + -1, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + ); + assert_eq!("2.2", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.44").unwrap(); + dec.round_with_mode( + -1, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + ); + assert_eq!("2.4", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.45").unwrap(); + dec.round_with_mode( + -1, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + ); + assert_eq!("2.5", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-2.44").unwrap(); + dec.round_with_mode( + -1, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + ); + assert_eq!("-2.4", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-2.45").unwrap(); + dec.round_with_mode( + -1, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + ); + assert_eq!("-2.5", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("22.222").unwrap(); + dec.round_with_mode( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + ); + assert_eq!("22.22", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("99.999").unwrap(); + dec.round_with_mode( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + ); + assert_eq!("100.00", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("99.999").unwrap(); + dec.round_with_mode( + -5, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + ); + assert_eq!("99.99900", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.round_with_mode( + -5, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + ); + assert_eq!("-99.99900", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.round_with_mode( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + ); + assert_eq!("-100.00", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("99.999").unwrap(); + dec.round_with_mode( + 4, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + ); + assert_eq!("0000", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.round_with_mode( + 4, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + ); + assert_eq!("-0000", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.009").unwrap(); + dec.round_with_mode( + -1, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + ); + assert_eq!("0.0", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-0.009").unwrap(); + dec.round_with_mode( + -1, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + ); + assert_eq!("-0.0", dec.to_string()); + + // Test specific cases + let mut dec = SignedFixedDecimal::from_str("1.108").unwrap(); + dec.round_with_mode( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + ); + assert_eq!("1.11", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("1.108").unwrap(); + dec.expand(-2); + assert_eq!("1.11", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("1.108").unwrap(); + dec.trunc(-2); + assert_eq!("1.10", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.78536913177").unwrap(); + dec.round_with_mode( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + ); + 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 = SignedFixedDecimal::from_str(cas.input_1).unwrap(); + let fd2 = SignedFixedDecimal::from_str(cas.input_2).unwrap(); + match fd1.absolute.concatenated_end(fd2.absolute) { + Ok(fd) => { + assert_eq!(cas.expected, Some(fd.to_string().as_str()), "{cas:?}"); + } + Err(_) => { + assert!(cas.expected.is_none(), "{cas:?}"); + } + } + } +} + +#[test] +fn test_rounding_increment() { + // Test Truncate Right + let mut dec = SignedFixedDecimal::from(4235970u32); + dec.multiply_pow10(-3); + assert_eq!("4235.970", dec.to_string()); + + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Trunc), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("4235.96", dec.to_string()); + + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Trunc), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("4235.5", dec.to_string()); + + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Trunc), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("4225", dec.to_string()); + + dec.round_with_mode_and_increment( + 5, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Trunc), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("00000", dec.to_string()); + + dec.round_with_mode_and_increment( + 2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Trunc), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("00000", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Trunc), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("-99.75", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("1234.56").unwrap(); + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Trunc), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("1234.4", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.009").unwrap(); + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Trunc), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("0.0", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.60").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Trunc), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0.50", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.40").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Trunc), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0.25", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.7000000099").unwrap(); + dec.round_with_mode_and_increment( + -3, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Trunc), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("0.700", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("5").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Trunc), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0", dec.to_string()); + + let mut dec = SignedFixedDecimal::from(7u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Trunc), + RoundingIncrement::MultiplesOf2, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(6u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(9u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Trunc), + RoundingIncrement::MultiplesOf5, + ); + + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(5u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(70u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Trunc), + RoundingIncrement::MultiplesOf25, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(50u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(7u32); + dec.multiply_pow10(i16::MAX); + dec.round_with_mode_and_increment( + i16::MAX, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Trunc), + RoundingIncrement::MultiplesOf2, + ); + let expected_max = { + let mut expected_max = SignedFixedDecimal::from(6u32); + expected_max.multiply_pow10(i16::MAX); + expected_max + }; + assert_eq!(expected_max, dec); + + let mut dec = SignedFixedDecimal::from(7u32); + dec.multiply_pow10(i16::MAX); + dec.round_with_mode_and_increment( + i16::MAX, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Trunc), + RoundingIncrement::MultiplesOf5, + ); + let expected_max = { + let mut expected_max = SignedFixedDecimal::from(5u32); + expected_max.multiply_pow10(i16::MAX); + expected_max + }; + assert_eq!(expected_max, dec); + + let mut dec = SignedFixedDecimal::from(7u32); + dec.multiply_pow10(i16::MAX); + dec.round_with_mode_and_increment( + i16::MAX, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Trunc), + RoundingIncrement::MultiplesOf25, + ); + let expected = { + let mut expected = SignedFixedDecimal::from(0u32); + expected.multiply_pow10(i16::MAX); + expected + }; + assert_eq!(expected, dec); + + // Test Expand + let mut dec = SignedFixedDecimal::from(4235970u32); + dec.multiply_pow10(-3); + assert_eq!("4235.970", dec.to_string()); + + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("4235.98", dec.to_string()); + + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("4236.0", dec.to_string()); + + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("4250", dec.to_string()); + + dec.round_with_mode_and_increment( + 5, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("500000", dec.to_string()); + + dec.round_with_mode_and_increment( + 2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("500000", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("-100.00", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("1234.56").unwrap(); + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("1234.6", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.009").unwrap(); + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("0.5", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.60").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0.75", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.40").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0.50", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.7000000099").unwrap(); + dec.round_with_mode_and_increment( + -3, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("0.702", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("5").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("25", dec.to_string()); + + let mut dec = SignedFixedDecimal::from(7u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf2, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(8u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(9u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf5, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(10u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(70u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf25, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(75u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(7u32); + dec.multiply_pow10(i16::MAX); + dec.round_with_mode_and_increment( + i16::MAX, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf2, + ); + let expected_max = { + let mut expected_max = SignedFixedDecimal::from(8u32); + expected_max.multiply_pow10(i16::MAX); + expected_max + }; + assert_eq!(expected_max, dec); + + let mut dec = SignedFixedDecimal::from(7u32); + dec.multiply_pow10(i16::MAX); + dec.round_with_mode_and_increment( + i16::MAX, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf5, + ); + let expected_max = { + let mut expected_max = SignedFixedDecimal::from(0u32); + expected_max.multiply_pow10(i16::MAX); + expected_max + }; + assert_eq!(expected_max, dec); + + let mut dec = SignedFixedDecimal::from(7u32); + dec.multiply_pow10(i16::MAX); + dec.round_with_mode_and_increment( + i16::MAX, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf25, + ); + let expected_max = { + let mut expected_max = SignedFixedDecimal::from(0u32); + expected_max.multiply_pow10(i16::MAX); + expected_max + }; + assert_eq!(expected_max, dec); + + // Test Half Truncate Right + let mut dec = SignedFixedDecimal::from(4235970u32); + dec.multiply_pow10(-3); + assert_eq!("4235.970", dec.to_string()); + + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("4235.96", dec.to_string()); + + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("4236.0", dec.to_string()); + + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("4225", dec.to_string()); + + dec.round_with_mode_and_increment( + 5, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("00000", dec.to_string()); + + dec.round_with_mode_and_increment( + 2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("00000", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("-100.00", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("1234.56").unwrap(); + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("1234.6", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.009").unwrap(); + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("0.0", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.60").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0.50", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.40").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0.50", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.7000000099").unwrap(); + dec.round_with_mode_and_increment( + -3, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("0.700", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("5").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0", dec.to_string()); + + let mut dec = SignedFixedDecimal::from(7u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc), + RoundingIncrement::MultiplesOf2, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(6u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(9u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc), + RoundingIncrement::MultiplesOf5, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(10u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(70u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc), + RoundingIncrement::MultiplesOf25, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(75u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(7u32); + dec.multiply_pow10(i16::MAX); + dec.round_with_mode_and_increment( + i16::MAX, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc), + RoundingIncrement::MultiplesOf2, + ); + let expected_max = { + let mut expected_max = SignedFixedDecimal::from(6u32); + expected_max.multiply_pow10(i16::MAX); + expected_max + }; + assert_eq!(expected_max, dec); + + let mut dec = SignedFixedDecimal::from(7u32); + dec.multiply_pow10(i16::MAX); + dec.round_with_mode_and_increment( + i16::MAX, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc), + RoundingIncrement::MultiplesOf5, + ); + let expected_max = { + let mut expected_max = SignedFixedDecimal::from(5u32); + expected_max.multiply_pow10(i16::MAX); + expected_max + }; + assert_eq!(expected_max, dec); + + let mut dec = SignedFixedDecimal::from(7u32); + dec.multiply_pow10(i16::MAX); + dec.round_with_mode_and_increment( + i16::MAX, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc), + RoundingIncrement::MultiplesOf25, + ); + let expected_max = { + let mut expected_max = SignedFixedDecimal::from(0u32); + expected_max.multiply_pow10(i16::MAX); + expected_max + }; + assert_eq!(expected_max, dec); + + // Test Half Expand + let mut dec = SignedFixedDecimal::from(4235970u32); + dec.multiply_pow10(-3); + assert_eq!("4235.970", dec.to_string()); + + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("4235.98", dec.to_string()); + + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("4236.0", dec.to_string()); + + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("4225", dec.to_string()); + + dec.round_with_mode_and_increment( + 5, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("00000", dec.to_string()); + + dec.round_with_mode_and_increment( + 2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("00000", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("-100.00", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("1234.56").unwrap(); + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("1234.6", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.009").unwrap(); + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("0.0", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.60").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0.50", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.40").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0.50", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.7000000099").unwrap(); + dec.round_with_mode_and_increment( + -3, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("0.700", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("5").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0", dec.to_string()); + + let mut dec = SignedFixedDecimal::from(7u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + RoundingIncrement::MultiplesOf2, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(8u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(9u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + RoundingIncrement::MultiplesOf5, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(10u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(70u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + RoundingIncrement::MultiplesOf25, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(75u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(7u32); + dec.multiply_pow10(i16::MAX); + dec.round_with_mode_and_increment( + i16::MAX, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + RoundingIncrement::MultiplesOf2, + ); + let expected_max = { + let mut expected_max = SignedFixedDecimal::from(8u32); + expected_max.multiply_pow10(i16::MAX); + expected_max + }; + assert_eq!(expected_max, dec); + + // Test Ceil + let mut dec = SignedFixedDecimal::from(4235970u32); + dec.multiply_pow10(-3); + assert_eq!("4235.970", dec.to_string()); + + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Ceil, + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("4235.98", dec.to_string()); + + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::Ceil, + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("4236.0", dec.to_string()); + + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Ceil, + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("4250", dec.to_string()); + + dec.round_with_mode_and_increment(5, SignedRoundingMode::Ceil, RoundingIncrement::MultiplesOf5); + assert_eq!("500000", dec.to_string()); + + dec.round_with_mode_and_increment(2, SignedRoundingMode::Ceil, RoundingIncrement::MultiplesOf2); + assert_eq!("500000", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Ceil, + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("-99.75", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("1234.56").unwrap(); + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::Ceil, + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("1234.6", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.009").unwrap(); + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::Ceil, + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("0.5", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.60").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Ceil, + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0.75", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.40").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Ceil, + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0.50", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.7000000099").unwrap(); + dec.round_with_mode_and_increment( + -3, + SignedRoundingMode::Ceil, + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("0.702", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("5").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Ceil, + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("25", dec.to_string()); + + let mut dec = SignedFixedDecimal::from(7u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::Ceil, + RoundingIncrement::MultiplesOf2, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(8u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(9u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::Ceil, + RoundingIncrement::MultiplesOf5, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(10u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(70u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::Ceil, + RoundingIncrement::MultiplesOf25, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(75u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(7u32); + dec.multiply_pow10(i16::MAX); + dec.round_with_mode_and_increment( + i16::MAX, + SignedRoundingMode::Ceil, + RoundingIncrement::MultiplesOf2, + ); + let expected_max = { + let mut expected_max = SignedFixedDecimal::from(8u32); + expected_max.multiply_pow10(i16::MAX); + expected_max + }; + assert_eq!(expected_max, dec); + + // Test Half Ceil + let mut dec = SignedFixedDecimal::from(4235970u32); + dec.multiply_pow10(-3); + assert_eq!("4235.970", dec.to_string()); + + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::HalfCeil, + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("4235.98", dec.to_string()); + + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::HalfCeil, + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("4236.0", dec.to_string()); + + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::HalfCeil, + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("4225", dec.to_string()); + + dec.round_with_mode_and_increment( + 5, + SignedRoundingMode::HalfCeil, + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("00000", dec.to_string()); + + dec.round_with_mode_and_increment( + 2, + SignedRoundingMode::HalfCeil, + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("00000", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::HalfCeil, + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("-100.00", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("1234.56").unwrap(); + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::HalfCeil, + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("1234.6", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.009").unwrap(); + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::HalfCeil, + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("0.0", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.60").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::HalfCeil, + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0.50", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.40").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::HalfCeil, + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0.50", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.7000000099").unwrap(); + dec.round_with_mode_and_increment( + -3, + SignedRoundingMode::HalfCeil, + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("0.700", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("5").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::HalfCeil, + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0", dec.to_string()); + + let mut dec = SignedFixedDecimal::from(7u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::HalfCeil, + RoundingIncrement::MultiplesOf2, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(8u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(9u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::HalfCeil, + RoundingIncrement::MultiplesOf5, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(10u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(70u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::HalfCeil, + RoundingIncrement::MultiplesOf25, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(75u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(7u32); + dec.multiply_pow10(i16::MAX); + dec.round_with_mode_and_increment( + i16::MAX, + SignedRoundingMode::HalfCeil, + RoundingIncrement::MultiplesOf2, + ); + let expected_max = { + let mut expected_max = SignedFixedDecimal::from(8u32); + expected_max.multiply_pow10(i16::MAX); + expected_max + }; + assert_eq!(expected_max, dec); + + // Test Floor + let mut dec = SignedFixedDecimal::from(4235970u32); + dec.multiply_pow10(-3); + assert_eq!("4235.970", dec.to_string()); + + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Floor, + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("4235.96", dec.to_string()); + + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::Floor, + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("4235.5", dec.to_string()); + + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Floor, + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("4225", dec.to_string()); + + dec.round_with_mode_and_increment( + 5, + SignedRoundingMode::Floor, + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("00000", dec.to_string()); + + dec.round_with_mode_and_increment( + 2, + SignedRoundingMode::Floor, + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("00000", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Floor, + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("-100.00", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("1234.56").unwrap(); + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::Floor, + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("1234.4", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.009").unwrap(); + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::Floor, + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("0.0", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.60").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Floor, + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0.50", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.40").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Floor, + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0.25", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.7000000099").unwrap(); + dec.round_with_mode_and_increment( + -3, + SignedRoundingMode::Floor, + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("0.700", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("5").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Floor, + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0", dec.to_string()); + + let mut dec = SignedFixedDecimal::from(7u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::Floor, + RoundingIncrement::MultiplesOf2, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(6u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(9u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::Floor, + RoundingIncrement::MultiplesOf5, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(5u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(70u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::Floor, + RoundingIncrement::MultiplesOf25, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(50u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(7u32); + dec.multiply_pow10(i16::MAX); + dec.round_with_mode_and_increment( + i16::MAX, + SignedRoundingMode::Floor, + RoundingIncrement::MultiplesOf2, + ); + let expected_max = { + let mut expected_max = SignedFixedDecimal::from(6u32); + expected_max.multiply_pow10(i16::MAX); + expected_max + }; + assert_eq!(expected_max, dec); + + // Test Half Floor + let mut dec = SignedFixedDecimal::from(4235970u32); + dec.multiply_pow10(-3); + assert_eq!("4235.970", dec.to_string()); + + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::HalfFloor, + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("4235.96", dec.to_string()); + + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::HalfFloor, + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("4236.0", dec.to_string()); + + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::HalfFloor, + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("4225", dec.to_string()); + + dec.round_with_mode_and_increment( + 5, + SignedRoundingMode::HalfFloor, + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("00000", dec.to_string()); + + dec.round_with_mode_and_increment( + 2, + SignedRoundingMode::HalfFloor, + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("00000", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::HalfFloor, + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("-100.00", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("1234.56").unwrap(); + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::HalfFloor, + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("1234.6", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.009").unwrap(); + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::HalfFloor, + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("0.0", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.60").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::HalfFloor, + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0.50", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.40").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::HalfFloor, + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0.50", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.7000000099").unwrap(); + dec.round_with_mode_and_increment( + -3, + SignedRoundingMode::HalfFloor, + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("0.700", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("5").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::HalfFloor, + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0", dec.to_string()); + + let mut dec = SignedFixedDecimal::from(7u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::HalfFloor, + RoundingIncrement::MultiplesOf2, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(6u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(9u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::HalfFloor, + RoundingIncrement::MultiplesOf5, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(10u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(70u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::HalfFloor, + RoundingIncrement::MultiplesOf25, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(75u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(7u32); + dec.multiply_pow10(i16::MAX); + dec.round_with_mode_and_increment( + i16::MAX, + SignedRoundingMode::HalfFloor, + RoundingIncrement::MultiplesOf2, + ); + let expected_max = { + let mut expected_max = SignedFixedDecimal::from(6u32); + expected_max.multiply_pow10(i16::MAX); + expected_max + }; + assert_eq!(expected_max, dec); + + // Test Half Even + let mut dec = SignedFixedDecimal::from(4235970u32); + dec.multiply_pow10(-3); + assert_eq!("4235.970", dec.to_string()); + + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("4235.96", dec.to_string()); + + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("4236.0", dec.to_string()); + + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("4225", dec.to_string()); + + dec.round_with_mode_and_increment( + 5, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("00000", dec.to_string()); + + dec.round_with_mode_and_increment( + 2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("00000", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-99.999").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("-100.00", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("1234.56").unwrap(); + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("1234.6", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.009").unwrap(); + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("0.0", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.60").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0.50", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.40").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0.50", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.7000000099").unwrap(); + dec.round_with_mode_and_increment( + -3, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("0.700", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("5").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0", dec.to_string()); + + let mut dec = SignedFixedDecimal::from(7u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf2, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(8u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(9u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf5, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(10u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(70u32); + dec.multiply_pow10(i16::MIN); + dec.round_with_mode_and_increment( + i16::MIN, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf25, + ); + let expected_min = { + let mut expected_min = SignedFixedDecimal::from(75u32); + expected_min.multiply_pow10(i16::MIN); + expected_min + }; + assert_eq!(expected_min, dec); + + let mut dec = SignedFixedDecimal::from(7u32); + dec.multiply_pow10(i16::MAX); + dec.round_with_mode_and_increment( + i16::MAX, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf2, + ); + let expected_max = { + let mut expected_max = SignedFixedDecimal::from(8u32); + expected_max.multiply_pow10(i16::MAX); + expected_max + }; + assert_eq!(expected_max, dec); + + // Test specific cases + let mut dec = SignedFixedDecimal::from_str("1.108").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("1.12", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("1.108").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("1.15", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("1.108").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("1.25", dec.to_string()); + + let mut dec = SignedFixedDecimal::from(9u32); + dec.multiply_pow10(i16::MAX - 1); + dec.round_with_mode_and_increment( + i16::MAX - 1, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf25, + ); + let expected_max_minus_1 = { + let mut expected_max_minus_1 = SignedFixedDecimal::from(25u32); + expected_max_minus_1.multiply_pow10(i16::MAX - 1); + expected_max_minus_1 + }; + assert_eq!(expected_max_minus_1, dec); + + let mut dec = SignedFixedDecimal::from(9u32); + dec.multiply_pow10(i16::MAX); + dec.round_with_mode_and_increment( + i16::MAX, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf25, + ); + let expected_max = { + let mut expected_max = SignedFixedDecimal::from(0u32); + expected_max.multiply_pow10(i16::MAX); + expected_max + }; + assert_eq!(expected_max, dec); + + let mut dec = SignedFixedDecimal::from_str("0").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("0", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("0", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.1").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("2", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.1").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("5", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.1").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("25", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("1").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("2", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("1").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("5", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("1").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("25", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("2", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("5", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.1").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("4", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.1").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("5", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("4").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("4", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("4").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("5", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("4.1").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("6", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("4.1").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("5", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("5").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("6", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("5").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("5", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("5.1").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("6", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("5.1").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("10", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("6").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("6", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("6").unwrap(); + dec.round_with_mode_and_increment( + 0, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("10", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("0.50").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::Expand), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("0.50", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("1.1025").unwrap(); + dec.round_with_mode_and_increment( + -3, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfTrunc), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("1.100", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("1.10125").unwrap(); + dec.round_with_mode_and_increment( + -4, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfExpand), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("1.1025", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-1.25").unwrap(); + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::HalfCeil, + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("-1.0", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-1.251").unwrap(); + dec.round_with_mode_and_increment( + -1, + SignedRoundingMode::HalfCeil, + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("-1.5", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("-1.125").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::HalfFloor, + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("-1.25", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.71").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("2.72", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.73").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("2.72", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.75").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("2.76", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.77").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("2.76", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.79").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("2.80", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.41").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("2.40", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.43").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("2.44", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.45").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("2.44", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.47").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("2.48", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.49").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf2, + ); + assert_eq!("2.48", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.725").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("2.70", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.775").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf5, + ); + assert_eq!("2.80", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.875").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("3.00", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.375").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("2.50", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.125").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("2.00", dec.to_string()); + + let mut dec = SignedFixedDecimal::from_str("2.625").unwrap(); + dec.round_with_mode_and_increment( + -2, + SignedRoundingMode::Unsigned(UnsignedRoundingMode::HalfEven), + RoundingIncrement::MultiplesOf25, + ); + assert_eq!("2.50", dec.to_string()); +} diff --git a/utils/fixed_decimal/src/variations.rs b/utils/fixed_decimal/src/variations.rs new file mode 100644 index 00000000000..a5371f661db --- /dev/null +++ b/utils/fixed_decimal/src/variations.rs @@ -0,0 +1,102 @@ +// 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 module defines variations of numeric types, including signed values, +/// values with infinity, and values with NaN. + +// TODO: move to sign.rs +/// A specification of the sign used when formatting a number. +#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)] +#[allow(clippy::exhaustive_enums)] +// There are only 3 sign values, and they correspond to the low-level data model of FixedDecimal and UTS 35. +pub enum Sign { + /// No sign (implicitly positive, e.g., 1729). + #[default] + None, + /// A negative sign, e.g., -1729. + Negative, + /// An explicit positive sign, e.g., +1729. + Positive, +} + +/// Configuration for when to render the minus sign or plus sign. +#[non_exhaustive] +#[derive(Debug, Eq, PartialEq, Clone, Copy)] +pub enum SignDisplay { + /// Render the sign according to locale preferences. In most cases, this means a minus sign + /// will be shown on negative numbers, and no sign will be shown on positive numbers. + Auto, + + /// Do not display the sign. Positive and negative numbers are indistinguishable. + Never, + + /// Show a minus sign on negative numbers and a plus sign on positive numbers, including zero. + Always, + + /// Show a minus sign on negative numbers and a plus sign on positive numbers, except do not + /// show any sign on positive or negative zero. + ExceptZero, + + /// Show a minus sign on strictly negative numbers. Do not show a sign on positive numbers or + /// on positive or negative zero. + /// + /// This differs from [`Auto`](SignDisplay::Auto) in that it does not render a sign on negative zero. + Negative, +} + +/// The `Signed` struct represents a numeric value with an associated sign. +#[non_exhaustive] +#[derive(Debug, Clone, PartialEq, Default)] +pub struct Signed { + pub sign: Sign, + pub absolute: T, +} + +impl Signed { + /// Returns the sign of this signed number. + pub fn sign(&self) -> Sign { + self.sign + } + + /// Changes the sign of this signed number to the one given. + pub fn set_sign(&mut self, sign: Sign) { + self.sign = sign; + } + + /// Returns this number with the sign changed to the one given. + pub fn with_sign(mut self, sign: Sign) -> Self { + self.set_sign(sign); + self + } +} + +// TODO(#5065): implement `WithCompactExponent` and `WithScientificExponent`. +// /// The `WithInfinity` enum represents a numeric value that may be either infinite or finite. +// #[derive(Debug)] +// pub enum WithInfinity { +// Infinity, +// Finite(T), +// } + +// /// The `WithNaN` enum represents a numeric value that may be NaN. +// #[derive(Debug)] +// pub enum WithNaN { +// NaN, +// N(T), +// } + +// TODO(#5065): implement `WithCompactExponent` and `WithScientificExponent`. +// /// The `WithCompactExponent` struct represents a numeric value with a compact exponent. +// #[derive(Debug)] +// pub struct WithCompactExponent { +// pub exponent: u8, +// pub significand: T, +// } + +// /// The `WithScientificExponent` struct represents a numeric value with a scientific exponent. +// #[derive(Debug)] +// pub struct WithScientificExponent { +// pub exponent: i16, +// pub significand: T, +// } diff --git a/utils/fixed_decimal/tests/rounding.rs b/utils/fixed_decimal/tests/rounding.rs index b4dad954484..525ff941535 100644 --- a/utils/fixed_decimal/tests/rounding.rs +++ b/utils/fixed_decimal/tests/rounding.rs @@ -3,41 +3,29 @@ // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). use core::ops::RangeInclusive; -use fixed_decimal::FixedDecimal; -use fixed_decimal::RoundingMode; -use fixed_decimal::Sign; +use fixed_decimal::UnsignedFixedDecimal; +use fixed_decimal::UnsignedRoundingMode; use writeable::Writeable; #[test] pub fn test_ecma402_table() { // Source: - let cases: [(_, _, _, _, _, _, _); 9] = [ - ("ceil", RoundingMode::Ceil, -1, 1, 1, 1, 2), - ("floor", RoundingMode::Floor, -2, 0, 0, 0, 1), - ("expand", RoundingMode::Expand, -2, 1, 1, 1, 2), - ("trunc", RoundingMode::Trunc, -1, 0, 0, 0, 1), - ("half_ceil", RoundingMode::HalfCeil, -1, 0, 1, 1, 2), - ("half_floor", RoundingMode::HalfFloor, -2, 0, 0, 1, 1), - ("half_expand", RoundingMode::HalfExpand, -2, 0, 1, 1, 2), - ("half_trunc", RoundingMode::HalfTrunc, -1, 0, 0, 1, 1), - ("half_even", RoundingMode::HalfEven, -2, 0, 0, 1, 2), + let cases: [(_, _, _, _, _, _); 5] = [ + ("expand", UnsignedRoundingMode::Expand, 1, 1, 1, 2), + ("trunc", UnsignedRoundingMode::Trunc, 0, 0, 0, 1), + ("half_expand", UnsignedRoundingMode::HalfExpand, 0, 1, 1, 2), + ("half_trunc", UnsignedRoundingMode::HalfTrunc, 0, 0, 1, 1), + ("half_even", UnsignedRoundingMode::HalfEven, 0, 0, 1, 2), ]; - for (name, mode, 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(); - fd1.round_with_mode(0, mode); + for (name, mode, e2, e3, e4, e5) in cases { + let mut fd2: UnsignedFixedDecimal = "0.4".parse().unwrap(); + let mut fd3: UnsignedFixedDecimal = "0.5".parse().unwrap(); + let mut fd4: UnsignedFixedDecimal = "0.6".parse().unwrap(); + let mut fd5: UnsignedFixedDecimal = "1.5".parse().unwrap(); fd2.round_with_mode(0, mode); fd3.round_with_mode(0, mode); fd4.round_with_mode(0, mode); fd5.round_with_mode(0, mode); - assert_eq!( - fd1.write_to_string(), - e1.write_to_string(), - "-1.5 failed for {name}" - ); assert_eq!( fd2.write_to_string(), e2.write_to_string(), @@ -65,92 +53,44 @@ pub fn test_ecma402_table() { pub fn test_within_ranges() { struct TestCase { rounding_mode_name: &'static str, - rounding_mode: RoundingMode, - range_n2000: RangeInclusive, - range_n1000: RangeInclusive, - range_0: RangeInclusive, - range_1000: RangeInclusive, - range_2000: RangeInclusive, + rounding_mode: UnsignedRoundingMode, + range_0: RangeInclusive, + range_1000: RangeInclusive, + range_2000: RangeInclusive, } - let cases: [TestCase; 9] = [ - TestCase { - rounding_mode_name: "ceil", - rounding_mode: RoundingMode::Ceil, - range_n2000: -2999..=-2000, - range_n1000: -1999..=-1000, - range_0: -999..=0, - range_1000: 1..=1000, - range_2000: 1001..=2000, - }, - TestCase { - rounding_mode_name: "floor", - rounding_mode: RoundingMode::Floor, - range_n2000: -2000..=-1001, - range_n1000: -1000..=-1, - range_0: 0..=999, - range_1000: 1000..=1999, - range_2000: 2000..=2999, - }, + let cases: [TestCase; 5] = [ TestCase { rounding_mode_name: "expand", - rounding_mode: RoundingMode::Expand, - range_n2000: -2000..=-1001, - range_n1000: -1000..=-1, + rounding_mode: UnsignedRoundingMode::Expand, range_0: 0..=0, range_1000: 1..=1000, range_2000: 1001..=2000, }, TestCase { rounding_mode_name: "trunc", - rounding_mode: RoundingMode::Trunc, - range_n2000: -2999..=-2000, - range_n1000: -1999..=-1000, - range_0: -999..=999, + rounding_mode: UnsignedRoundingMode::Trunc, + range_0: 0..=999, range_1000: 1000..=1999, range_2000: 2000..=2999, }, - TestCase { - rounding_mode_name: "half_ceil", - rounding_mode: RoundingMode::HalfCeil, - range_n2000: -2500..=-1501, - range_n1000: -1500..=-501, - range_0: -500..=449, - range_1000: 500..=1449, - range_2000: 1500..=2449, - }, - TestCase { - rounding_mode_name: "half_floor", - rounding_mode: RoundingMode::HalfFloor, - range_n2000: -2449..=-1500, - range_n1000: -1449..=-500, - range_0: -449..=500, - range_1000: 501..=1500, - range_2000: 1501..=2500, - }, TestCase { rounding_mode_name: "half_expand", - rounding_mode: RoundingMode::HalfExpand, - range_n2000: -2449..=-1500, - range_n1000: -1449..=-500, - range_0: -449..=449, + rounding_mode: UnsignedRoundingMode::HalfExpand, + range_0: 0..=449, range_1000: 500..=1449, range_2000: 1500..=2449, }, TestCase { rounding_mode_name: "half_trunc", - rounding_mode: RoundingMode::HalfTrunc, - range_n2000: -2500..=-1501, - range_n1000: -1500..=-501, - range_0: -500..=500, + rounding_mode: UnsignedRoundingMode::HalfTrunc, + range_0: 0..=500, range_1000: 501..=1500, range_2000: 1501..=2500, }, TestCase { rounding_mode_name: "half_even", - rounding_mode: RoundingMode::HalfEven, - range_n2000: -2500..=-1500, - range_n1000: -1449..=-501, - range_0: -500..=500, + rounding_mode: UnsignedRoundingMode::HalfEven, + range_0: 0..=500, range_1000: 501..=1449, range_2000: 1500..=2500, }, @@ -158,53 +98,19 @@ pub fn test_within_ranges() { for TestCase { rounding_mode_name, rounding_mode, - range_n2000, - range_n1000, range_0, range_1000, range_2000, } in cases { - for n in range_n2000 { - let mut fd = FixedDecimal::from(n); - fd.round_with_mode(3, rounding_mode); - assert_eq!(fd.write_to_string(), "-2000", "{rounding_mode_name}: {n}"); - let mut fd = FixedDecimal::from(n - 1000000).multiplied_pow10(-5); - fd.round_with_mode(-2, rounding_mode); - assert_eq!( - fd.write_to_string(), - "-10.02", - "{rounding_mode_name}: {n} ÷ 10^5 ± 10" - ); - } - for n in range_n1000 { - let mut fd = FixedDecimal::from(n); - fd.round_with_mode(3, rounding_mode); - assert_eq!(fd.write_to_string(), "-1000", "{rounding_mode_name}: {n}"); - let mut fd = FixedDecimal::from(n - 1000000).multiplied_pow10(-5); - fd.round_with_mode(-2, rounding_mode); - assert_eq!( - fd.write_to_string(), - "-10.01", - "{rounding_mode_name}: {n} ÷ 10^5 ± 10" - ); - } for n in range_0 { - let mut fd = FixedDecimal::from(n); + let mut fd = UnsignedFixedDecimal::from(n); fd.round_with_mode(3, rounding_mode); - fd.set_sign(Sign::None); // get rid of -0 assert_eq!(fd.write_to_string(), "000", "{rounding_mode_name}: {n}"); - let (mut fd, expected) = if n < 0 { - ( - FixedDecimal::from(n - 1000000).multiplied_pow10(-5), - "-10.00", - ) - } else { - ( - FixedDecimal::from(n + 1000000).multiplied_pow10(-5), - "10.00", - ) - }; + let (mut fd, expected) = ( + UnsignedFixedDecimal::from(n + 1000000).multiplied_pow10(-5), + "10.00", + ); fd.round_with_mode(-2, rounding_mode); assert_eq!( fd.write_to_string(), @@ -213,10 +119,10 @@ pub fn test_within_ranges() { ); } for n in range_1000 { - let mut fd = FixedDecimal::from(n); + let mut fd = UnsignedFixedDecimal::from(n); fd.round_with_mode(3, rounding_mode); assert_eq!(fd.write_to_string(), "1000", "{rounding_mode_name}: {n}"); - let mut fd = FixedDecimal::from(n + 1000000).multiplied_pow10(-5); + let mut fd = UnsignedFixedDecimal::from(n + 1000000).multiplied_pow10(-5); fd.round_with_mode(-2, rounding_mode); assert_eq!( fd.write_to_string(), @@ -225,10 +131,10 @@ pub fn test_within_ranges() { ); } for n in range_2000 { - let mut fd = FixedDecimal::from(n); + let mut fd = UnsignedFixedDecimal::from(n); fd.round_with_mode(3, rounding_mode); assert_eq!(fd.write_to_string(), "2000", "{rounding_mode_name}: {n}"); - let mut fd = FixedDecimal::from(n + 1000000).multiplied_pow10(-5); + let mut fd = UnsignedFixedDecimal::from(n + 1000000).multiplied_pow10(-5); fd.round_with_mode(-2, rounding_mode); assert_eq!( fd.write_to_string(), @@ -244,80 +150,58 @@ pub fn extra_rounding_mode_cases() { struct TestCase { input: &'static str, position: i16, - // ceil, floor, expand, trunc, half_ceil, half_floor, half_expand, half_trunc, half_even - all_expected: [&'static str; 9], + // expand, trunc, half_expand, half_trunc, half_even + all_expected: [&'static str; 5], } let cases: [TestCase; 8] = [ TestCase { input: "505.050", position: -3, - all_expected: [ - "505.050", "505.050", "505.050", "505.050", "505.050", "505.050", "505.050", - "505.050", "505.050", - ], + all_expected: ["505.050", "505.050", "505.050", "505.050", "505.050"], }, TestCase { input: "505.050", position: -2, - all_expected: [ - "505.05", "505.05", "505.05", "505.05", "505.05", "505.05", "505.05", "505.05", - "505.05", - ], + all_expected: ["505.05", "505.05", "505.05", "505.05", "505.05"], }, TestCase { input: "505.050", position: -1, - all_expected: [ - "505.1", "505.0", "505.1", "505.0", "505.1", "505.0", "505.1", "505.0", "505.0", - ], + all_expected: ["505.1", "505.0", "505.1", "505.0", "505.0"], }, TestCase { input: "505.050", position: 0, - all_expected: [ - "506", "505", "506", "505", "505", "505", "505", "505", "505", - ], + all_expected: ["506", "505", "505", "505", "505"], }, TestCase { input: "505.050", position: 1, - all_expected: [ - "510", "500", "510", "500", "510", "510", "510", "510", "510", - ], + all_expected: ["510", "500", "510", "510", "510"], }, TestCase { input: "505.050", position: 2, - all_expected: [ - "600", "500", "600", "500", "500", "500", "500", "500", "500", - ], + all_expected: ["600", "500", "500", "500", "500"], }, TestCase { input: "505.050", position: 3, - all_expected: [ - "1000", "000", "1000", "000", "1000", "1000", "1000", "1000", "1000", - ], + all_expected: ["1000", "000", "1000", "1000", "1000"], }, TestCase { input: "505.050", position: 4, - all_expected: [ - "10000", "0000", "10000", "0000", "0000", "0000", "0000", "0000", "0000", - ], + all_expected: ["10000", "0000", "0000", "0000", "0000"], }, ]; #[allow(clippy::type_complexity)] // most compact representation in code - let rounding_modes: [(&'static str, RoundingMode); 9] = [ - ("ceil", RoundingMode::Ceil), - ("floor", RoundingMode::Floor), - ("expand", RoundingMode::Expand), - ("trunc", RoundingMode::Trunc), - ("half_ceil", RoundingMode::HalfCeil), - ("half_floor", RoundingMode::HalfFloor), - ("half_expand", RoundingMode::HalfExpand), - ("half_trunc", RoundingMode::HalfTrunc), - ("half_even", RoundingMode::HalfEven), + let rounding_modes: [(&'static str, UnsignedRoundingMode); 5] = [ + ("expand", UnsignedRoundingMode::Expand), + ("trunc", UnsignedRoundingMode::Trunc), + ("half_expand", UnsignedRoundingMode::HalfExpand), + ("half_trunc", UnsignedRoundingMode::HalfTrunc), + ("half_even", UnsignedRoundingMode::HalfEven), ]; for TestCase { input, @@ -328,7 +212,7 @@ pub fn extra_rounding_mode_cases() { for ((rounding_mode_name, rounding_mode), expected) in rounding_modes.iter().zip(all_expected.iter()) { - let mut fd: FixedDecimal = input.parse().unwrap(); + let mut fd: UnsignedFixedDecimal = input.parse().unwrap(); fd.round_with_mode(position, *rounding_mode); assert_eq!( &*fd.write_to_string(), @@ -345,62 +229,44 @@ pub fn test_ecma402_table_with_increments() { #[rustfmt::skip] // Don't split everything on its own line. Makes it look a lot nicer. #[allow(clippy::type_complexity)] - let cases: [(_, _, [(_, _, _, _, _, _, _); 9]); 3] = [ + let cases: [(_, _, [(_, _, _, _, _, _); 5]); 3] = [ ("two", RoundingIncrement::MultiplesOf2, [ - ("ceil", RoundingMode::Ceil, "-1.4", "0.4", "0.6", "0.6", "1.6"), - ("floor", RoundingMode::Floor, "-1.6", "0.4", "0.4", "0.6", "1.4"), - ("expand", RoundingMode::Expand, "-1.6", "0.4", "0.6", "0.6", "1.6"), - ("trunc", RoundingMode::Trunc, "-1.4", "0.4", "0.4", "0.6", "1.4"), - ("half_ceil", RoundingMode::HalfCeil, "-1.4", "0.4", "0.6", "0.6", "1.6"), - ("half_floor", RoundingMode::HalfFloor, "-1.6", "0.4", "0.4", "0.6", "1.4"), - ("half_expand", RoundingMode::HalfExpand, "-1.6", "0.4", "0.6", "0.6", "1.6"), - ("half_trunc", RoundingMode::HalfTrunc, "-1.4", "0.4", "0.4", "0.6", "1.4"), - ("half_even", RoundingMode::HalfEven, "-1.6", "0.4", "0.4", "0.6", "1.6"), + ("expand", UnsignedRoundingMode::Expand, "0.4", "0.6", "0.6", "1.6"), + ("trunc", UnsignedRoundingMode::Trunc, "0.4", "0.4", "0.6", "1.4"), + ("half_expand", UnsignedRoundingMode::HalfExpand, "0.4", "0.6", "0.6", "1.6"), + ("half_trunc", UnsignedRoundingMode::HalfTrunc, "0.4", "0.4", "0.6", "1.4"), + ("half_even", UnsignedRoundingMode::HalfEven, "0.4", "0.4", "0.6", "1.6"), ]), ("five", RoundingIncrement::MultiplesOf5, [ - ("ceil", RoundingMode::Ceil, "-1.5", "0.5", "0.5", "1.0", "1.5"), - ("floor", RoundingMode::Floor, "-1.5", "0.0", "0.5", "0.5", "1.5"), - ("expand", RoundingMode::Expand, "-1.5", "0.5", "0.5", "1.0", "1.5"), - ("trunc", RoundingMode::Trunc, "-1.5", "0.0", "0.5", "0.5", "1.5"), - ("half_ceil", RoundingMode::HalfCeil, "-1.5", "0.5", "0.5", "0.5", "1.5"), - ("half_floor", RoundingMode::HalfFloor, "-1.5", "0.5", "0.5", "0.5", "1.5"), - ("half_expand", RoundingMode::HalfExpand, "-1.5", "0.5", "0.5", "0.5", "1.5"), - ("half_trunc", RoundingMode::HalfTrunc, "-1.5", "0.5", "0.5", "0.5", "1.5"), - ("half_even", RoundingMode::HalfEven, "-1.5", "0.5", "0.5", "0.5", "1.5"), + ("expand", UnsignedRoundingMode::Expand, "0.5", "0.5", "1.0", "1.5"), + ("trunc", UnsignedRoundingMode::Trunc, "0.0", "0.5", "0.5", "1.5"), + ("half_expand", UnsignedRoundingMode::HalfExpand, "0.5", "0.5", "0.5", "1.5"), + ("half_trunc", UnsignedRoundingMode::HalfTrunc, "0.5", "0.5", "0.5", "1.5"), + ("half_even", UnsignedRoundingMode::HalfEven, "0.5", "0.5", "0.5", "1.5"), ]), ("twenty-five", RoundingIncrement::MultiplesOf25, [ - ("ceil", RoundingMode::Ceil, "-0.0", "2.5", "2.5", "2.5", "2.5"), - ("floor", RoundingMode::Floor, "-2.5", "0.0", "0.0", "0.0", "0.0"), - ("expand", RoundingMode::Expand, "-2.5", "2.5", "2.5", "2.5", "2.5"), - ("trunc", RoundingMode::Trunc, "-0.0", "0.0", "0.0", "0.0", "0.0"), - ("half_ceil", RoundingMode::HalfCeil, "-2.5", "0.0", "0.0", "0.0", "2.5"), - ("half_floor", RoundingMode::HalfFloor, "-2.5", "0.0", "0.0", "0.0", "2.5"), - ("half_expand", RoundingMode::HalfExpand, "-2.5", "0.0", "0.0", "0.0", "2.5"), - ("half_trunc", RoundingMode::HalfTrunc, "-2.5", "0.0", "0.0", "0.0", "2.5"), - ("half_even", RoundingMode::HalfEven, "-2.5", "0.0", "0.0", "0.0", "2.5"), + ("expand", UnsignedRoundingMode::Expand, "2.5", "2.5", "2.5", "2.5"), + ("trunc", UnsignedRoundingMode::Trunc, "0.0", "0.0", "0.0", "0.0"), + ("half_expand", UnsignedRoundingMode::HalfExpand, "0.0", "0.0", "0.0", "2.5"), + ("half_trunc", UnsignedRoundingMode::HalfTrunc, "0.0", "0.0", "0.0", "2.5"), + ("half_even", UnsignedRoundingMode::HalfEven, "0.0", "0.0", "0.0", "2.5"), ]), ]; for (increment_str, increment, cases) in cases { - for (rounding_mode_name, rounding_mode, 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(); + for (rounding_mode_name, rounding_mode, e2, e3, e4, e5) in cases { + let mut fd2: UnsignedFixedDecimal = "0.4".parse().unwrap(); + let mut fd3: UnsignedFixedDecimal = "0.5".parse().unwrap(); + let mut fd4: UnsignedFixedDecimal = "0.6".parse().unwrap(); + let mut fd5: UnsignedFixedDecimal = "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. - fd1.round_with_mode_and_increment(-1, rounding_mode, increment); fd2.round_with_mode_and_increment(-1, rounding_mode, increment); fd3.round_with_mode_and_increment(-1, rounding_mode, increment); fd4.round_with_mode_and_increment(-1, rounding_mode, increment); fd5.round_with_mode_and_increment(-1, rounding_mode, increment); - assert_eq!( - fd1.write_to_string(), - e1, - "-1.5 failed for {rounding_mode_name} with increments of {increment_str}" - ); + assert_eq!( fd2.write_to_string(), e2, diff --git a/utils/fixed_decimal/tests/signed_rounding.rs b/utils/fixed_decimal/tests/signed_rounding.rs new file mode 100644 index 00000000000..94c9650fd3f --- /dev/null +++ b/utils/fixed_decimal/tests/signed_rounding.rs @@ -0,0 +1,448 @@ +// 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 ). + +use core::ops::RangeInclusive; +use fixed_decimal::Sign; +use fixed_decimal::SignedFixedDecimal; +use fixed_decimal::SignedRoundingMode as SRM; +use fixed_decimal::UnsignedRoundingMode as URM; +use writeable::Writeable; + +#[test] +pub fn test_ecma402_table() { + // Source: + let cases: [(_, _, _, _, _, _, _); 9] = [ + ("ceil", SRM::Ceil, -1, 1, 1, 1, 2), + ("floor", SRM::Floor, -2, 0, 0, 0, 1), + ("expand", SRM::Unsigned(URM::Expand), -2, 1, 1, 1, 2), + ("trunc", SRM::Unsigned(URM::Trunc), -1, 0, 0, 0, 1), + ("half_ceil", SRM::HalfCeil, -1, 0, 1, 1, 2), + ("half_floor", SRM::HalfFloor, -2, 0, 0, 1, 1), + ( + "half_expand", + SRM::Unsigned(URM::HalfExpand), + -2, + 0, + 1, + 1, + 2, + ), + ("half_trunc", SRM::Unsigned(URM::HalfTrunc), -1, 0, 0, 1, 1), + ("half_even", SRM::Unsigned(URM::HalfEven), -2, 0, 0, 1, 2), + ]; + for (name, mode, e1, e2, e3, e4, e5) in cases { + let mut fd1: SignedFixedDecimal = "-1.5".parse().unwrap(); + let mut fd2: SignedFixedDecimal = "0.4".parse().unwrap(); + let mut fd3: SignedFixedDecimal = "0.5".parse().unwrap(); + let mut fd4: SignedFixedDecimal = "0.6".parse().unwrap(); + let mut fd5: SignedFixedDecimal = "1.5".parse().unwrap(); + fd1.round_with_mode(0, mode); + fd2.round_with_mode(0, mode); + fd3.round_with_mode(0, mode); + fd4.round_with_mode(0, mode); + fd5.round_with_mode(0, mode); + assert_eq!( + fd1.write_to_string(), + e1.write_to_string(), + "-1.5 failed for {name}" + ); + assert_eq!( + fd2.write_to_string(), + e2.write_to_string(), + "0.4 failed for {name}" + ); + assert_eq!( + fd3.write_to_string(), + e3.write_to_string(), + "0.5 failed for {name}" + ); + assert_eq!( + fd4.write_to_string(), + e4.write_to_string(), + "0.6 failed for {name}" + ); + assert_eq!( + fd5.write_to_string(), + e5.write_to_string(), + "1.5 failed for {name}" + ); + } +} + +#[test] +pub fn test_within_ranges() { + struct TestCase { + rounding_mode_name: &'static str, + rounding_mode: SRM, + range_n2000: RangeInclusive, + range_n1000: RangeInclusive, + range_0: RangeInclusive, + range_1000: RangeInclusive, + range_2000: RangeInclusive, + } + let cases: [TestCase; 9] = [ + TestCase { + rounding_mode_name: "ceil", + rounding_mode: SRM::Ceil, + range_n2000: -2999..=-2000, + range_n1000: -1999..=-1000, + range_0: -999..=0, + range_1000: 1..=1000, + range_2000: 1001..=2000, + }, + TestCase { + rounding_mode_name: "floor", + rounding_mode: SRM::Floor, + range_n2000: -2000..=-1001, + range_n1000: -1000..=-1, + range_0: 0..=999, + range_1000: 1000..=1999, + range_2000: 2000..=2999, + }, + TestCase { + rounding_mode_name: "expand", + rounding_mode: SRM::Unsigned(URM::Expand), + range_n2000: -2000..=-1001, + range_n1000: -1000..=-1, + range_0: 0..=0, + range_1000: 1..=1000, + range_2000: 1001..=2000, + }, + TestCase { + rounding_mode_name: "trunc", + rounding_mode: SRM::Unsigned(URM::Trunc), + range_n2000: -2999..=-2000, + range_n1000: -1999..=-1000, + range_0: -999..=999, + range_1000: 1000..=1999, + range_2000: 2000..=2999, + }, + TestCase { + rounding_mode_name: "half_ceil", + rounding_mode: SRM::HalfCeil, + range_n2000: -2500..=-1501, + range_n1000: -1500..=-501, + range_0: -500..=449, + range_1000: 500..=1449, + range_2000: 1500..=2449, + }, + TestCase { + rounding_mode_name: "half_floor", + rounding_mode: SRM::HalfFloor, + range_n2000: -2449..=-1500, + range_n1000: -1449..=-500, + range_0: -449..=500, + range_1000: 501..=1500, + range_2000: 1501..=2500, + }, + TestCase { + rounding_mode_name: "half_expand", + rounding_mode: SRM::Unsigned(URM::HalfExpand), + range_n2000: -2449..=-1500, + range_n1000: -1449..=-500, + range_0: -449..=449, + range_1000: 500..=1449, + range_2000: 1500..=2449, + }, + TestCase { + rounding_mode_name: "half_trunc", + rounding_mode: SRM::Unsigned(URM::HalfTrunc), + range_n2000: -2500..=-1501, + range_n1000: -1500..=-501, + range_0: -500..=500, + range_1000: 501..=1500, + range_2000: 1501..=2500, + }, + TestCase { + rounding_mode_name: "half_even", + rounding_mode: SRM::Unsigned(URM::HalfEven), + range_n2000: -2500..=-1500, + range_n1000: -1449..=-501, + range_0: -500..=500, + range_1000: 501..=1449, + range_2000: 1500..=2500, + }, + ]; + for TestCase { + rounding_mode_name, + rounding_mode, + range_n2000, + range_n1000, + range_0, + range_1000, + range_2000, + } in cases + { + for n in range_n2000 { + let mut fd = SignedFixedDecimal::from(n); + fd.round_with_mode(3, rounding_mode); + assert_eq!(fd.write_to_string(), "-2000", "{rounding_mode_name}: {n}"); + let mut fd = SignedFixedDecimal::from(n - 1000000); + fd.multiply_pow10(-5); + fd.round_with_mode(-2, rounding_mode); + assert_eq!( + fd.write_to_string(), + "-10.02", + "{rounding_mode_name}: {n} ÷ 10^5 ± 10" + ); + } + for n in range_n1000 { + let mut fd = SignedFixedDecimal::from(n); + fd.round_with_mode(3, rounding_mode); + assert_eq!(fd.write_to_string(), "-1000", "{rounding_mode_name}: {n}"); + let mut fd = SignedFixedDecimal::from(n - 1000000); + fd.multiply_pow10(-5); + fd.round_with_mode(-2, rounding_mode); + assert_eq!( + fd.write_to_string(), + "-10.01", + "{rounding_mode_name}: {n} ÷ 10^5 ± 10" + ); + } + for n in range_0 { + let mut fd = SignedFixedDecimal::from(n); + fd.round_with_mode(3, rounding_mode); + fd.set_sign(Sign::None); // get rid of -0 + assert_eq!(fd.write_to_string(), "000", "{rounding_mode_name}: {n}"); + + let (mut fd, expected) = if n < 0 { + ( + { + let mut fd = SignedFixedDecimal::from(n - 1000000); + fd.multiply_pow10(-5); + fd + }, + "-10.00", + ) + } else { + ( + { + let mut fd = SignedFixedDecimal::from(n + 1000000); + fd.multiply_pow10(-5); + fd + }, + "10.00", + ) + }; + fd.round_with_mode(-2, rounding_mode); + assert_eq!( + fd.write_to_string(), + expected, + "{rounding_mode_name}: {n} ÷ 10^5 ± 10" + ); + } + for n in range_1000 { + let mut fd = SignedFixedDecimal::from(n); + fd.round_with_mode(3, rounding_mode); + assert_eq!(fd.write_to_string(), "1000", "{rounding_mode_name}: {n}"); + let mut fd = SignedFixedDecimal::from(n + 1000000); + fd.multiply_pow10(-5); + fd.round_with_mode(-2, rounding_mode); + assert_eq!( + fd.write_to_string(), + "10.01", + "{rounding_mode_name}: {n} ÷ 10^5 ± 10" + ); + } + for n in range_2000 { + let mut fd = SignedFixedDecimal::from(n); + fd.round_with_mode(3, rounding_mode); + assert_eq!(fd.write_to_string(), "2000", "{rounding_mode_name}: {n}"); + let mut fd = SignedFixedDecimal::from(n + 1000000); + fd.multiply_pow10(-5); + fd.round_with_mode(-2, rounding_mode); + assert_eq!( + fd.write_to_string(), + "10.02", + "{rounding_mode_name}: {n} ÷ 10^5 ± 10" + ); + } + } +} + +#[test] +pub fn extra_rounding_mode_cases() { + struct TestCase { + input: &'static str, + position: i16, + // ceil, floor, expand, trunc, half_ceil, half_floor, half_expand, half_trunc, half_even + all_expected: [&'static str; 9], + } + let cases: [TestCase; 8] = [ + TestCase { + input: "505.050", + position: -3, + all_expected: [ + "505.050", "505.050", "505.050", "505.050", "505.050", "505.050", "505.050", + "505.050", "505.050", + ], + }, + TestCase { + input: "505.050", + position: -2, + all_expected: [ + "505.05", "505.05", "505.05", "505.05", "505.05", "505.05", "505.05", "505.05", + "505.05", + ], + }, + TestCase { + input: "505.050", + position: -1, + all_expected: [ + "505.1", "505.0", "505.1", "505.0", "505.1", "505.0", "505.1", "505.0", "505.0", + ], + }, + TestCase { + input: "505.050", + position: 0, + all_expected: [ + "506", "505", "506", "505", "505", "505", "505", "505", "505", + ], + }, + TestCase { + input: "505.050", + position: 1, + all_expected: [ + "510", "500", "510", "500", "510", "510", "510", "510", "510", + ], + }, + TestCase { + input: "505.050", + position: 2, + all_expected: [ + "600", "500", "600", "500", "500", "500", "500", "500", "500", + ], + }, + TestCase { + input: "505.050", + position: 3, + all_expected: [ + "1000", "000", "1000", "000", "1000", "1000", "1000", "1000", "1000", + ], + }, + TestCase { + input: "505.050", + position: 4, + all_expected: [ + "10000", "0000", "10000", "0000", "0000", "0000", "0000", "0000", "0000", + ], + }, + ]; + #[allow(clippy::type_complexity)] // most compact representation in code + let rounding_modes: [(&'static str, SRM); 9] = [ + ("ceil", SRM::Ceil), + ("floor", SRM::Floor), + ("expand", SRM::Unsigned(URM::Expand)), + ("trunc", SRM::Unsigned(URM::Trunc)), + ("half_ceil", SRM::HalfCeil), + ("half_floor", SRM::HalfFloor), + ("half_expand", SRM::Unsigned(URM::HalfExpand)), + ("half_trunc", SRM::Unsigned(URM::HalfTrunc)), + ("half_even", SRM::Unsigned(URM::HalfEven)), + ]; + for TestCase { + input, + position, + all_expected, + } in cases + { + for ((rounding_mode_name, rounding_mode), expected) in + rounding_modes.iter().zip(all_expected.iter()) + { + let mut fd: SignedFixedDecimal = input.parse().unwrap(); + fd.round_with_mode(position, *rounding_mode); + assert_eq!( + &*fd.write_to_string(), + *expected, + "{input}: {rounding_mode_name} @ {position}" + ) + } + } +} + +#[test] +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: [(_, _, [(_, _, _, _, _, _, _); 9]); 3] = [ + ("two", RoundingIncrement::MultiplesOf2, [ + ("ceil", SRM::Ceil, "-1.4", "0.4", "0.6", "0.6", "1.6"), + ("floor", SRM::Floor, "-1.6", "0.4", "0.4", "0.6", "1.4"), + ("expand", SRM::Unsigned(URM::Expand), "-1.6", "0.4", "0.6", "0.6", "1.6"), + ("trunc", SRM::Unsigned(URM::Trunc), "-1.4", "0.4", "0.4", "0.6", "1.4"), + ("half_ceil", SRM::HalfCeil, "-1.4", "0.4", "0.6", "0.6", "1.6"), + ("half_floor", SRM::HalfFloor, "-1.6", "0.4", "0.4", "0.6", "1.4"), + ("half_expand", SRM::Unsigned(URM::HalfExpand), "-1.6", "0.4", "0.6", "0.6", "1.6"), + ("half_trunc", SRM::Unsigned(URM::HalfTrunc), "-1.4", "0.4", "0.4", "0.6", "1.4"), + ("half_even", SRM::Unsigned(URM::HalfEven), "-1.6", "0.4", "0.4", "0.6", "1.6"), + ]), + ("five", RoundingIncrement::MultiplesOf5, [ + ("ceil", SRM::Ceil, "-1.5", "0.5", "0.5", "1.0", "1.5"), + ("floor", SRM::Floor, "-1.5", "0.0", "0.5", "0.5", "1.5"), + ("expand", SRM::Unsigned(URM::Expand), "-1.5", "0.5", "0.5", "1.0", "1.5"), + ("trunc", SRM::Unsigned(URM::Trunc), "-1.5", "0.0", "0.5", "0.5", "1.5"), + ("half_ceil", SRM::HalfCeil, "-1.5", "0.5", "0.5", "0.5", "1.5"), + ("half_floor", SRM::HalfFloor, "-1.5", "0.5", "0.5", "0.5", "1.5"), + ("half_expand", SRM::Unsigned(URM::HalfExpand), "-1.5", "0.5", "0.5", "0.5", "1.5"), + ("half_trunc", SRM::Unsigned(URM::HalfTrunc), "-1.5", "0.5", "0.5", "0.5", "1.5"), + ("half_even", SRM::Unsigned(URM::HalfEven), "-1.5", "0.5", "0.5", "0.5", "1.5"), + ]), + ("twenty-five", RoundingIncrement::MultiplesOf25, [ + ("ceil", SRM::Ceil, "-0.0", "2.5", "2.5", "2.5", "2.5"), + ("floor", SRM::Floor, "-2.5", "0.0", "0.0", "0.0", "0.0"), + ("expand", SRM::Unsigned(URM::Expand), "-2.5", "2.5", "2.5", "2.5", "2.5"), + ("trunc", SRM::Unsigned(URM::Trunc), "-0.0", "0.0", "0.0", "0.0", "0.0"), + ("half_ceil", SRM::HalfCeil, "-2.5", "0.0", "0.0", "0.0", "2.5"), + ("half_floor", SRM::HalfFloor, "-2.5", "0.0", "0.0", "0.0", "2.5"), + ("half_expand", SRM::Unsigned(URM::HalfExpand), "-2.5", "0.0", "0.0", "0.0", "2.5"), + ("half_trunc", SRM::Unsigned(URM::HalfTrunc), "-2.5", "0.0", "0.0", "0.0", "2.5"), + ("half_even", SRM::Unsigned(URM::HalfEven), "-2.5", "0.0", "0.0", "0.0", "2.5"), + ]), + ]; + + for (increment_str, increment, cases) in cases { + for (rounding_mode_name, rounding_mode, e1, e2, e3, e4, e5) in cases { + let mut fd1: SignedFixedDecimal = "-1.5".parse().unwrap(); + let mut fd2: SignedFixedDecimal = "0.4".parse().unwrap(); + let mut fd3: SignedFixedDecimal = "0.5".parse().unwrap(); + let mut fd4: SignedFixedDecimal = "0.6".parse().unwrap(); + let mut fd5: SignedFixedDecimal = "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. + fd1.round_with_mode_and_increment(-1, rounding_mode, increment); + fd2.round_with_mode_and_increment(-1, rounding_mode, increment); + fd3.round_with_mode_and_increment(-1, rounding_mode, increment); + fd4.round_with_mode_and_increment(-1, rounding_mode, increment); + fd5.round_with_mode_and_increment(-1, rounding_mode, increment); + assert_eq!( + fd1.write_to_string(), + e1, + "-1.5 failed for {rounding_mode_name} with increments of {increment_str}" + ); + assert_eq!( + fd2.write_to_string(), + e2, + "0.4 failed for {rounding_mode_name} with increments of {increment_str}" + ); + assert_eq!( + fd3.write_to_string(), + e3, + "0.5 failed for {rounding_mode_name} with increments of {increment_str}" + ); + assert_eq!( + fd4.write_to_string(), + e4, + "0.6 failed for {rounding_mode_name} with increments of {increment_str}" + ); + assert_eq!( + fd5.write_to_string(), + e5, + "1.5 failed for {rounding_mode_name} with increments of {increment_str}" + ); + } + } +}