From 861dbd203c5c22bb66bdd23581c8d2e7bb90d6dc Mon Sep 17 00:00:00 2001 From: jedel1043 Date: Wed, 1 Nov 2023 18:10:50 -0600 Subject: [PATCH] Implement remaining round to increment methods --- ffi/capi/c/include/ICU4XFixedDecimal.h | 14 + .../cpp/docs/source/fixed_decimal_ffi.rst | 35 + ffi/capi/cpp/include/ICU4XFixedDecimal.h | 14 + ffi/capi/cpp/include/ICU4XFixedDecimal.hpp | 70 + ffi/capi/js/docs/source/fixed_decimal_ffi.rst | 35 + ffi/capi/js/include/ICU4XFixedDecimal.d.ts | 42 + ffi/capi/js/include/ICU4XFixedDecimal.js | 28 + ffi/capi/src/fixed_decimal.rs | 78 + utils/fixed_decimal/src/decimal.rs | 1382 +++++++++++++++-- 9 files changed, 1604 insertions(+), 94 deletions(-) diff --git a/ffi/capi/c/include/ICU4XFixedDecimal.h b/ffi/capi/c/include/ICU4XFixedDecimal.h index b8de62c2bdd..8725e74cbee 100644 --- a/ffi/capi/c/include/ICU4XFixedDecimal.h +++ b/ffi/capi/c/include/ICU4XFixedDecimal.h @@ -78,22 +78,36 @@ void ICU4XFixedDecimal_trunc_to_increment(ICU4XFixedDecimal* self, int16_t posit void ICU4XFixedDecimal_half_trunc(ICU4XFixedDecimal* self, int16_t position); +void ICU4XFixedDecimal_half_trunc_to_increment(ICU4XFixedDecimal* self, int16_t position, ICU4XRoundingIncrement increment); + void ICU4XFixedDecimal_expand(ICU4XFixedDecimal* self, int16_t position); void ICU4XFixedDecimal_expand_to_increment(ICU4XFixedDecimal* self, int16_t position, ICU4XRoundingIncrement increment); void ICU4XFixedDecimal_half_expand(ICU4XFixedDecimal* self, int16_t position); +void ICU4XFixedDecimal_half_expand_to_increment(ICU4XFixedDecimal* self, int16_t position, ICU4XRoundingIncrement increment); + void ICU4XFixedDecimal_ceil(ICU4XFixedDecimal* self, int16_t position); +void ICU4XFixedDecimal_ceil_to_increment(ICU4XFixedDecimal* self, int16_t position, ICU4XRoundingIncrement increment); + void ICU4XFixedDecimal_half_ceil(ICU4XFixedDecimal* self, int16_t position); +void ICU4XFixedDecimal_half_ceil_to_increment(ICU4XFixedDecimal* self, int16_t position, ICU4XRoundingIncrement increment); + void ICU4XFixedDecimal_floor(ICU4XFixedDecimal* self, int16_t position); +void ICU4XFixedDecimal_floor_to_increment(ICU4XFixedDecimal* self, int16_t position, ICU4XRoundingIncrement increment); + void ICU4XFixedDecimal_half_floor(ICU4XFixedDecimal* self, int16_t position); +void ICU4XFixedDecimal_half_floor_to_increment(ICU4XFixedDecimal* self, int16_t position, ICU4XRoundingIncrement increment); + void ICU4XFixedDecimal_half_even(ICU4XFixedDecimal* self, int16_t position); +void ICU4XFixedDecimal_half_even_to_increment(ICU4XFixedDecimal* self, int16_t position, ICU4XRoundingIncrement increment); + diplomat_result_void_void ICU4XFixedDecimal_concatenate_end(ICU4XFixedDecimal* self, ICU4XFixedDecimal* other); void ICU4XFixedDecimal_to_string(const ICU4XFixedDecimal* self, DiplomatWriteable* to); diff --git a/ffi/capi/cpp/docs/source/fixed_decimal_ffi.rst b/ffi/capi/cpp/docs/source/fixed_decimal_ffi.rst index 99baa77e6f1..6e36bf89dc4 100644 --- a/ffi/capi/cpp/docs/source/fixed_decimal_ffi.rst +++ b/ffi/capi/cpp/docs/source/fixed_decimal_ffi.rst @@ -177,6 +177,11 @@ See the `Rust documentation for half_trunc `__ for more information. + .. cpp:function:: void half_trunc_to_increment(int16_t position, ICU4XRoundingIncrement increment) + + See the `Rust documentation for half_trunc_to_increment `__ for more information. + + .. cpp:function:: void expand(int16_t position) See the `Rust documentation for expand `__ for more information. @@ -192,31 +197,61 @@ See the `Rust documentation for half_expand `__ for more information. + .. cpp:function:: void half_expand_to_increment(int16_t position, ICU4XRoundingIncrement increment) + + See the `Rust documentation for half_expand_to_increment `__ for more information. + + .. cpp:function:: void ceil(int16_t position) See the `Rust documentation for ceil `__ for more information. + .. cpp:function:: void ceil_to_increment(int16_t position, ICU4XRoundingIncrement increment) + + See the `Rust documentation for ceil_to_increment `__ for more information. + + .. cpp:function:: void half_ceil(int16_t position) See the `Rust documentation for half_ceil `__ for more information. + .. cpp:function:: void half_ceil_to_increment(int16_t position, ICU4XRoundingIncrement increment) + + See the `Rust documentation for half_ceil_to_increment `__ for more information. + + .. cpp:function:: void floor(int16_t position) See the `Rust documentation for floor `__ for more information. + .. cpp:function:: void floor_to_increment(int16_t position, ICU4XRoundingIncrement increment) + + See the `Rust documentation for floor_to_increment `__ for more information. + + .. cpp:function:: void half_floor(int16_t position) See the `Rust documentation for half_floor `__ for more information. + .. cpp:function:: void half_floor_to_increment(int16_t position, ICU4XRoundingIncrement increment) + + See the `Rust documentation for half_floor_to_increment `__ for more information. + + .. cpp:function:: void half_even(int16_t position) See the `Rust documentation for half_even `__ for more information. + .. cpp:function:: void half_even_to_increment(int16_t position, ICU4XRoundingIncrement increment) + + See the `Rust documentation for half_even_to_increment `__ for more information. + + .. cpp:function:: diplomat::result concatenate_end(ICU4XFixedDecimal& other) Concatenates ``other`` to the end of ``self``. diff --git a/ffi/capi/cpp/include/ICU4XFixedDecimal.h b/ffi/capi/cpp/include/ICU4XFixedDecimal.h index b8de62c2bdd..8725e74cbee 100644 --- a/ffi/capi/cpp/include/ICU4XFixedDecimal.h +++ b/ffi/capi/cpp/include/ICU4XFixedDecimal.h @@ -78,22 +78,36 @@ void ICU4XFixedDecimal_trunc_to_increment(ICU4XFixedDecimal* self, int16_t posit void ICU4XFixedDecimal_half_trunc(ICU4XFixedDecimal* self, int16_t position); +void ICU4XFixedDecimal_half_trunc_to_increment(ICU4XFixedDecimal* self, int16_t position, ICU4XRoundingIncrement increment); + void ICU4XFixedDecimal_expand(ICU4XFixedDecimal* self, int16_t position); void ICU4XFixedDecimal_expand_to_increment(ICU4XFixedDecimal* self, int16_t position, ICU4XRoundingIncrement increment); void ICU4XFixedDecimal_half_expand(ICU4XFixedDecimal* self, int16_t position); +void ICU4XFixedDecimal_half_expand_to_increment(ICU4XFixedDecimal* self, int16_t position, ICU4XRoundingIncrement increment); + void ICU4XFixedDecimal_ceil(ICU4XFixedDecimal* self, int16_t position); +void ICU4XFixedDecimal_ceil_to_increment(ICU4XFixedDecimal* self, int16_t position, ICU4XRoundingIncrement increment); + void ICU4XFixedDecimal_half_ceil(ICU4XFixedDecimal* self, int16_t position); +void ICU4XFixedDecimal_half_ceil_to_increment(ICU4XFixedDecimal* self, int16_t position, ICU4XRoundingIncrement increment); + void ICU4XFixedDecimal_floor(ICU4XFixedDecimal* self, int16_t position); +void ICU4XFixedDecimal_floor_to_increment(ICU4XFixedDecimal* self, int16_t position, ICU4XRoundingIncrement increment); + void ICU4XFixedDecimal_half_floor(ICU4XFixedDecimal* self, int16_t position); +void ICU4XFixedDecimal_half_floor_to_increment(ICU4XFixedDecimal* self, int16_t position, ICU4XRoundingIncrement increment); + void ICU4XFixedDecimal_half_even(ICU4XFixedDecimal* self, int16_t position); +void ICU4XFixedDecimal_half_even_to_increment(ICU4XFixedDecimal* self, int16_t position, ICU4XRoundingIncrement increment); + diplomat_result_void_void ICU4XFixedDecimal_concatenate_end(ICU4XFixedDecimal* self, ICU4XFixedDecimal* other); void ICU4XFixedDecimal_to_string(const ICU4XFixedDecimal* self, DiplomatWriteable* to); diff --git a/ffi/capi/cpp/include/ICU4XFixedDecimal.hpp b/ffi/capi/cpp/include/ICU4XFixedDecimal.hpp index 8dff04e6307..060a36c9cf4 100644 --- a/ffi/capi/cpp/include/ICU4XFixedDecimal.hpp +++ b/ffi/capi/cpp/include/ICU4XFixedDecimal.hpp @@ -233,6 +233,13 @@ class ICU4XFixedDecimal { */ void half_trunc(int16_t position); + /** + * + * + * See the [Rust documentation for `half_trunc_to_increment`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.half_trunc_to_increment) for more information. + */ + void half_trunc_to_increment(int16_t position, ICU4XRoundingIncrement increment); + /** * * @@ -254,6 +261,13 @@ class ICU4XFixedDecimal { */ void half_expand(int16_t position); + /** + * + * + * See the [Rust documentation for `half_expand_to_increment`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.half_expand_to_increment) for more information. + */ + void half_expand_to_increment(int16_t position, ICU4XRoundingIncrement increment); + /** * * @@ -261,6 +275,13 @@ class ICU4XFixedDecimal { */ void ceil(int16_t position); + /** + * + * + * See the [Rust documentation for `ceil_to_increment`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.ceil_to_increment) for more information. + */ + void ceil_to_increment(int16_t position, ICU4XRoundingIncrement increment); + /** * * @@ -268,6 +289,13 @@ class ICU4XFixedDecimal { */ void half_ceil(int16_t position); + /** + * + * + * See the [Rust documentation for `half_ceil_to_increment`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.half_ceil_to_increment) for more information. + */ + void half_ceil_to_increment(int16_t position, ICU4XRoundingIncrement increment); + /** * * @@ -275,6 +303,13 @@ class ICU4XFixedDecimal { */ void floor(int16_t position); + /** + * + * + * See the [Rust documentation for `floor_to_increment`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.floor_to_increment) for more information. + */ + void floor_to_increment(int16_t position, ICU4XRoundingIncrement increment); + /** * * @@ -282,6 +317,13 @@ class ICU4XFixedDecimal { */ void half_floor(int16_t position); + /** + * + * + * See the [Rust documentation for `half_floor_to_increment`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.half_floor_to_increment) for more information. + */ + void half_floor_to_increment(int16_t position, ICU4XRoundingIncrement increment); + /** * * @@ -289,6 +331,13 @@ class ICU4XFixedDecimal { */ void half_even(int16_t position); + /** + * + * + * See the [Rust documentation for `half_even_to_increment`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.half_even_to_increment) for more information. + */ + void half_even_to_increment(int16_t position, ICU4XRoundingIncrement increment); + /** * Concatenates `other` to the end of `self`. * @@ -440,6 +489,9 @@ inline void ICU4XFixedDecimal::trunc_to_increment(int16_t position, ICU4XRoundin inline void ICU4XFixedDecimal::half_trunc(int16_t position) { capi::ICU4XFixedDecimal_half_trunc(this->inner.get(), position); } +inline void ICU4XFixedDecimal::half_trunc_to_increment(int16_t position, ICU4XRoundingIncrement increment) { + capi::ICU4XFixedDecimal_half_trunc_to_increment(this->inner.get(), position, static_cast(increment)); +} inline void ICU4XFixedDecimal::expand(int16_t position) { capi::ICU4XFixedDecimal_expand(this->inner.get(), position); } @@ -449,21 +501,39 @@ inline void ICU4XFixedDecimal::expand_to_increment(int16_t position, ICU4XRoundi inline void ICU4XFixedDecimal::half_expand(int16_t position) { capi::ICU4XFixedDecimal_half_expand(this->inner.get(), position); } +inline void ICU4XFixedDecimal::half_expand_to_increment(int16_t position, ICU4XRoundingIncrement increment) { + capi::ICU4XFixedDecimal_half_expand_to_increment(this->inner.get(), position, static_cast(increment)); +} inline void ICU4XFixedDecimal::ceil(int16_t position) { capi::ICU4XFixedDecimal_ceil(this->inner.get(), position); } +inline void ICU4XFixedDecimal::ceil_to_increment(int16_t position, ICU4XRoundingIncrement increment) { + capi::ICU4XFixedDecimal_ceil_to_increment(this->inner.get(), position, static_cast(increment)); +} inline void ICU4XFixedDecimal::half_ceil(int16_t position) { capi::ICU4XFixedDecimal_half_ceil(this->inner.get(), position); } +inline void ICU4XFixedDecimal::half_ceil_to_increment(int16_t position, ICU4XRoundingIncrement increment) { + capi::ICU4XFixedDecimal_half_ceil_to_increment(this->inner.get(), position, static_cast(increment)); +} inline void ICU4XFixedDecimal::floor(int16_t position) { capi::ICU4XFixedDecimal_floor(this->inner.get(), position); } +inline void ICU4XFixedDecimal::floor_to_increment(int16_t position, ICU4XRoundingIncrement increment) { + capi::ICU4XFixedDecimal_floor_to_increment(this->inner.get(), position, static_cast(increment)); +} inline void ICU4XFixedDecimal::half_floor(int16_t position) { capi::ICU4XFixedDecimal_half_floor(this->inner.get(), position); } +inline void ICU4XFixedDecimal::half_floor_to_increment(int16_t position, ICU4XRoundingIncrement increment) { + capi::ICU4XFixedDecimal_half_floor_to_increment(this->inner.get(), position, static_cast(increment)); +} inline void ICU4XFixedDecimal::half_even(int16_t position) { capi::ICU4XFixedDecimal_half_even(this->inner.get(), position); } +inline void ICU4XFixedDecimal::half_even_to_increment(int16_t position, ICU4XRoundingIncrement increment) { + capi::ICU4XFixedDecimal_half_even_to_increment(this->inner.get(), position, static_cast(increment)); +} inline diplomat::result ICU4XFixedDecimal::concatenate_end(ICU4XFixedDecimal& other) { auto diplomat_result_raw_out_value = capi::ICU4XFixedDecimal_concatenate_end(this->inner.get(), other.AsFFIMut()); diplomat::result diplomat_result_out_value; diff --git a/ffi/capi/js/docs/source/fixed_decimal_ffi.rst b/ffi/capi/js/docs/source/fixed_decimal_ffi.rst index b8828c6e866..05600edf1a9 100644 --- a/ffi/capi/js/docs/source/fixed_decimal_ffi.rst +++ b/ffi/capi/js/docs/source/fixed_decimal_ffi.rst @@ -177,6 +177,11 @@ See the `Rust documentation for half_trunc `__ for more information. + .. js:method:: half_trunc_to_increment(position, increment) + + See the `Rust documentation for half_trunc_to_increment `__ for more information. + + .. js:method:: expand(position) See the `Rust documentation for expand `__ for more information. @@ -192,31 +197,61 @@ See the `Rust documentation for half_expand `__ for more information. + .. js:method:: half_expand_to_increment(position, increment) + + See the `Rust documentation for half_expand_to_increment `__ for more information. + + .. js:method:: ceil(position) See the `Rust documentation for ceil `__ for more information. + .. js:method:: ceil_to_increment(position, increment) + + See the `Rust documentation for ceil_to_increment `__ for more information. + + .. js:method:: half_ceil(position) See the `Rust documentation for half_ceil `__ for more information. + .. js:method:: half_ceil_to_increment(position, increment) + + See the `Rust documentation for half_ceil_to_increment `__ for more information. + + .. js:method:: floor(position) See the `Rust documentation for floor `__ for more information. + .. js:method:: floor_to_increment(position, increment) + + See the `Rust documentation for floor_to_increment `__ for more information. + + .. js:method:: half_floor(position) See the `Rust documentation for half_floor `__ for more information. + .. js:method:: half_floor_to_increment(position, increment) + + See the `Rust documentation for half_floor_to_increment `__ for more information. + + .. js:method:: half_even(position) See the `Rust documentation for half_even `__ for more information. + .. js:method:: half_even_to_increment(position, increment) + + See the `Rust documentation for half_even_to_increment `__ for more information. + + .. js:method:: concatenate_end(other) Concatenates ``other`` to the end of ``self``. diff --git a/ffi/capi/js/include/ICU4XFixedDecimal.d.ts b/ffi/capi/js/include/ICU4XFixedDecimal.d.ts index 8107f34450c..25b9d03cb36 100644 --- a/ffi/capi/js/include/ICU4XFixedDecimal.d.ts +++ b/ffi/capi/js/include/ICU4XFixedDecimal.d.ts @@ -214,6 +214,12 @@ export class ICU4XFixedDecimal { */ half_trunc(position: i16): void; + /** + + * See the {@link https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.half_trunc_to_increment Rust documentation for `half_trunc_to_increment`} for more information. + */ + half_trunc_to_increment(position: i16, increment: ICU4XRoundingIncrement): void; + /** * See the {@link https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.expand Rust documentation for `expand`} for more information. @@ -232,36 +238,72 @@ export class ICU4XFixedDecimal { */ half_expand(position: i16): void; + /** + + * See the {@link https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.half_expand_to_increment Rust documentation for `half_expand_to_increment`} for more information. + */ + half_expand_to_increment(position: i16, increment: ICU4XRoundingIncrement): void; + /** * See the {@link https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.ceil Rust documentation for `ceil`} for more information. */ ceil(position: i16): void; + /** + + * See the {@link https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.ceil_to_increment Rust documentation for `ceil_to_increment`} for more information. + */ + ceil_to_increment(position: i16, increment: ICU4XRoundingIncrement): void; + /** * See the {@link https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.half_ceil Rust documentation for `half_ceil`} for more information. */ half_ceil(position: i16): void; + /** + + * See the {@link https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.half_ceil_to_increment Rust documentation for `half_ceil_to_increment`} for more information. + */ + half_ceil_to_increment(position: i16, increment: ICU4XRoundingIncrement): void; + /** * See the {@link https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.floor Rust documentation for `floor`} for more information. */ floor(position: i16): void; + /** + + * See the {@link https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.floor_to_increment Rust documentation for `floor_to_increment`} for more information. + */ + floor_to_increment(position: i16, increment: ICU4XRoundingIncrement): void; + /** * See the {@link https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.half_floor Rust documentation for `half_floor`} for more information. */ half_floor(position: i16): void; + /** + + * See the {@link https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.half_floor_to_increment Rust documentation for `half_floor_to_increment`} for more information. + */ + half_floor_to_increment(position: i16, increment: ICU4XRoundingIncrement): void; + /** * See the {@link https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.half_even Rust documentation for `half_even`} for more information. */ half_even(position: i16): void; + /** + + * See the {@link https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.half_even_to_increment Rust documentation for `half_even_to_increment`} for more information. + */ + half_even_to_increment(position: i16, increment: ICU4XRoundingIncrement): void; + /** * Concatenates `other` to the end of `self`. diff --git a/ffi/capi/js/include/ICU4XFixedDecimal.js b/ffi/capi/js/include/ICU4XFixedDecimal.js index 5a4db0bf25a..931a3abd8c4 100644 --- a/ffi/capi/js/include/ICU4XFixedDecimal.js +++ b/ffi/capi/js/include/ICU4XFixedDecimal.js @@ -195,6 +195,10 @@ export class ICU4XFixedDecimal { wasm.ICU4XFixedDecimal_half_trunc(this.underlying, arg_position); } + half_trunc_to_increment(arg_position, arg_increment) { + wasm.ICU4XFixedDecimal_half_trunc_to_increment(this.underlying, arg_position, ICU4XRoundingIncrement_js_to_rust[arg_increment]); + } + expand(arg_position) { wasm.ICU4XFixedDecimal_expand(this.underlying, arg_position); } @@ -207,26 +211,50 @@ export class ICU4XFixedDecimal { wasm.ICU4XFixedDecimal_half_expand(this.underlying, arg_position); } + half_expand_to_increment(arg_position, arg_increment) { + wasm.ICU4XFixedDecimal_half_expand_to_increment(this.underlying, arg_position, ICU4XRoundingIncrement_js_to_rust[arg_increment]); + } + ceil(arg_position) { wasm.ICU4XFixedDecimal_ceil(this.underlying, arg_position); } + ceil_to_increment(arg_position, arg_increment) { + wasm.ICU4XFixedDecimal_ceil_to_increment(this.underlying, arg_position, ICU4XRoundingIncrement_js_to_rust[arg_increment]); + } + half_ceil(arg_position) { wasm.ICU4XFixedDecimal_half_ceil(this.underlying, arg_position); } + half_ceil_to_increment(arg_position, arg_increment) { + wasm.ICU4XFixedDecimal_half_ceil_to_increment(this.underlying, arg_position, ICU4XRoundingIncrement_js_to_rust[arg_increment]); + } + floor(arg_position) { wasm.ICU4XFixedDecimal_floor(this.underlying, arg_position); } + floor_to_increment(arg_position, arg_increment) { + wasm.ICU4XFixedDecimal_floor_to_increment(this.underlying, arg_position, ICU4XRoundingIncrement_js_to_rust[arg_increment]); + } + half_floor(arg_position) { wasm.ICU4XFixedDecimal_half_floor(this.underlying, arg_position); } + half_floor_to_increment(arg_position, arg_increment) { + wasm.ICU4XFixedDecimal_half_floor_to_increment(this.underlying, arg_position, ICU4XRoundingIncrement_js_to_rust[arg_increment]); + } + half_even(arg_position) { wasm.ICU4XFixedDecimal_half_even(this.underlying, arg_position); } + half_even_to_increment(arg_position, arg_increment) { + wasm.ICU4XFixedDecimal_half_even_to_increment(this.underlying, arg_position, ICU4XRoundingIncrement_js_to_rust[arg_increment]); + } + concatenate_end(arg_other) { return (() => { const is_ok = wasm.ICU4XFixedDecimal_concatenate_end(this.underlying, arg_other.underlying) == 1; diff --git a/ffi/capi/src/fixed_decimal.rs b/ffi/capi/src/fixed_decimal.rs index e64ccb7aaae..194ff17f8e9 100644 --- a/ffi/capi/src/fixed_decimal.rs +++ b/ffi/capi/src/fixed_decimal.rs @@ -246,6 +246,20 @@ pub mod ffi { self.0.half_trunc(position) } + #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_trunc_to_increment, FnInStruct)] + #[diplomat::rust_link( + fixed_decimal::FixedDecimal::half_trunced_to_increment, + FnInStruct, + hidden + )] + pub fn half_trunc_to_increment( + &mut self, + position: i16, + increment: ICU4XRoundingIncrement, + ) { + self.0.half_trunc_to_increment(position, increment.into()) + } + #[diplomat::rust_link(fixed_decimal::FixedDecimal::expand, FnInStruct)] #[diplomat::rust_link(fixed_decimal::FixedDecimal::expanded, FnInStruct, hidden)] pub fn expand(&mut self, position: i16) { @@ -268,36 +282,100 @@ pub mod ffi { self.0.half_expand(position) } + #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_expand_to_increment, FnInStruct)] + #[diplomat::rust_link( + fixed_decimal::FixedDecimal::half_expanded_to_increment, + FnInStruct, + hidden + )] + pub fn half_expand_to_increment( + &mut self, + position: i16, + increment: ICU4XRoundingIncrement, + ) { + self.0.half_expand_to_increment(position, increment.into()) + } + #[diplomat::rust_link(fixed_decimal::FixedDecimal::ceil, FnInStruct)] #[diplomat::rust_link(fixed_decimal::FixedDecimal::ceiled, FnInStruct, hidden)] pub fn ceil(&mut self, position: i16) { self.0.ceil(position) } + #[diplomat::rust_link(fixed_decimal::FixedDecimal::ceil_to_increment, FnInStruct)] + #[diplomat::rust_link(fixed_decimal::FixedDecimal::ceiled_to_increment, FnInStruct, hidden)] + pub fn ceil_to_increment(&mut self, position: i16, increment: ICU4XRoundingIncrement) { + self.0.ceil_to_increment(position, increment.into()) + } + #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_ceil, FnInStruct)] #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_ceiled, FnInStruct, hidden)] pub fn half_ceil(&mut self, position: i16) { self.0.half_ceil(position) } + #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_ceil_to_increment, FnInStruct)] + #[diplomat::rust_link( + fixed_decimal::FixedDecimal::half_ceiled_to_increment, + FnInStruct, + hidden + )] + pub fn half_ceil_to_increment(&mut self, position: i16, increment: ICU4XRoundingIncrement) { + self.0.half_ceil_to_increment(position, increment.into()) + } + #[diplomat::rust_link(fixed_decimal::FixedDecimal::floor, FnInStruct)] #[diplomat::rust_link(fixed_decimal::FixedDecimal::floored, FnInStruct, hidden)] pub fn floor(&mut self, position: i16) { self.0.floor(position) } + #[diplomat::rust_link(fixed_decimal::FixedDecimal::floor_to_increment, FnInStruct)] + #[diplomat::rust_link( + fixed_decimal::FixedDecimal::floored_to_increment, + FnInStruct, + hidden + )] + pub fn floor_to_increment(&mut self, position: i16, increment: ICU4XRoundingIncrement) { + self.0.floor_to_increment(position, increment.into()) + } + #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_floor, FnInStruct)] #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_floored, FnInStruct, hidden)] pub fn half_floor(&mut self, position: i16) { self.0.half_floor(position) } + #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_floor_to_increment, FnInStruct)] + #[diplomat::rust_link( + fixed_decimal::FixedDecimal::half_floored_to_increment, + FnInStruct, + hidden + )] + pub fn half_floor_to_increment( + &mut self, + position: i16, + increment: ICU4XRoundingIncrement, + ) { + self.0.half_floor_to_increment(position, increment.into()) + } + #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_even, FnInStruct)] #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_evened, FnInStruct, hidden)] pub fn half_even(&mut self, position: i16) { self.0.half_even(position) } + #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_even_to_increment, FnInStruct)] + #[diplomat::rust_link( + fixed_decimal::FixedDecimal::half_evened_to_increment, + FnInStruct, + hidden + )] + pub fn half_even_to_increment(&mut self, position: i16, increment: ICU4XRoundingIncrement) { + self.0.half_even_to_increment(position, increment.into()) + } + /// Concatenates `other` to the end of `self`. /// /// If successful, `other` will be set to 0 and a successful status is returned. diff --git a/utils/fixed_decimal/src/decimal.rs b/utils/fixed_decimal/src/decimal.rs index c1de8879d38..d82fa422d6a 100644 --- a/utils/fixed_decimal/src/decimal.rs +++ b/utils/fixed_decimal/src/decimal.rs @@ -1096,15 +1096,35 @@ impl FixedDecimal { /// # use std::str::FromStr; /// /// let mut dec = FixedDecimal::from_str("-3.5").unwrap(); - /// assert_eq!("-2", dec.trunced_to_increment(0, RoundingIncrement::MultiplesOf2).to_string()); + /// assert_eq!( + /// "-2", + /// dec.trunced_to_increment(0, RoundingIncrement::MultiplesOf2) + /// .to_string() + /// ); /// let mut dec = FixedDecimal::from_str("7.57").unwrap(); - /// assert_eq!("7.5", dec.trunced_to_increment(-1, RoundingIncrement::MultiplesOf5).to_string()); + /// assert_eq!( + /// "7.5", + /// dec.trunced_to_increment(-1, RoundingIncrement::MultiplesOf5) + /// .to_string() + /// ); /// let mut dec = FixedDecimal::from_str("5.45").unwrap(); - /// assert_eq!("5.25", dec.trunced_to_increment(-2, RoundingIncrement::MultiplesOf25).to_string()); + /// assert_eq!( + /// "5.25", + /// dec.trunced_to_increment(-2, RoundingIncrement::MultiplesOf25) + /// .to_string() + /// ); /// let mut dec = FixedDecimal::from_str("9.99").unwrap(); - /// assert_eq!("7.5", dec.trunced_to_increment(-1, RoundingIncrement::MultiplesOf25).to_string()); + /// assert_eq!( + /// "7.5", + /// dec.trunced_to_increment(-1, RoundingIncrement::MultiplesOf25) + /// .to_string() + /// ); /// let mut dec = FixedDecimal::from_str("9.99").unwrap(); - /// assert_eq!("9.98", dec.trunced_to_increment(-2, RoundingIncrement::MultiplesOf2).to_string()); + /// assert_eq!( + /// "9.98", + /// dec.trunced_to_increment(-2, RoundingIncrement::MultiplesOf2) + /// .to_string() + /// ); /// ``` pub fn trunced_to_increment(mut self, position: i16, increment: RoundingIncrement) -> Self { self.trunc_to_increment(position, increment); @@ -1282,21 +1302,93 @@ impl FixedDecimal { /// assert_eq!("4", dec.to_string()); /// ``` pub fn half_trunc(&mut self, position: i16) { - let digit_after_position = self.digit_at_next_position(position); - let should_expand = match digit_after_position.cmp(&5) { - Ordering::Less => false, - Ordering::Greater => true, - Ordering::Equal => - // NOTE: `digit_after_position` equals 5, this means, position does not equal to `i16::MIN`. - { - self.nonzero_magnitude_end() < position - 1 + self.half_trunc_to_increment(position, RoundingIncrement::MultiplesOf1); + } + + /// Half Truncates the number on the right to a particular position and rounding increment, + /// deleting digits if necessary. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::{FixedDecimal, RoundingIncrement}; + /// # use std::str::FromStr; + /// + /// let mut dec = FixedDecimal::from_str("-3.5").unwrap(); + /// dec.half_trunc_to_increment(0, RoundingIncrement::MultiplesOf2); + /// assert_eq!("-4", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("7.57").unwrap(); + /// dec.half_trunc_to_increment(-1, RoundingIncrement::MultiplesOf5); + /// assert_eq!("7.5", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("5.45").unwrap(); + /// dec.half_trunc_to_increment(-2, RoundingIncrement::MultiplesOf25); + /// assert_eq!("5.50", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("9.99").unwrap(); + /// dec.half_trunc_to_increment(-1, RoundingIncrement::MultiplesOf25); + /// assert_eq!("10.0", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("9.99").unwrap(); + /// dec.half_trunc_to_increment(-2, RoundingIncrement::MultiplesOf2); + /// assert_eq!("9.98", dec.to_string()); + /// ``` + pub fn half_trunc_to_increment(&mut self, position: i16, increment: RoundingIncrement) { + fn next_digits_exceed_five(number: &mut FixedDecimal, position: i16) -> bool { + let digit_after_position = number.digit_at_next_position(position); + match digit_after_position.cmp(&5) { + Ordering::Less => false, + Ordering::Greater => true, + Ordering::Equal => + // NOTE: `digit_after_position` equals 5, this means that `position` + // does not equal `i16::MIN`. + { + number.nonzero_magnitude_end() < position - 1 + } + } + } + + let should_expand = match increment { + RoundingIncrement::MultiplesOf1 => next_digits_exceed_five(self, position), + RoundingIncrement::MultiplesOf2 => { + let current_digit = self.digit_at(position); + + // Equivalent to "if current_digit is odd". + if current_digit & 0x01 == 1 { + self.nonzero_magnitude_end() < position + } else { + // Even numbers are always below the threshold to expand. + false + } + } + RoundingIncrement::MultiplesOf5 => { + let current_digit = self.digit_at(position); + match (current_digit % 5).cmp(&2) { + Ordering::Less => false, + Ordering::Greater => true, + Ordering::Equal => { + // Need to know if the number exceeds 2.5. + next_digits_exceed_five(self, position) + } + } + } + RoundingIncrement::MultiplesOf25 => { + let current_digit = self.digit_at(position); + let prev_digit = self.digit_at_previous_position(position); + let number = prev_digit * 10 + current_digit; + + match (number % 25).cmp(&12) { + Ordering::Less => false, + Ordering::Greater => true, + Ordering::Equal => { + // Need to know if the number exceeds 12.5. + next_digits_exceed_five(self, position) + } + } } }; if should_expand { - self.expand(position); + self.expand_to_increment(position, increment); } else { - self.trunc(position); + self.trunc_to_increment(position, increment); } } @@ -1327,6 +1419,55 @@ impl FixedDecimal { self } + /// Half Truncates the number on the right to a particular position and rounding increment, + /// deleting digits if necessary. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::{FixedDecimal, RoundingIncrement}; + /// # use std::str::FromStr; + /// + /// let mut dec = FixedDecimal::from_str("-3.5").unwrap(); + /// assert_eq!( + /// "-4", + /// dec.half_trunced_to_increment(0, RoundingIncrement::MultiplesOf2) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("7.57").unwrap(); + /// assert_eq!( + /// "7.5", + /// dec.half_trunced_to_increment(-1, RoundingIncrement::MultiplesOf5) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("5.45").unwrap(); + /// assert_eq!( + /// "5.50", + /// dec.half_trunced_to_increment(-2, RoundingIncrement::MultiplesOf25) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("9.99").unwrap(); + /// assert_eq!( + /// "10.0", + /// dec.half_trunced_to_increment(-1, RoundingIncrement::MultiplesOf25) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("9.99").unwrap(); + /// assert_eq!( + /// "9.98", + /// dec.half_trunced_to_increment(-2, RoundingIncrement::MultiplesOf2) + /// .to_string() + /// ); + /// ``` + pub fn half_trunced_to_increment( + mut self, + position: i16, + increment: RoundingIncrement, + ) -> Self { + self.half_trunc_to_increment(position, increment); + self + } + /// Take the expand of the number at a particular position. /// /// # Examples @@ -1703,12 +1844,64 @@ impl FixedDecimal { /// assert_eq!("2", dec.to_string()); /// ``` pub fn half_expand(&mut self, position: i16) { - let digit_after_position = self.digit_at_next_position(position); + self.half_expand_to_increment(position, RoundingIncrement::MultiplesOf1); + } + + /// Take the half expand of the number at a particular position and rounding increment. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::{FixedDecimal, RoundingIncrement}; + /// # use std::str::FromStr; + /// + /// let mut dec = FixedDecimal::from_str("-3.5").unwrap(); + /// dec.half_expand_to_increment(0, RoundingIncrement::MultiplesOf2); + /// assert_eq!("-4", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("7.57").unwrap(); + /// dec.half_expand_to_increment(-1, RoundingIncrement::MultiplesOf5); + /// assert_eq!("7.5", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("5.45").unwrap(); + /// dec.half_expand_to_increment(-2, RoundingIncrement::MultiplesOf25); + /// assert_eq!("5.50", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("9.99").unwrap(); + /// dec.half_expand_to_increment(-1, RoundingIncrement::MultiplesOf25); + /// assert_eq!("10.0", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("9.99").unwrap(); + /// dec.half_expand_to_increment(-2, RoundingIncrement::MultiplesOf2); + /// assert_eq!("10.00", dec.to_string()); + /// ``` + pub fn half_expand_to_increment(&mut self, position: i16, increment: RoundingIncrement) { + let should_expand = match increment { + RoundingIncrement::MultiplesOf1 => self.digit_at_next_position(position) >= 5, + RoundingIncrement::MultiplesOf2 => self.digit_at(position) & 0x01 == 1, + RoundingIncrement::MultiplesOf5 => { + // Need to know if the number is greater or equal than 2.5. + let current_digit = self.digit_at(position); + match (current_digit % 5).cmp(&2) { + Ordering::Less => false, + Ordering::Greater => true, + Ordering::Equal => self.digit_at_next_position(position) >= 5, + } + } + RoundingIncrement::MultiplesOf25 => { + let current_digit = self.digit_at(position); + let prev_digit = self.digit_at_previous_position(position); + let number = prev_digit * 10 + current_digit; + + // Need to know if the number is greater or equal than 12.5. + match (number % 25).cmp(&12) { + Ordering::Less => false, + Ordering::Greater => true, + Ordering::Equal => self.digit_at_next_position(position) >= 5, + } + } + }; - if digit_after_position >= 5 { - self.expand(position); + if should_expand { + self.expand_to_increment(position, increment); } else { - self.trunc(position); + self.trunc_to_increment(position, increment); } } @@ -1736,6 +1929,54 @@ impl FixedDecimal { self } + /// Take the half expand of the number at a particular position and rounding increment. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::{FixedDecimal, RoundingIncrement}; + /// # use std::str::FromStr; + /// + /// let mut dec = FixedDecimal::from_str("-3.5").unwrap(); + /// assert_eq!( + /// "-4", + /// dec.half_expanded_to_increment(0, RoundingIncrement::MultiplesOf2) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("7.57").unwrap(); + /// assert_eq!( + /// "7.5", + /// dec.half_expanded_to_increment(-1, RoundingIncrement::MultiplesOf5) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("5.45").unwrap(); + /// assert_eq!( + /// "5.50", + /// dec.half_expanded_to_increment(-2, RoundingIncrement::MultiplesOf25) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("9.99").unwrap(); + /// assert_eq!( + /// "10.0", + /// dec.half_expanded_to_increment(-1, RoundingIncrement::MultiplesOf25) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("9.99").unwrap(); + /// assert_eq!( + /// "10.00", + /// dec.half_expanded_to_increment(-2, RoundingIncrement::MultiplesOf2) + /// .to_string() + /// ); + /// ``` + pub fn half_expanded_to_increment( + mut self, + position: i16, + increment: RoundingIncrement, + ) -> Self { + self.half_expand_to_increment(position, increment); + self + } + /// Take the ceiling of the number at a particular position. /// /// # Examples @@ -1761,12 +2002,40 @@ impl FixedDecimal { /// assert_eq!("2", dec.to_string()); /// ``` pub fn ceil(&mut self, position: i16) { + self.ceil_to_increment(position, RoundingIncrement::MultiplesOf1); + } + + /// Take the ceiling of the number at a particular position and rounding increment. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::{FixedDecimal, RoundingIncrement}; + /// # use std::str::FromStr; + /// + /// let mut dec = FixedDecimal::from_str("-3.5").unwrap(); + /// dec.ceil_to_increment(0, RoundingIncrement::MultiplesOf2); + /// assert_eq!("-2", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("7.57").unwrap(); + /// dec.ceil_to_increment(-1, RoundingIncrement::MultiplesOf5); + /// assert_eq!("8.0", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("-5.45").unwrap(); + /// dec.ceil_to_increment(-2, RoundingIncrement::MultiplesOf25); + /// assert_eq!("-5.25", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("9.99").unwrap(); + /// dec.ceil_to_increment(-1, RoundingIncrement::MultiplesOf25); + /// assert_eq!("10.0", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("-9.99").unwrap(); + /// dec.ceil_to_increment(-2, RoundingIncrement::MultiplesOf2); + /// assert_eq!("-9.98", dec.to_string()); + /// ``` + pub fn ceil_to_increment(&mut self, position: i16, increment: RoundingIncrement) { if self.sign == Sign::Negative { - self.trunc(position); + self.trunc_to_increment(position, increment); return; } - self.expand(position); + self.expand_to_increment(position, increment); } /// Take the ceiling of the number at a particular position. @@ -1793,6 +2062,50 @@ impl FixedDecimal { self } + /// Take the ceiling of the number at a particular position and rounding increment. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::{FixedDecimal, RoundingIncrement}; + /// # use std::str::FromStr; + /// + /// let mut dec = FixedDecimal::from_str("-3.5").unwrap(); + /// assert_eq!( + /// "-2", + /// dec.ceiled_to_increment(0, RoundingIncrement::MultiplesOf2) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("7.57").unwrap(); + /// assert_eq!( + /// "8.0", + /// dec.ceiled_to_increment(-1, RoundingIncrement::MultiplesOf5) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("-5.45").unwrap(); + /// assert_eq!( + /// "-5.25", + /// dec.ceiled_to_increment(-2, RoundingIncrement::MultiplesOf25) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("9.99").unwrap(); + /// assert_eq!( + /// "10.0", + /// dec.ceiled_to_increment(-1, RoundingIncrement::MultiplesOf25) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("-9.99").unwrap(); + /// assert_eq!( + /// "-9.98", + /// dec.ceiled_to_increment(-2, RoundingIncrement::MultiplesOf2) + /// .to_string() + /// ); + /// ``` + pub fn ceiled_to_increment(mut self, position: i16, increment: RoundingIncrement) -> Self { + self.ceil_to_increment(position, increment); + self + } + /// Take the half ceiling of the number at a particular position. /// /// # Examples @@ -1818,12 +2131,39 @@ impl FixedDecimal { /// assert_eq!("2", dec.to_string()); /// ``` pub fn half_ceil(&mut self, position: i16) { + self.half_ceil_to_increment(position, RoundingIncrement::MultiplesOf1); + } + + /// Take the half ceiling of the number at a particular position and rounding increment. + /// # Examples + /// + /// ``` + /// use fixed_decimal::{FixedDecimal, RoundingIncrement}; + /// # use std::str::FromStr; + /// + /// let mut dec = FixedDecimal::from_str("-3.5").unwrap(); + /// dec.half_ceil_to_increment(0, RoundingIncrement::MultiplesOf2); + /// assert_eq!("-4", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("7.57").unwrap(); + /// dec.half_ceil_to_increment(-1, RoundingIncrement::MultiplesOf5); + /// assert_eq!("7.5", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("-5.45").unwrap(); + /// dec.half_ceil_to_increment(-2, RoundingIncrement::MultiplesOf25); + /// assert_eq!("-5.50", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("9.99").unwrap(); + /// dec.half_ceil_to_increment(-1, RoundingIncrement::MultiplesOf25); + /// assert_eq!("10.0", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("-9.99").unwrap(); + /// dec.half_ceil_to_increment(-2, RoundingIncrement::MultiplesOf2); + /// assert_eq!("-9.98", dec.to_string()); + /// ``` + pub fn half_ceil_to_increment(&mut self, position: i16, increment: RoundingIncrement) { if self.sign == Sign::Negative { - self.half_trunc(position); + self.half_trunc_to_increment(position, increment); return; } - self.half_expand(position); + self.half_expand_to_increment(position, increment); } /// Take the half ceiling of the number at a particular position. @@ -1850,6 +2190,50 @@ impl FixedDecimal { self } + /// Take the half ceiling of the number at a particular position and rounding increment. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::{FixedDecimal, RoundingIncrement}; + /// # use std::str::FromStr; + /// + /// let mut dec = FixedDecimal::from_str("-3.5").unwrap(); + /// assert_eq!( + /// "-4", + /// dec.half_ceiled_to_increment(0, RoundingIncrement::MultiplesOf2) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("7.57").unwrap(); + /// assert_eq!( + /// "7.5", + /// dec.half_ceiled_to_increment(-1, RoundingIncrement::MultiplesOf5) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("-5.45").unwrap(); + /// assert_eq!( + /// "-5.50", + /// dec.half_ceiled_to_increment(-2, RoundingIncrement::MultiplesOf25) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("9.99").unwrap(); + /// assert_eq!( + /// "10.0", + /// dec.half_ceiled_to_increment(-1, RoundingIncrement::MultiplesOf25) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("-9.99").unwrap(); + /// assert_eq!( + /// "-9.98", + /// dec.half_ceiled_to_increment(-2, RoundingIncrement::MultiplesOf2) + /// .to_string() + /// ); + /// ``` + pub fn half_ceiled_to_increment(mut self, position: i16, increment: RoundingIncrement) -> Self { + self.half_ceil_to_increment(position, increment); + self + } + /// Take the floor of the number at a particular position. /// /// # Examples @@ -1875,23 +2259,51 @@ impl FixedDecimal { /// assert_eq!("1", dec.to_string()); /// ``` pub fn floor(&mut self, position: i16) { - if self.sign == Sign::Negative { - self.expand(position); - return; - } - - self.trunc(position); + self.floor_to_increment(position, RoundingIncrement::MultiplesOf1); } - /// Take the floor of the number at a particular position. + /// Take the floor of the number at a particular position and rounding increment. /// /// # Examples /// /// ``` - /// use fixed_decimal::FixedDecimal; + /// use fixed_decimal::{FixedDecimal, RoundingIncrement}; /// # use std::str::FromStr; /// - /// let dec = FixedDecimal::from_str("-1.5").unwrap(); + /// let mut dec = FixedDecimal::from_str("-3.5").unwrap(); + /// dec.floor_to_increment(0, RoundingIncrement::MultiplesOf2); + /// assert_eq!("-4", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("7.57").unwrap(); + /// dec.floor_to_increment(-1, RoundingIncrement::MultiplesOf5); + /// assert_eq!("7.5", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("-5.45").unwrap(); + /// dec.floor_to_increment(-2, RoundingIncrement::MultiplesOf25); + /// assert_eq!("-5.50", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("9.99").unwrap(); + /// dec.floor_to_increment(-1, RoundingIncrement::MultiplesOf25); + /// assert_eq!("7.5", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("-9.99").unwrap(); + /// dec.floor_to_increment(-2, RoundingIncrement::MultiplesOf2); + /// assert_eq!("-10.00", dec.to_string()); + /// ``` + pub fn floor_to_increment(&mut self, position: i16, increment: RoundingIncrement) { + if self.sign == Sign::Negative { + self.expand_to_increment(position, increment); + return; + } + + self.trunc_to_increment(position, increment); + } + + /// Take the floor of the number at a particular position. + /// + /// # Examples + /// + /// ``` + /// 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()); @@ -1907,6 +2319,50 @@ impl FixedDecimal { self } + /// Take the floor of the number at a particular position and rounding increment. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::{FixedDecimal, RoundingIncrement}; + /// # use std::str::FromStr; + /// + /// let mut dec = FixedDecimal::from_str("-3.5").unwrap(); + /// assert_eq!( + /// "-4", + /// dec.floored_to_increment(0, RoundingIncrement::MultiplesOf2) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("7.57").unwrap(); + /// assert_eq!( + /// "7.5", + /// dec.floored_to_increment(-1, RoundingIncrement::MultiplesOf5) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("-5.45").unwrap(); + /// assert_eq!( + /// "-5.50", + /// dec.floored_to_increment(-2, RoundingIncrement::MultiplesOf25) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("9.99").unwrap(); + /// assert_eq!( + /// "7.5", + /// dec.floored_to_increment(-1, RoundingIncrement::MultiplesOf25) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("-9.99").unwrap(); + /// assert_eq!( + /// "-10.00", + /// dec.floored_to_increment(-2, RoundingIncrement::MultiplesOf2) + /// .to_string() + /// ); + /// ``` + pub fn floored_to_increment(mut self, position: i16, increment: RoundingIncrement) -> Self { + self.floor_to_increment(position, increment); + self + } + /// Take the half floor of the number at a particular position. /// /// # Examples @@ -1932,12 +2388,40 @@ impl FixedDecimal { /// assert_eq!("1", dec.to_string()); /// ``` pub fn half_floor(&mut self, position: i16) { + self.half_floor_to_increment(position, RoundingIncrement::MultiplesOf1); + } + + /// Take the half floor of the number at a particular position and rounding increment. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::{FixedDecimal, RoundingIncrement}; + /// # use std::str::FromStr; + /// + /// let mut dec = FixedDecimal::from_str("-3.5").unwrap(); + /// dec.half_floor_to_increment(0, RoundingIncrement::MultiplesOf2); + /// assert_eq!("-4", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("7.57").unwrap(); + /// dec.half_floor_to_increment(-1, RoundingIncrement::MultiplesOf5); + /// assert_eq!("7.5", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("-5.45").unwrap(); + /// dec.half_floor_to_increment(-2, RoundingIncrement::MultiplesOf25); + /// assert_eq!("-5.50", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("9.99").unwrap(); + /// dec.half_floor_to_increment(-1, RoundingIncrement::MultiplesOf25); + /// assert_eq!("10.0", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("-9.99").unwrap(); + /// dec.half_floor_to_increment(-2, RoundingIncrement::MultiplesOf2); + /// assert_eq!("-10.00", dec.to_string()); + /// ``` + pub fn half_floor_to_increment(&mut self, position: i16, increment: RoundingIncrement) { if self.sign == Sign::Negative { - self.half_expand(position); + self.half_expand_to_increment(position, increment); return; } - self.half_trunc(position); + self.half_trunc_to_increment(position, increment); } /// Take the half floor of the number at a particular position. @@ -1964,6 +2448,54 @@ impl FixedDecimal { self } + /// Take the half floor of the number at a particular position and rounding increment. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::{FixedDecimal, RoundingIncrement}; + /// # use std::str::FromStr; + /// + /// let mut dec = FixedDecimal::from_str("-3.5").unwrap(); + /// assert_eq!( + /// "-4", + /// dec.half_floored_to_increment(0, RoundingIncrement::MultiplesOf2) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("7.57").unwrap(); + /// assert_eq!( + /// "7.5", + /// dec.half_floored_to_increment(-1, RoundingIncrement::MultiplesOf5) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("-5.45").unwrap(); + /// assert_eq!( + /// "-5.50", + /// dec.half_floored_to_increment(-2, RoundingIncrement::MultiplesOf25) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("9.99").unwrap(); + /// assert_eq!( + /// "10.0", + /// dec.half_floored_to_increment(-1, RoundingIncrement::MultiplesOf25) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("-9.99").unwrap(); + /// assert_eq!( + /// "-10.00", + /// dec.half_floored_to_increment(-2, RoundingIncrement::MultiplesOf2) + /// .to_string() + /// ); + /// ``` + pub fn half_floored_to_increment( + mut self, + position: i16, + increment: RoundingIncrement, + ) -> Self { + self.half_floor_to_increment(position, increment); + self + } + /// Take the half even of the number at a particular position. /// /// # Examples @@ -1989,24 +2521,130 @@ impl FixedDecimal { /// assert_eq!("2", dec.to_string()); /// ``` pub fn half_even(&mut self, position: i16) { - let digit_after_position = self.digit_at_next_position(position); - let should_expand = match digit_after_position.cmp(&5) { - Ordering::Less => false, - Ordering::Greater => true, - Ordering::Equal => { - // NOTE: `digit_after_position` equals to 5, this means that positon does not equal i16::MIN. - if self.nonzero_magnitude_end() < position - 1 { - true + self.half_even_to_increment(position, RoundingIncrement::MultiplesOf1); + } + + /// Take the half even of the number at a particular position and rounding increment. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::{FixedDecimal, RoundingIncrement}; + /// # use std::str::FromStr; + /// + /// let mut dec = FixedDecimal::from_str("-3.5").unwrap(); + /// dec.half_even_to_increment(0, RoundingIncrement::MultiplesOf2); + /// assert_eq!("-4", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("7.57").unwrap(); + /// dec.half_even_to_increment(-1, RoundingIncrement::MultiplesOf5); + /// assert_eq!("7.5", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("5.45").unwrap(); + /// dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf25); + /// assert_eq!("5.50", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("9.99").unwrap(); + /// dec.half_even_to_increment(-1, RoundingIncrement::MultiplesOf25); + /// assert_eq!("10.0", dec.to_string()); + /// let mut dec = FixedDecimal::from_str("9.99").unwrap(); + /// dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf2); + /// assert_eq!("9.98", dec.to_string()); + /// ``` + pub fn half_even_to_increment(&mut self, position: i16, increment: RoundingIncrement) { + let should_expand = match increment { + RoundingIncrement::MultiplesOf1 => { + let digit_after_position = self.digit_at_next_position(position); + match digit_after_position.cmp(&5) { + Ordering::Less => false, + Ordering::Greater => true, + Ordering::Equal => { + // NOTE: `digit_after_position` equals to 5, this means that `position` + // does not equal i16::MIN. + if self.nonzero_magnitude_end() < position - 1 { + true + } else { + self.digit_at(position) % 2 != 0 + } + } + } + } + RoundingIncrement::MultiplesOf2 => { + let current_digit = self.digit_at(position); + + // Equivalent to "if current_digit is odd". + if (current_digit & 0x01) == 1 { + if self.nonzero_magnitude_end() < position { + true + } else { + // This essentially expands to the "even" increments, + // or the increments that are in the even places on the + // rounding range: [0, 4, 8] + // Equivalent to `(current_digit / 2) is odd`. + (current_digit >> 1) & 0x01 == 1 + } } else { - self.digit_at(position) % 2 != 0 + // Even numbers are always below the threshold to expand. + false + } + } + RoundingIncrement::MultiplesOf5 => { + let current_digit = self.digit_at(position); + match (current_digit % 5).cmp(&2) { + Ordering::Less => false, + Ordering::Greater => true, + Ordering::Equal => { + // Need to know if the number exceeds 2.5. + let digit_after_position = self.digit_at_next_position(position); + match digit_after_position.cmp(&5) { + Ordering::Less => false, + Ordering::Greater => true, + Ordering::Equal => { + // NOTE: `digit_after_position` equals to 5, this means that `position` + // does not equal i16::MIN. + if self.nonzero_magnitude_end() < position - 1 { + true + } else { + // Expand 7.5 to 10 and truncate 2.5 to 0. + current_digit == 7 + } + } + } + } + } + } + RoundingIncrement::MultiplesOf25 => { + let current_digit = self.digit_at(position); + let prev_digit = self.digit_at_previous_position(position); + let full_number = prev_digit * 10 + current_digit; + + match (full_number % 25).cmp(&12) { + Ordering::Less => false, + Ordering::Greater => true, + Ordering::Equal => { + // Need to know if the number exceeds 12.5. + let digit_after_position = self.digit_at_next_position(position); + match digit_after_position.cmp(&5) { + Ordering::Less => false, + Ordering::Greater => true, + Ordering::Equal => { + // NOTE: `digit_after_position` equals to 5, this means that `position` + // does not equal i16::MIN. + if self.nonzero_magnitude_end() < position - 1 { + true + } else { + // Expand `37.5` to 50 and `87.5` to 100. + // Truncate `12.5` to 0 and `62.5` to 50. + full_number == 37 || full_number == 87 + } + } + } + } } } }; if should_expand { - self.expand(position); + self.expand_to_increment(position, increment); } else { - self.trunc(position); + self.trunc_to_increment(position, increment); } } @@ -2034,6 +2672,50 @@ impl FixedDecimal { self } + /// Take the half even of the number at a particular position and rounding increment. + /// + /// # Examples + /// + /// ``` + /// use fixed_decimal::{FixedDecimal, RoundingIncrement}; + /// # use std::str::FromStr; + /// + /// let mut dec = FixedDecimal::from_str("-3.5").unwrap(); + /// assert_eq!( + /// "-4", + /// dec.half_evened_to_increment(0, RoundingIncrement::MultiplesOf2) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("7.57").unwrap(); + /// assert_eq!( + /// "7.5", + /// dec.half_evened_to_increment(-1, RoundingIncrement::MultiplesOf5) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("5.45").unwrap(); + /// assert_eq!( + /// "5.50", + /// dec.half_evened_to_increment(-2, RoundingIncrement::MultiplesOf25) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("9.99").unwrap(); + /// assert_eq!( + /// "10.0", + /// dec.half_evened_to_increment(-1, RoundingIncrement::MultiplesOf25) + /// .to_string() + /// ); + /// let mut dec = FixedDecimal::from_str("9.99").unwrap(); + /// assert_eq!( + /// "9.98", + /// dec.half_evened_to_increment(-2, RoundingIncrement::MultiplesOf2) + /// .to_string() + /// ); + /// ``` + pub fn half_evened_to_increment(mut self, position: i16, increment: RoundingIncrement) -> Self { + self.half_even_to_increment(position, increment); + self + } + /// Concatenate another `FixedDecimal` into the end of this `FixedDecimal`. /// /// All nonzero digits in `other` must have lower magnitude than nonzero digits in `self`. @@ -4070,71 +4752,519 @@ fn test_rounding_increment() { dec.expand_to_increment(i16::MAX, RoundingIncrement::MultiplesOf25); assert_eq!(FixedDecimal::from(0).multiplied_pow10(i16::MAX), dec); - // Test specific cases + // Test Half Truncate Right + let mut dec = FixedDecimal::from(4235970).multiplied_pow10(-3); + assert_eq!("4235.970", dec.to_string()); - let mut dec = FixedDecimal::from_str("1.108").unwrap(); - dec.expand_to_increment(-2, RoundingIncrement::MultiplesOf2); - assert_eq!("1.12", dec.to_string()); + dec.half_trunc_to_increment(-2, RoundingIncrement::MultiplesOf2); + assert_eq!("4235.96", dec.to_string()); - let mut dec = FixedDecimal::from_str("1.108").unwrap(); - dec.expand_to_increment(-2, RoundingIncrement::MultiplesOf5); - assert_eq!("1.15", dec.to_string()); + dec.half_trunc_to_increment(-1, RoundingIncrement::MultiplesOf5); + assert_eq!("4236.0", dec.to_string()); - let mut dec = FixedDecimal::from_str("1.108").unwrap(); - dec.expand_to_increment(-2, RoundingIncrement::MultiplesOf25); - assert_eq!("1.25", dec.to_string()); + dec.half_trunc_to_increment(0, RoundingIncrement::MultiplesOf25); + assert_eq!("4225", dec.to_string()); - let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MAX - 1); - dec.expand_to_increment(i16::MAX - 1, RoundingIncrement::MultiplesOf25); - assert_eq!(FixedDecimal::from(25).multiplied_pow10(i16::MAX - 1), dec); + dec.half_trunc_to_increment(5, RoundingIncrement::MultiplesOf5); + assert_eq!("00000", dec.to_string()); - let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MAX); - dec.expand_to_increment(i16::MAX, RoundingIncrement::MultiplesOf25); - assert_eq!(FixedDecimal::from(0).multiplied_pow10(i16::MAX), dec); + dec.half_trunc_to_increment(2, RoundingIncrement::MultiplesOf2); + assert_eq!("00000", dec.to_string()); - let mut dec = FixedDecimal::from_str("0").unwrap(); - dec.expand_to_increment(0, RoundingIncrement::MultiplesOf2); - assert_eq!("0", dec.to_string()); + let mut dec = FixedDecimal::from_str("-99.999").unwrap(); + dec.half_trunc_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("-100.00", dec.to_string()); - let mut dec = FixedDecimal::from_str("0").unwrap(); - dec.expand_to_increment(0, RoundingIncrement::MultiplesOf5); - assert_eq!("0", dec.to_string()); + let mut dec = FixedDecimal::from_str("1234.56").unwrap(); + dec.half_trunc_to_increment(-1, RoundingIncrement::MultiplesOf2); + assert_eq!("1234.6", dec.to_string()); - let mut dec = FixedDecimal::from_str("0").unwrap(); - dec.expand_to_increment(0, RoundingIncrement::MultiplesOf25); - assert_eq!("0", dec.to_string()); + let mut dec = FixedDecimal::from_str("0.009").unwrap(); + dec.half_trunc_to_increment(-1, RoundingIncrement::MultiplesOf5); + assert_eq!("0.0", dec.to_string()); - let mut dec = FixedDecimal::from_str("0.1").unwrap(); - dec.expand_to_increment(0, RoundingIncrement::MultiplesOf2); - assert_eq!("2", dec.to_string()); + let mut dec = FixedDecimal::from_str("0.60").unwrap(); + dec.half_trunc_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("0.50", dec.to_string()); - let mut dec = FixedDecimal::from_str("0.1").unwrap(); - dec.expand_to_increment(0, RoundingIncrement::MultiplesOf5); - assert_eq!("5", dec.to_string()); + let mut dec = FixedDecimal::from_str("0.40").unwrap(); + dec.half_trunc_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("0.50", dec.to_string()); - let mut dec = FixedDecimal::from_str("0.1").unwrap(); - dec.expand_to_increment(0, RoundingIncrement::MultiplesOf25); - assert_eq!("25", dec.to_string()); + let mut dec = FixedDecimal::from_str("0.7000000099").unwrap(); + dec.half_trunc_to_increment(-3, RoundingIncrement::MultiplesOf2); + assert_eq!("0.700", dec.to_string()); - let mut dec = FixedDecimal::from_str("1").unwrap(); - dec.expand_to_increment(0, RoundingIncrement::MultiplesOf2); - assert_eq!("2", dec.to_string()); + let mut dec = FixedDecimal::from_str("5").unwrap(); + dec.half_trunc_to_increment(0, RoundingIncrement::MultiplesOf25); + assert_eq!("0", dec.to_string()); - let mut dec = FixedDecimal::from_str("1").unwrap(); - dec.expand_to_increment(0, RoundingIncrement::MultiplesOf5); - assert_eq!("5", dec.to_string()); + let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MIN); + dec.half_trunc_to_increment(i16::MIN, RoundingIncrement::MultiplesOf2); + assert_eq!(FixedDecimal::from(6).multiplied_pow10(i16::MIN), dec); - let mut dec = FixedDecimal::from_str("1").unwrap(); - dec.expand_to_increment(0, RoundingIncrement::MultiplesOf25); - assert_eq!("25", dec.to_string()); + let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MIN); + dec.half_trunc_to_increment(i16::MIN, RoundingIncrement::MultiplesOf5); + assert_eq!(FixedDecimal::from(10).multiplied_pow10(i16::MIN), dec); - let mut dec = FixedDecimal::from_str("2").unwrap(); - dec.expand_to_increment(0, RoundingIncrement::MultiplesOf2); - assert_eq!("2", dec.to_string()); + let mut dec = FixedDecimal::from(70).multiplied_pow10(i16::MIN); + dec.half_trunc_to_increment(i16::MIN, RoundingIncrement::MultiplesOf25); + assert_eq!(FixedDecimal::from(75).multiplied_pow10(i16::MIN), dec); - let mut dec = FixedDecimal::from_str("2").unwrap(); - dec.expand_to_increment(0, RoundingIncrement::MultiplesOf5); - assert_eq!("5", dec.to_string()); + let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX); + dec.half_trunc_to_increment(i16::MAX, RoundingIncrement::MultiplesOf2); + assert_eq!(FixedDecimal::from(6).multiplied_pow10(i16::MAX), dec); + + let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX); + dec.half_trunc_to_increment(i16::MAX, RoundingIncrement::MultiplesOf5); + assert_eq!(FixedDecimal::from(5).multiplied_pow10(i16::MAX), dec); + + let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX); + dec.half_trunc_to_increment(i16::MAX, RoundingIncrement::MultiplesOf25); + assert_eq!(FixedDecimal::from(0).multiplied_pow10(i16::MAX), dec); + + // Test Half Expand + let mut dec = FixedDecimal::from(4235970).multiplied_pow10(-3); + assert_eq!("4235.970", dec.to_string()); + + dec.half_expand_to_increment(-2, RoundingIncrement::MultiplesOf2); + assert_eq!("4235.98", dec.to_string()); + + dec.half_expand_to_increment(-1, RoundingIncrement::MultiplesOf5); + assert_eq!("4236.0", dec.to_string()); + + dec.half_expand_to_increment(0, RoundingIncrement::MultiplesOf25); + assert_eq!("4225", dec.to_string()); + + dec.half_expand_to_increment(5, RoundingIncrement::MultiplesOf5); + assert_eq!("00000", dec.to_string()); + + dec.half_expand_to_increment(2, RoundingIncrement::MultiplesOf2); + assert_eq!("00000", dec.to_string()); + + let mut dec = FixedDecimal::from_str("-99.999").unwrap(); + dec.half_expand_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("-100.00", dec.to_string()); + + let mut dec = FixedDecimal::from_str("1234.56").unwrap(); + dec.half_expand_to_increment(-1, RoundingIncrement::MultiplesOf2); + assert_eq!("1234.6", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.009").unwrap(); + dec.half_expand_to_increment(-1, RoundingIncrement::MultiplesOf5); + assert_eq!("0.0", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.60").unwrap(); + dec.half_expand_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("0.50", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.40").unwrap(); + dec.half_expand_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("0.50", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.7000000099").unwrap(); + dec.half_expand_to_increment(-3, RoundingIncrement::MultiplesOf2); + assert_eq!("0.700", dec.to_string()); + + let mut dec = FixedDecimal::from_str("5").unwrap(); + dec.half_expand_to_increment(0, RoundingIncrement::MultiplesOf25); + assert_eq!("0", dec.to_string()); + + let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MIN); + dec.half_expand_to_increment(i16::MIN, RoundingIncrement::MultiplesOf2); + assert_eq!(FixedDecimal::from(8).multiplied_pow10(i16::MIN), dec); + + let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MIN); + dec.half_expand_to_increment(i16::MIN, RoundingIncrement::MultiplesOf5); + assert_eq!(FixedDecimal::from(10).multiplied_pow10(i16::MIN), dec); + + let mut dec = FixedDecimal::from(70).multiplied_pow10(i16::MIN); + dec.half_expand_to_increment(i16::MIN, RoundingIncrement::MultiplesOf25); + assert_eq!(FixedDecimal::from(75).multiplied_pow10(i16::MIN), dec); + + let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX); + dec.half_expand_to_increment(i16::MAX, RoundingIncrement::MultiplesOf2); + assert_eq!(FixedDecimal::from(8).multiplied_pow10(i16::MAX), dec); + + // Test Ceil + let mut dec = FixedDecimal::from(4235970).multiplied_pow10(-3); + assert_eq!("4235.970", dec.to_string()); + + dec.ceil_to_increment(-2, RoundingIncrement::MultiplesOf2); + assert_eq!("4235.98", dec.to_string()); + + dec.ceil_to_increment(-1, RoundingIncrement::MultiplesOf5); + assert_eq!("4236.0", dec.to_string()); + + dec.ceil_to_increment(0, RoundingIncrement::MultiplesOf25); + assert_eq!("4250", dec.to_string()); + + dec.ceil_to_increment(5, RoundingIncrement::MultiplesOf5); + assert_eq!("500000", dec.to_string()); + + dec.ceil_to_increment(2, RoundingIncrement::MultiplesOf2); + assert_eq!("500000", dec.to_string()); + + let mut dec = FixedDecimal::from_str("-99.999").unwrap(); + dec.ceil_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("-99.75", dec.to_string()); + + let mut dec = FixedDecimal::from_str("1234.56").unwrap(); + dec.ceil_to_increment(-1, RoundingIncrement::MultiplesOf2); + assert_eq!("1234.6", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.009").unwrap(); + dec.ceil_to_increment(-1, RoundingIncrement::MultiplesOf5); + assert_eq!("0.5", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.60").unwrap(); + dec.ceil_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("0.75", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.40").unwrap(); + dec.ceil_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("0.50", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.7000000099").unwrap(); + dec.ceil_to_increment(-3, RoundingIncrement::MultiplesOf2); + assert_eq!("0.702", dec.to_string()); + + let mut dec = FixedDecimal::from_str("5").unwrap(); + dec.ceil_to_increment(0, RoundingIncrement::MultiplesOf25); + assert_eq!("25", dec.to_string()); + + let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MIN); + dec.ceil_to_increment(i16::MIN, RoundingIncrement::MultiplesOf2); + assert_eq!(FixedDecimal::from(8).multiplied_pow10(i16::MIN), dec); + + let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MIN); + dec.ceil_to_increment(i16::MIN, RoundingIncrement::MultiplesOf5); + assert_eq!(FixedDecimal::from(10).multiplied_pow10(i16::MIN), dec); + + let mut dec = FixedDecimal::from(70).multiplied_pow10(i16::MIN); + dec.ceil_to_increment(i16::MIN, RoundingIncrement::MultiplesOf25); + assert_eq!(FixedDecimal::from(75).multiplied_pow10(i16::MIN), dec); + + let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX); + dec.ceil_to_increment(i16::MAX, RoundingIncrement::MultiplesOf2); + assert_eq!(FixedDecimal::from(8).multiplied_pow10(i16::MAX), dec); + + // Test Half Ceil + let mut dec = FixedDecimal::from(4235970).multiplied_pow10(-3); + assert_eq!("4235.970", dec.to_string()); + + dec.half_ceil_to_increment(-2, RoundingIncrement::MultiplesOf2); + assert_eq!("4235.98", dec.to_string()); + + dec.half_ceil_to_increment(-1, RoundingIncrement::MultiplesOf5); + assert_eq!("4236.0", dec.to_string()); + + dec.half_ceil_to_increment(0, RoundingIncrement::MultiplesOf25); + assert_eq!("4225", dec.to_string()); + + dec.half_ceil_to_increment(5, RoundingIncrement::MultiplesOf5); + assert_eq!("00000", dec.to_string()); + + dec.half_ceil_to_increment(2, RoundingIncrement::MultiplesOf2); + assert_eq!("00000", dec.to_string()); + + let mut dec = FixedDecimal::from_str("-99.999").unwrap(); + dec.half_ceil_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("-100.00", dec.to_string()); + + let mut dec = FixedDecimal::from_str("1234.56").unwrap(); + dec.half_ceil_to_increment(-1, RoundingIncrement::MultiplesOf2); + assert_eq!("1234.6", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.009").unwrap(); + dec.half_ceil_to_increment(-1, RoundingIncrement::MultiplesOf5); + assert_eq!("0.0", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.60").unwrap(); + dec.half_ceil_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("0.50", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.40").unwrap(); + dec.half_ceil_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("0.50", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.7000000099").unwrap(); + dec.half_ceil_to_increment(-3, RoundingIncrement::MultiplesOf2); + assert_eq!("0.700", dec.to_string()); + + let mut dec = FixedDecimal::from_str("5").unwrap(); + dec.half_ceil_to_increment(0, RoundingIncrement::MultiplesOf25); + assert_eq!("0", dec.to_string()); + + let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MIN); + dec.half_ceil_to_increment(i16::MIN, RoundingIncrement::MultiplesOf2); + assert_eq!(FixedDecimal::from(8).multiplied_pow10(i16::MIN), dec); + + let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MIN); + dec.half_ceil_to_increment(i16::MIN, RoundingIncrement::MultiplesOf5); + assert_eq!(FixedDecimal::from(10).multiplied_pow10(i16::MIN), dec); + + let mut dec = FixedDecimal::from(70).multiplied_pow10(i16::MIN); + dec.half_ceil_to_increment(i16::MIN, RoundingIncrement::MultiplesOf25); + assert_eq!(FixedDecimal::from(75).multiplied_pow10(i16::MIN), dec); + + let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX); + dec.half_ceil_to_increment(i16::MAX, RoundingIncrement::MultiplesOf2); + assert_eq!(FixedDecimal::from(8).multiplied_pow10(i16::MAX), dec); + + // Test Floor + let mut dec = FixedDecimal::from(4235970).multiplied_pow10(-3); + assert_eq!("4235.970", dec.to_string()); + + dec.floor_to_increment(-2, RoundingIncrement::MultiplesOf2); + assert_eq!("4235.96", dec.to_string()); + + dec.floor_to_increment(-1, RoundingIncrement::MultiplesOf5); + assert_eq!("4235.5", dec.to_string()); + + dec.floor_to_increment(0, RoundingIncrement::MultiplesOf25); + assert_eq!("4225", dec.to_string()); + + dec.floor_to_increment(5, RoundingIncrement::MultiplesOf5); + assert_eq!("00000", dec.to_string()); + + dec.floor_to_increment(2, RoundingIncrement::MultiplesOf2); + assert_eq!("00000", dec.to_string()); + + let mut dec = FixedDecimal::from_str("-99.999").unwrap(); + dec.floor_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("-100.00", dec.to_string()); + + let mut dec = FixedDecimal::from_str("1234.56").unwrap(); + dec.floor_to_increment(-1, RoundingIncrement::MultiplesOf2); + assert_eq!("1234.4", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.009").unwrap(); + dec.floor_to_increment(-1, RoundingIncrement::MultiplesOf5); + assert_eq!("0.0", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.60").unwrap(); + dec.floor_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("0.50", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.40").unwrap(); + dec.floor_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("0.25", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.7000000099").unwrap(); + dec.floor_to_increment(-3, RoundingIncrement::MultiplesOf2); + assert_eq!("0.700", dec.to_string()); + + let mut dec = FixedDecimal::from_str("5").unwrap(); + dec.floor_to_increment(0, RoundingIncrement::MultiplesOf25); + assert_eq!("0", dec.to_string()); + + let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MIN); + dec.floor_to_increment(i16::MIN, RoundingIncrement::MultiplesOf2); + assert_eq!(FixedDecimal::from(6).multiplied_pow10(i16::MIN), dec); + + let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MIN); + dec.floor_to_increment(i16::MIN, RoundingIncrement::MultiplesOf5); + assert_eq!(FixedDecimal::from(5).multiplied_pow10(i16::MIN), dec); + + let mut dec = FixedDecimal::from(70).multiplied_pow10(i16::MIN); + dec.floor_to_increment(i16::MIN, RoundingIncrement::MultiplesOf25); + assert_eq!(FixedDecimal::from(50).multiplied_pow10(i16::MIN), dec); + + let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX); + dec.floor_to_increment(i16::MAX, 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.half_floor_to_increment(-2, RoundingIncrement::MultiplesOf2); + assert_eq!("4235.96", dec.to_string()); + + dec.half_floor_to_increment(-1, RoundingIncrement::MultiplesOf5); + assert_eq!("4236.0", dec.to_string()); + + dec.half_floor_to_increment(0, RoundingIncrement::MultiplesOf25); + assert_eq!("4225", dec.to_string()); + + dec.half_floor_to_increment(5, RoundingIncrement::MultiplesOf5); + assert_eq!("00000", dec.to_string()); + + dec.half_floor_to_increment(2, RoundingIncrement::MultiplesOf2); + assert_eq!("00000", dec.to_string()); + + let mut dec = FixedDecimal::from_str("-99.999").unwrap(); + dec.half_floor_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("-100.00", dec.to_string()); + + let mut dec = FixedDecimal::from_str("1234.56").unwrap(); + dec.half_floor_to_increment(-1, RoundingIncrement::MultiplesOf2); + assert_eq!("1234.6", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.009").unwrap(); + dec.half_floor_to_increment(-1, RoundingIncrement::MultiplesOf5); + assert_eq!("0.0", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.60").unwrap(); + dec.half_floor_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("0.50", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.40").unwrap(); + dec.half_floor_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("0.50", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.7000000099").unwrap(); + dec.half_floor_to_increment(-3, RoundingIncrement::MultiplesOf2); + assert_eq!("0.700", dec.to_string()); + + let mut dec = FixedDecimal::from_str("5").unwrap(); + dec.half_floor_to_increment(0, RoundingIncrement::MultiplesOf25); + assert_eq!("0", dec.to_string()); + + let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MIN); + dec.half_floor_to_increment(i16::MIN, RoundingIncrement::MultiplesOf2); + assert_eq!(FixedDecimal::from(6).multiplied_pow10(i16::MIN), dec); + + let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MIN); + dec.half_floor_to_increment(i16::MIN, RoundingIncrement::MultiplesOf5); + assert_eq!(FixedDecimal::from(10).multiplied_pow10(i16::MIN), dec); + + let mut dec = FixedDecimal::from(70).multiplied_pow10(i16::MIN); + dec.half_floor_to_increment(i16::MIN, RoundingIncrement::MultiplesOf25); + assert_eq!(FixedDecimal::from(75).multiplied_pow10(i16::MIN), dec); + + let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX); + dec.half_floor_to_increment(i16::MAX, RoundingIncrement::MultiplesOf2); + 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.half_even_to_increment(-2, RoundingIncrement::MultiplesOf2); + assert_eq!("4235.98", dec.to_string()); + + dec.half_even_to_increment(-1, RoundingIncrement::MultiplesOf5); + assert_eq!("4236.0", dec.to_string()); + + dec.half_even_to_increment(0, RoundingIncrement::MultiplesOf25); + assert_eq!("4225", dec.to_string()); + + dec.half_even_to_increment(5, RoundingIncrement::MultiplesOf5); + assert_eq!("00000", dec.to_string()); + + dec.half_even_to_increment(2, RoundingIncrement::MultiplesOf2); + assert_eq!("00000", dec.to_string()); + + let mut dec = FixedDecimal::from_str("-99.999").unwrap(); + dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("-100.00", dec.to_string()); + + let mut dec = FixedDecimal::from_str("1234.56").unwrap(); + dec.half_even_to_increment(-1, RoundingIncrement::MultiplesOf2); + assert_eq!("1234.6", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.009").unwrap(); + dec.half_even_to_increment(-1, RoundingIncrement::MultiplesOf5); + assert_eq!("0.0", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.60").unwrap(); + dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("0.50", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.40").unwrap(); + dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("0.50", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.7000000099").unwrap(); + dec.half_even_to_increment(-3, RoundingIncrement::MultiplesOf2); + assert_eq!("0.700", dec.to_string()); + + let mut dec = FixedDecimal::from_str("5").unwrap(); + dec.half_even_to_increment(0, RoundingIncrement::MultiplesOf25); + assert_eq!("0", dec.to_string()); + + let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MIN); + dec.half_even_to_increment(i16::MIN, RoundingIncrement::MultiplesOf2); + assert_eq!(FixedDecimal::from(8).multiplied_pow10(i16::MIN), dec); + + let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MIN); + dec.half_even_to_increment(i16::MIN, RoundingIncrement::MultiplesOf5); + assert_eq!(FixedDecimal::from(10).multiplied_pow10(i16::MIN), dec); + + let mut dec = FixedDecimal::from(70).multiplied_pow10(i16::MIN); + dec.half_even_to_increment(i16::MIN, RoundingIncrement::MultiplesOf25); + assert_eq!(FixedDecimal::from(75).multiplied_pow10(i16::MIN), dec); + + let mut dec = FixedDecimal::from(7).multiplied_pow10(i16::MAX); + dec.half_even_to_increment(i16::MAX, 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.expand_to_increment(-2, RoundingIncrement::MultiplesOf2); + assert_eq!("1.12", dec.to_string()); + + let mut dec = FixedDecimal::from_str("1.108").unwrap(); + dec.expand_to_increment(-2, RoundingIncrement::MultiplesOf5); + assert_eq!("1.15", dec.to_string()); + + let mut dec = FixedDecimal::from_str("1.108").unwrap(); + dec.expand_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("1.25", dec.to_string()); + + let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MAX - 1); + dec.expand_to_increment(i16::MAX - 1, RoundingIncrement::MultiplesOf25); + assert_eq!(FixedDecimal::from(25).multiplied_pow10(i16::MAX - 1), dec); + + let mut dec = FixedDecimal::from(9).multiplied_pow10(i16::MAX); + dec.expand_to_increment(i16::MAX, RoundingIncrement::MultiplesOf25); + assert_eq!(FixedDecimal::from(0).multiplied_pow10(i16::MAX), dec); + + let mut dec = FixedDecimal::from_str("0").unwrap(); + dec.expand_to_increment(0, RoundingIncrement::MultiplesOf2); + assert_eq!("0", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0").unwrap(); + dec.expand_to_increment(0, RoundingIncrement::MultiplesOf5); + assert_eq!("0", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0").unwrap(); + dec.expand_to_increment(0, RoundingIncrement::MultiplesOf25); + assert_eq!("0", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.1").unwrap(); + dec.expand_to_increment(0, RoundingIncrement::MultiplesOf2); + assert_eq!("2", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.1").unwrap(); + dec.expand_to_increment(0, RoundingIncrement::MultiplesOf5); + assert_eq!("5", dec.to_string()); + + let mut dec = FixedDecimal::from_str("0.1").unwrap(); + dec.expand_to_increment(0, RoundingIncrement::MultiplesOf25); + assert_eq!("25", dec.to_string()); + + let mut dec = FixedDecimal::from_str("1").unwrap(); + dec.expand_to_increment(0, RoundingIncrement::MultiplesOf2); + assert_eq!("2", dec.to_string()); + + let mut dec = FixedDecimal::from_str("1").unwrap(); + dec.expand_to_increment(0, RoundingIncrement::MultiplesOf5); + assert_eq!("5", dec.to_string()); + + let mut dec = FixedDecimal::from_str("1").unwrap(); + dec.expand_to_increment(0, RoundingIncrement::MultiplesOf25); + assert_eq!("25", dec.to_string()); + + let mut dec = FixedDecimal::from_str("2").unwrap(); + dec.expand_to_increment(0, RoundingIncrement::MultiplesOf2); + assert_eq!("2", dec.to_string()); + + let mut dec = FixedDecimal::from_str("2").unwrap(); + dec.expand_to_increment(0, RoundingIncrement::MultiplesOf5); + assert_eq!("5", dec.to_string()); let mut dec = FixedDecimal::from_str("2.1").unwrap(); dec.expand_to_increment(0, RoundingIncrement::MultiplesOf2); @@ -4187,4 +5317,68 @@ fn test_rounding_increment() { let mut dec = FixedDecimal::from_str("0.50").unwrap(); dec.expand_to_increment(-2, RoundingIncrement::MultiplesOf25); assert_eq!("0.50", dec.to_string()); + + let mut dec = FixedDecimal::from_str("1.1025").unwrap(); + dec.half_trunc_to_increment(-3, RoundingIncrement::MultiplesOf5); + assert_eq!("1.100", dec.to_string()); + + let mut dec = FixedDecimal::from_str("1.10125").unwrap(); + dec.half_expand_to_increment(-4, RoundingIncrement::MultiplesOf25); + assert_eq!("1.1025", dec.to_string()); + + let mut dec = FixedDecimal::from_str("-1.25").unwrap(); + dec.half_ceil_to_increment(-1, RoundingIncrement::MultiplesOf5); + assert_eq!("-1.0", dec.to_string()); + + let mut dec = FixedDecimal::from_str("-1.251").unwrap(); + dec.half_ceil_to_increment(-1, RoundingIncrement::MultiplesOf5); + assert_eq!("-1.5", dec.to_string()); + + let mut dec = FixedDecimal::from_str("-1.125").unwrap(); + dec.half_floor_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("-1.25", dec.to_string()); + + let mut dec = FixedDecimal::from_str("2.71").unwrap(); + dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf2); + assert_eq!("2.70", dec.to_string()); + + let mut dec = FixedDecimal::from_str("2.73").unwrap(); + dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf2); + assert_eq!("2.74", dec.to_string()); + + let mut dec = FixedDecimal::from_str("2.75").unwrap(); + dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf2); + assert_eq!("2.74", dec.to_string()); + + let mut dec = FixedDecimal::from_str("2.77").unwrap(); + dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf2); + assert_eq!("2.78", dec.to_string()); + + let mut dec = FixedDecimal::from_str("2.79").unwrap(); + dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf2); + assert_eq!("2.78", dec.to_string()); + + let mut dec = FixedDecimal::from_str("2.725").unwrap(); + dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf5); + assert_eq!("2.70", dec.to_string()); + + let mut dec = FixedDecimal::from_str("2.775").unwrap(); + dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf5); + assert_eq!("2.80", dec.to_string()); + + let mut dec = FixedDecimal::from_str("2.875").unwrap(); + dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("3.00", dec.to_string()); + + let mut dec = FixedDecimal::from_str("2.375").unwrap(); + dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("2.50", dec.to_string()); + + let mut dec = FixedDecimal::from_str("2.125").unwrap(); + dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("2.00", dec.to_string()); + + let mut dec = FixedDecimal::from_str("2.625").unwrap(); + dec.half_even_to_increment(-2, RoundingIncrement::MultiplesOf25); + assert_eq!("2.50", dec.to_string()); }