1use smallvec::SmallVec;
6
7use core::cmp;
8use core::cmp::Ordering;
9use core::fmt;
10use core::ops::RangeInclusive;
11use core::str::FromStr;
12
13use crate::{uint_iterator::IntIterator, IncrementLike, NoIncrement};
14#[cfg(feature = "ryu")]
15use crate::{FloatPrecision, LimitError};
16use crate::{ParseError, RoundingIncrement, UnsignedRoundingMode};
17
18#[cfg(not(any(
20 target_pointer_width = "16",
21 target_pointer_width = "32",
22 target_pointer_width = "64"
23)))]
24compile_error!("The fixed_decimal crate only works if usizes are at least the size of a u16");
25
26#[derive(Debug, Clone, PartialEq)]
88pub struct UnsignedDecimal {
89 digits: SmallVec<[u8; 8]>,
96
97 magnitude: i16,
103
104 upper_magnitude: i16,
110
111 lower_magnitude: i16,
117}
118
119impl Default for UnsignedDecimal {
120 fn default() -> Self {
122 Self {
123 digits: SmallVec::new(),
124 magnitude: 0,
125 upper_magnitude: 0,
126 lower_magnitude: 0,
127 }
128 }
129}
130
131macro_rules! impl_from_unsigned_integer_type {
132 ($utype: ident) => {
133 impl From<$utype> for UnsignedDecimal {
134 fn from(value: $utype) -> Self {
135 let int_iterator: IntIterator<$utype> = value.into();
136 Self::from_ascending(int_iterator).expect("All built-in integer types should fit")
137 }
138 }
139 };
140}
141
142impl_from_unsigned_integer_type!(usize);
143impl_from_unsigned_integer_type!(u128);
144impl_from_unsigned_integer_type!(u64);
145impl_from_unsigned_integer_type!(u32);
146impl_from_unsigned_integer_type!(u16);
147impl_from_unsigned_integer_type!(u8);
148
149impl UnsignedDecimal {
150 pub(crate) fn from_ascending<T>(digits_iter: T) -> Result<Self, ParseError>
155 where
156 T: Iterator<Item = u8>,
157 {
158 const X: usize = 39;
162 let mut mem: [u8; X] = [0u8; X];
166 let mut trailing_zeros: usize = 0;
167 let mut i: usize = 0;
168 for (x, d) in digits_iter.enumerate() {
169 if x > i16::MAX as usize {
171 return Err(ParseError::Limit);
172 }
173 if i != 0 || d != 0 {
176 i += 1;
177 match X.checked_sub(i) {
178 #[allow(clippy::indexing_slicing)] Some(v) => mem[v] = d,
180 None => return Err(ParseError::Limit),
182 }
183 } else {
184 trailing_zeros += 1;
185 }
186 }
187 let mut result: Self = Default::default();
188 if i != 0 {
189 let magnitude = trailing_zeros + i - 1;
190 debug_assert!(magnitude <= i16::MAX as usize);
191 result.magnitude = magnitude as i16;
192 result.upper_magnitude = result.magnitude;
193 debug_assert!(i <= X);
194 #[allow(clippy::indexing_slicing)] result.digits.extend_from_slice(&mem[(X - i)..]);
196 }
197 #[cfg(debug_assertions)]
198 result.check_invariants();
199 Ok(result)
200 }
201
202 pub fn digit_at(&self, magnitude: i16) -> u8 {
218 if magnitude > self.magnitude {
219 0 } else {
221 let j = crate::ops::i16_abs_sub(self.magnitude, magnitude) as usize;
225 match self.digits.get(j) {
226 Some(v) => *v,
227 None => 0, }
229 }
230 }
231
232 fn digit_at_previous_position(&self, magnitude: i16) -> u8 {
236 if magnitude == i16::MAX {
237 0
238 } else {
239 self.digit_at(magnitude + 1)
240 }
241 }
242
243 fn digit_at_next_position(&self, magnitude: i16) -> u8 {
247 if magnitude == i16::MIN {
248 0
249 } else {
250 self.digit_at(magnitude - 1)
251 }
252 }
253
254 fn half_at_next_magnitude(&self, magnitude: i16) -> Ordering {
256 #[cfg(debug_assertions)] self.check_invariants();
258
259 match self.digit_at_next_position(magnitude).cmp(&5) {
260 Ordering::Equal => match (magnitude - 1).cmp(&self.nonzero_magnitude_end()) {
264 Ordering::Greater => {
265 Ordering::Greater
268 }
269 Ordering::Equal => {
270 Ordering::Equal
273 }
274 Ordering::Less => {
275 debug_assert!(false, "digit `magnitude - 1` should not be zero");
276 Ordering::Less
277 }
278 },
279 ord => ord,
282 }
283 }
284
285 fn half_increment_at_magnitude<R: IncrementLike>(
288 &self,
289 magnitude: i16,
290 increment: R,
291 ) -> Ordering {
292 #[cfg(debug_assertions)] self.check_invariants();
294
295 match Some(increment) {
296 x if x == R::MULTIPLES_OF_1 => self.half_at_next_magnitude(magnitude),
297 x if x == R::MULTIPLES_OF_2 => {
298 let current_digit = self.digit_at(magnitude);
299
300 if current_digit & 0x01 == 1 {
302 match magnitude.cmp(&self.nonzero_magnitude_end()) {
303 Ordering::Greater => {
304 Ordering::Greater
308 }
309 Ordering::Equal => {
310 Ordering::Equal
313 }
314 Ordering::Less => {
315 debug_assert!(false, "digit `magnitude` should not be zero");
316 Ordering::Less
317 }
318 }
319 } else {
320 Ordering::Less
322 }
323 }
324 x if x == R::MULTIPLES_OF_5 => {
325 let current_digit = self.digit_at(magnitude);
326 match (current_digit % 5).cmp(&2) {
327 Ordering::Equal => {
328 self.half_at_next_magnitude(magnitude)
330 }
331 ord => ord,
334 }
335 }
336 x if x == R::MULTIPLES_OF_25 => {
337 let current_digit = self.digit_at(magnitude);
338 let prev_digit = self.digit_at_previous_position(magnitude);
339 let number = prev_digit * 10 + current_digit;
340
341 match (number % 25).cmp(&12) {
342 Ordering::Equal => {
343 self.half_at_next_magnitude(magnitude)
345 }
346 ord => ord,
349 }
350 }
351 _ => {
352 debug_assert!(false, "increment should be 1, 2, 5, or 25");
353 Ordering::Equal
354 }
355 }
356 }
357
358 fn is_rounded<R: IncrementLike>(&self, position: i16, increment: R) -> bool {
361 if self.is_zero() {
364 return true;
365 }
366
367 match Some(increment) {
368 x if x == R::MULTIPLES_OF_1 => {
369 position <= self.nonzero_magnitude_end()
371 }
372 x if x == R::MULTIPLES_OF_2 => {
373 match position.cmp(&self.nonzero_magnitude_end()) {
377 Ordering::Less => true,
378 Ordering::Equal => self.digit_at(position) & 0x01 == 0,
379 Ordering::Greater => false,
380 }
381 }
382 x if x == R::MULTIPLES_OF_5 => {
383 match position.cmp(&self.nonzero_magnitude_end()) {
387 Ordering::Less => true,
388 Ordering::Equal => self.digit_at(position) == 5,
389 Ordering::Greater => false,
390 }
391 }
392 x if x == R::MULTIPLES_OF_25 => {
393 match position.cmp(&self.nonzero_magnitude_end()) {
396 Ordering::Less => {
397 if position + 1 < self.nonzero_magnitude_end() {
400 true
401 } else {
402 self.digit_at(position + 1) == 5
405 }
406 }
407 Ordering::Equal => {
408 let current_digit = self.digit_at(position);
409 let prev_digit = self.digit_at_previous_position(position);
410 let number = prev_digit * 10 + current_digit;
411
412 matches!(number, 25 | 75)
413 }
414 Ordering::Greater => false,
415 }
416 }
417 _ => {
418 debug_assert!(false, "INCREMENT should be 1, 2, 5, or 25");
419 false
420 }
421 }
422 }
423
424 pub const fn magnitude_range(&self) -> RangeInclusive<i16> {
437 self.lower_magnitude..=self.upper_magnitude
438 }
439
440 pub fn nonzero_magnitude_start(&self) -> i16 {
453 self.magnitude
454 }
455
456 pub fn nonzero_magnitude_end(&self) -> i16 {
469 if self.is_zero() {
470 0
471 } else {
472 crate::ops::i16_sub_unsigned(self.magnitude, self.digits.len() as u16 - 1)
473 }
474 }
475
476 #[inline]
487 pub fn is_zero(&self) -> bool {
488 self.digits.is_empty()
489 }
490
491 pub(crate) fn clear(&mut self) {
493 self.upper_magnitude = 0;
494 self.lower_magnitude = 0;
495 self.magnitude = 0;
496 self.digits.clear();
497
498 #[cfg(debug_assertions)]
499 self.check_invariants();
500 }
501
502 pub fn multiply_pow10(&mut self, delta: i16) {
521 match delta.cmp(&0) {
522 Ordering::Greater => {
523 let upper_magnitude = self.upper_magnitude.checked_add(delta);
524 match upper_magnitude {
525 Some(upper_magnitude) => {
526 self.upper_magnitude = upper_magnitude;
527 let lower_magnitude = self.lower_magnitude + delta;
529 self.lower_magnitude = cmp::min(0, lower_magnitude);
530 }
531 None => {
532 self.clear();
534 }
535 }
536 }
537 Ordering::Less => {
538 let lower_magnitude = self.lower_magnitude.checked_add(delta);
539 match lower_magnitude {
540 Some(lower_magnitude) => {
541 self.lower_magnitude = lower_magnitude;
542 let upper_magnitude = self.upper_magnitude + delta;
544 self.upper_magnitude = cmp::max(0, upper_magnitude);
545 }
546 None => {
547 self.clear();
549 }
550 }
551 }
552 Ordering::Equal => {}
553 };
554 if !self.is_zero() {
555 self.magnitude += delta;
556 }
557 #[cfg(debug_assertions)]
558 self.check_invariants();
559 }
560
561 pub fn multiplied_pow10(mut self, delta: i16) -> Self {
577 self.multiply_pow10(delta);
578 self
579 }
580
581 pub fn trimmed_start(mut self) -> Self {
596 self.trim_start();
597 self
598 }
599
600 pub fn trim_start(&mut self) {
627 self.upper_magnitude = cmp::max(self.magnitude, 0);
628 #[cfg(debug_assertions)]
629 self.check_invariants();
630 }
631
632 pub fn trimmed_end(mut self) -> Self {
647 self.trim_end();
648 self
649 }
650
651 pub fn trim_end(&mut self) {
678 self.lower_magnitude = cmp::min(0, self.nonzero_magnitude_end());
679 #[cfg(debug_assertions)]
680 self.check_invariants();
681 }
682
683 pub fn trimmed_end_if_integer(mut self) -> Self {
703 self.trim_end_if_integer();
704 self
705 }
706
707 pub fn trim_end_if_integer(&mut self) {
734 if self.nonzero_magnitude_end() >= 0 {
735 self.lower_magnitude = 0;
736 }
737 #[cfg(debug_assertions)]
738 self.check_invariants();
739 }
740
741 pub fn padded_start(mut self, position: i16) -> Self {
763 self.pad_start(position);
764 self
765 }
766
767 pub fn pad_start(&mut self, position: i16) {
794 if position <= 0 {
795 return;
796 }
797 let mut magnitude = position - 1;
798 if magnitude <= self.magnitude {
800 magnitude = self.magnitude;
801 }
802 self.upper_magnitude = magnitude;
803 #[cfg(debug_assertions)]
804 self.check_invariants();
805 }
806
807 pub fn padded_end(mut self, position: i16) -> Self {
832 self.pad_end(position);
833 self
834 }
835
836 pub fn pad_end(&mut self, position: i16) {
863 if position > 0 {
864 return;
865 }
866 let bottom_magnitude = self.nonzero_magnitude_end();
867 let mut magnitude = position;
868 if magnitude >= bottom_magnitude {
870 magnitude = bottom_magnitude;
871 }
872 self.lower_magnitude = magnitude;
873 #[cfg(debug_assertions)]
874 self.check_invariants();
875 }
876
877 pub fn with_max_position(mut self, position: i16) -> Self {
905 self.set_max_position(position);
906 self
907 }
908
909 pub fn set_max_position(&mut self, position: i16) {
944 self.lower_magnitude = cmp::min(self.lower_magnitude, position);
945 self.upper_magnitude = if position <= 0 { 0 } else { position - 1 };
946 if position <= self.nonzero_magnitude_end() {
947 self.digits.clear();
948 self.magnitude = 0;
949 #[cfg(debug_assertions)]
950 self.check_invariants();
951 return;
952 }
953 let magnitude = position - 1;
954 if self.magnitude >= magnitude {
955 let cut = crate::ops::i16_abs_sub(self.magnitude, magnitude) as usize;
956 let _ = self.digits.drain(0..cut).count();
957 let extra_zeroes = self.digits.iter().position(|x| *x != 0).unwrap_or(0);
959 let _ = self.digits.drain(0..extra_zeroes).count();
960 debug_assert!(!self.digits.is_empty());
961 self.magnitude = crate::ops::i16_sub_unsigned(magnitude, extra_zeroes as u16);
962 }
963 #[cfg(debug_assertions)]
964 self.check_invariants();
965 }
966
967 pub fn round(&mut self, position: i16) {
992 self.half_even_to_increment_internal(position, NoIncrement)
993 }
994
995 pub fn rounded(mut self, position: i16) -> Self {
1016 self.round(position);
1017 self
1018 }
1019
1020 #[inline(never)]
1042 pub fn expand(&mut self, position: i16) {
1043 self.expand_to_increment_internal(position, NoIncrement)
1044 }
1045
1046 pub fn expanded(mut self, position: i16) -> Self {
1064 self.expand(position);
1065 self
1066 }
1067
1068 #[inline(never)]
1092 pub fn trunc(&mut self, position: i16) {
1093 self.trunc_to_increment_internal(position, NoIncrement)
1094 }
1095
1096 pub fn trunced(mut self, position: i16) -> Self {
1116 self.trunc(position);
1117 self
1118 }
1119
1120 pub fn round_with_mode(&mut self, position: i16, mode: UnsignedRoundingMode) {
1136 match mode {
1137 UnsignedRoundingMode::Expand => {
1138 self.expand_to_increment_internal(position, NoIncrement)
1139 }
1140 UnsignedRoundingMode::Trunc => self.trunc_to_increment_internal(position, NoIncrement),
1141 UnsignedRoundingMode::HalfExpand => {
1142 self.half_expand_to_increment_internal(position, NoIncrement)
1143 }
1144 UnsignedRoundingMode::HalfTrunc => {
1145 self.half_trunc_to_increment_internal(position, NoIncrement)
1146 }
1147 UnsignedRoundingMode::HalfEven => {
1148 self.half_even_to_increment_internal(position, NoIncrement)
1149 }
1150 }
1151 }
1152
1153 pub fn rounded_with_mode(mut self, position: i16, mode: UnsignedRoundingMode) -> Self {
1175 self.round_with_mode(position, mode);
1176 self
1177 }
1178
1179 pub fn round_with_mode_and_increment(
1206 &mut self,
1207 position: i16,
1208 mode: UnsignedRoundingMode,
1209 increment: RoundingIncrement,
1210 ) {
1211 match mode {
1212 UnsignedRoundingMode::Expand => self.expand_to_increment_internal(position, increment),
1213 UnsignedRoundingMode::Trunc => self.trunc_to_increment_internal(position, increment),
1214 UnsignedRoundingMode::HalfExpand => {
1215 self.half_expand_to_increment_internal(position, increment)
1216 }
1217 UnsignedRoundingMode::HalfTrunc => {
1218 self.half_trunc_to_increment_internal(position, increment)
1219 }
1220 UnsignedRoundingMode::HalfEven => {
1221 self.half_even_to_increment_internal(position, increment)
1222 }
1223 }
1224 }
1225
1226 pub fn rounded_with_mode_and_increment(
1259 mut self,
1260 position: i16,
1261 mode: UnsignedRoundingMode,
1262 increment: RoundingIncrement,
1263 ) -> Self {
1264 self.round_with_mode_and_increment(position, mode, increment);
1265 self
1266 }
1267
1268 pub(crate) fn expand_to_increment_internal<R: IncrementLike>(
1269 &mut self,
1270 position: i16,
1271 inner_increment: R,
1272 ) {
1273 fn overflow(number: &mut UnsignedDecimal) {
1275 number.digits.clear();
1277 number.magnitude = 0;
1278 #[cfg(debug_assertions)]
1279 number.check_invariants();
1280 }
1281
1282 let increment = Some(inner_increment);
1283
1284 self.lower_magnitude = cmp::min(position, 0);
1286
1287 match position.cmp(&i16::MIN) {
1288 Ordering::Equal if increment == R::MULTIPLES_OF_1 => {
1291 #[cfg(debug_assertions)]
1293 self.check_invariants();
1294 return;
1295 }
1296 Ordering::Greater => {
1297 self.upper_magnitude = cmp::max(self.upper_magnitude, position - 1);
1298 }
1299 _ => {
1300 }
1305 }
1306
1307 if self.is_rounded(position, inner_increment) {
1309 #[cfg(debug_assertions)]
1310 self.check_invariants();
1311 return;
1312 }
1313
1314 if position <= self.magnitude {
1316 let digits_to_retain = crate::ops::i16_abs_sub(self.magnitude, position) + 1;
1318 self.digits.truncate(digits_to_retain as usize);
1319
1320 let iter = match increment {
1322 x if x == R::MULTIPLES_OF_1 => {
1323 self.digits.iter_mut().rev().enumerate()
1326 }
1327 x if x == R::MULTIPLES_OF_2 => {
1328 let mut iter = self.digits.iter_mut().rev().enumerate();
1329
1330 let Some((_, digit)) = iter.next() else {
1332 debug_assert!(false, "`self.digits` should have at least a digit");
1333 return;
1334 };
1335
1336 *digit = (*digit + 2) & 0xFE;
1339
1340 if *digit < 10 {
1341 #[cfg(debug_assertions)]
1343 self.check_invariants();
1344 return;
1345 }
1346
1347 iter
1348 }
1349 x if x == R::MULTIPLES_OF_5 => {
1350 let mut iter = self.digits.iter_mut().rev().enumerate();
1351
1352 let Some((_, digit)) = iter.next() else {
1354 debug_assert!(false, "`self.digits` should have at least a digit");
1355 return;
1356 };
1357
1358 if *digit < 5 {
1359 *digit = 5;
1360
1361 #[cfg(debug_assertions)]
1363 self.check_invariants();
1364 return;
1365 }
1366
1367 *digit = 10;
1368
1369 iter
1370 }
1371 x if x == R::MULTIPLES_OF_25 => {
1372 self.digits.resize(digits_to_retain as usize, 0);
1375
1376 let Some((last_digit, digits)) = self.digits.split_last_mut() else {
1377 debug_assert!(false, "`self.digits` should have at least a digit");
1378 return;
1379 };
1380
1381 let Some((second_last_digit, _)) = digits.split_last_mut() else {
1382 if self.magnitude == i16::MAX {
1386 overflow(self);
1387 return;
1388 }
1389
1390 self.digits.clear();
1391 self.digits.extend_from_slice(&[2, 5]);
1392 self.magnitude += 1;
1393 self.upper_magnitude = cmp::max(self.upper_magnitude, self.magnitude);
1394
1395 #[cfg(debug_assertions)]
1396 self.check_invariants();
1397 return;
1398 };
1399
1400 let number = *second_last_digit * 10 + *last_digit;
1401
1402 if number < 75 {
1403 if number < 25 {
1406 *second_last_digit = 2;
1407 *last_digit = 5;
1408 } else if number < 50 {
1409 *second_last_digit = 5;
1410 self.digits.pop();
1411 } else {
1412 *second_last_digit = 7;
1413 *last_digit = 5;
1414 }
1415
1416 #[cfg(debug_assertions)]
1417 self.check_invariants();
1418 return;
1419 }
1420
1421 *second_last_digit = 10;
1425 *last_digit = 10;
1426
1427 let mut iter = self.digits.iter_mut().rev().enumerate();
1428
1429 iter.next();
1431 iter.next();
1432
1433 iter
1434 }
1435 _ => {
1436 debug_assert!(false, "INCREMENT should be 1, 2, 5, or 25");
1437 return;
1438 }
1439 };
1440
1441 for (zero_count, digit) in iter {
1444 *digit += 1;
1445 if *digit < 10 {
1446 self.digits.truncate(self.digits.len() - zero_count);
1447 #[cfg(debug_assertions)]
1448 self.check_invariants();
1449 return;
1450 }
1451 }
1452
1453 if self.magnitude == i16::MAX {
1457 overflow(self);
1458 return;
1459 }
1460
1461 self.digits.clear();
1462 self.digits.push(1);
1463
1464 self.magnitude += 1;
1465 self.upper_magnitude = cmp::max(self.upper_magnitude, self.magnitude);
1466
1467 #[cfg(debug_assertions)]
1468 self.check_invariants();
1469 return;
1470 }
1471
1472 if increment == R::MULTIPLES_OF_25 && position == i16::MAX {
1477 overflow(self);
1479 return;
1480 }
1481
1482 self.digits.clear();
1483
1484 let increment_digits = match increment {
1488 x if x == R::MULTIPLES_OF_1 => [1].as_slice(),
1489 x if x == R::MULTIPLES_OF_2 => [2].as_slice(),
1490 x if x == R::MULTIPLES_OF_5 => [5].as_slice(),
1491 x if x == R::MULTIPLES_OF_25 => [2, 5].as_slice(),
1492 _ => {
1493 debug_assert!(false, "INCREMENT should be 1, 2, 5, or 25");
1494 return;
1495 }
1496 };
1497 self.digits.extend_from_slice(increment_digits);
1498
1499 self.magnitude = if increment == R::MULTIPLES_OF_25 {
1502 position + 1
1503 } else {
1504 position
1505 };
1506
1507 self.upper_magnitude = cmp::max(self.upper_magnitude, self.magnitude);
1508
1509 #[cfg(debug_assertions)]
1510 self.check_invariants();
1511 }
1512
1513 pub(crate) fn trunc_to_increment_internal<R: IncrementLike>(
1514 &mut self,
1515 position: i16,
1516 inner_increment: R,
1517 ) {
1518 let increment = Some(inner_increment);
1519
1520 self.lower_magnitude = cmp::min(position, 0);
1522
1523 match position.cmp(&i16::MIN) {
1524 Ordering::Equal if increment == R::MULTIPLES_OF_1 => {
1527 #[cfg(debug_assertions)]
1529 self.check_invariants();
1530 return;
1531 }
1532 Ordering::Greater => {
1533 self.upper_magnitude = cmp::max(self.upper_magnitude, position - 1);
1534 }
1535 _ => {
1536 }
1541 }
1542
1543 if self.is_rounded(position, inner_increment) {
1545 #[cfg(debug_assertions)]
1546 self.check_invariants();
1547 return;
1548 }
1549
1550 if position <= self.magnitude {
1552 let digits_to_retain = crate::ops::i16_abs_sub(self.magnitude, position) + 1;
1554 self.digits.truncate(digits_to_retain as usize);
1555
1556 match increment {
1558 x if x == R::MULTIPLES_OF_1 => {
1559 }
1561 x if x == R::MULTIPLES_OF_2 => {
1562 let Some(last_digit) = self.digits.last_mut() else {
1563 debug_assert!(false, "`self.digits` should have at least a digit");
1564 return;
1565 };
1566
1567 *last_digit &= 0xFE;
1570 }
1571 x if x == R::MULTIPLES_OF_5 => {
1572 let Some(last_digit) = self.digits.last_mut() else {
1573 debug_assert!(false, "`self.digits` should have at least a digit");
1574 return;
1575 };
1576
1577 *last_digit = if *last_digit < 5 { 0 } else { 5 };
1578 }
1579 x if x == R::MULTIPLES_OF_25 => {
1580 self.digits.resize(digits_to_retain as usize, 0);
1582
1583 let Some((last_digit, digits)) = self.digits.split_last_mut() else {
1584 debug_assert!(false, "`self.digits` should have at least a digit");
1585 return;
1586 };
1587
1588 if let Some(second_last_digit) = digits.last_mut() {
1589 let number = *second_last_digit * 10 + *last_digit;
1590
1591 (*second_last_digit, *last_digit) = if number < 25 {
1594 (0, 0)
1595 } else if number < 50 {
1596 (2, 5)
1597 } else if number < 75 {
1598 (5, 0)
1599 } else {
1600 (7, 5)
1601 };
1602 } else {
1603 *last_digit = 0;
1606 };
1607 }
1608 _ => {
1609 debug_assert!(false, "INCREMENT should be 1, 2, 5, or 25");
1610 return;
1611 }
1612 }
1613
1614 let position_last_nonzero_digit = self
1617 .digits
1618 .iter()
1619 .rposition(|x| *x != 0)
1620 .map(|x| x + 1)
1621 .unwrap_or(0);
1622 self.digits.truncate(position_last_nonzero_digit);
1623
1624 if self.digits.is_empty() {
1627 self.magnitude = 0;
1628 }
1629 } else {
1630 self.digits.clear();
1633 self.magnitude = 0;
1634 }
1635
1636 #[cfg(debug_assertions)]
1637 self.check_invariants();
1638 }
1639
1640 pub(crate) fn half_even_to_increment_internal<R: IncrementLike>(
1641 &mut self,
1642 position: i16,
1643 increment: R,
1644 ) {
1645 let should_expand = match self.half_increment_at_magnitude(position, increment) {
1646 Ordering::Greater => true,
1647 Ordering::Less => false,
1648 Ordering::Equal => match Some(increment) {
1649 x if x == R::MULTIPLES_OF_1 => {
1650 self.digit_at(position) & 0x01 == 1
1652 }
1653 x if x == R::MULTIPLES_OF_2 => {
1654 let current_digit = self.digit_at(position);
1655 let previous_digit = self.digit_at_previous_position(position);
1656 let full = previous_digit * 10 + current_digit;
1657
1658 (full >> 1) & 0x01 == 1
1669 }
1670 x if x == R::MULTIPLES_OF_5 => {
1671 self.digit_at(position) == 7
1673 }
1674 x if x == R::MULTIPLES_OF_25 => {
1675 let current_digit = self.digit_at(position);
1676 let prev_digit = self.digit_at_previous_position(position);
1677 let full_number = prev_digit * 10 + current_digit;
1678
1679 full_number == 37 || full_number == 87
1682 }
1683 _ => {
1684 debug_assert!(false, "INCREMENT should be 1, 2, 5, or 25");
1685 return;
1686 }
1687 },
1688 };
1689
1690 if should_expand {
1691 self.expand_to_increment_internal(position, increment);
1692 } else {
1693 self.trunc_to_increment_internal(position, increment);
1694 }
1695 }
1696
1697 pub(crate) fn half_expand_to_increment_internal<R: IncrementLike>(
1698 &mut self,
1699 position: i16,
1700 increment: R,
1701 ) {
1702 let should_trunc = self.half_increment_at_magnitude(position, increment) == Ordering::Less;
1705
1706 if should_trunc {
1707 self.trunc_to_increment_internal(position, increment);
1708 } else {
1709 self.expand_to_increment_internal(position, increment);
1710 }
1711 }
1712
1713 pub(crate) fn half_trunc_to_increment_internal<R: IncrementLike>(
1714 &mut self,
1715 position: i16,
1716 increment: R,
1717 ) {
1718 let should_expand =
1721 self.half_increment_at_magnitude(position, increment) == Ordering::Greater;
1722
1723 if should_expand {
1724 self.expand_to_increment_internal(position, increment);
1725 } else {
1726 self.trunc_to_increment_internal(position, increment);
1727 }
1728 }
1729
1730 pub fn concatenated_end(
1751 mut self,
1752 other: UnsignedDecimal,
1753 ) -> Result<Self, (UnsignedDecimal, UnsignedDecimal)> {
1754 match self.concatenate_end(other) {
1755 Ok(()) => Ok(self),
1756 Err(err) => Err((self, err)),
1757 }
1758 }
1759
1760 pub fn concatenate_end(&mut self, other: UnsignedDecimal) -> Result<(), UnsignedDecimal> {
1781 let self_right = self.nonzero_magnitude_end();
1782 let other_left = other.nonzero_magnitude_start();
1783 if self.is_zero() {
1784 self.digits = other.digits;
1786 self.magnitude = other.magnitude;
1787 } else if other.is_zero() {
1788 } else if self_right <= other_left {
1790 return Err(other);
1792 } else {
1793 let inner_zeroes = crate::ops::i16_abs_sub(self_right, other_left) as usize - 1;
1795 self.append_digits(inner_zeroes, &other.digits);
1796 }
1797 self.upper_magnitude = cmp::max(self.upper_magnitude, other.upper_magnitude);
1798 self.lower_magnitude = cmp::min(self.lower_magnitude, other.lower_magnitude);
1799 #[cfg(debug_assertions)]
1800 self.check_invariants();
1801 Ok(())
1802 }
1803
1804 fn append_digits(&mut self, inner_zeroes: usize, new_digits: &[u8]) {
1808 let new_len = self.digits.len() + inner_zeroes;
1809 self.digits.resize_with(new_len, || 0);
1810 self.digits.extend_from_slice(new_digits);
1811 }
1812
1813 #[cfg(debug_assertions)]
1818 #[allow(clippy::indexing_slicing)]
1819 fn check_invariants(&self) {
1820 debug_assert!(
1822 self.upper_magnitude >= self.magnitude,
1823 "Upper magnitude too small {self:?}"
1824 );
1825 debug_assert!(
1826 self.lower_magnitude <= self.magnitude,
1827 "Lower magnitude too large {self:?}"
1828 );
1829 debug_assert!(
1830 self.upper_magnitude >= 0,
1831 "Upper magnitude below zero {self:?}"
1832 );
1833 debug_assert!(
1834 self.lower_magnitude <= 0,
1835 "Lower magnitude above zero {self:?}",
1836 );
1837
1838 debug_assert!(
1840 self.digits.len() <= (self.magnitude as i32 - self.lower_magnitude as i32 + 1) as usize,
1841 "{self:?}"
1842 );
1843 if !self.digits.is_empty() {
1844 debug_assert_ne!(self.digits[0], 0, "Starts with a zero {self:?}");
1845 debug_assert_ne!(
1846 self.digits[self.digits.len() - 1],
1847 0,
1848 "Ends with a zero {self:?}",
1849 );
1850 } else {
1851 debug_assert_eq!(self.magnitude, 0);
1852 }
1853 }
1854}
1855
1856impl writeable::Writeable for UnsignedDecimal {
1867 fn write_to<W: fmt::Write + ?Sized>(&self, sink: &mut W) -> fmt::Result {
1868 for m in self.magnitude_range().rev() {
1869 if m == -1 {
1870 sink.write_char('.')?;
1871 }
1872 let d = self.digit_at(m);
1873 sink.write_char((b'0' + d) as char)?;
1874 }
1875 Ok(())
1876 }
1877
1878 fn writeable_length_hint(&self) -> writeable::LengthHint {
1879 writeable::LengthHint::exact(1)
1880 + ((self.upper_magnitude as i32 - self.lower_magnitude as i32) as usize)
1881 + (self.lower_magnitude < 0) as usize
1882 }
1883}
1884
1885writeable::impl_display_with_writeable!(UnsignedDecimal);
1886
1887impl UnsignedDecimal {
1888 #[inline]
1889 pub fn try_from_str(s: &str) -> Result<Self, ParseError> {
1891 Self::try_from_utf8(s.as_bytes())
1892 }
1893
1894 pub fn try_from_utf8(input_str: &[u8]) -> Result<Self, ParseError> {
1914 if input_str.is_empty() {
1915 return Err(ParseError::Syntax);
1916 }
1917
1918 Self::try_from_no_sign_utf8(input_str)
1920 }
1921
1922 pub(crate) fn try_from_no_sign_utf8(no_sign_str: &[u8]) -> Result<Self, ParseError> {
1923 let mut has_dot = false;
1932 let mut has_exponent = false;
1933 let mut dot_index = no_sign_str.len();
1934 let mut exponent_index = no_sign_str.len();
1935 for (i, c) in no_sign_str.iter().enumerate() {
1940 if *c == b'.' {
1941 if has_dot || has_exponent {
1942 return Err(ParseError::Syntax);
1944 }
1945 dot_index = i;
1946 has_dot = true;
1947 if i == no_sign_str.len() - 1 {
1950 return Err(ParseError::Syntax);
1951 }
1952 } else if *c == b'e' || *c == b'E' {
1953 if has_exponent {
1954 return Err(ParseError::Syntax);
1956 }
1957 exponent_index = i;
1958 has_exponent = true;
1959 if i == 0 || i == no_sign_str.len() - 1 {
1960 return Err(ParseError::Syntax);
1961 }
1962 } else if *c == b'-' {
1963 if has_exponent && exponent_index == i - 1 {
1965 continue;
1966 } else {
1967 return Err(ParseError::Syntax);
1968 }
1969 } else if *c < b'0' || *c > b'9' {
1970 return Err(ParseError::Syntax);
1971 }
1972 }
1973
1974 #[allow(clippy::indexing_slicing)] let no_exponent_str = &no_sign_str[..exponent_index];
1979
1980 if dot_index > exponent_index {
1982 dot_index = exponent_index;
1983 }
1984
1985 let mut dec = Self::default();
1987
1988 let mut no_dot_str_len = no_exponent_str.len();
1990 if has_dot {
1991 no_dot_str_len -= 1;
1992 }
1993
1994 let temp_upper_magnitude = dot_index.saturating_sub(1);
2000 if temp_upper_magnitude > i16::MAX as usize {
2001 return Err(ParseError::Limit);
2002 }
2003 dec.upper_magnitude = temp_upper_magnitude as i16;
2004
2005 let temp_lower_magnitude = no_dot_str_len - dot_index;
2007 if temp_lower_magnitude > (i16::MIN as u16) as usize {
2008 return Err(ParseError::Limit);
2009 }
2010 dec.lower_magnitude = (temp_lower_magnitude as i16).wrapping_neg();
2011
2012 let leftmost_digit = no_exponent_str
2022 .iter()
2023 .position(|c| *c != b'.' && *c != b'0');
2024
2025 let leftmost_digit = if let Some(leftmost_digit) = leftmost_digit {
2028 leftmost_digit
2029 } else {
2030 return Ok(dec);
2031 };
2032
2033 let mut temp_magnitude = ((dot_index as i32) - (leftmost_digit as i32) - 1i32) as i16;
2036 if dot_index < leftmost_digit {
2037 temp_magnitude += 1;
2038 }
2039 dec.magnitude = temp_magnitude;
2040
2041 let rightmost_digit_end = no_exponent_str
2043 .iter()
2044 .rposition(|c| *c != b'.' && *c != b'0')
2045 .map(|p| p + 1)
2046 .unwrap_or(no_exponent_str.len());
2047
2048 let mut digits_str_len = rightmost_digit_end - leftmost_digit;
2050 if leftmost_digit < dot_index && dot_index < rightmost_digit_end {
2051 digits_str_len -= 1;
2052 }
2053
2054 #[allow(clippy::indexing_slicing)]
2056 let v: SmallVec<[u8; 8]> = no_exponent_str[leftmost_digit..rightmost_digit_end]
2058 .iter()
2059 .filter(|c| **c != b'.')
2060 .map(|c| c - b'0')
2061 .collect();
2062
2063 let v_len = v.len();
2064 debug_assert_eq!(v_len, digits_str_len);
2065 dec.digits = v;
2066
2067 if has_exponent {
2069 let mut pow = 0;
2070 let mut pos_neg = 1;
2071 #[allow(clippy::indexing_slicing)]
2072 for digit in &no_sign_str[exponent_index + 1..] {
2074 if *digit == b'-' {
2075 pos_neg = -1;
2076 continue;
2077 }
2078 pow *= 10;
2079 pow += (digit - b'0') as i16;
2080 }
2081
2082 dec.multiply_pow10(pos_neg * pow);
2083
2084 if dec.magnitude > 0 {
2086 dec.upper_magnitude = dec.magnitude;
2087 }
2088 let neg_mag = dec.magnitude - dec.digits.len() as i16 + 1;
2089 if neg_mag < 0 {
2090 dec.lower_magnitude = neg_mag;
2091 }
2092 }
2093
2094 Ok(dec)
2095 }
2096}
2097
2098impl FromStr for UnsignedDecimal {
2099 type Err = ParseError;
2100 fn from_str(s: &str) -> Result<Self, Self::Err> {
2101 Self::try_from_str(s)
2102 }
2103}
2104
2105#[cfg(feature = "ryu")]
2106impl UnsignedDecimal {
2107 pub fn try_from_f64(float: f64, precision: FloatPrecision) -> Result<Self, LimitError> {
2141 let mut decimal = Self::new_from_f64_raw(float)?;
2142 let n_digits = decimal.digits.len();
2143 let lowest_magnitude = decimal.magnitude - n_digits as i16 + 1;
2145 if lowest_magnitude >= 0 && decimal.lower_magnitude < 0 {
2148 decimal.lower_magnitude = 0;
2149 }
2150 match precision {
2151 FloatPrecision::RoundTrip => (),
2152 FloatPrecision::Integer => {
2153 if lowest_magnitude < 0 {
2154 return Err(LimitError);
2155 }
2156 }
2157 FloatPrecision::Magnitude(mag) => {
2158 decimal.round(mag);
2159 }
2160 FloatPrecision::SignificantDigits(sig) => {
2161 if sig == 0 {
2162 return Err(LimitError);
2163 }
2164
2165 let position = decimal.magnitude - (sig as i16) + 1;
2166 let old_magnitude = decimal.magnitude;
2167 decimal.round(position);
2168
2169 if decimal.magnitude > old_magnitude {
2171 decimal.lower_magnitude = cmp::min(0, position + 1);
2172 }
2173 }
2174 }
2175 #[cfg(debug_assertions)]
2176 decimal.check_invariants();
2177 Ok(decimal)
2178 }
2179
2180 fn new_from_f64_raw(float: f64) -> Result<Self, LimitError> {
2182 if !float.is_finite() || float.is_sign_negative() {
2183 return Err(LimitError);
2184 }
2185 let mut buf = ryu::Buffer::new();
2187 let formatted = buf.format_finite(float);
2188 Self::from_str(formatted).map_err(|e| match e {
2189 ParseError::Limit => LimitError,
2190 ParseError::Syntax => unreachable!("ryu produces correct syntax"),
2191 })
2192 }
2193}
2194
2195#[cfg(feature = "ryu")]
2196#[test]
2197fn test_float() {
2198 #[derive(Debug)]
2199 struct TestCase {
2200 pub input: f64,
2201 pub precision: FloatPrecision,
2202 pub expected: &'static str,
2203 }
2204 let cases = [
2205 TestCase {
2206 input: 1.234567,
2207 precision: FloatPrecision::RoundTrip,
2208 expected: "1.234567",
2209 },
2210 TestCase {
2211 input: 888999.,
2212 precision: FloatPrecision::RoundTrip,
2213 expected: "888999",
2214 },
2215 TestCase {
2217 input: 1.234567,
2218 precision: FloatPrecision::Magnitude(-2),
2219 expected: "1.23",
2220 },
2221 TestCase {
2222 input: 1.235567,
2223 precision: FloatPrecision::Magnitude(-2),
2224 expected: "1.24",
2225 },
2226 TestCase {
2227 input: 1.2002,
2228 precision: FloatPrecision::Magnitude(-3),
2229 expected: "1.200",
2230 },
2231 TestCase {
2232 input: 888999.,
2233 precision: FloatPrecision::Magnitude(2),
2234 expected: "889000",
2235 },
2236 TestCase {
2237 input: 888999.,
2238 precision: FloatPrecision::Magnitude(4),
2239 expected: "890000",
2240 },
2241 TestCase {
2242 input: 0.9,
2243 precision: FloatPrecision::Magnitude(0),
2244 expected: "1",
2245 },
2246 TestCase {
2247 input: 0.9,
2248 precision: FloatPrecision::Magnitude(2),
2249 expected: "00",
2250 },
2251 TestCase {
2252 input: 0.009,
2253 precision: FloatPrecision::Magnitude(-2),
2254 expected: "0.01",
2255 },
2256 TestCase {
2257 input: 0.009,
2258 precision: FloatPrecision::Magnitude(-1),
2259 expected: "0.0",
2260 },
2261 TestCase {
2262 input: 0.009,
2263 precision: FloatPrecision::Magnitude(0),
2264 expected: "0",
2265 },
2266 TestCase {
2267 input: 0.0000009,
2268 precision: FloatPrecision::Magnitude(0),
2269 expected: "0",
2270 },
2271 TestCase {
2272 input: 0.0000009,
2273 precision: FloatPrecision::Magnitude(-7),
2274 expected: "0.0000009",
2275 },
2276 TestCase {
2277 input: 0.0000009,
2278 precision: FloatPrecision::Magnitude(-6),
2279 expected: "0.000001",
2280 },
2281 TestCase {
2282 input: 1.234567,
2283 precision: FloatPrecision::SignificantDigits(1),
2284 expected: "1",
2285 },
2286 TestCase {
2287 input: 1.234567,
2288 precision: FloatPrecision::SignificantDigits(2),
2289 expected: "1.2",
2290 },
2291 TestCase {
2292 input: 1.234567,
2293 precision: FloatPrecision::SignificantDigits(4),
2294 expected: "1.235",
2295 },
2296 TestCase {
2297 input: 1.234567,
2298 precision: FloatPrecision::SignificantDigits(10),
2299 expected: "1.234567000",
2300 },
2301 TestCase {
2302 input: 888999.,
2303 precision: FloatPrecision::SignificantDigits(1),
2304 expected: "900000",
2305 },
2306 TestCase {
2307 input: 888999.,
2308 precision: FloatPrecision::SignificantDigits(2),
2309 expected: "890000",
2310 },
2311 TestCase {
2312 input: 888999.,
2313 precision: FloatPrecision::SignificantDigits(4),
2314 expected: "889000",
2315 },
2316 TestCase {
2317 input: 988999.,
2318 precision: FloatPrecision::SignificantDigits(1),
2319 expected: "1000000",
2320 },
2321 TestCase {
2322 input: 99888.,
2323 precision: FloatPrecision::SignificantDigits(1),
2324 expected: "100000",
2325 },
2326 TestCase {
2327 input: 99888.,
2328 precision: FloatPrecision::SignificantDigits(2),
2329 expected: "100000",
2330 },
2331 TestCase {
2332 input: 99888.,
2333 precision: FloatPrecision::SignificantDigits(3),
2334 expected: "99900",
2335 },
2336 TestCase {
2337 input: 0.0099,
2338 precision: FloatPrecision::SignificantDigits(1),
2339 expected: "0.01",
2340 },
2341 TestCase {
2342 input: 9.9888,
2343 precision: FloatPrecision::SignificantDigits(1),
2344 expected: "10",
2345 },
2346 TestCase {
2347 input: 9.9888,
2348 precision: FloatPrecision::SignificantDigits(2),
2349 expected: "10",
2350 },
2351 TestCase {
2352 input: 99888.0,
2353 precision: FloatPrecision::SignificantDigits(1),
2354 expected: "100000",
2355 },
2356 TestCase {
2357 input: 99888.0,
2358 precision: FloatPrecision::SignificantDigits(2),
2359 expected: "100000",
2360 },
2361 TestCase {
2362 input: 9.9888,
2363 precision: FloatPrecision::SignificantDigits(3),
2364 expected: "9.99",
2365 },
2366 ];
2367
2368 for case in &cases {
2369 let dec = UnsignedDecimal::try_from_f64(case.input, case.precision).unwrap();
2370 writeable::assert_writeable_eq!(dec, case.expected, "{:?}", case);
2371 }
2372}
2373
2374#[test]
2375fn test_basic() {
2376 #[derive(Debug)]
2377 struct TestCase {
2378 pub input: usize,
2379 pub delta: i16,
2380 pub expected: &'static str,
2381 }
2382 let cases = [
2383 TestCase {
2384 input: 51423,
2385 delta: 0,
2386 expected: "51423",
2387 },
2388 TestCase {
2389 input: 51423,
2390 delta: -2,
2391 expected: "514.23",
2392 },
2393 TestCase {
2394 input: 51423,
2395 delta: -5,
2396 expected: "0.51423",
2397 },
2398 TestCase {
2399 input: 51423,
2400 delta: -8,
2401 expected: "0.00051423",
2402 },
2403 TestCase {
2404 input: 51423,
2405 delta: 3,
2406 expected: "51423000",
2407 },
2408 TestCase {
2409 input: 0,
2410 delta: 0,
2411 expected: "0",
2412 },
2413 TestCase {
2414 input: 0,
2415 delta: -2,
2416 expected: "0.00",
2417 },
2418 TestCase {
2419 input: 0,
2420 delta: 3,
2421 expected: "0000",
2422 },
2423 TestCase {
2424 input: 500,
2425 delta: 0,
2426 expected: "500",
2427 },
2428 TestCase {
2429 input: 500,
2430 delta: -1,
2431 expected: "50.0",
2432 },
2433 TestCase {
2434 input: 500,
2435 delta: -2,
2436 expected: "5.00",
2437 },
2438 TestCase {
2439 input: 500,
2440 delta: -3,
2441 expected: "0.500",
2442 },
2443 TestCase {
2444 input: 500,
2445 delta: -4,
2446 expected: "0.0500",
2447 },
2448 TestCase {
2449 input: 500,
2450 delta: 3,
2451 expected: "500000",
2452 },
2453 ];
2454 for cas in &cases {
2455 let mut dec: UnsignedDecimal = cas.input.into();
2456 dec.multiply_pow10(cas.delta);
2458 writeable::assert_writeable_eq!(dec, cas.expected, "{:?}", cas);
2459 }
2460}
2461
2462#[test]
2463fn test_from_str() {
2464 #[derive(Debug)]
2465 struct TestCase {
2466 pub input_str: &'static str,
2467 pub output_str: Option<&'static str>,
2469 pub magnitudes: [i16; 4],
2471 }
2472 let cases = [
2473 TestCase {
2474 input_str: "00123400",
2475 output_str: None,
2476 magnitudes: [7, 5, 2, 0],
2477 },
2478 TestCase {
2479 input_str: "0.0123400",
2480 output_str: None,
2481 magnitudes: [0, -2, -5, -7],
2482 },
2483 TestCase {
2484 input_str: "0012.3400",
2485 output_str: None,
2486 magnitudes: [3, 1, -2, -4],
2487 },
2488 TestCase {
2489 input_str: "1234",
2490 output_str: None,
2491 magnitudes: [3, 3, 0, 0],
2492 },
2493 TestCase {
2494 input_str: "1000000",
2495 output_str: None,
2496 magnitudes: [6, 6, 6, 0],
2497 },
2498 TestCase {
2499 input_str: "10000001",
2500 output_str: None,
2501 magnitudes: [7, 7, 0, 0],
2502 },
2503 TestCase {
2504 input_str: "123",
2505 output_str: None,
2506 magnitudes: [2, 2, 0, 0],
2507 },
2508 TestCase {
2509 input_str: "922337203685477580898230948203840239384.9823094820384023938423424",
2510 output_str: None,
2511 magnitudes: [38, 38, -25, -25],
2512 },
2513 TestCase {
2514 input_str: "009223372000.003685477580898230948203840239384000",
2515 output_str: None,
2516 magnitudes: [11, 9, -33, -36],
2517 },
2518 TestCase {
2519 input_str: "0",
2520 output_str: None,
2521 magnitudes: [0, 0, 0, 0],
2522 },
2523 TestCase {
2524 input_str: "000",
2525 output_str: None,
2526 magnitudes: [2, 0, 0, 0],
2527 },
2528 TestCase {
2530 input_str: ".0123400",
2531 output_str: Some("0.0123400"),
2532 magnitudes: [0, -2, -5, -7],
2533 },
2534 TestCase {
2535 input_str: ".000000001",
2536 output_str: Some("0.000000001"),
2537 magnitudes: [0, -9, -9, -9],
2538 },
2539 ];
2540 for cas in &cases {
2541 println!("cas: {:?}", cas);
2542 let fd = UnsignedDecimal::from_str(cas.input_str).unwrap();
2543 assert_eq!(
2544 fd.magnitude_range(),
2545 cas.magnitudes[3]..=cas.magnitudes[0],
2546 "{cas:?}"
2547 );
2548 assert_eq!(fd.nonzero_magnitude_start(), cas.magnitudes[1], "{cas:?}");
2549 assert_eq!(fd.nonzero_magnitude_end(), cas.magnitudes[2], "{cas:?}");
2550 let input_str_roundtrip = fd.to_string();
2551 let output_str = cas.output_str.unwrap_or(cas.input_str);
2552
2553 let output_str = match output_str.strip_prefix('+') {
2556 Some(stripped) => stripped,
2557 None => output_str,
2558 };
2559 assert_eq!(output_str, input_str_roundtrip, "{cas:?}");
2560 }
2561}
2562
2563#[test]
2564fn test_from_str_scientific() {
2565 #[derive(Debug)]
2566 struct TestCase {
2567 pub input_str: &'static str,
2568 pub output: &'static str,
2569 }
2570 let cases = [
2571 TestCase {
2572 input_str: "5.4e-2",
2573 output: "0.054",
2574 },
2575 TestCase {
2576 input_str: "54.1e-2",
2577 output: "0.541",
2578 },
2579 TestCase {
2580 input_str: "0.009E10",
2581 output: "90000000",
2582 },
2583 ];
2584 for cas in &cases {
2585 let input_str_roundtrip = UnsignedDecimal::from_str(cas.input_str)
2586 .unwrap()
2587 .to_string();
2588 assert_eq!(cas.output, input_str_roundtrip);
2589 }
2590}
2591
2592#[test]
2593fn test_usize_limits() {
2594 for num in &[usize::MAX, usize::MIN] {
2595 let dec: UnsignedDecimal = (*num).into();
2596 let dec_str = dec.to_string();
2597 assert_eq!(num.to_string(), dec_str);
2598 assert_eq!(dec, UnsignedDecimal::from_str(&dec_str).unwrap());
2599 writeable::assert_writeable_eq!(dec, dec_str);
2600 }
2601}
2602
2603#[test]
2604fn test_u128_limits() {
2605 for num in &[u128::MAX, u128::MIN] {
2606 let dec: UnsignedDecimal = (*num).into();
2607 let dec_str = dec.to_string();
2608 assert_eq!(num.to_string(), dec_str);
2609 assert_eq!(dec, UnsignedDecimal::from_str(&dec_str).unwrap());
2610 writeable::assert_writeable_eq!(dec, dec_str);
2611 }
2612}
2613
2614#[test]
2615fn test_upper_magnitude_bounds() {
2616 let mut dec: UnsignedDecimal = 98765u32.into();
2617 assert_eq!(dec.upper_magnitude, 4);
2618 dec.multiply_pow10(i16::MAX - 4);
2619 assert_eq!(dec.upper_magnitude, i16::MAX);
2620 assert_eq!(dec.nonzero_magnitude_start(), i16::MAX);
2621 let dec_backup = dec.clone();
2622 dec.multiply_pow10(1);
2623 assert!(dec.is_zero());
2624 assert_ne!(dec, dec_backup, "Value should be unchanged on failure");
2625
2626 let dec_roundtrip = UnsignedDecimal::from_str(&dec.to_string()).unwrap();
2628 assert_eq!(dec, dec_roundtrip);
2629}
2630
2631#[test]
2632fn test_lower_magnitude_bounds() {
2633 let mut dec: UnsignedDecimal = 98765u32.into();
2634 assert_eq!(dec.lower_magnitude, 0);
2635 dec.multiply_pow10(i16::MIN);
2636 assert_eq!(dec.lower_magnitude, i16::MIN);
2637 assert_eq!(dec.nonzero_magnitude_end(), i16::MIN);
2638 let dec_backup = dec.clone();
2639 dec.multiply_pow10(-1);
2640 assert!(dec.is_zero());
2641 assert_ne!(dec, dec_backup);
2642
2643 let dec_roundtrip = UnsignedDecimal::from_str(&dec.to_string()).unwrap();
2645 assert_eq!(dec, dec_roundtrip);
2646}
2647
2648#[test]
2649fn test_zero_str_bounds() {
2650 #[derive(Debug)]
2651 struct TestCase {
2652 pub zeros_before_dot: usize,
2653 pub zeros_after_dot: usize,
2654 pub expected_err: Option<ParseError>,
2655 }
2656 let cases = [
2657 TestCase {
2658 zeros_before_dot: i16::MAX as usize + 1,
2659 zeros_after_dot: 0,
2660 expected_err: None,
2661 },
2662 TestCase {
2663 zeros_before_dot: i16::MAX as usize,
2664 zeros_after_dot: 0,
2665 expected_err: None,
2666 },
2667 TestCase {
2668 zeros_before_dot: i16::MAX as usize + 2,
2669 zeros_after_dot: 0,
2670 expected_err: Some(ParseError::Limit),
2671 },
2672 TestCase {
2673 zeros_before_dot: 0,
2674 zeros_after_dot: i16::MAX as usize + 2,
2675 expected_err: Some(ParseError::Limit),
2676 },
2677 TestCase {
2678 zeros_before_dot: i16::MAX as usize + 1,
2679 zeros_after_dot: i16::MAX as usize + 1,
2680 expected_err: None,
2681 },
2682 TestCase {
2683 zeros_before_dot: i16::MAX as usize + 2,
2684 zeros_after_dot: i16::MAX as usize + 1,
2685 expected_err: Some(ParseError::Limit),
2686 },
2687 TestCase {
2688 zeros_before_dot: i16::MAX as usize + 1,
2689 zeros_after_dot: i16::MAX as usize + 2,
2690 expected_err: Some(ParseError::Limit),
2691 },
2692 TestCase {
2693 zeros_before_dot: i16::MAX as usize,
2694 zeros_after_dot: i16::MAX as usize + 2,
2695 expected_err: Some(ParseError::Limit),
2696 },
2697 TestCase {
2698 zeros_before_dot: i16::MAX as usize,
2699 zeros_after_dot: i16::MAX as usize,
2700 expected_err: None,
2701 },
2702 TestCase {
2703 zeros_before_dot: i16::MAX as usize + 1,
2704 zeros_after_dot: i16::MAX as usize,
2705 expected_err: None,
2706 },
2707 ];
2708 for cas in &cases {
2709 let mut input_str = format!("{:0fill$}", 0, fill = cas.zeros_before_dot);
2710 if cas.zeros_after_dot > 0 {
2711 input_str.push('.');
2712 input_str.push_str(&format!("{:0fill$}", 0, fill = cas.zeros_after_dot));
2713 }
2714 match UnsignedDecimal::from_str(&input_str) {
2715 Ok(dec) => {
2716 assert_eq!(cas.expected_err, None, "{cas:?}");
2717 assert_eq!(input_str, dec.to_string(), "{cas:?}");
2718 }
2719 Err(err) => {
2720 assert_eq!(cas.expected_err, Some(err), "{cas:?}");
2721 }
2722 }
2723 }
2724}
2725
2726#[test]
2727fn test_syntax_error() {
2728 #[derive(Debug)]
2729 struct TestCase {
2730 pub input_str: &'static str,
2731 pub expected_err: Option<ParseError>,
2732 }
2733 let cases = [
2734 TestCase {
2735 input_str: "+1234567890",
2736 expected_err: Some(ParseError::Syntax),
2737 },
2738 TestCase {
2739 input_str: "-1234567890",
2740 expected_err: Some(ParseError::Syntax),
2741 },
2742 TestCase {
2743 input_str: "-12a34",
2744 expected_err: Some(ParseError::Syntax),
2745 },
2746 TestCase {
2747 input_str: "0.0123√400",
2748 expected_err: Some(ParseError::Syntax),
2749 },
2750 TestCase {
2751 input_str: "0.012.3400",
2752 expected_err: Some(ParseError::Syntax),
2753 },
2754 TestCase {
2755 input_str: "-0-0123400",
2756 expected_err: Some(ParseError::Syntax),
2757 },
2758 TestCase {
2759 input_str: "0-0123400",
2760 expected_err: Some(ParseError::Syntax),
2761 },
2762 TestCase {
2763 input_str: "-0.00123400",
2764 expected_err: Some(ParseError::Syntax),
2765 },
2766 TestCase {
2767 input_str: "00123400.",
2768 expected_err: Some(ParseError::Syntax),
2769 },
2770 TestCase {
2771 input_str: "00123400.0",
2772 expected_err: None,
2773 },
2774 TestCase {
2775 input_str: "123_456",
2776 expected_err: Some(ParseError::Syntax),
2777 },
2778 TestCase {
2779 input_str: "",
2780 expected_err: Some(ParseError::Syntax),
2781 },
2782 TestCase {
2783 input_str: "-",
2784 expected_err: Some(ParseError::Syntax),
2785 },
2786 TestCase {
2787 input_str: "+",
2788 expected_err: Some(ParseError::Syntax),
2789 },
2790 TestCase {
2791 input_str: "-1",
2792 expected_err: Some(ParseError::Syntax),
2793 },
2794 ];
2795 for cas in &cases {
2796 match UnsignedDecimal::from_str(cas.input_str) {
2797 Ok(dec) => {
2798 assert_eq!(cas.expected_err, None, "{cas:?}");
2799 assert_eq!(cas.input_str, dec.to_string(), "{cas:?}");
2800 }
2801 Err(err) => {
2802 assert_eq!(cas.expected_err, Some(err), "{cas:?}");
2803 }
2804 }
2805 }
2806}
2807
2808#[test]
2809fn test_pad() {
2810 let mut dec = UnsignedDecimal::from_str("0.42").unwrap();
2811 assert_eq!("0.42", dec.to_string());
2812
2813 dec.pad_start(1);
2814 assert_eq!("0.42", dec.to_string());
2815
2816 dec.pad_start(4);
2817 assert_eq!("0000.42", dec.to_string());
2818
2819 dec.pad_start(2);
2820 assert_eq!("00.42", dec.to_string());
2821}
2822
2823#[test]
2824fn test_set_max_position() {
2825 let mut dec = UnsignedDecimal::from(1000u32);
2826 assert_eq!("1000", dec.to_string());
2827
2828 dec.set_max_position(2);
2829 assert_eq!("00", dec.to_string());
2830
2831 dec.set_max_position(0);
2832 assert_eq!("0", dec.to_string());
2833
2834 dec.set_max_position(3);
2835 assert_eq!("000", dec.to_string());
2836
2837 let mut dec = UnsignedDecimal::from_str("0.456").unwrap();
2838 assert_eq!("0.456", dec.to_string());
2839
2840 dec.set_max_position(0);
2841 assert_eq!("0.456", dec.to_string());
2842
2843 dec.set_max_position(-1);
2844 assert_eq!("0.056", dec.to_string());
2845
2846 dec.set_max_position(-2);
2847 assert_eq!("0.006", dec.to_string());
2848
2849 dec.set_max_position(-3);
2850 assert_eq!("0.000", dec.to_string());
2851
2852 dec.set_max_position(-4);
2853 assert_eq!("0.0000", dec.to_string());
2854
2855 let mut dec = UnsignedDecimal::from_str("100.01").unwrap();
2856 dec.set_max_position(1);
2857 assert_eq!("0.01", dec.to_string());
2858}
2859
2860#[test]
2861fn test_pad_start_bounds() {
2862 let mut dec = UnsignedDecimal::from_str("299792.458").unwrap();
2863 let max_integer_digits = i16::MAX as usize + 1;
2864
2865 dec.pad_start(i16::MAX - 1);
2866 assert_eq!(
2867 max_integer_digits - 2,
2868 dec.to_string().split_once('.').unwrap().0.len()
2869 );
2870
2871 dec.pad_start(i16::MAX);
2872 assert_eq!(
2873 max_integer_digits - 1,
2874 dec.to_string().split_once('.').unwrap().0.len()
2875 );
2876}
2877
2878#[test]
2879fn test_pad_end_bounds() {
2880 let mut dec = UnsignedDecimal::from_str("299792.458").unwrap();
2881 let max_fractional_digits = -(i16::MIN as isize) as usize;
2882
2883 dec.pad_end(i16::MIN + 1);
2884 assert_eq!(
2885 max_fractional_digits - 1,
2886 dec.to_string().split_once('.').unwrap().1.len()
2887 );
2888
2889 dec.pad_end(i16::MIN);
2890 assert_eq!(
2891 max_fractional_digits,
2892 dec.to_string().split_once('.').unwrap().1.len()
2893 );
2894}
2895
2896#[test]
2897fn test_rounding() {
2898 pub(crate) use std::str::FromStr;
2899
2900 let mut dec = UnsignedDecimal::from(4235970u32).multiplied_pow10(-3);
2902 assert_eq!("4235.970", dec.to_string());
2903
2904 dec.trunc(-5);
2905 assert_eq!("4235.97000", dec.to_string());
2906
2907 dec.trunc(-1);
2908 assert_eq!("4235.9", dec.to_string());
2909
2910 dec.trunc(0);
2911 assert_eq!("4235", dec.to_string());
2912
2913 dec.trunc(1);
2914 assert_eq!("4230", dec.to_string());
2915
2916 dec.trunc(5);
2917 assert_eq!("00000", dec.to_string());
2918
2919 dec.trunc(2);
2920 assert_eq!("00000", dec.to_string());
2921
2922 let mut dec = UnsignedDecimal::from_str("1234.56").unwrap();
2923 dec.trunc(-1);
2924 assert_eq!("1234.5", dec.to_string());
2925
2926 let mut dec = UnsignedDecimal::from_str("0.009").unwrap();
2927 dec.trunc(-1);
2928 assert_eq!("0.0", dec.to_string());
2929
2930 let dec = UnsignedDecimal::from(4235970u32).multiplied_pow10(-3);
2932 assert_eq!("4235.970", dec.to_string());
2933
2934 assert_eq!("4235.97000", dec.clone().trunced(-5).to_string());
2935
2936 assert_eq!("4230", dec.clone().trunced(1).to_string());
2937
2938 assert_eq!("4200", dec.clone().trunced(2).to_string());
2939
2940 assert_eq!("00000", dec.trunced(5).to_string());
2941
2942 let mut dec = UnsignedDecimal::from_str("3.234").unwrap();
2944 dec.expand(0);
2945 assert_eq!("4", dec.to_string());
2946
2947 let mut dec = UnsignedDecimal::from_str("2.222").unwrap();
2948 dec.expand(-1);
2949 assert_eq!("2.3", dec.to_string());
2950
2951 let mut dec = UnsignedDecimal::from_str("22.222").unwrap();
2952 dec.expand(-2);
2953 assert_eq!("22.23", dec.to_string());
2954
2955 let mut dec = UnsignedDecimal::from_str("99.999").unwrap();
2956 dec.expand(-2);
2957 assert_eq!("100.00", dec.to_string());
2958
2959 let mut dec = UnsignedDecimal::from_str("99.999").unwrap();
2960 dec.expand(-5);
2961 assert_eq!("99.99900", dec.to_string());
2962
2963 let mut dec = UnsignedDecimal::from_str("99.999").unwrap();
2964 dec.expand(4);
2965 assert_eq!("10000", dec.to_string());
2966
2967 let mut dec = UnsignedDecimal::from_str("0.009").unwrap();
2968 dec.expand(-1);
2969 assert_eq!("0.1", dec.to_string());
2970
2971 let mut dec = UnsignedDecimal::from_str("3.954").unwrap();
2972 dec.expand(0);
2973 assert_eq!("4", dec.to_string());
2974
2975 let mut dec = UnsignedDecimal::from_str("3.234").unwrap();
2977 dec.round_with_mode(0, UnsignedRoundingMode::HalfExpand);
2978 assert_eq!("3", dec.to_string());
2979
2980 let mut dec = UnsignedDecimal::from_str("3.534").unwrap();
2981 dec.round_with_mode(0, UnsignedRoundingMode::HalfExpand);
2982 assert_eq!("4", dec.to_string());
2983
2984 let mut dec = UnsignedDecimal::from_str("3.934").unwrap();
2985 dec.round_with_mode(0, UnsignedRoundingMode::HalfExpand);
2986 assert_eq!("4", dec.to_string());
2987
2988 let mut dec = UnsignedDecimal::from_str("2.222").unwrap();
2989 dec.round_with_mode(-1, UnsignedRoundingMode::HalfExpand);
2990 assert_eq!("2.2", dec.to_string());
2991
2992 let mut dec = UnsignedDecimal::from_str("2.44").unwrap();
2993 dec.round_with_mode(-1, UnsignedRoundingMode::HalfExpand);
2994 assert_eq!("2.4", dec.to_string());
2995
2996 let mut dec = UnsignedDecimal::from_str("2.45").unwrap();
2997 dec.round_with_mode(-1, UnsignedRoundingMode::HalfExpand);
2998 assert_eq!("2.5", dec.to_string());
2999
3000 let mut dec = UnsignedDecimal::from_str("22.222").unwrap();
3001 dec.round_with_mode(-2, UnsignedRoundingMode::HalfExpand);
3002 assert_eq!("22.22", dec.to_string());
3003
3004 let mut dec = UnsignedDecimal::from_str("99.999").unwrap();
3005 dec.round_with_mode(-2, UnsignedRoundingMode::HalfExpand);
3006 assert_eq!("100.00", dec.to_string());
3007
3008 let mut dec = UnsignedDecimal::from_str("99.999").unwrap();
3009 dec.round_with_mode(-5, UnsignedRoundingMode::HalfExpand);
3010 assert_eq!("99.99900", dec.to_string());
3011
3012 let mut dec = UnsignedDecimal::from_str("99.999").unwrap();
3013 dec.round_with_mode(4, UnsignedRoundingMode::HalfExpand);
3014 assert_eq!("0000", dec.to_string());
3015
3016 let mut dec = UnsignedDecimal::from_str("0.009").unwrap();
3017 dec.round_with_mode(-1, UnsignedRoundingMode::HalfExpand);
3018 assert_eq!("0.0", dec.to_string());
3019
3020 let mut dec = UnsignedDecimal::from_str("1.108").unwrap();
3022 dec.round_with_mode(-2, UnsignedRoundingMode::HalfEven);
3023 assert_eq!("1.11", dec.to_string());
3024
3025 let mut dec = UnsignedDecimal::from_str("1.108").unwrap();
3026 dec.expand(-2);
3027 assert_eq!("1.11", dec.to_string());
3028
3029 let mut dec = UnsignedDecimal::from_str("1.108").unwrap();
3030 dec.trunc(-2);
3031 assert_eq!("1.10", dec.to_string());
3032
3033 let mut dec = UnsignedDecimal::from_str("2.78536913177").unwrap();
3034 dec.round_with_mode(-2, UnsignedRoundingMode::HalfEven);
3035 assert_eq!("2.79", dec.to_string());
3036}
3037
3038#[test]
3039fn test_concatenate() {
3040 #[derive(Debug)]
3041 struct TestCase {
3042 pub input_1: &'static str,
3043 pub input_2: &'static str,
3044 pub expected: Option<&'static str>,
3045 }
3046 let cases = [
3047 TestCase {
3048 input_1: "123",
3049 input_2: "0.456",
3050 expected: Some("123.456"),
3051 },
3052 TestCase {
3053 input_1: "0.456",
3054 input_2: "123",
3055 expected: None,
3056 },
3057 TestCase {
3058 input_1: "123",
3059 input_2: "0.0456",
3060 expected: Some("123.0456"),
3061 },
3062 TestCase {
3063 input_1: "0.0456",
3064 input_2: "123",
3065 expected: None,
3066 },
3067 TestCase {
3068 input_1: "100",
3069 input_2: "0.456",
3070 expected: Some("100.456"),
3071 },
3072 TestCase {
3073 input_1: "0.456",
3074 input_2: "100",
3075 expected: None,
3076 },
3077 TestCase {
3078 input_1: "100",
3079 input_2: "0.001",
3080 expected: Some("100.001"),
3081 },
3082 TestCase {
3083 input_1: "0.001",
3084 input_2: "100",
3085 expected: None,
3086 },
3087 TestCase {
3088 input_1: "123000",
3089 input_2: "456",
3090 expected: Some("123456"),
3091 },
3092 TestCase {
3093 input_1: "456",
3094 input_2: "123000",
3095 expected: None,
3096 },
3097 TestCase {
3098 input_1: "5",
3099 input_2: "5",
3100 expected: None,
3101 },
3102 TestCase {
3103 input_1: "120",
3104 input_2: "25",
3105 expected: None,
3106 },
3107 TestCase {
3108 input_1: "1.1",
3109 input_2: "0.2",
3110 expected: None,
3111 },
3112 TestCase {
3113 input_1: "0",
3114 input_2: "222",
3115 expected: Some("222"),
3116 },
3117 TestCase {
3118 input_1: "222",
3119 input_2: "0",
3120 expected: Some("222"),
3121 },
3122 TestCase {
3123 input_1: "0",
3124 input_2: "0",
3125 expected: Some("0"),
3126 },
3127 TestCase {
3128 input_1: "000",
3129 input_2: "0",
3130 expected: Some("000"),
3131 },
3132 TestCase {
3133 input_1: "0.00",
3134 input_2: "0",
3135 expected: Some("0.00"),
3136 },
3137 ];
3138 for cas in &cases {
3139 let fd1 = UnsignedDecimal::from_str(cas.input_1).unwrap();
3140 let fd2 = UnsignedDecimal::from_str(cas.input_2).unwrap();
3141 match fd1.concatenated_end(fd2) {
3142 Ok(fd) => {
3143 assert_eq!(cas.expected, Some(fd.to_string().as_str()), "{cas:?}");
3144 }
3145 Err(_) => {
3146 assert!(cas.expected.is_none(), "{cas:?}");
3147 }
3148 }
3149 }
3150}
3151
3152#[test]
3153fn test_rounding_increment() {
3154 let mut dec = UnsignedDecimal::from(4235970u32).multiplied_pow10(-3);
3156 assert_eq!("4235.970", dec.to_string());
3157
3158 dec.round_with_mode_and_increment(
3159 -2,
3160 UnsignedRoundingMode::Trunc,
3161 RoundingIncrement::MultiplesOf2,
3162 );
3163 assert_eq!("4235.96", dec.to_string());
3164
3165 dec.round_with_mode_and_increment(
3166 -1,
3167 UnsignedRoundingMode::Trunc,
3168 RoundingIncrement::MultiplesOf5,
3169 );
3170 assert_eq!("4235.5", dec.to_string());
3171
3172 dec.round_with_mode_and_increment(
3173 0,
3174 UnsignedRoundingMode::Trunc,
3175 RoundingIncrement::MultiplesOf25,
3176 );
3177 assert_eq!("4225", dec.to_string());
3178
3179 dec.round_with_mode_and_increment(
3180 5,
3181 UnsignedRoundingMode::Trunc,
3182 RoundingIncrement::MultiplesOf5,
3183 );
3184 assert_eq!("00000", dec.to_string());
3185
3186 dec.round_with_mode_and_increment(
3187 2,
3188 UnsignedRoundingMode::Trunc,
3189 RoundingIncrement::MultiplesOf2,
3190 );
3191 assert_eq!("00000", dec.to_string());
3192
3193 let mut dec = UnsignedDecimal::from_str("1234.56").unwrap();
3194 dec.round_with_mode_and_increment(
3195 -1,
3196 UnsignedRoundingMode::Trunc,
3197 RoundingIncrement::MultiplesOf2,
3198 );
3199 assert_eq!("1234.4", dec.to_string());
3200
3201 let mut dec = UnsignedDecimal::from_str("0.009").unwrap();
3202 dec.round_with_mode_and_increment(
3203 -1,
3204 UnsignedRoundingMode::Trunc,
3205 RoundingIncrement::MultiplesOf5,
3206 );
3207 assert_eq!("0.0", dec.to_string());
3208
3209 let mut dec = UnsignedDecimal::from_str("0.60").unwrap();
3210 dec.round_with_mode_and_increment(
3211 -2,
3212 UnsignedRoundingMode::Trunc,
3213 RoundingIncrement::MultiplesOf25,
3214 );
3215 assert_eq!("0.50", dec.to_string());
3216
3217 let mut dec = UnsignedDecimal::from_str("0.40").unwrap();
3218 dec.round_with_mode_and_increment(
3219 -2,
3220 UnsignedRoundingMode::Trunc,
3221 RoundingIncrement::MultiplesOf25,
3222 );
3223 assert_eq!("0.25", dec.to_string());
3224
3225 let mut dec = UnsignedDecimal::from_str("0.7000000099").unwrap();
3226 dec.round_with_mode_and_increment(
3227 -3,
3228 UnsignedRoundingMode::Trunc,
3229 RoundingIncrement::MultiplesOf2,
3230 );
3231 assert_eq!("0.700", dec.to_string());
3232
3233 let mut dec = UnsignedDecimal::from_str("5").unwrap();
3234 dec.round_with_mode_and_increment(
3235 0,
3236 UnsignedRoundingMode::Trunc,
3237 RoundingIncrement::MultiplesOf25,
3238 );
3239 assert_eq!("0", dec.to_string());
3240
3241 let mut dec = UnsignedDecimal::from(7u32).multiplied_pow10(i16::MIN);
3242 dec.round_with_mode_and_increment(
3243 i16::MIN,
3244 UnsignedRoundingMode::Trunc,
3245 RoundingIncrement::MultiplesOf2,
3246 );
3247 assert_eq!(UnsignedDecimal::from(6u32).multiplied_pow10(i16::MIN), dec);
3248
3249 let mut dec = UnsignedDecimal::from(9u32).multiplied_pow10(i16::MIN);
3250 dec.round_with_mode_and_increment(
3251 i16::MIN,
3252 UnsignedRoundingMode::Trunc,
3253 RoundingIncrement::MultiplesOf5,
3254 );
3255 assert_eq!(UnsignedDecimal::from(5u32).multiplied_pow10(i16::MIN), dec);
3256
3257 let mut dec = UnsignedDecimal::from(70u32).multiplied_pow10(i16::MIN);
3258 dec.round_with_mode_and_increment(
3259 i16::MIN,
3260 UnsignedRoundingMode::Trunc,
3261 RoundingIncrement::MultiplesOf25,
3262 );
3263 assert_eq!(UnsignedDecimal::from(50u32).multiplied_pow10(i16::MIN), dec);
3264
3265 let mut dec = UnsignedDecimal::from(7u32).multiplied_pow10(i16::MAX);
3266 dec.round_with_mode_and_increment(
3267 i16::MAX,
3268 UnsignedRoundingMode::Trunc,
3269 RoundingIncrement::MultiplesOf2,
3270 );
3271 assert_eq!(UnsignedDecimal::from(6u32).multiplied_pow10(i16::MAX), dec);
3272
3273 let mut dec = UnsignedDecimal::from(7u32).multiplied_pow10(i16::MAX);
3274 dec.round_with_mode_and_increment(
3275 i16::MAX,
3276 UnsignedRoundingMode::Trunc,
3277 RoundingIncrement::MultiplesOf5,
3278 );
3279 assert_eq!(UnsignedDecimal::from(5u32).multiplied_pow10(i16::MAX), dec);
3280
3281 let mut dec = UnsignedDecimal::from(7u32).multiplied_pow10(i16::MAX);
3282 dec.round_with_mode_and_increment(
3283 i16::MAX,
3284 UnsignedRoundingMode::Trunc,
3285 RoundingIncrement::MultiplesOf25,
3286 );
3287 assert_eq!(UnsignedDecimal::from(0u32).multiplied_pow10(i16::MAX), dec);
3288
3289 let mut dec = UnsignedDecimal::from(4235970u32).multiplied_pow10(-3);
3291 assert_eq!("4235.970", dec.to_string());
3292
3293 dec.round_with_mode_and_increment(
3294 -2,
3295 UnsignedRoundingMode::Expand,
3296 RoundingIncrement::MultiplesOf2,
3297 );
3298 assert_eq!("4235.98", dec.to_string());
3299
3300 dec.round_with_mode_and_increment(
3301 -1,
3302 UnsignedRoundingMode::Expand,
3303 RoundingIncrement::MultiplesOf5,
3304 );
3305 assert_eq!("4236.0", dec.to_string());
3306
3307 dec.round_with_mode_and_increment(
3308 0,
3309 UnsignedRoundingMode::Expand,
3310 RoundingIncrement::MultiplesOf25,
3311 );
3312 assert_eq!("4250", dec.to_string());
3313
3314 dec.round_with_mode_and_increment(
3315 5,
3316 UnsignedRoundingMode::Expand,
3317 RoundingIncrement::MultiplesOf5,
3318 );
3319 assert_eq!("500000", dec.to_string());
3320
3321 dec.round_with_mode_and_increment(
3322 2,
3323 UnsignedRoundingMode::Expand,
3324 RoundingIncrement::MultiplesOf2,
3325 );
3326 assert_eq!("500000", dec.to_string());
3327
3328 let mut dec = UnsignedDecimal::from_str("1234.56").unwrap();
3329 dec.round_with_mode_and_increment(
3330 -1,
3331 UnsignedRoundingMode::Expand,
3332 RoundingIncrement::MultiplesOf2,
3333 );
3334 assert_eq!("1234.6", dec.to_string());
3335
3336 let mut dec = UnsignedDecimal::from_str("0.009").unwrap();
3337 dec.round_with_mode_and_increment(
3338 -1,
3339 UnsignedRoundingMode::Expand,
3340 RoundingIncrement::MultiplesOf5,
3341 );
3342 assert_eq!("0.5", dec.to_string());
3343
3344 let mut dec = UnsignedDecimal::from_str("0.60").unwrap();
3345 dec.round_with_mode_and_increment(
3346 -2,
3347 UnsignedRoundingMode::Expand,
3348 RoundingIncrement::MultiplesOf25,
3349 );
3350 assert_eq!("0.75", dec.to_string());
3351
3352 let mut dec = UnsignedDecimal::from_str("0.40").unwrap();
3353 dec.round_with_mode_and_increment(
3354 -2,
3355 UnsignedRoundingMode::Expand,
3356 RoundingIncrement::MultiplesOf25,
3357 );
3358 assert_eq!("0.50", dec.to_string());
3359
3360 let mut dec = UnsignedDecimal::from_str("0.7000000099").unwrap();
3361 dec.round_with_mode_and_increment(
3362 -3,
3363 UnsignedRoundingMode::Expand,
3364 RoundingIncrement::MultiplesOf2,
3365 );
3366 assert_eq!("0.702", dec.to_string());
3367
3368 let mut dec = UnsignedDecimal::from_str("5").unwrap();
3369 dec.round_with_mode_and_increment(
3370 0,
3371 UnsignedRoundingMode::Expand,
3372 RoundingIncrement::MultiplesOf25,
3373 );
3374 assert_eq!("25", dec.to_string());
3375
3376 let mut dec = UnsignedDecimal::from(7u32).multiplied_pow10(i16::MIN);
3377 dec.round_with_mode_and_increment(
3378 i16::MIN,
3379 UnsignedRoundingMode::Expand,
3380 RoundingIncrement::MultiplesOf2,
3381 );
3382 assert_eq!(UnsignedDecimal::from(8u32).multiplied_pow10(i16::MIN), dec);
3383
3384 let mut dec = UnsignedDecimal::from(9u32).multiplied_pow10(i16::MIN);
3385 dec.round_with_mode_and_increment(
3386 i16::MIN,
3387 UnsignedRoundingMode::Expand,
3388 RoundingIncrement::MultiplesOf5,
3389 );
3390 assert_eq!(UnsignedDecimal::from(10u32).multiplied_pow10(i16::MIN), dec);
3391
3392 let mut dec = UnsignedDecimal::from(70u32).multiplied_pow10(i16::MIN);
3393 dec.round_with_mode_and_increment(
3394 i16::MIN,
3395 UnsignedRoundingMode::Expand,
3396 RoundingIncrement::MultiplesOf25,
3397 );
3398 assert_eq!(UnsignedDecimal::from(75u32).multiplied_pow10(i16::MIN), dec);
3399
3400 let mut dec = UnsignedDecimal::from(7u32).multiplied_pow10(i16::MAX);
3401 dec.round_with_mode_and_increment(
3402 i16::MAX,
3403 UnsignedRoundingMode::Expand,
3404 RoundingIncrement::MultiplesOf2,
3405 );
3406 assert_eq!(UnsignedDecimal::from(8u32).multiplied_pow10(i16::MAX), dec);
3407
3408 let mut dec = UnsignedDecimal::from(7u32).multiplied_pow10(i16::MAX);
3409 dec.round_with_mode_and_increment(
3410 i16::MAX,
3411 UnsignedRoundingMode::Expand,
3412 RoundingIncrement::MultiplesOf5,
3413 );
3414 assert_eq!(UnsignedDecimal::from(0u32).multiplied_pow10(i16::MAX), dec);
3415
3416 let mut dec = UnsignedDecimal::from(7u32).multiplied_pow10(i16::MAX);
3417 dec.round_with_mode_and_increment(
3418 i16::MAX,
3419 UnsignedRoundingMode::Expand,
3420 RoundingIncrement::MultiplesOf25,
3421 );
3422 assert_eq!(UnsignedDecimal::from(0u32).multiplied_pow10(i16::MAX), dec);
3423
3424 let mut dec = UnsignedDecimal::from(4235970u32).multiplied_pow10(-3);
3426 assert_eq!("4235.970", dec.to_string());
3427
3428 dec.round_with_mode_and_increment(
3429 -2,
3430 UnsignedRoundingMode::HalfTrunc,
3431 RoundingIncrement::MultiplesOf2,
3432 );
3433 assert_eq!("4235.96", dec.to_string());
3434
3435 dec.round_with_mode_and_increment(
3436 -1,
3437 UnsignedRoundingMode::HalfTrunc,
3438 RoundingIncrement::MultiplesOf5,
3439 );
3440 assert_eq!("4236.0", dec.to_string());
3441
3442 dec.round_with_mode_and_increment(
3443 0,
3444 UnsignedRoundingMode::HalfTrunc,
3445 RoundingIncrement::MultiplesOf25,
3446 );
3447 assert_eq!("4225", dec.to_string());
3448
3449 dec.round_with_mode_and_increment(
3450 5,
3451 UnsignedRoundingMode::HalfTrunc,
3452 RoundingIncrement::MultiplesOf5,
3453 );
3454 assert_eq!("00000", dec.to_string());
3455
3456 dec.round_with_mode_and_increment(
3457 2,
3458 UnsignedRoundingMode::HalfTrunc,
3459 RoundingIncrement::MultiplesOf2,
3460 );
3461 assert_eq!("00000", dec.to_string());
3462
3463 let mut dec = UnsignedDecimal::from_str("1234.56").unwrap();
3464 dec.round_with_mode_and_increment(
3465 -1,
3466 UnsignedRoundingMode::HalfTrunc,
3467 RoundingIncrement::MultiplesOf2,
3468 );
3469 assert_eq!("1234.6", dec.to_string());
3470
3471 let mut dec = UnsignedDecimal::from_str("0.009").unwrap();
3472 dec.round_with_mode_and_increment(
3473 -1,
3474 UnsignedRoundingMode::HalfTrunc,
3475 RoundingIncrement::MultiplesOf5,
3476 );
3477 assert_eq!("0.0", dec.to_string());
3478
3479 let mut dec = UnsignedDecimal::from_str("0.60").unwrap();
3480 dec.round_with_mode_and_increment(
3481 -2,
3482 UnsignedRoundingMode::HalfTrunc,
3483 RoundingIncrement::MultiplesOf25,
3484 );
3485 assert_eq!("0.50", dec.to_string());
3486
3487 let mut dec = UnsignedDecimal::from_str("0.40").unwrap();
3488 dec.round_with_mode_and_increment(
3489 -2,
3490 UnsignedRoundingMode::HalfTrunc,
3491 RoundingIncrement::MultiplesOf25,
3492 );
3493 assert_eq!("0.50", dec.to_string());
3494
3495 let mut dec = UnsignedDecimal::from_str("0.7000000099").unwrap();
3496 dec.round_with_mode_and_increment(
3497 -3,
3498 UnsignedRoundingMode::HalfTrunc,
3499 RoundingIncrement::MultiplesOf2,
3500 );
3501 assert_eq!("0.700", dec.to_string());
3502
3503 let mut dec = UnsignedDecimal::from_str("5").unwrap();
3504 dec.round_with_mode_and_increment(
3505 0,
3506 UnsignedRoundingMode::HalfTrunc,
3507 RoundingIncrement::MultiplesOf25,
3508 );
3509 assert_eq!("0", dec.to_string());
3510
3511 let mut dec = UnsignedDecimal::from(7u32).multiplied_pow10(i16::MIN);
3512 dec.round_with_mode_and_increment(
3513 i16::MIN,
3514 UnsignedRoundingMode::HalfTrunc,
3515 RoundingIncrement::MultiplesOf2,
3516 );
3517 assert_eq!(UnsignedDecimal::from(6u32).multiplied_pow10(i16::MIN), dec);
3518
3519 let mut dec = UnsignedDecimal::from(9u32).multiplied_pow10(i16::MIN);
3520 dec.round_with_mode_and_increment(
3521 i16::MIN,
3522 UnsignedRoundingMode::HalfTrunc,
3523 RoundingIncrement::MultiplesOf5,
3524 );
3525 assert_eq!(UnsignedDecimal::from(10u32).multiplied_pow10(i16::MIN), dec);
3526
3527 let mut dec = UnsignedDecimal::from(70u32).multiplied_pow10(i16::MIN);
3528 dec.round_with_mode_and_increment(
3529 i16::MIN,
3530 UnsignedRoundingMode::HalfTrunc,
3531 RoundingIncrement::MultiplesOf25,
3532 );
3533 assert_eq!(UnsignedDecimal::from(75u32).multiplied_pow10(i16::MIN), dec);
3534
3535 let mut dec = UnsignedDecimal::from(7u32).multiplied_pow10(i16::MAX);
3536 dec.round_with_mode_and_increment(
3537 i16::MAX,
3538 UnsignedRoundingMode::HalfTrunc,
3539 RoundingIncrement::MultiplesOf2,
3540 );
3541 assert_eq!(UnsignedDecimal::from(6u32).multiplied_pow10(i16::MAX), dec);
3542
3543 let mut dec = UnsignedDecimal::from(7u32).multiplied_pow10(i16::MAX);
3544 dec.round_with_mode_and_increment(
3545 i16::MAX,
3546 UnsignedRoundingMode::HalfTrunc,
3547 RoundingIncrement::MultiplesOf5,
3548 );
3549 assert_eq!(UnsignedDecimal::from(5u32).multiplied_pow10(i16::MAX), dec);
3550
3551 let mut dec = UnsignedDecimal::from(7u32).multiplied_pow10(i16::MAX);
3552 dec.round_with_mode_and_increment(
3553 i16::MAX,
3554 UnsignedRoundingMode::HalfTrunc,
3555 RoundingIncrement::MultiplesOf25,
3556 );
3557 assert_eq!(UnsignedDecimal::from(0u32).multiplied_pow10(i16::MAX), dec);
3558
3559 let mut dec = UnsignedDecimal::from(4235970u32).multiplied_pow10(-3);
3561 assert_eq!("4235.970", dec.to_string());
3562
3563 dec.round_with_mode_and_increment(
3564 -2,
3565 UnsignedRoundingMode::HalfExpand,
3566 RoundingIncrement::MultiplesOf2,
3567 );
3568 assert_eq!("4235.98", dec.to_string());
3569
3570 dec.round_with_mode_and_increment(
3571 -1,
3572 UnsignedRoundingMode::HalfExpand,
3573 RoundingIncrement::MultiplesOf5,
3574 );
3575 assert_eq!("4236.0", dec.to_string());
3576
3577 dec.round_with_mode_and_increment(
3578 0,
3579 UnsignedRoundingMode::HalfExpand,
3580 RoundingIncrement::MultiplesOf25,
3581 );
3582 assert_eq!("4225", dec.to_string());
3583
3584 dec.round_with_mode_and_increment(
3585 5,
3586 UnsignedRoundingMode::HalfExpand,
3587 RoundingIncrement::MultiplesOf5,
3588 );
3589 assert_eq!("00000", dec.to_string());
3590
3591 dec.round_with_mode_and_increment(
3592 2,
3593 UnsignedRoundingMode::HalfExpand,
3594 RoundingIncrement::MultiplesOf2,
3595 );
3596 assert_eq!("00000", dec.to_string());
3597
3598 let mut dec = UnsignedDecimal::from_str("1234.56").unwrap();
3599 dec.round_with_mode_and_increment(
3600 -1,
3601 UnsignedRoundingMode::HalfExpand,
3602 RoundingIncrement::MultiplesOf2,
3603 );
3604 assert_eq!("1234.6", dec.to_string());
3605
3606 let mut dec = UnsignedDecimal::from_str("0.009").unwrap();
3607 dec.round_with_mode_and_increment(
3608 -1,
3609 UnsignedRoundingMode::HalfExpand,
3610 RoundingIncrement::MultiplesOf5,
3611 );
3612 assert_eq!("0.0", dec.to_string());
3613
3614 let mut dec = UnsignedDecimal::from_str("0.60").unwrap();
3615 dec.round_with_mode_and_increment(
3616 -2,
3617 UnsignedRoundingMode::HalfExpand,
3618 RoundingIncrement::MultiplesOf25,
3619 );
3620 assert_eq!("0.50", dec.to_string());
3621
3622 let mut dec = UnsignedDecimal::from_str("0.40").unwrap();
3623 dec.round_with_mode_and_increment(
3624 -2,
3625 UnsignedRoundingMode::HalfExpand,
3626 RoundingIncrement::MultiplesOf25,
3627 );
3628 assert_eq!("0.50", dec.to_string());
3629
3630 let mut dec = UnsignedDecimal::from_str("0.7000000099").unwrap();
3631 dec.round_with_mode_and_increment(
3632 -3,
3633 UnsignedRoundingMode::HalfExpand,
3634 RoundingIncrement::MultiplesOf2,
3635 );
3636 assert_eq!("0.700", dec.to_string());
3637
3638 let mut dec = UnsignedDecimal::from_str("5").unwrap();
3639 dec.round_with_mode_and_increment(
3640 0,
3641 UnsignedRoundingMode::HalfExpand,
3642 RoundingIncrement::MultiplesOf25,
3643 );
3644 assert_eq!("0", dec.to_string());
3645
3646 let mut dec = UnsignedDecimal::from(7u32).multiplied_pow10(i16::MIN);
3647 dec.round_with_mode_and_increment(
3648 i16::MIN,
3649 UnsignedRoundingMode::HalfExpand,
3650 RoundingIncrement::MultiplesOf2,
3651 );
3652 assert_eq!(UnsignedDecimal::from(8u32).multiplied_pow10(i16::MIN), dec);
3653
3654 let mut dec = UnsignedDecimal::from(9u32).multiplied_pow10(i16::MIN);
3655 dec.round_with_mode_and_increment(
3656 i16::MIN,
3657 UnsignedRoundingMode::HalfExpand,
3658 RoundingIncrement::MultiplesOf5,
3659 );
3660 assert_eq!(UnsignedDecimal::from(10u32).multiplied_pow10(i16::MIN), dec);
3661
3662 let mut dec = UnsignedDecimal::from(70u32).multiplied_pow10(i16::MIN);
3663 dec.round_with_mode_and_increment(
3664 i16::MIN,
3665 UnsignedRoundingMode::HalfExpand,
3666 RoundingIncrement::MultiplesOf25,
3667 );
3668 assert_eq!(UnsignedDecimal::from(75u32).multiplied_pow10(i16::MIN), dec);
3669
3670 let mut dec = UnsignedDecimal::from(7u32).multiplied_pow10(i16::MAX);
3671 dec.round_with_mode_and_increment(
3672 i16::MAX,
3673 UnsignedRoundingMode::HalfExpand,
3674 RoundingIncrement::MultiplesOf2,
3675 );
3676 assert_eq!(UnsignedDecimal::from(8u32).multiplied_pow10(i16::MAX), dec);
3677
3678 let mut dec = UnsignedDecimal::from(4235970u32).multiplied_pow10(-3);
3680 assert_eq!("4235.970", dec.to_string());
3681
3682 dec.round_with_mode_and_increment(
3683 -2,
3684 UnsignedRoundingMode::HalfEven,
3685 RoundingIncrement::MultiplesOf2,
3686 );
3687 assert_eq!("4235.96", dec.to_string());
3688
3689 dec.round_with_mode_and_increment(
3690 -1,
3691 UnsignedRoundingMode::HalfEven,
3692 RoundingIncrement::MultiplesOf5,
3693 );
3694 assert_eq!("4236.0", dec.to_string());
3695
3696 dec.round_with_mode_and_increment(
3697 0,
3698 UnsignedRoundingMode::HalfEven,
3699 RoundingIncrement::MultiplesOf25,
3700 );
3701 assert_eq!("4225", dec.to_string());
3702
3703 dec.round_with_mode_and_increment(
3704 5,
3705 UnsignedRoundingMode::HalfEven,
3706 RoundingIncrement::MultiplesOf5,
3707 );
3708 assert_eq!("00000", dec.to_string());
3709
3710 dec.round_with_mode_and_increment(
3711 2,
3712 UnsignedRoundingMode::HalfEven,
3713 RoundingIncrement::MultiplesOf2,
3714 );
3715 assert_eq!("00000", dec.to_string());
3716
3717 let mut dec = UnsignedDecimal::from_str("1234.56").unwrap();
3718 dec.round_with_mode_and_increment(
3719 -1,
3720 UnsignedRoundingMode::HalfEven,
3721 RoundingIncrement::MultiplesOf2,
3722 );
3723 assert_eq!("1234.6", dec.to_string());
3724
3725 let mut dec = UnsignedDecimal::from_str("0.009").unwrap();
3726 dec.round_with_mode_and_increment(
3727 -1,
3728 UnsignedRoundingMode::HalfEven,
3729 RoundingIncrement::MultiplesOf5,
3730 );
3731 assert_eq!("0.0", dec.to_string());
3732
3733 let mut dec = UnsignedDecimal::from_str("0.60").unwrap();
3734 dec.round_with_mode_and_increment(
3735 -2,
3736 UnsignedRoundingMode::HalfEven,
3737 RoundingIncrement::MultiplesOf25,
3738 );
3739 assert_eq!("0.50", dec.to_string());
3740
3741 let mut dec = UnsignedDecimal::from_str("0.40").unwrap();
3742 dec.round_with_mode_and_increment(
3743 -2,
3744 UnsignedRoundingMode::HalfEven,
3745 RoundingIncrement::MultiplesOf25,
3746 );
3747 assert_eq!("0.50", dec.to_string());
3748
3749 let mut dec = UnsignedDecimal::from_str("0.7000000099").unwrap();
3750 dec.round_with_mode_and_increment(
3751 -3,
3752 UnsignedRoundingMode::HalfEven,
3753 RoundingIncrement::MultiplesOf2,
3754 );
3755 assert_eq!("0.700", dec.to_string());
3756
3757 let mut dec = UnsignedDecimal::from_str("5").unwrap();
3758 dec.round_with_mode_and_increment(
3759 0,
3760 UnsignedRoundingMode::HalfEven,
3761 RoundingIncrement::MultiplesOf25,
3762 );
3763 assert_eq!("0", dec.to_string());
3764
3765 let mut dec = UnsignedDecimal::from(7u32).multiplied_pow10(i16::MIN);
3766 dec.round_with_mode_and_increment(
3767 i16::MIN,
3768 UnsignedRoundingMode::HalfEven,
3769 RoundingIncrement::MultiplesOf2,
3770 );
3771 assert_eq!(UnsignedDecimal::from(8u32).multiplied_pow10(i16::MIN), dec);
3772
3773 let mut dec = UnsignedDecimal::from(9u32).multiplied_pow10(i16::MIN);
3774 dec.round_with_mode_and_increment(
3775 i16::MIN,
3776 UnsignedRoundingMode::HalfEven,
3777 RoundingIncrement::MultiplesOf5,
3778 );
3779 assert_eq!(UnsignedDecimal::from(10u32).multiplied_pow10(i16::MIN), dec);
3780
3781 let mut dec = UnsignedDecimal::from(70u32).multiplied_pow10(i16::MIN);
3782 dec.round_with_mode_and_increment(
3783 i16::MIN,
3784 UnsignedRoundingMode::HalfEven,
3785 RoundingIncrement::MultiplesOf25,
3786 );
3787 assert_eq!(UnsignedDecimal::from(75u32).multiplied_pow10(i16::MIN), dec);
3788
3789 let mut dec = UnsignedDecimal::from(7u32).multiplied_pow10(i16::MAX);
3790 dec.round_with_mode_and_increment(
3791 i16::MAX,
3792 UnsignedRoundingMode::HalfEven,
3793 RoundingIncrement::MultiplesOf2,
3794 );
3795 assert_eq!(UnsignedDecimal::from(8u32).multiplied_pow10(i16::MAX), dec);
3796
3797 let mut dec = UnsignedDecimal::from_str("1.108").unwrap();
3799 dec.round_with_mode_and_increment(
3800 -2,
3801 UnsignedRoundingMode::Expand,
3802 RoundingIncrement::MultiplesOf2,
3803 );
3804 assert_eq!("1.12", dec.to_string());
3805
3806 let mut dec = UnsignedDecimal::from_str("1.108").unwrap();
3807 dec.round_with_mode_and_increment(
3808 -2,
3809 UnsignedRoundingMode::Expand,
3810 RoundingIncrement::MultiplesOf5,
3811 );
3812 assert_eq!("1.15", dec.to_string());
3813
3814 let mut dec = UnsignedDecimal::from_str("1.108").unwrap();
3815 dec.round_with_mode_and_increment(
3816 -2,
3817 UnsignedRoundingMode::Expand,
3818 RoundingIncrement::MultiplesOf25,
3819 );
3820 assert_eq!("1.25", dec.to_string());
3821
3822 let mut dec = UnsignedDecimal::from(9u32).multiplied_pow10(i16::MAX - 1);
3823 dec.round_with_mode_and_increment(
3824 i16::MAX - 1,
3825 UnsignedRoundingMode::Expand,
3826 RoundingIncrement::MultiplesOf25,
3827 );
3828 assert_eq!(
3829 UnsignedDecimal::from(25u32).multiplied_pow10(i16::MAX - 1),
3830 dec
3831 );
3832
3833 let mut dec = UnsignedDecimal::from(9u32).multiplied_pow10(i16::MAX);
3834 dec.round_with_mode_and_increment(
3835 i16::MAX,
3836 UnsignedRoundingMode::Expand,
3837 RoundingIncrement::MultiplesOf25,
3838 );
3839 assert_eq!(UnsignedDecimal::from(0u32).multiplied_pow10(i16::MAX), dec);
3840
3841 let mut dec = UnsignedDecimal::from_str("0").unwrap();
3842 dec.round_with_mode_and_increment(
3843 0,
3844 UnsignedRoundingMode::Expand,
3845 RoundingIncrement::MultiplesOf2,
3846 );
3847 assert_eq!("0", dec.to_string());
3848
3849 let mut dec = UnsignedDecimal::from_str("0").unwrap();
3850 dec.round_with_mode_and_increment(
3851 0,
3852 UnsignedRoundingMode::Expand,
3853 RoundingIncrement::MultiplesOf5,
3854 );
3855 assert_eq!("0", dec.to_string());
3856
3857 let mut dec = UnsignedDecimal::from_str("0").unwrap();
3858 dec.round_with_mode_and_increment(
3859 0,
3860 UnsignedRoundingMode::Expand,
3861 RoundingIncrement::MultiplesOf25,
3862 );
3863 assert_eq!("0", dec.to_string());
3864
3865 let mut dec = UnsignedDecimal::from_str("0.1").unwrap();
3866 dec.round_with_mode_and_increment(
3867 0,
3868 UnsignedRoundingMode::Expand,
3869 RoundingIncrement::MultiplesOf2,
3870 );
3871 assert_eq!("2", dec.to_string());
3872
3873 let mut dec = UnsignedDecimal::from_str("0.1").unwrap();
3874 dec.round_with_mode_and_increment(
3875 0,
3876 UnsignedRoundingMode::Expand,
3877 RoundingIncrement::MultiplesOf5,
3878 );
3879 assert_eq!("5", dec.to_string());
3880
3881 let mut dec = UnsignedDecimal::from_str("0.1").unwrap();
3882 dec.round_with_mode_and_increment(
3883 0,
3884 UnsignedRoundingMode::Expand,
3885 RoundingIncrement::MultiplesOf25,
3886 );
3887 assert_eq!("25", dec.to_string());
3888
3889 let mut dec = UnsignedDecimal::from_str("1").unwrap();
3890 dec.round_with_mode_and_increment(
3891 0,
3892 UnsignedRoundingMode::Expand,
3893 RoundingIncrement::MultiplesOf2,
3894 );
3895 assert_eq!("2", dec.to_string());
3896
3897 let mut dec = UnsignedDecimal::from_str("1").unwrap();
3898 dec.round_with_mode_and_increment(
3899 0,
3900 UnsignedRoundingMode::Expand,
3901 RoundingIncrement::MultiplesOf5,
3902 );
3903 assert_eq!("5", dec.to_string());
3904
3905 let mut dec = UnsignedDecimal::from_str("1").unwrap();
3906 dec.round_with_mode_and_increment(
3907 0,
3908 UnsignedRoundingMode::Expand,
3909 RoundingIncrement::MultiplesOf25,
3910 );
3911 assert_eq!("25", dec.to_string());
3912
3913 let mut dec = UnsignedDecimal::from_str("2").unwrap();
3914 dec.round_with_mode_and_increment(
3915 0,
3916 UnsignedRoundingMode::Expand,
3917 RoundingIncrement::MultiplesOf2,
3918 );
3919 assert_eq!("2", dec.to_string());
3920
3921 let mut dec = UnsignedDecimal::from_str("2").unwrap();
3922 dec.round_with_mode_and_increment(
3923 0,
3924 UnsignedRoundingMode::Expand,
3925 RoundingIncrement::MultiplesOf5,
3926 );
3927 assert_eq!("5", dec.to_string());
3928
3929 let mut dec = UnsignedDecimal::from_str("2.1").unwrap();
3930 dec.round_with_mode_and_increment(
3931 0,
3932 UnsignedRoundingMode::Expand,
3933 RoundingIncrement::MultiplesOf2,
3934 );
3935 assert_eq!("4", dec.to_string());
3936
3937 let mut dec = UnsignedDecimal::from_str("2.1").unwrap();
3938 dec.round_with_mode_and_increment(
3939 0,
3940 UnsignedRoundingMode::Expand,
3941 RoundingIncrement::MultiplesOf5,
3942 );
3943 assert_eq!("5", dec.to_string());
3944
3945 let mut dec = UnsignedDecimal::from_str("4").unwrap();
3946 dec.round_with_mode_and_increment(
3947 0,
3948 UnsignedRoundingMode::Expand,
3949 RoundingIncrement::MultiplesOf2,
3950 );
3951 assert_eq!("4", dec.to_string());
3952
3953 let mut dec = UnsignedDecimal::from_str("4").unwrap();
3954 dec.round_with_mode_and_increment(
3955 0,
3956 UnsignedRoundingMode::Expand,
3957 RoundingIncrement::MultiplesOf5,
3958 );
3959 assert_eq!("5", dec.to_string());
3960
3961 let mut dec = UnsignedDecimal::from_str("4.1").unwrap();
3962 dec.round_with_mode_and_increment(
3963 0,
3964 UnsignedRoundingMode::Expand,
3965 RoundingIncrement::MultiplesOf2,
3966 );
3967 assert_eq!("6", dec.to_string());
3968
3969 let mut dec = UnsignedDecimal::from_str("4.1").unwrap();
3970 dec.round_with_mode_and_increment(
3971 0,
3972 UnsignedRoundingMode::Expand,
3973 RoundingIncrement::MultiplesOf5,
3974 );
3975 assert_eq!("5", dec.to_string());
3976
3977 let mut dec = UnsignedDecimal::from_str("5").unwrap();
3978 dec.round_with_mode_and_increment(
3979 0,
3980 UnsignedRoundingMode::Expand,
3981 RoundingIncrement::MultiplesOf2,
3982 );
3983 assert_eq!("6", dec.to_string());
3984
3985 let mut dec = UnsignedDecimal::from_str("5").unwrap();
3986 dec.round_with_mode_and_increment(
3987 0,
3988 UnsignedRoundingMode::Expand,
3989 RoundingIncrement::MultiplesOf5,
3990 );
3991 assert_eq!("5", dec.to_string());
3992
3993 let mut dec = UnsignedDecimal::from_str("5.1").unwrap();
3994 dec.round_with_mode_and_increment(
3995 0,
3996 UnsignedRoundingMode::Expand,
3997 RoundingIncrement::MultiplesOf2,
3998 );
3999 assert_eq!("6", dec.to_string());
4000
4001 let mut dec = UnsignedDecimal::from_str("5.1").unwrap();
4002 dec.round_with_mode_and_increment(
4003 0,
4004 UnsignedRoundingMode::Expand,
4005 RoundingIncrement::MultiplesOf5,
4006 );
4007 assert_eq!("10", dec.to_string());
4008
4009 let mut dec = UnsignedDecimal::from_str("6").unwrap();
4010 dec.round_with_mode_and_increment(
4011 0,
4012 UnsignedRoundingMode::Expand,
4013 RoundingIncrement::MultiplesOf2,
4014 );
4015 assert_eq!("6", dec.to_string());
4016
4017 let mut dec = UnsignedDecimal::from_str("6").unwrap();
4018 dec.round_with_mode_and_increment(
4019 0,
4020 UnsignedRoundingMode::Expand,
4021 RoundingIncrement::MultiplesOf5,
4022 );
4023 assert_eq!("10", dec.to_string());
4024
4025 let mut dec = UnsignedDecimal::from_str("0.50").unwrap();
4026 dec.round_with_mode_and_increment(
4027 -2,
4028 UnsignedRoundingMode::Expand,
4029 RoundingIncrement::MultiplesOf25,
4030 );
4031 assert_eq!("0.50", dec.to_string());
4032
4033 let mut dec = UnsignedDecimal::from_str("1.1025").unwrap();
4034 dec.round_with_mode_and_increment(
4035 -3,
4036 UnsignedRoundingMode::HalfTrunc,
4037 RoundingIncrement::MultiplesOf5,
4038 );
4039 assert_eq!("1.100", dec.to_string());
4040
4041 let mut dec = UnsignedDecimal::from_str("1.10125").unwrap();
4042 dec.round_with_mode_and_increment(
4043 -4,
4044 UnsignedRoundingMode::HalfExpand,
4045 RoundingIncrement::MultiplesOf25,
4046 );
4047 assert_eq!("1.1025", dec.to_string());
4048
4049 let mut dec = UnsignedDecimal::from_str("2.71").unwrap();
4050 dec.round_with_mode_and_increment(
4051 -2,
4052 UnsignedRoundingMode::HalfEven,
4053 RoundingIncrement::MultiplesOf2,
4054 );
4055 assert_eq!("2.72", dec.to_string());
4056
4057 let mut dec = UnsignedDecimal::from_str("2.73").unwrap();
4058 dec.round_with_mode_and_increment(
4059 -2,
4060 UnsignedRoundingMode::HalfEven,
4061 RoundingIncrement::MultiplesOf2,
4062 );
4063 assert_eq!("2.72", dec.to_string());
4064
4065 let mut dec = UnsignedDecimal::from_str("2.75").unwrap();
4066 dec.round_with_mode_and_increment(
4067 -2,
4068 UnsignedRoundingMode::HalfEven,
4069 RoundingIncrement::MultiplesOf2,
4070 );
4071 assert_eq!("2.76", dec.to_string());
4072
4073 let mut dec = UnsignedDecimal::from_str("2.77").unwrap();
4074 dec.round_with_mode_and_increment(
4075 -2,
4076 UnsignedRoundingMode::HalfEven,
4077 RoundingIncrement::MultiplesOf2,
4078 );
4079 assert_eq!("2.76", dec.to_string());
4080
4081 let mut dec = UnsignedDecimal::from_str("2.79").unwrap();
4082 dec.round_with_mode_and_increment(
4083 -2,
4084 UnsignedRoundingMode::HalfEven,
4085 RoundingIncrement::MultiplesOf2,
4086 );
4087 assert_eq!("2.80", dec.to_string());
4088
4089 let mut dec = UnsignedDecimal::from_str("2.41").unwrap();
4090 dec.round_with_mode_and_increment(
4091 -2,
4092 UnsignedRoundingMode::HalfEven,
4093 RoundingIncrement::MultiplesOf2,
4094 );
4095 assert_eq!("2.40", dec.to_string());
4096
4097 let mut dec = UnsignedDecimal::from_str("2.43").unwrap();
4098 dec.round_with_mode_and_increment(
4099 -2,
4100 UnsignedRoundingMode::HalfEven,
4101 RoundingIncrement::MultiplesOf2,
4102 );
4103 assert_eq!("2.44", dec.to_string());
4104
4105 let mut dec = UnsignedDecimal::from_str("2.45").unwrap();
4106 dec.round_with_mode_and_increment(
4107 -2,
4108 UnsignedRoundingMode::HalfEven,
4109 RoundingIncrement::MultiplesOf2,
4110 );
4111 assert_eq!("2.44", dec.to_string());
4112
4113 let mut dec = UnsignedDecimal::from_str("2.47").unwrap();
4114 dec.round_with_mode_and_increment(
4115 -2,
4116 UnsignedRoundingMode::HalfEven,
4117 RoundingIncrement::MultiplesOf2,
4118 );
4119 assert_eq!("2.48", dec.to_string());
4120
4121 let mut dec = UnsignedDecimal::from_str("2.49").unwrap();
4122 dec.round_with_mode_and_increment(
4123 -2,
4124 UnsignedRoundingMode::HalfEven,
4125 RoundingIncrement::MultiplesOf2,
4126 );
4127 assert_eq!("2.48", dec.to_string());
4128
4129 let mut dec = UnsignedDecimal::from_str("2.725").unwrap();
4130 dec.round_with_mode_and_increment(
4131 -2,
4132 UnsignedRoundingMode::HalfEven,
4133 RoundingIncrement::MultiplesOf5,
4134 );
4135 assert_eq!("2.70", dec.to_string());
4136
4137 let mut dec = UnsignedDecimal::from_str("2.775").unwrap();
4138 dec.round_with_mode_and_increment(
4139 -2,
4140 UnsignedRoundingMode::HalfEven,
4141 RoundingIncrement::MultiplesOf5,
4142 );
4143 assert_eq!("2.80", dec.to_string());
4144
4145 let mut dec = UnsignedDecimal::from_str("2.875").unwrap();
4146 dec.round_with_mode_and_increment(
4147 -2,
4148 UnsignedRoundingMode::HalfEven,
4149 RoundingIncrement::MultiplesOf25,
4150 );
4151 assert_eq!("3.00", dec.to_string());
4152
4153 let mut dec = UnsignedDecimal::from_str("2.375").unwrap();
4154 dec.round_with_mode_and_increment(
4155 -2,
4156 UnsignedRoundingMode::HalfEven,
4157 RoundingIncrement::MultiplesOf25,
4158 );
4159 assert_eq!("2.50", dec.to_string());
4160
4161 let mut dec = UnsignedDecimal::from_str("2.125").unwrap();
4162 dec.round_with_mode_and_increment(
4163 -2,
4164 UnsignedRoundingMode::HalfEven,
4165 RoundingIncrement::MultiplesOf25,
4166 );
4167 assert_eq!("2.00", dec.to_string());
4168
4169 let mut dec = UnsignedDecimal::from_str("2.625").unwrap();
4170 dec.round_with_mode_and_increment(
4171 -2,
4172 UnsignedRoundingMode::HalfEven,
4173 RoundingIncrement::MultiplesOf25,
4174 );
4175 assert_eq!("2.50", dec.to_string());
4176}