1use std::cmp::Ordering;
21use std::f64::consts::PI;
22use std::fmt::{self, Debug, Display, Formatter};
23use std::hash;
24use std::iter::{Product, Sum};
25use std::ops::{self, Add, Div, Mul, Neg, Rem, Sub};
26use std::str::FromStr;
27
28use anyhow::{Result, bail, ensure};
29use fastnum::D128;
30use revision::revisioned;
31use rust_decimal::Decimal;
32use rust_decimal::prelude::*;
33use storekey::{BorrowDecode, Encode};
34use surrealdb_types::{SqlFormat, ToSql, fmt_non_finite_f64, write_sql};
35
36use super::IndexFormat;
37use crate::expr::Error;
38use crate::expr::decimal::DecimalLexEncoder;
39use crate::val::{TryAdd, TryDiv, TryFloatDiv, TryMul, TryNeg, TryPow, TryRem, TrySub};
40
41#[derive(Copy, Clone, Encode, BorrowDecode)]
42pub enum NumberKind {
43 Int,
44 Float,
45 Decimal,
46}
47
48#[revisioned(revision = 1)]
49#[derive(Clone, Copy, Debug)]
50#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
51pub enum Number {
52 Int(i64),
53 Float(f64),
54 Decimal(Decimal),
55 }
57
58impl Default for Number {
59 fn default() -> Self {
60 Self::Int(0)
61 }
62}
63
64macro_rules! from_prim_ints {
65 ($($int: ty),*) => {
66 $(
67 impl From<$int> for Number {
68 fn from(i: $int) -> Self {
69 Self::Int(i as i64)
70 }
71 }
72 )*
73 };
74}
75
76from_prim_ints!(i8, i16, i32, i64, isize, u8, u16, u32);
80
81impl From<u64> for Number {
85 fn from(i: u64) -> Self {
86 match i64::try_from(i) {
87 Ok(v) => Self::Int(v),
88 Err(_) => Self::Decimal(Decimal::from(i)),
89 }
90 }
91}
92
93impl From<usize> for Number {
94 fn from(i: usize) -> Self {
95 Self::from(i as u64)
97 }
98}
99
100impl TryFrom<i128> for Number {
104 type Error = Error;
105 fn try_from(i: i128) -> Result<Self, Self::Error> {
106 if let Ok(v) = i64::try_from(i) {
107 Ok(Self::Int(v))
108 } else if let Some(v) = Decimal::from_i128(i) {
109 Ok(Self::Decimal(v))
110 } else {
111 Err(Error::TryFrom(i.to_string(), "Number"))
112 }
113 }
114}
115
116impl TryFrom<u128> for Number {
117 type Error = Error;
118 fn try_from(i: u128) -> Result<Self, Self::Error> {
119 if let Ok(v) = i64::try_from(i) {
120 Ok(Self::Int(v))
121 } else if let Some(v) = Decimal::from_u128(i) {
122 Ok(Self::Decimal(v))
123 } else {
124 Err(Error::TryFrom(i.to_string(), "Number"))
125 }
126 }
127}
128
129impl From<f32> for Number {
130 fn from(f: f32) -> Self {
131 Self::Float(f as f64)
132 }
133}
134
135impl From<f64> for Number {
136 fn from(f: f64) -> Self {
137 Self::Float(f)
138 }
139}
140
141impl From<Decimal> for Number {
142 fn from(v: Decimal) -> Self {
143 Self::Decimal(v)
144 }
145}
146
147impl From<surrealdb_types::Number> for Number {
148 fn from(v: surrealdb_types::Number) -> Self {
149 match v {
150 surrealdb_types::Number::Int(i) => Self::Int(i),
151 surrealdb_types::Number::Float(f) => Self::Float(f),
152 surrealdb_types::Number::Decimal(d) => Self::Decimal(d),
153 }
154 }
155}
156
157impl From<Number> for surrealdb_types::Number {
158 fn from(v: Number) -> Self {
159 match v {
160 Number::Int(i) => Self::Int(i),
161 Number::Float(f) => Self::Float(f),
162 Number::Decimal(d) => Self::Decimal(d),
163 }
164 }
165}
166
167impl FromStr for Number {
168 type Err = ();
169 fn from_str(s: &str) -> Result<Self, Self::Err> {
170 match s.parse::<i64>() {
172 Ok(v) => Ok(Self::Int(v)),
174 _ => match s.parse::<f64>() {
176 Ok(v) => Ok(Self::Float(v)),
178 _ => Err(()),
180 },
181 }
182 }
183}
184
185macro_rules! try_into_prim {
186 ($($int: ty => $to_int: ident),*) => {
188 $(
189 impl TryFrom<Number> for $int {
190 type Error = Error;
191 fn try_from(value: Number) -> Result<Self, Self::Error> {
192 match value {
193 Number::Int(v) => match v.$to_int() {
194 Some(v) => Ok(v),
195 None => Err(Error::TryFrom(value.to_sql(), stringify!($int))),
196 },
197 Number::Float(v) => match v.$to_int() {
198 Some(v) => Ok(v),
199 None => Err(Error::TryFrom(value.to_sql(), stringify!($int))),
200 },
201 Number::Decimal(ref v) => match v.$to_int() {
202 Some(v) => Ok(v),
203 None => Err(Error::TryFrom(value.to_sql(), stringify!($int))),
204 },
205 }
206 }
207 }
208 )*
209 };
210}
211
212try_into_prim!(
213 i8 => to_i8, i16 => to_i16, i32 => to_i32, i64 => to_i64, i128 => to_i128,
214 u8 => to_u8, u16 => to_u16, u32 => to_u32, u64 => to_u64, u128 => to_u128,
215 f32 => to_f32, f64 => to_f64
216);
217
218impl TryFrom<Number> for Decimal {
219 type Error = Error;
220 fn try_from(value: Number) -> Result<Self, Self::Error> {
221 match value {
222 Number::Int(v) => match Decimal::from_i64(v) {
223 Some(v) => Ok(v),
224 None => Err(Error::TryFrom(value.to_sql(), "Decimal")),
225 },
226 Number::Float(v) => match Decimal::try_from(v) {
227 Ok(v) => Ok(v),
228 _ => Err(Error::TryFrom(value.to_sql(), "Decimal")),
229 },
230 Number::Decimal(x) => Ok(x),
231 }
232 }
233}
234
235impl Display for Number {
236 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
237 match self {
238 Number::Int(v) => Display::fmt(v, f),
239 Number::Float(v) => Display::fmt(v, f),
240 Number::Decimal(v) => Display::fmt(v, f),
241 }
242 }
243}
244
245impl ToSql for Number {
246 fn fmt_sql(&self, f: &mut String, sql_fmt: SqlFormat) {
247 match self {
248 Number::Int(v) => v.fmt_sql(f, sql_fmt),
249 Number::Float(v) => {
250 match fmt_non_finite_f64(*v) {
251 Some(special) => write_sql!(f, sql_fmt, "{}", special),
253 None => write_sql!(f, sql_fmt, "{v}f"),
255 }
256 }
257 Number::Decimal(v) => v.fmt_sql(f, sql_fmt),
258 }
259 }
260}
261
262impl Number {
263 pub const NAN: Number = Number::Float(f64::NAN);
268
269 pub fn is_int(&self) -> bool {
274 matches!(self, Number::Int(_))
275 }
276
277 pub fn is_float(&self) -> bool {
278 matches!(self, Number::Float(_))
279 }
280
281 pub fn is_truthy(&self) -> bool {
282 match self {
283 Number::Int(v) => v != &0,
284 Number::Float(v) => v != &0.0,
285 Number::Decimal(v) => v != &Decimal::ZERO,
286 }
287 }
288
289 pub fn is_zero(&self) -> bool {
290 match self {
291 Number::Int(v) => v == &0,
292 Number::Float(v) => v == &0.0,
293 Number::Decimal(v) => v == &Decimal::ZERO,
294 }
295 }
296
297 pub fn as_usize(self) -> usize {
302 match self {
303 Number::Int(v) => v as usize,
304 Number::Float(v) => v as usize,
305 Number::Decimal(v) => v.try_into().unwrap_or_default(),
306 }
307 }
308
309 pub fn as_int(self) -> i64 {
310 match self {
311 Number::Int(v) => v,
312 Number::Float(v) => v as i64,
313 Number::Decimal(v) => v.try_into().unwrap_or_default(),
314 }
315 }
316
317 pub fn as_float(self) -> f64 {
318 match self {
319 Number::Int(v) => v as f64,
320 Number::Float(v) => v,
321 Number::Decimal(v) => v.try_into().unwrap_or_default(),
322 }
323 }
324
325 pub fn as_decimal(self) -> Decimal {
326 match self {
327 Number::Int(v) => Decimal::from(v),
328 Number::Float(v) => Decimal::try_from(v).unwrap_or_default(),
329 Number::Decimal(v) => v,
330 }
331 }
332
333 pub fn as_int_lossless(self) -> Option<i64> {
345 match self {
346 Number::Int(v) => Some(v),
347 Number::Float(v) => {
348 if !v.is_finite()
352 || v.fract() != 0.0
353 || v < i64::MIN as f64
354 || v >= -(i64::MIN as f64)
355 {
356 return None;
357 }
358 Some(v as i64)
359 }
360 Number::Decimal(v) => {
361 if v.fract().is_zero() {
362 v.try_into().ok()
363 } else {
364 None
365 }
366 }
367 }
368 }
369
370 pub fn as_array_index(self) -> Option<usize> {
376 match self {
377 Number::Int(v) => usize::try_from(v).ok(),
378 Number::Float(v) => {
379 if !v.is_finite() || v < 0.0 || v.fract() != 0.0 {
380 return None;
381 }
382 let idx = v as usize;
386 (idx as f64 == v).then_some(idx)
387 }
388 Number::Decimal(v) => {
389 if v.fract().is_zero() {
390 v.to_usize()
391 } else {
392 None
393 }
394 }
395 }
396 }
397
398 pub fn to_int(self) -> i64 {
399 match self {
400 Number::Int(v) => v,
401 Number::Float(v) => v as i64,
402 Number::Decimal(v) => v.to_i64().unwrap_or_default(),
403 }
404 }
405
406 pub fn to_float(self) -> f64 {
407 match self {
408 Number::Int(v) => v as f64,
409 Number::Float(v) => v,
410 Number::Decimal(v) => v.try_into().unwrap_or_default(),
411 }
412 }
413
414 pub fn to_decimal(self) -> Decimal {
415 match self {
416 Number::Int(v) => Decimal::from(v),
417 Number::Float(v) => Decimal::from_f64(v).unwrap_or_default(),
418 Number::Decimal(v) => v,
419 }
420 }
421
422 pub fn as_decimal_buf(&self) -> Vec<u8> {
448 match self {
449 Self::Int(v) => {
450 DecimalLexEncoder::encode(D128::from(*v))
452 }
453 Self::Float(v) => {
454 DecimalLexEncoder::encode(D128::from_f64(*v))
456 }
457 Self::Decimal(v) => {
458 DecimalLexEncoder::encode(DecimalLexEncoder::to_d128(*v))
460 }
461 }
462 }
463
464 pub fn from_decimal_buf(b: &[u8]) -> Result<Self> {
481 let dec = DecimalLexEncoder::decode(b)?;
482 if dec.is_finite() {
483 match DecimalLexEncoder::to_decimal(dec) {
484 Ok(dec) => Ok(Number::Decimal(dec)),
485 Err(_) => Ok(Number::Float(dec.to_f64())),
486 }
487 } else if dec.is_nan() {
488 Ok(Number::Float(f64::NAN))
489 } else if dec.is_infinite() {
490 if dec.is_negative() {
491 Ok(Number::Float(f64::NEG_INFINITY))
492 } else {
493 Ok(Number::Float(f64::INFINITY))
494 }
495 } else {
496 bail!(Error::Serialization(format!("Invalid decimal value: {dec}")))
497 }
498 }
499
500 pub fn from_decimal_buf_kind(b: &[u8], kind: NumberKind) -> Result<Self> {
501 let dec = DecimalLexEncoder::decode(b)?;
502 match kind {
503 NumberKind::Int => {
504 ensure!(dec.is_finite(), format!("Invalid integer value: {dec}"));
505 Ok(Number::Int(dec.to_string().parse::<i64>()?))
506 }
507 NumberKind::Float => {
508 if dec.is_nan() {
509 Ok(Number::Float(f64::NAN))
510 } else if dec.is_infinite() {
511 if dec.is_negative() {
512 Ok(Number::Float(f64::NEG_INFINITY))
513 } else {
514 Ok(Number::Float(f64::INFINITY))
515 }
516 } else {
517 let dec = DecimalLexEncoder::to_decimal(dec)?;
518 dec.to_f64()
519 .ok_or_else(|| anyhow::Error::msg(format!("Invalid f64 {dec}")))
520 .map(Number::Float)
521 }
522 }
523 NumberKind::Decimal => {
524 ensure!(dec.is_finite(), format!("Invalid integer value: {dec}"));
525 Ok(Number::Decimal(DecimalLexEncoder::to_decimal(dec)?))
526 }
527 }
528 }
529
530 pub fn abs(self) -> Self {
535 match self {
536 Number::Int(v) => v.abs().into(),
537 Number::Float(v) => v.abs().into(),
538 Number::Decimal(v) => v.abs().into(),
539 }
540 }
541
542 pub fn checked_abs(self) -> Option<Self> {
543 match self {
544 Number::Int(v) => v.checked_abs().map(|x| x.into()),
545 Number::Float(v) => Some(v.abs().into()),
546 Number::Decimal(v) => Some(v.abs().into()),
547 }
548 }
549
550 pub fn acos(self) -> Self {
551 self.to_float().acos().into()
552 }
553
554 pub fn asin(self) -> Self {
555 self.to_float().asin().into()
556 }
557
558 pub fn atan(self) -> Self {
559 self.to_float().atan().into()
560 }
561
562 pub fn acot(self) -> Self {
563 (PI / 2.0 - self.atan().to_float()).into()
564 }
565
566 pub fn ceil(self) -> Self {
567 match self {
568 Number::Int(v) => v.into(),
569 Number::Float(v) => v.ceil().into(),
570 Number::Decimal(v) => v.ceil().into(),
571 }
572 }
573
574 pub fn clamp(self, min: Self, max: Self) -> Self {
575 match (self, min, max) {
576 (Number::Int(n), Number::Int(min), Number::Int(max)) => n.clamp(min, max).into(),
577 (Number::Decimal(n), min, max) => n.clamp(min.to_decimal(), max.to_decimal()).into(),
578 (Number::Float(n), min, max) => n.clamp(min.to_float(), max.to_float()).into(),
579 (Number::Int(n), min, max) => n.to_float().clamp(min.to_float(), max.to_float()).into(),
580 }
581 }
582
583 pub fn cos(self) -> Self {
584 self.to_float().cos().into()
585 }
586
587 pub fn cot(self) -> Self {
588 (1.0 / self.to_float().tan()).into()
589 }
590
591 pub fn deg2rad(self) -> Self {
592 self.to_float().to_radians().into()
593 }
594
595 pub fn floor(self) -> Self {
596 match self {
597 Number::Int(v) => v.into(),
598 Number::Float(v) => v.floor().into(),
599 Number::Decimal(v) => v.floor().into(),
600 }
601 }
602
603 fn lerp_f64(from: f64, to: f64, factor: f64) -> f64 {
604 from + factor * (to - from)
605 }
606
607 fn lerp_decimal(from: Decimal, to: Decimal, factor: Decimal) -> Decimal {
608 from + factor * (to - from)
609 }
610
611 pub fn lerp(self, from: Self, to: Self) -> Self {
612 match (self, from, to) {
613 (Number::Decimal(val), from, to) => {
614 Self::lerp_decimal(from.to_decimal(), to.to_decimal(), val).into()
615 }
616 (val, from, to) => {
617 Self::lerp_f64(from.to_float(), to.to_float(), val.to_float()).into()
618 }
619 }
620 }
621
622 fn repeat_f64(t: f64, m: f64) -> f64 {
623 (t - (t / m).floor() * m).clamp(0.0, m)
624 }
625
626 fn repeat_decimal(t: Decimal, m: Decimal) -> Decimal {
627 (t - (t / m).floor() * m).clamp(Decimal::ZERO, m)
628 }
629
630 pub fn lerp_angle(self, from: Self, to: Self) -> Self {
631 match (self, from, to) {
632 (Number::Decimal(val), from, to) => {
633 let from = from.to_decimal();
634 let to = to.to_decimal();
635 let mut dt = Self::repeat_decimal(to - from, Decimal::from(360));
636 if dt > Decimal::from(180) {
637 dt = Decimal::from(360) - dt;
638 }
639 Self::lerp_decimal(from, from + dt, val).into()
640 }
641 (val, from, to) => {
642 let val = val.to_float();
643 let from = from.to_float();
644 let to = to.to_float();
645 let mut dt = Self::repeat_f64(to - from, 360.0);
646 if dt > 180.0 {
647 dt = 360.0 - dt;
648 }
649 Self::lerp_f64(from, from + dt, val).into()
650 }
651 }
652 }
653
654 pub fn ln(self) -> Self {
655 self.to_float().ln().into()
656 }
657
658 pub fn log(self, base: Self) -> Self {
659 self.to_float().log(base.to_float()).into()
660 }
661
662 pub fn log2(self) -> Self {
663 self.to_float().log2().into()
664 }
665
666 pub fn log10(self) -> Self {
667 self.to_float().log10().into()
668 }
669
670 pub fn rad2deg(self) -> Self {
671 self.to_float().to_degrees().into()
672 }
673
674 pub fn round(self) -> Self {
675 match self {
676 Number::Int(v) => v.into(),
677 Number::Float(v) => v.round().into(),
678 Number::Decimal(v) => v.round().into(),
679 }
680 }
681
682 pub fn fixed(self, precision: usize) -> Number {
683 match self {
684 Number::Int(v) => v.into(),
685 Number::Float(v) => format!("{v:.precision$}")
689 .parse::<f64>()
690 .expect("formatted f64 always parses back as f64")
691 .into(),
692 Number::Decimal(v) => v.round_dp(precision as u32).into(),
693 }
694 }
695
696 pub fn sign(self) -> Self {
697 match self {
698 Number::Int(n) => n.signum().into(),
699 Number::Float(n) => n.signum().into(),
700 Number::Decimal(n) => n.signum().into(),
701 }
702 }
703
704 pub fn sin(self) -> Self {
705 self.to_float().sin().into()
706 }
707
708 pub fn tan(self) -> Self {
709 self.to_float().tan().into()
710 }
711
712 pub fn sqrt(self) -> Self {
713 match self {
714 Number::Int(v) => (v as f64).sqrt().into(),
715 Number::Float(v) => v.sqrt().into(),
716 Number::Decimal(v) => v.sqrt().unwrap_or_default().into(),
717 }
718 }
719}
720
721impl Eq for Number {}
722
723impl Ord for Number {
724 fn cmp(&self, other: &Self) -> Ordering {
725 fn total_cmp_f64(a: f64, b: f64) -> Ordering {
726 if a == 0.0 && b == 0.0 {
727 Ordering::Equal
729 } else {
730 a.total_cmp(&b)
732 }
733 }
734
735 macro_rules! greater {
737 ($f:ident) => {
738 if $f.is_sign_positive() {
739 Ordering::Greater
740 } else {
741 Ordering::Less
742 }
743 };
744 }
745
746 match (self, other) {
747 (Number::Int(v), Number::Int(w)) => v.cmp(w),
748 (Number::Float(v), Number::Float(w)) => total_cmp_f64(*v, *w),
749 (Number::Decimal(v), Number::Decimal(w)) => v.cmp(w),
750 (Number::Int(v), Number::Float(w)) => {
752 if !w.is_finite() {
754 return greater!(w).reverse();
755 }
756 let l = *v as i128;
758 let r = *w as i128;
760 match l.cmp(&r) {
762 Ordering::Equal => total_cmp_f64(0.0, w.fract()),
764 ordering => ordering,
766 }
767 }
768 (v @ Number::Float(_), w @ Number::Int(_)) => w.cmp(v).reverse(),
769 (Number::Int(v), Number::Decimal(w)) => Decimal::from(*v).cmp(w),
771 (Number::Decimal(v), Number::Int(w)) => v.cmp(&Decimal::from(*w)),
772 (Number::Float(v), Number::Decimal(w)) => {
774 macro_rules! compare_fractions {
776 ($l:ident, $r:ident) => {
777 match ($l == 0.0, $r == Decimal::ZERO) {
778 (true, true) => {
780 return Ordering::Equal;
781 }
782 (true, false) => {
784 return greater!($r).reverse();
785 }
786 (false, true) => {
788 return greater!($l);
789 }
790 (false, false) => {
792 continue;
793 }
794 }
795 };
796 }
797 if !v.is_finite() {
799 return greater!(v);
800 }
801 let l = *v as i128;
803 let Ok(r) = i128::try_from(*w) else {
805 return greater!(w).reverse();
806 };
807 match l.cmp(&r) {
809 Ordering::Equal => {
811 const SAFE_MULTIPLIER: i64 = 9_007_199_254_740_000;
826 let mut l = v.fract();
828 let mut r = w.fract();
830 for _ in 0..12 {
835 l *= SAFE_MULTIPLIER as f64;
836 r *= Decimal::new(SAFE_MULTIPLIER, 0);
837 match r.to_i64() {
840 Some(ref right) => match (l as i64).cmp(right) {
841 Ordering::Equal => {
844 l = l.fract();
846 r = r.fract();
847 compare_fractions!(l, r);
850 }
851 ordering => {
852 return ordering;
855 }
856 },
857 None => {
861 return greater!(w).reverse();
864 }
865 }
866 }
867 Ordering::Equal
872 }
873 ordering => ordering,
875 }
876 }
877 (v @ Number::Decimal(..), w @ Number::Float(..)) => w.cmp(v).reverse(),
878 }
879 }
880}
881
882impl hash::Hash for Number {
883 fn hash<H: hash::Hasher>(&self, state: &mut H) {
903 self.as_decimal_buf().hash(state);
904 }
905}
906
907impl PartialEq for Number {
908 fn eq(&self, other: &Self) -> bool {
909 fn total_eq_f64(a: f64, b: f64) -> bool {
910 a.to_bits().eq(&b.to_bits()) || (a == 0.0 && b == 0.0)
911 }
912
913 match (self, other) {
914 (Number::Int(v), Number::Int(w)) => v.eq(w),
915 (Number::Float(v), Number::Float(w)) => total_eq_f64(*v, *w),
916 (Number::Decimal(v), Number::Decimal(w)) => v.eq(w),
917 (v @ Number::Int(_), w @ Number::Float(_)) => v.cmp(w) == Ordering::Equal,
919 (v @ Number::Float(_), w @ Number::Int(_)) => v.cmp(w) == Ordering::Equal,
920 (Number::Int(v), Number::Decimal(w)) => Decimal::from(*v).eq(w),
922 (Number::Decimal(v), Number::Int(w)) => v.eq(&Decimal::from(*w)),
923 (v @ Number::Float(_), w @ Number::Decimal(_)) => v.cmp(w) == Ordering::Equal,
925 (v @ Number::Decimal(_), w @ Number::Float(_)) => v.cmp(w) == Ordering::Equal,
926 }
927 }
928}
929
930impl PartialOrd for Number {
931 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
932 Some(self.cmp(other))
933 }
934}
935
936macro_rules! impl_simple_try_op {
937 ($trt:ident, $fn:ident, $unchecked:ident, $checked:ident) => {
938 impl $trt for Number {
939 type Output = Self;
940 fn $fn(self, other: Self) -> Result<Self> {
941 Ok(match (self, other) {
942 (Number::Int(v), Number::Int(w)) => Number::Int(
943 v.$checked(w).ok_or_else(|| Error::$trt(v.to_string(), w.to_string()))?,
944 ),
945 (Number::Float(v), Number::Float(w)) => Number::Float(v.$unchecked(w)),
946 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(
947 v.$checked(w).ok_or_else(|| Error::$trt(v.to_string(), w.to_string()))?,
948 ),
949 (Number::Int(v), Number::Float(w)) => Number::Float((v as f64).$unchecked(w)),
950 (Number::Float(v), Number::Int(w)) => Number::Float(v.$unchecked(w as f64)),
951 (v, w) => Number::Decimal(
952 v.to_decimal()
953 .$checked(w.to_decimal())
954 .ok_or_else(|| Error::$trt(v.to_sql(), w.to_sql()))?,
955 ),
956 })
957 }
958 }
959 };
960}
961
962impl_simple_try_op!(TryAdd, try_add, add, checked_add);
963impl_simple_try_op!(TrySub, try_sub, sub, checked_sub);
964impl_simple_try_op!(TryMul, try_mul, mul, checked_mul);
965impl_simple_try_op!(TryDiv, try_div, div, checked_div);
966impl_simple_try_op!(TryRem, try_rem, rem, checked_rem);
967
968impl TryPow for Number {
969 type Output = Self;
970 fn try_pow(self, power: Self) -> Result<Self> {
971 Ok(match (self, power) {
972 (Self::Int(v), Self::Int(p)) => Self::Int(match v {
973 0 => match p.cmp(&0) {
974 Ordering::Less => bail!(Error::TryPow(v.to_string(), p.to_string())),
976 Ordering::Equal => 1,
978 Ordering::Greater => 0,
980 },
981 1 => 1,
983 -1 => {
984 if p % 2 == 0 {
985 1
987 } else {
988 -1
990 }
991 }
992 _ => p
994 .try_into()
995 .ok()
996 .and_then(|p| v.checked_pow(p))
997 .ok_or_else(|| Error::TryPow(v.to_string(), p.to_string()))?,
998 }),
999 (Self::Decimal(v), Self::Int(p)) => Self::Decimal(
1000 v.checked_powi(p).ok_or_else(|| Error::TryPow(v.to_string(), p.to_string()))?,
1001 ),
1002 (Self::Decimal(v), Self::Float(p)) => Self::Decimal(
1003 v.checked_powf(p).ok_or_else(|| Error::TryPow(v.to_string(), p.to_string()))?,
1004 ),
1005 (Self::Decimal(v), Self::Decimal(p)) => Self::Decimal(
1006 v.checked_powd(p).ok_or_else(|| Error::TryPow(v.to_string(), p.to_string()))?,
1007 ),
1008 (v, p) => v.as_float().powf(p.as_float()).into(),
1009 })
1010 }
1011}
1012
1013impl TryNeg for Number {
1014 type Output = Self;
1015
1016 fn try_neg(self) -> Result<Self::Output> {
1017 Ok(match self {
1018 Self::Int(n) => {
1019 Number::Int(n.checked_neg().ok_or_else(|| Error::TryNeg(n.to_string()))?)
1020 }
1021 Self::Float(n) => Number::Float(-n),
1022 Self::Decimal(n) => Number::Decimal(-n),
1023 })
1024 }
1025}
1026
1027impl TryFloatDiv for Number {
1028 type Output = Self;
1029 fn try_float_div(self, other: Self) -> Result<Self> {
1030 Ok(match (self, other) {
1031 (Number::Int(v), Number::Int(w)) => {
1032 let quotient = (v as f64).div(w as f64);
1033 if quotient.fract() != 0.0 {
1034 return Ok(Number::Float(quotient));
1035 }
1036 Number::Int(
1037 v.checked_div(w).ok_or_else(|| Error::TryDiv(v.to_string(), w.to_string()))?,
1038 )
1039 }
1040 (v, w) => v.try_div(w)?,
1041 })
1042 }
1043}
1044
1045impl ops::Add for Number {
1046 type Output = Self;
1047 fn add(self, other: Self) -> Self {
1048 match (self, other) {
1049 (Number::Int(v), Number::Int(w)) => Number::Int(v + w),
1050 (Number::Float(v), Number::Float(w)) => Number::Float(v + w),
1051 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v + w),
1052 (Number::Int(v), Number::Float(w)) => Number::Float(v as f64 + w),
1053 (Number::Float(v), Number::Int(w)) => Number::Float(v + w as f64),
1054 (v, w) => Number::from(v.as_decimal() + w.as_decimal()),
1055 }
1056 }
1057}
1058
1059impl<'b> ops::Add<&'b Number> for &Number {
1060 type Output = Number;
1061 fn add(self, other: &'b Number) -> Number {
1062 match (self, other) {
1063 (Number::Int(v), Number::Int(w)) => Number::Int(v + w),
1064 (Number::Float(v), Number::Float(w)) => Number::Float(v + w),
1065 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v + w),
1066 (Number::Int(v), Number::Float(w)) => Number::Float(*v as f64 + w),
1067 (Number::Float(v), Number::Int(w)) => Number::Float(v + *w as f64),
1068 (v, w) => Number::from(v.to_decimal() + w.to_decimal()),
1069 }
1070 }
1071}
1072
1073impl ops::Sub for Number {
1074 type Output = Self;
1075 fn sub(self, other: Self) -> Self {
1076 match (self, other) {
1077 (Number::Int(v), Number::Int(w)) => Number::Int(v - w),
1078 (Number::Float(v), Number::Float(w)) => Number::Float(v - w),
1079 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v - w),
1080 (Number::Int(v), Number::Float(w)) => Number::Float(v as f64 - w),
1081 (Number::Float(v), Number::Int(w)) => Number::Float(v - w as f64),
1082 (v, w) => Number::from(v.as_decimal() - w.as_decimal()),
1083 }
1084 }
1085}
1086
1087impl<'b> ops::Sub<&'b Number> for &Number {
1088 type Output = Number;
1089 fn sub(self, other: &'b Number) -> Number {
1090 match (self, other) {
1091 (Number::Int(v), Number::Int(w)) => Number::Int(v - w),
1092 (Number::Float(v), Number::Float(w)) => Number::Float(v - w),
1093 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v - w),
1094 (Number::Int(v), Number::Float(w)) => Number::Float(*v as f64 - w),
1095 (Number::Float(v), Number::Int(w)) => Number::Float(v - *w as f64),
1096 (v, w) => Number::from(v.to_decimal() - w.to_decimal()),
1097 }
1098 }
1099}
1100
1101impl ops::Mul for Number {
1102 type Output = Self;
1103 fn mul(self, other: Self) -> Self {
1104 match (self, other) {
1105 (Number::Int(v), Number::Int(w)) => Number::Int(v * w),
1106 (Number::Float(v), Number::Float(w)) => Number::Float(v * w),
1107 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v * w),
1108 (Number::Int(v), Number::Float(w)) => Number::Float(v as f64 * w),
1109 (Number::Float(v), Number::Int(w)) => Number::Float(v * w as f64),
1110 (v, w) => Number::from(v.as_decimal() * w.as_decimal()),
1111 }
1112 }
1113}
1114
1115impl<'b> ops::Mul<&'b Number> for &Number {
1116 type Output = Number;
1117 fn mul(self, other: &'b Number) -> Number {
1118 match (self, other) {
1119 (Number::Int(v), Number::Int(w)) => Number::Int(v * w),
1120 (Number::Float(v), Number::Float(w)) => Number::Float(v * w),
1121 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v * w),
1122 (Number::Int(v), Number::Float(w)) => Number::Float(*v as f64 * w),
1123 (Number::Float(v), Number::Int(w)) => Number::Float(v * *w as f64),
1124 (v, w) => Number::from(v.to_decimal() * w.to_decimal()),
1125 }
1126 }
1127}
1128
1129impl ops::Div for Number {
1130 type Output = Self;
1131 fn div(self, other: Self) -> Self {
1132 match (self, other) {
1133 (Number::Int(v), Number::Int(w)) => Number::Int(v / w),
1134 (Number::Float(v), Number::Float(w)) => Number::Float(v / w),
1135 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v / w),
1136 (Number::Int(v), Number::Float(w)) => Number::Float(v as f64 / w),
1137 (Number::Float(v), Number::Int(w)) => Number::Float(v / w as f64),
1138 (v, w) => Number::from(v.as_decimal() / w.as_decimal()),
1139 }
1140 }
1141}
1142
1143impl<'b> ops::Div<&'b Number> for &Number {
1144 type Output = Number;
1145 fn div(self, other: &'b Number) -> Number {
1146 match (self, other) {
1147 (Number::Int(v), Number::Int(w)) => Number::Int(v / w),
1148 (Number::Float(v), Number::Float(w)) => Number::Float(v / w),
1149 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v / w),
1150 (Number::Int(v), Number::Float(w)) => Number::Float(*v as f64 / w),
1151 (Number::Float(v), Number::Int(w)) => Number::Float(v / *w as f64),
1152 (v, w) => Number::from(v.to_decimal() / w.to_decimal()),
1153 }
1154 }
1155}
1156
1157impl Neg for Number {
1158 type Output = Self;
1159
1160 fn neg(self) -> Self::Output {
1161 match self {
1162 Self::Int(n) => Number::Int(-n),
1163 Self::Float(n) => Number::Float(-n),
1164 Self::Decimal(n) => Number::Decimal(-n),
1165 }
1166 }
1167}
1168
1169impl Sum<Self> for Number {
1172 fn sum<I>(iter: I) -> Number
1173 where
1174 I: Iterator<Item = Self>,
1175 {
1176 iter.fold(Number::Int(0), |a, b| a + b)
1177 }
1178}
1179
1180impl<'a> Sum<&'a Self> for Number {
1181 fn sum<I>(iter: I) -> Number
1182 where
1183 I: Iterator<Item = &'a Self>,
1184 {
1185 iter.fold(Number::Int(0), |a, b| &a + b)
1186 }
1187}
1188
1189impl Product<Self> for Number {
1190 fn product<I>(iter: I) -> Number
1191 where
1192 I: Iterator<Item = Self>,
1193 {
1194 iter.fold(Number::Int(1), |a, b| a * b)
1195 }
1196}
1197
1198impl<'a> Product<&'a Self> for Number {
1199 fn product<I>(iter: I) -> Number
1200 where
1201 I: Iterator<Item = &'a Self>,
1202 {
1203 iter.fold(Number::Int(1), |a, b| &a * b)
1204 }
1205}
1206
1207pub struct Sorted<T>(pub T);
1208
1209pub trait Sort {
1210 fn sorted(&mut self) -> Sorted<&Self>
1211 where
1212 Self: Sized;
1213}
1214
1215impl Sort for Vec<Number> {
1216 fn sorted(&mut self) -> Sorted<&Vec<Number>> {
1217 self.sort();
1218 Sorted(self)
1219 }
1220}
1221
1222impl ToFloat for Number {
1223 fn to_float(&self) -> f64 {
1224 Number::to_float(*self)
1225 }
1226}
1227
1228impl Encode<()> for Number {
1229 fn encode<W: std::io::Write>(
1230 &self,
1231 w: &mut storekey::Writer<W>,
1232 ) -> std::result::Result<(), storekey::EncodeError> {
1233 let slice = self.as_decimal_buf();
1234 w.write_slice(&slice)?;
1235 let kind = match self {
1236 Number::Int(_) => NumberKind::Int,
1237 Number::Float(_) => NumberKind::Float,
1238 Number::Decimal(_) => NumberKind::Decimal,
1239 };
1240 Encode::<()>::encode(&kind, w)?;
1241 Ok(())
1242 }
1243}
1244
1245impl<'de> BorrowDecode<'de, ()> for Number {
1246 fn borrow_decode(
1247 r: &mut storekey::BorrowReader<'de>,
1248 ) -> std::result::Result<Self, storekey::DecodeError> {
1249 let slice = r.read_cow()?;
1250 let kind: NumberKind = BorrowDecode::<'de, ()>::borrow_decode(r)?;
1251 Number::from_decimal_buf_kind(slice.as_ref(), kind)
1252 .map_err(|_| storekey::DecodeError::InvalidFormat)
1253 }
1254}
1255
1256impl Encode<IndexFormat> for Number {
1257 fn encode<W: std::io::Write>(
1258 &self,
1259 w: &mut storekey::Writer<W>,
1260 ) -> std::result::Result<(), storekey::EncodeError> {
1261 let slice = self.as_decimal_buf();
1262 w.write_slice(&slice)
1263 }
1264}
1265
1266impl<'de> BorrowDecode<'de, IndexFormat> for Number {
1267 fn borrow_decode(
1268 r: &mut storekey::BorrowReader<'de>,
1269 ) -> std::result::Result<Self, storekey::DecodeError> {
1270 let slice = r.read_cow()?;
1271 Number::from_decimal_buf(slice.as_ref()).map_err(|_| storekey::DecodeError::InvalidFormat)
1272 }
1273}
1274
1275pub trait ToFloat {
1276 fn to_float(&self) -> f64;
1277}
1278
1279impl ToFloat for f64 {
1280 fn to_float(&self) -> f64 {
1281 *self
1282 }
1283}
1284
1285impl ToFloat for f32 {
1286 fn to_float(&self) -> f64 {
1287 *self as f64
1288 }
1289}
1290
1291impl ToFloat for half::f16 {
1292 fn to_float(&self) -> f64 {
1293 f64::from(*self)
1294 }
1295}
1296
1297impl ToFloat for i64 {
1298 fn to_float(&self) -> f64 {
1299 *self as f64
1300 }
1301}
1302
1303impl ToFloat for i32 {
1304 fn to_float(&self) -> f64 {
1305 *self as f64
1306 }
1307}
1308
1309impl ToFloat for i16 {
1310 fn to_float(&self) -> f64 {
1311 *self as f64
1312 }
1313}
1314
1315impl ToFloat for i8 {
1316 fn to_float(&self) -> f64 {
1317 *self as f64
1318 }
1319}
1320
1321impl ToFloat for u8 {
1322 fn to_float(&self) -> f64 {
1323 *self as f64
1324 }
1325}
1326
1327#[cfg(test)]
1328mod tests {
1329 use std::cmp::Ordering;
1330
1331 use ahash::HashSet;
1332 use common::decimal::DecimalExt;
1333 use rand::Rng;
1334 use rand::seq::SliceRandom;
1335 use rust_decimal::Decimal;
1336 use rust_decimal::prelude::ToPrimitive;
1337
1338 use super::*;
1339
1340 #[test]
1341 fn test_decimal_ext_from_str_normalized() {
1342 let decimal = Decimal::from_str_normalized("0.0").unwrap();
1343 assert_eq!(decimal.to_string(), "0");
1344 assert_eq!(decimal.to_i64(), Some(0));
1345 assert_eq!(decimal.to_f64(), Some(0.0));
1346
1347 let decimal = Decimal::from_str_normalized("123.456").unwrap();
1348 assert_eq!(decimal.to_string(), "123.456");
1349 assert_eq!(decimal.to_i64(), Some(123));
1350 assert_eq!(decimal.to_f64(), Some(123.456));
1351
1352 let decimal =
1353 Decimal::from_str_normalized("13.5719384719384719385639856394139476937756394756")
1354 .unwrap();
1355 assert_eq!(decimal.to_string(), "13.571938471938471938563985639");
1356 assert_eq!(decimal.to_i64(), Some(13));
1357 assert_eq!(decimal.to_f64(), Some(13.571_938_471_938_472));
1358 }
1359
1360 #[test]
1361 fn test_try_float_div() {
1362 let (sum_one, count_one) = (Number::Int(5), Number::Int(2));
1363 assert_eq!(sum_one.try_float_div(count_one).unwrap(), Number::Float(2.5));
1364 let (sum_two, count_two) = (Number::Int(10), Number::Int(5));
1367 assert_eq!(sum_two.try_float_div(count_two).unwrap(), Number::Int(2));
1368
1369 let (sum_three, count_three) = (Number::Float(6.3), Number::Int(3));
1370 assert_eq!(sum_three.try_float_div(count_three).unwrap(), Number::Float(2.1));
1371 }
1372
1373 #[test]
1374 fn ord_test() {
1375 let a = Number::Float(-f64::NAN);
1376 let b = Number::Float(-f64::INFINITY);
1377 let c = Number::Float(1f64);
1378 let d = Number::Decimal(
1379 Decimal::from_str_normalized("1.0000000000000000000000000002").unwrap(),
1380 );
1381 let e = Number::Decimal(Decimal::from_str_normalized("1.1").unwrap());
1382 let f = Number::Float(1.1f64);
1383 let g = Number::Float(1.5f64);
1384 let h = Number::Decimal(Decimal::from_str_normalized("1.5").unwrap());
1385 let i = Number::Float(f64::INFINITY);
1386 let j = Number::Float(f64::NAN);
1387 let original = vec![a, b, c, d, e, f, g, h, i, j];
1388 let mut copy = original.clone();
1389 let mut rng = rand::rng();
1390 copy.shuffle(&mut rng);
1391 copy.sort();
1392 assert_eq!(original, copy);
1393 }
1394
1395 #[test]
1396 fn ord_fuzz() {
1397 fn random_number() -> Number {
1398 let mut rng = rand::rng();
1399 match rng.random_range(0..3) {
1400 0 => Number::Int(rng.random()),
1401 1 => Number::Float(f64::from_bits(rng.random())),
1402 _ => Number::Decimal(Number::Float(f64::from_bits(rng.random())).as_decimal()),
1403 }
1404 }
1405
1406 fn random_permutation(number: Number) -> Number {
1407 let mut rng = rand::rng();
1408 let value = match rng.random_range(0..4) {
1409 0 => number + Number::from(rng.random::<f64>()),
1410 1 if !matches!(number, Number::Int(i64::MIN)) => number * Number::from(-1),
1411 2 => Number::Float(number.as_float().next_down()),
1412 _ => number,
1413 };
1414 match rng.random_range(0..3) {
1415 0 => Number::Int(value.as_int()),
1416 1 => Number::Float(value.as_float()),
1417 _ => Number::Decimal(value.as_decimal()),
1418 }
1419 }
1420
1421 fn assert_partial_ord(x: Number, y: Number) {
1422 assert_eq!(x == y, x.partial_cmp(&y) == Some(Ordering::Equal), "{x:?} {y:?}");
1424
1425 assert_eq!(x.partial_cmp(&y), Some(x.cmp(&y)), "{x:?} {y:?}");
1427 }
1428
1429 fn assert_consistent(a: Number, b: Number, c: Number) {
1430 assert_partial_ord(a, b);
1431 assert_partial_ord(b, c);
1432 assert_partial_ord(c, a);
1433
1434 if a == b && b == c {
1436 assert_eq!(a, c, "{a:?} {b:?} {c:?}");
1437 }
1438 if a != b && b == c {
1439 assert_ne!(a, c, "{a:?} {b:?} {c:?}");
1440 }
1441 if a < b && b < c {
1442 assert!(a < c, "{a:?} {b:?} {c:?}");
1443 }
1444 if a > b && b > c {
1445 assert!(a > c, "{a:?} {b:?} {c:?}");
1446 }
1447
1448 assert_eq!(a == b, b == a, "{a:?} {b:?}");
1450 assert_eq!(a < b, b > a, "{a:?} {b:?}");
1451 }
1452
1453 for _ in 0..100000 {
1454 let base = random_number();
1455 let a = random_permutation(base);
1456 let b = random_permutation(a);
1457 let c = random_permutation(b);
1458 assert_consistent(a, b, c);
1459 }
1460 }
1461
1462 #[test]
1463 fn serialised_ord_test() {
1464 let ordering = [
1465 Number::from(f64::NEG_INFINITY),
1466 Number::from(f64::MIN),
1467 Number::Int(i64::MIN),
1468 Number::from(-1000),
1469 Number::from(-100),
1470 Number::from(-10),
1471 Number::from(-1.5),
1472 Number::from(-1),
1473 Number::from(0),
1474 Number::from(1),
1475 Number::from(1.5),
1476 Number::from(2),
1477 Number::from(10),
1478 Number::from(100),
1479 Number::from(1000),
1480 Number::from(i64::MAX),
1481 Number::from(f64::MAX),
1482 Number::from(f64::INFINITY),
1483 Number::from(f64::NAN),
1484 ];
1485 for window in ordering.windows(2) {
1486 let n1 = &window[0];
1487 let n2 = &window[1];
1488 assert!(n1 < n2, "{n1:?} < {n2:?} (before serialization)");
1489 let b1 = n1.as_decimal_buf();
1490 let b2 = n2.as_decimal_buf();
1491 assert!(b1 < b2, "{n1:?} < {n2:?} (after serialization) - {b1:?} < {b2:?}");
1492 let r1 = Number::from_decimal_buf(&b1).unwrap();
1493 let r2 = Number::from_decimal_buf(&b2).unwrap();
1494 assert!(r1.eq(n1), "{r1:?} = {n1:?} (after deserialization)");
1495 assert!(r2.eq(n2), "{r2:?} = {n2:?} (after deserialization)");
1496 }
1497 }
1498
1499 #[test]
1500 fn serialised_test() {
1501 let check = |numbers: &[Number]| {
1502 let mut buffers = HashSet::default();
1503 for n1 in numbers {
1504 let b = n1.as_decimal_buf();
1505 let n2 = Number::from_decimal_buf(&b).unwrap();
1506 buffers.insert(b);
1507 assert!(n1.eq(&n2), "{n1:?} = {n2:?} (after deserialization)");
1508 }
1509 assert_eq!(buffers.len(), 1, "{numbers:?}");
1510 };
1511 check(&[Number::Int(0), Number::Float(0.0), Number::Decimal(Decimal::ZERO)]);
1512 check(&[Number::Int(1), Number::Float(1.0), Number::Decimal(Decimal::ONE)]);
1513 check(&[Number::Int(-1), Number::Float(-1.0), Number::Decimal(Decimal::NEGATIVE_ONE)]);
1514 check(&[Number::Float(1.5), Number::Decimal(Decimal::from_str_normalized("1.5").unwrap())]);
1515 }
1516
1517 #[test]
1518 fn as_int_lossless_accepts_valid() {
1519 assert_eq!(Number::Int(0).as_int_lossless(), Some(0));
1520 assert_eq!(Number::Int(i64::MIN).as_int_lossless(), Some(i64::MIN));
1521 assert_eq!(Number::Int(i64::MAX).as_int_lossless(), Some(i64::MAX));
1522 assert_eq!(Number::Float(0.0).as_int_lossless(), Some(0));
1523 assert_eq!(Number::Float(-0.0).as_int_lossless(), Some(0));
1524 assert_eq!(Number::Float(7.0).as_int_lossless(), Some(7));
1525 assert_eq!(Number::Float(i64::MIN as f64).as_int_lossless(), Some(i64::MIN));
1527 assert_eq!(Number::Decimal(Decimal::ZERO).as_int_lossless(), Some(0));
1528 assert_eq!(Number::Decimal(Decimal::ONE).as_int_lossless(), Some(1));
1529 assert_eq!(Number::Decimal(Decimal::NEGATIVE_ONE).as_int_lossless(), Some(-1));
1530 }
1531
1532 #[test]
1533 fn as_int_lossless_rejects_invalid() {
1534 assert_eq!(Number::Float(1.5).as_int_lossless(), None);
1535 assert_eq!(Number::Float(-1.5).as_int_lossless(), None);
1536 assert_eq!(Number::Float(f64::NAN).as_int_lossless(), None);
1537 assert_eq!(Number::Float(f64::INFINITY).as_int_lossless(), None);
1538 assert_eq!(Number::Float(f64::NEG_INFINITY).as_int_lossless(), None);
1539 assert_eq!(Number::Float(i64::MAX as f64).as_int_lossless(), None);
1542 assert_eq!(Number::Float(1e30).as_int_lossless(), None);
1543 assert_eq!(Number::Float(-1e30).as_int_lossless(), None);
1544 assert_eq!(
1545 Number::Decimal(Decimal::from_str_normalized("1.5").unwrap()).as_int_lossless(),
1546 None,
1547 );
1548 }
1549
1550 #[test]
1551 fn as_array_index_accepts_valid() {
1552 assert_eq!(Number::Int(0).as_array_index(), Some(0));
1553 assert_eq!(Number::Int(7).as_array_index(), Some(7));
1554 assert_eq!(Number::Float(0.0).as_array_index(), Some(0));
1555 assert_eq!(Number::Float(-0.0).as_array_index(), Some(0));
1556 assert_eq!(Number::Float(3.0).as_array_index(), Some(3));
1557 assert_eq!(Number::Decimal(Decimal::ZERO).as_array_index(), Some(0));
1558 assert_eq!(Number::Decimal(Decimal::ONE).as_array_index(), Some(1));
1559 }
1560
1561 #[test]
1562 fn as_array_index_rejects_invalid() {
1563 assert_eq!(Number::Int(-1).as_array_index(), None);
1564 assert_eq!(Number::Int(i64::MIN).as_array_index(), None);
1565 assert_eq!(Number::Float(-1.0).as_array_index(), None);
1566 assert_eq!(Number::Float(1.5).as_array_index(), None);
1567 assert_eq!(Number::Float(f64::NAN).as_array_index(), None);
1568 assert_eq!(Number::Float(f64::INFINITY).as_array_index(), None);
1569 assert_eq!(Number::Float(f64::NEG_INFINITY).as_array_index(), None);
1570 assert_eq!(Number::Float(1e30).as_array_index(), None);
1572 assert_eq!(Number::Decimal(Decimal::NEGATIVE_ONE).as_array_index(), None);
1573 assert_eq!(
1574 Number::Decimal(Decimal::from_str_normalized("1.5").unwrap()).as_array_index(),
1575 None,
1576 );
1577 }
1578
1579 #[test]
1580 fn fixed_int_is_unchanged_regardless_of_precision() {
1581 assert_eq!(Number::Int(101).fixed(0), Number::Int(101));
1582 assert_eq!(Number::Int(101).fixed(2), Number::Int(101));
1583 assert_eq!(Number::Int(101).fixed(319), Number::Int(101));
1584 assert_eq!(Number::Int(-7).fixed(5), Number::Int(-7));
1585 }
1586
1587 #[test]
1588 fn fixed_float_rounds_to_requested_precision() {
1589 assert_eq!(Number::Float(101.5).fixed(2), Number::Float(101.5));
1590 assert_eq!(Number::Float(101.1111111).fixed(2), Number::Float(101.11));
1591 assert_eq!(
1595 Number::Float(2.2250738585072014e-308).fixed(319),
1596 Number::Float(2.22507385851e-308),
1597 );
1598 }
1599
1600 #[test]
1601 fn fixed_float_preserves_non_finite() {
1602 let Number::Float(nan) = Number::Float(f64::NAN).fixed(2) else {
1607 panic!("expected Number::Float(NaN)");
1608 };
1609 assert!(nan.is_nan());
1610 assert_eq!(Number::Float(f64::INFINITY).fixed(2), Number::Float(f64::INFINITY));
1611 assert_eq!(Number::Float(f64::NEG_INFINITY).fixed(2), Number::Float(f64::NEG_INFINITY));
1612 }
1613
1614 #[test]
1615 fn fixed_decimal_uses_round_dp() {
1616 let d = Decimal::from_str_normalized("1.2345").unwrap();
1617 assert_eq!(
1618 Number::Decimal(d).fixed(2),
1619 Number::Decimal(Decimal::from_str_normalized("1.23").unwrap()),
1620 );
1621 }
1622}