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 #[inline]
410 pub fn to_float(self) -> f64 {
411 match self {
412 Number::Int(v) => v as f64,
413 Number::Float(v) => v,
414 Number::Decimal(v) => v.try_into().unwrap_or_default(),
415 }
416 }
417
418 pub fn to_decimal(self) -> Decimal {
419 match self {
420 Number::Int(v) => Decimal::from(v),
421 Number::Float(v) => Decimal::from_f64(v).unwrap_or_default(),
422 Number::Decimal(v) => v,
423 }
424 }
425
426 pub fn as_decimal_buf(&self) -> Vec<u8> {
452 match self {
453 Self::Int(v) => {
454 DecimalLexEncoder::encode(D128::from(*v))
456 }
457 Self::Float(v) => {
458 DecimalLexEncoder::encode(D128::from_f64(*v))
460 }
461 Self::Decimal(v) => {
462 DecimalLexEncoder::encode(DecimalLexEncoder::to_d128(*v))
464 }
465 }
466 }
467
468 pub fn from_decimal_buf(b: &[u8]) -> Result<Self> {
485 let dec = DecimalLexEncoder::decode(b)?;
486 if dec.is_finite() {
487 match DecimalLexEncoder::to_decimal(dec) {
488 Ok(dec) => Ok(Number::Decimal(dec)),
489 Err(_) => Ok(Number::Float(dec.to_f64())),
490 }
491 } else if dec.is_nan() {
492 Ok(Number::Float(f64::NAN))
493 } else if dec.is_infinite() {
494 if dec.is_negative() {
495 Ok(Number::Float(f64::NEG_INFINITY))
496 } else {
497 Ok(Number::Float(f64::INFINITY))
498 }
499 } else {
500 bail!(Error::Serialization(format!("Invalid decimal value: {dec}")))
501 }
502 }
503
504 pub fn from_decimal_buf_kind(b: &[u8], kind: NumberKind) -> Result<Self> {
519 let dec = DecimalLexEncoder::decode(b)?;
520 match kind {
521 NumberKind::Int => {
522 ensure!(dec.is_finite(), format!("Invalid integer value: {dec}"));
523 Ok(Number::Int(dec.to_string().parse::<i64>()?))
524 }
525 NumberKind::Float => {
526 if dec.is_nan() {
527 Ok(Number::Float(f64::NAN))
528 } else if dec.is_infinite() {
529 if dec.is_negative() {
530 Ok(Number::Float(f64::NEG_INFINITY))
531 } else {
532 Ok(Number::Float(f64::INFINITY))
533 }
534 } else {
535 Ok(Number::Float(dec.to_f64()))
536 }
537 }
538 NumberKind::Decimal => {
539 ensure!(dec.is_finite(), format!("Invalid decimal value: {dec}"));
540 Ok(Number::Decimal(DecimalLexEncoder::to_decimal_exact(dec)?))
541 }
542 }
543 }
544
545 pub fn abs(self) -> Self {
550 match self {
551 Number::Int(v) => v.abs().into(),
552 Number::Float(v) => v.abs().into(),
553 Number::Decimal(v) => v.abs().into(),
554 }
555 }
556
557 pub fn checked_abs(self) -> Option<Self> {
558 match self {
559 Number::Int(v) => v.checked_abs().map(|x| x.into()),
560 Number::Float(v) => Some(v.abs().into()),
561 Number::Decimal(v) => Some(v.abs().into()),
562 }
563 }
564
565 pub fn acos(self) -> Self {
566 self.to_float().acos().into()
567 }
568
569 pub fn asin(self) -> Self {
570 self.to_float().asin().into()
571 }
572
573 pub fn atan(self) -> Self {
574 self.to_float().atan().into()
575 }
576
577 pub fn acot(self) -> Self {
578 (PI / 2.0 - self.atan().to_float()).into()
579 }
580
581 pub fn ceil(self) -> Self {
582 match self {
583 Number::Int(v) => v.into(),
584 Number::Float(v) => v.ceil().into(),
585 Number::Decimal(v) => v.ceil().into(),
586 }
587 }
588
589 pub fn clamp(self, min: Self, max: Self) -> Self {
590 match (self, min, max) {
591 (Number::Int(n), Number::Int(min), Number::Int(max)) => n.clamp(min, max).into(),
592 (Number::Decimal(n), min, max) => n.clamp(min.to_decimal(), max.to_decimal()).into(),
593 (Number::Float(n), min, max) => n.clamp(min.to_float(), max.to_float()).into(),
594 (Number::Int(n), min, max) => n.to_float().clamp(min.to_float(), max.to_float()).into(),
595 }
596 }
597
598 pub fn cos(self) -> Self {
599 self.to_float().cos().into()
600 }
601
602 pub fn cot(self) -> Self {
603 (1.0 / self.to_float().tan()).into()
604 }
605
606 pub fn deg2rad(self) -> Self {
607 self.to_float().to_radians().into()
608 }
609
610 pub fn floor(self) -> Self {
611 match self {
612 Number::Int(v) => v.into(),
613 Number::Float(v) => v.floor().into(),
614 Number::Decimal(v) => v.floor().into(),
615 }
616 }
617
618 fn lerp_f64(from: f64, to: f64, factor: f64) -> f64 {
619 from + factor * (to - from)
620 }
621
622 fn lerp_decimal(from: Decimal, to: Decimal, factor: Decimal) -> Decimal {
623 from + factor * (to - from)
624 }
625
626 pub fn lerp(self, from: Self, to: Self) -> Self {
627 match (self, from, to) {
628 (Number::Decimal(val), from, to) => {
629 Self::lerp_decimal(from.to_decimal(), to.to_decimal(), val).into()
630 }
631 (val, from, to) => {
632 Self::lerp_f64(from.to_float(), to.to_float(), val.to_float()).into()
633 }
634 }
635 }
636
637 fn repeat_f64(t: f64, m: f64) -> f64 {
638 (t - (t / m).floor() * m).clamp(0.0, m)
639 }
640
641 fn repeat_decimal(t: Decimal, m: Decimal) -> Decimal {
642 (t - (t / m).floor() * m).clamp(Decimal::ZERO, m)
643 }
644
645 pub fn lerp_angle(self, from: Self, to: Self) -> Self {
646 match (self, from, to) {
647 (Number::Decimal(val), from, to) => {
648 let from = from.to_decimal();
649 let to = to.to_decimal();
650 let mut dt = Self::repeat_decimal(to - from, Decimal::from(360));
651 if dt > Decimal::from(180) {
652 dt = Decimal::from(360) - dt;
653 }
654 Self::lerp_decimal(from, from + dt, val).into()
655 }
656 (val, from, to) => {
657 let val = val.to_float();
658 let from = from.to_float();
659 let to = to.to_float();
660 let mut dt = Self::repeat_f64(to - from, 360.0);
661 if dt > 180.0 {
662 dt = 360.0 - dt;
663 }
664 Self::lerp_f64(from, from + dt, val).into()
665 }
666 }
667 }
668
669 pub fn ln(self) -> Self {
670 self.to_float().ln().into()
671 }
672
673 pub fn log(self, base: Self) -> Self {
674 self.to_float().log(base.to_float()).into()
675 }
676
677 pub fn log2(self) -> Self {
678 self.to_float().log2().into()
679 }
680
681 pub fn log10(self) -> Self {
682 self.to_float().log10().into()
683 }
684
685 pub fn rad2deg(self) -> Self {
686 self.to_float().to_degrees().into()
687 }
688
689 pub fn round(self) -> Self {
690 match self {
691 Number::Int(v) => v.into(),
692 Number::Float(v) => v.round().into(),
693 Number::Decimal(v) => v.round().into(),
694 }
695 }
696
697 pub fn fixed(self, precision: usize) -> Number {
698 match self {
699 Number::Int(v) => v.into(),
700 Number::Float(v) => format!("{v:.precision$}")
704 .parse::<f64>()
705 .expect("formatted f64 always parses back as f64")
706 .into(),
707 Number::Decimal(v) => v.round_dp(precision as u32).into(),
708 }
709 }
710
711 pub fn sign(self) -> Self {
712 match self {
713 Number::Int(n) => n.signum().into(),
714 Number::Float(n) => n.signum().into(),
715 Number::Decimal(n) => n.signum().into(),
716 }
717 }
718
719 pub fn sin(self) -> Self {
720 self.to_float().sin().into()
721 }
722
723 pub fn tan(self) -> Self {
724 self.to_float().tan().into()
725 }
726
727 pub fn sqrt(self) -> Self {
728 match self {
729 Number::Int(v) => (v as f64).sqrt().into(),
730 Number::Float(v) => v.sqrt().into(),
731 Number::Decimal(v) => v.sqrt().unwrap_or_default().into(),
732 }
733 }
734}
735
736impl Eq for Number {}
737
738impl Ord for Number {
739 fn cmp(&self, other: &Self) -> Ordering {
740 fn total_cmp_f64(a: f64, b: f64) -> Ordering {
741 if a == 0.0 && b == 0.0 {
742 Ordering::Equal
744 } else {
745 a.total_cmp(&b)
747 }
748 }
749
750 macro_rules! greater {
752 ($f:ident) => {
753 if $f.is_sign_positive() {
754 Ordering::Greater
755 } else {
756 Ordering::Less
757 }
758 };
759 }
760
761 match (self, other) {
762 (Number::Int(v), Number::Int(w)) => v.cmp(w),
763 (Number::Float(v), Number::Float(w)) => total_cmp_f64(*v, *w),
764 (Number::Decimal(v), Number::Decimal(w)) => v.cmp(w),
765 (Number::Int(v), Number::Float(w)) => {
767 if !w.is_finite() {
769 return greater!(w).reverse();
770 }
771 let l = *v as i128;
773 let r = *w as i128;
775 match l.cmp(&r) {
777 Ordering::Equal => total_cmp_f64(0.0, w.fract()),
779 ordering => ordering,
781 }
782 }
783 (v @ Number::Float(_), w @ Number::Int(_)) => w.cmp(v).reverse(),
784 (Number::Int(v), Number::Decimal(w)) => Decimal::from(*v).cmp(w),
786 (Number::Decimal(v), Number::Int(w)) => v.cmp(&Decimal::from(*w)),
787 (Number::Float(v), Number::Decimal(w)) => {
789 macro_rules! compare_fractions {
791 ($l:ident, $r:ident) => {
792 match ($l == 0.0, $r == Decimal::ZERO) {
793 (true, true) => {
795 return Ordering::Equal;
796 }
797 (true, false) => {
799 return greater!($r).reverse();
800 }
801 (false, true) => {
803 return greater!($l);
804 }
805 (false, false) => {
807 continue;
808 }
809 }
810 };
811 }
812 if !v.is_finite() {
814 return greater!(v);
815 }
816 let l = *v as i128;
818 let Ok(r) = i128::try_from(*w) else {
820 return greater!(w).reverse();
821 };
822 match l.cmp(&r) {
824 Ordering::Equal => {
826 const SAFE_MULTIPLIER: i64 = 9_007_199_254_740_000;
841 let mut l = v.fract();
843 let mut r = w.fract();
845 for _ in 0..12 {
850 l *= SAFE_MULTIPLIER as f64;
851 r *= Decimal::new(SAFE_MULTIPLIER, 0);
852 match r.to_i64() {
855 Some(ref right) => match (l as i64).cmp(right) {
856 Ordering::Equal => {
859 l = l.fract();
861 r = r.fract();
862 compare_fractions!(l, r);
865 }
866 ordering => {
867 return ordering;
870 }
871 },
872 None => {
876 return greater!(w).reverse();
879 }
880 }
881 }
882 Ordering::Equal
887 }
888 ordering => ordering,
890 }
891 }
892 (v @ Number::Decimal(..), w @ Number::Float(..)) => w.cmp(v).reverse(),
893 }
894 }
895}
896
897impl hash::Hash for Number {
898 fn hash<H: hash::Hasher>(&self, state: &mut H) {
918 self.as_decimal_buf().hash(state);
919 }
920}
921
922impl PartialEq for Number {
923 fn eq(&self, other: &Self) -> bool {
924 fn total_eq_f64(a: f64, b: f64) -> bool {
925 a.to_bits().eq(&b.to_bits()) || (a == 0.0 && b == 0.0)
926 }
927
928 match (self, other) {
929 (Number::Int(v), Number::Int(w)) => v.eq(w),
930 (Number::Float(v), Number::Float(w)) => total_eq_f64(*v, *w),
931 (Number::Decimal(v), Number::Decimal(w)) => v.eq(w),
932 (v @ Number::Int(_), w @ Number::Float(_)) => v.cmp(w) == Ordering::Equal,
934 (v @ Number::Float(_), w @ Number::Int(_)) => v.cmp(w) == Ordering::Equal,
935 (Number::Int(v), Number::Decimal(w)) => Decimal::from(*v).eq(w),
937 (Number::Decimal(v), Number::Int(w)) => v.eq(&Decimal::from(*w)),
938 (v @ Number::Float(_), w @ Number::Decimal(_)) => v.cmp(w) == Ordering::Equal,
940 (v @ Number::Decimal(_), w @ Number::Float(_)) => v.cmp(w) == Ordering::Equal,
941 }
942 }
943}
944
945impl PartialOrd for Number {
946 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
947 Some(self.cmp(other))
948 }
949}
950
951macro_rules! impl_simple_try_op {
952 ($trt:ident, $fn:ident, $unchecked:ident, $checked:ident) => {
953 impl $trt for Number {
954 type Output = Self;
955 fn $fn(self, other: Self) -> Result<Self> {
956 Ok(match (self, other) {
957 (Number::Int(v), Number::Int(w)) => Number::Int(
958 v.$checked(w).ok_or_else(|| Error::$trt(v.to_string(), w.to_string()))?,
959 ),
960 (Number::Float(v), Number::Float(w)) => Number::Float(v.$unchecked(w)),
961 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(
962 v.$checked(w).ok_or_else(|| Error::$trt(v.to_string(), w.to_string()))?,
963 ),
964 (Number::Int(v), Number::Float(w)) => Number::Float((v as f64).$unchecked(w)),
965 (Number::Float(v), Number::Int(w)) => Number::Float(v.$unchecked(w as f64)),
966 (v, w) => Number::Decimal(
967 v.to_decimal()
968 .$checked(w.to_decimal())
969 .ok_or_else(|| Error::$trt(v.to_sql(), w.to_sql()))?,
970 ),
971 })
972 }
973 }
974 };
975}
976
977impl_simple_try_op!(TryAdd, try_add, add, checked_add);
978impl_simple_try_op!(TrySub, try_sub, sub, checked_sub);
979impl_simple_try_op!(TryMul, try_mul, mul, checked_mul);
980impl_simple_try_op!(TryDiv, try_div, div, checked_div);
981impl_simple_try_op!(TryRem, try_rem, rem, checked_rem);
982
983impl TryPow for Number {
984 type Output = Self;
985 fn try_pow(self, power: Self) -> Result<Self> {
986 Ok(match (self, power) {
987 (Self::Int(v), Self::Int(p)) => Self::Int(match v {
988 0 => match p.cmp(&0) {
989 Ordering::Less => bail!(Error::TryPow(v.to_string(), p.to_string())),
991 Ordering::Equal => 1,
993 Ordering::Greater => 0,
995 },
996 1 => 1,
998 -1 => {
999 if p % 2 == 0 {
1000 1
1002 } else {
1003 -1
1005 }
1006 }
1007 _ => p
1009 .try_into()
1010 .ok()
1011 .and_then(|p| v.checked_pow(p))
1012 .ok_or_else(|| Error::TryPow(v.to_string(), p.to_string()))?,
1013 }),
1014 (Self::Decimal(v), Self::Int(p)) => Self::Decimal(
1015 v.checked_powi(p).ok_or_else(|| Error::TryPow(v.to_string(), p.to_string()))?,
1016 ),
1017 (Self::Decimal(v), Self::Float(p)) => Self::Decimal(
1018 v.checked_powf(p).ok_or_else(|| Error::TryPow(v.to_string(), p.to_string()))?,
1019 ),
1020 (Self::Decimal(v), Self::Decimal(p)) => Self::Decimal(
1021 v.checked_powd(p).ok_or_else(|| Error::TryPow(v.to_string(), p.to_string()))?,
1022 ),
1023 (v, p) => v.as_float().powf(p.as_float()).into(),
1024 })
1025 }
1026}
1027
1028impl TryNeg for Number {
1029 type Output = Self;
1030
1031 fn try_neg(self) -> Result<Self::Output> {
1032 Ok(match self {
1033 Self::Int(n) => {
1034 Number::Int(n.checked_neg().ok_or_else(|| Error::TryNeg(n.to_string()))?)
1035 }
1036 Self::Float(n) => Number::Float(-n),
1037 Self::Decimal(n) => Number::Decimal(-n),
1038 })
1039 }
1040}
1041
1042impl TryFloatDiv for Number {
1043 type Output = Self;
1044 fn try_float_div(self, other: Self) -> Result<Self> {
1045 Ok(match (self, other) {
1046 (Number::Int(v), Number::Int(w)) => {
1047 let quotient = (v as f64).div(w as f64);
1048 if quotient.fract() != 0.0 {
1049 return Ok(Number::Float(quotient));
1050 }
1051 Number::Int(
1052 v.checked_div(w).ok_or_else(|| Error::TryDiv(v.to_string(), w.to_string()))?,
1053 )
1054 }
1055 (v, w) => v.try_div(w)?,
1056 })
1057 }
1058}
1059
1060impl ops::Add for Number {
1061 type Output = Self;
1062 fn add(self, other: Self) -> Self {
1063 match (self, other) {
1064 (Number::Int(v), Number::Int(w)) => Number::Int(v + w),
1065 (Number::Float(v), Number::Float(w)) => Number::Float(v + w),
1066 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v + w),
1067 (Number::Int(v), Number::Float(w)) => Number::Float(v as f64 + w),
1068 (Number::Float(v), Number::Int(w)) => Number::Float(v + w as f64),
1069 (v, w) => Number::from(v.as_decimal() + w.as_decimal()),
1070 }
1071 }
1072}
1073
1074impl<'b> ops::Add<&'b Number> for &Number {
1075 type Output = Number;
1076 fn add(self, other: &'b Number) -> Number {
1077 match (self, other) {
1078 (Number::Int(v), Number::Int(w)) => Number::Int(v + w),
1079 (Number::Float(v), Number::Float(w)) => Number::Float(v + w),
1080 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v + w),
1081 (Number::Int(v), Number::Float(w)) => Number::Float(*v as f64 + w),
1082 (Number::Float(v), Number::Int(w)) => Number::Float(v + *w as f64),
1083 (v, w) => Number::from(v.to_decimal() + w.to_decimal()),
1084 }
1085 }
1086}
1087
1088impl ops::Sub for Number {
1089 type Output = Self;
1090 fn sub(self, other: Self) -> Self {
1091 match (self, other) {
1092 (Number::Int(v), Number::Int(w)) => Number::Int(v - w),
1093 (Number::Float(v), Number::Float(w)) => Number::Float(v - w),
1094 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v - w),
1095 (Number::Int(v), Number::Float(w)) => Number::Float(v as f64 - w),
1096 (Number::Float(v), Number::Int(w)) => Number::Float(v - w as f64),
1097 (v, w) => Number::from(v.as_decimal() - w.as_decimal()),
1098 }
1099 }
1100}
1101
1102impl<'b> ops::Sub<&'b Number> for &Number {
1103 type Output = Number;
1104 fn sub(self, other: &'b Number) -> Number {
1105 match (self, other) {
1106 (Number::Int(v), Number::Int(w)) => Number::Int(v - w),
1107 (Number::Float(v), Number::Float(w)) => Number::Float(v - w),
1108 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v - w),
1109 (Number::Int(v), Number::Float(w)) => Number::Float(*v as f64 - w),
1110 (Number::Float(v), Number::Int(w)) => Number::Float(v - *w as f64),
1111 (v, w) => Number::from(v.to_decimal() - w.to_decimal()),
1112 }
1113 }
1114}
1115
1116impl ops::Mul for Number {
1117 type Output = Self;
1118 fn mul(self, other: Self) -> Self {
1119 match (self, other) {
1120 (Number::Int(v), Number::Int(w)) => Number::Int(v * w),
1121 (Number::Float(v), Number::Float(w)) => Number::Float(v * w),
1122 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v * w),
1123 (Number::Int(v), Number::Float(w)) => Number::Float(v as f64 * w),
1124 (Number::Float(v), Number::Int(w)) => Number::Float(v * w as f64),
1125 (v, w) => Number::from(v.as_decimal() * w.as_decimal()),
1126 }
1127 }
1128}
1129
1130impl<'b> ops::Mul<&'b Number> for &Number {
1131 type Output = Number;
1132 fn mul(self, other: &'b Number) -> Number {
1133 match (self, other) {
1134 (Number::Int(v), Number::Int(w)) => Number::Int(v * w),
1135 (Number::Float(v), Number::Float(w)) => Number::Float(v * w),
1136 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v * w),
1137 (Number::Int(v), Number::Float(w)) => Number::Float(*v as f64 * w),
1138 (Number::Float(v), Number::Int(w)) => Number::Float(v * *w as f64),
1139 (v, w) => Number::from(v.to_decimal() * w.to_decimal()),
1140 }
1141 }
1142}
1143
1144impl ops::Div for Number {
1145 type Output = Self;
1146 fn div(self, other: Self) -> Self {
1147 match (self, other) {
1148 (Number::Int(v), Number::Int(w)) => Number::Int(v / w),
1149 (Number::Float(v), Number::Float(w)) => Number::Float(v / w),
1150 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v / w),
1151 (Number::Int(v), Number::Float(w)) => Number::Float(v as f64 / w),
1152 (Number::Float(v), Number::Int(w)) => Number::Float(v / w as f64),
1153 (v, w) => Number::from(v.as_decimal() / w.as_decimal()),
1154 }
1155 }
1156}
1157
1158impl<'b> ops::Div<&'b Number> for &Number {
1159 type Output = Number;
1160 fn div(self, other: &'b Number) -> Number {
1161 match (self, other) {
1162 (Number::Int(v), Number::Int(w)) => Number::Int(v / w),
1163 (Number::Float(v), Number::Float(w)) => Number::Float(v / w),
1164 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v / w),
1165 (Number::Int(v), Number::Float(w)) => Number::Float(*v as f64 / w),
1166 (Number::Float(v), Number::Int(w)) => Number::Float(v / *w as f64),
1167 (v, w) => Number::from(v.to_decimal() / w.to_decimal()),
1168 }
1169 }
1170}
1171
1172impl Neg for Number {
1173 type Output = Self;
1174
1175 fn neg(self) -> Self::Output {
1176 match self {
1177 Self::Int(n) => Number::Int(-n),
1178 Self::Float(n) => Number::Float(-n),
1179 Self::Decimal(n) => Number::Decimal(-n),
1180 }
1181 }
1182}
1183
1184impl Sum<Self> for Number {
1187 fn sum<I>(iter: I) -> Number
1188 where
1189 I: Iterator<Item = Self>,
1190 {
1191 iter.fold(Number::Int(0), |a, b| a + b)
1192 }
1193}
1194
1195impl<'a> Sum<&'a Self> for Number {
1196 fn sum<I>(iter: I) -> Number
1197 where
1198 I: Iterator<Item = &'a Self>,
1199 {
1200 iter.fold(Number::Int(0), |a, b| &a + b)
1201 }
1202}
1203
1204impl Product<Self> for Number {
1205 fn product<I>(iter: I) -> Number
1206 where
1207 I: Iterator<Item = Self>,
1208 {
1209 iter.fold(Number::Int(1), |a, b| a * b)
1210 }
1211}
1212
1213impl<'a> Product<&'a Self> for Number {
1214 fn product<I>(iter: I) -> Number
1215 where
1216 I: Iterator<Item = &'a Self>,
1217 {
1218 iter.fold(Number::Int(1), |a, b| &a * b)
1219 }
1220}
1221
1222pub struct Sorted<T>(pub T);
1223
1224pub trait Sort {
1225 fn sorted(&mut self) -> Sorted<&Self>
1226 where
1227 Self: Sized;
1228}
1229
1230impl Sort for Vec<Number> {
1231 fn sorted(&mut self) -> Sorted<&Vec<Number>> {
1232 self.sort();
1233 Sorted(self)
1234 }
1235}
1236
1237impl ToFloat for Number {
1238 #[inline]
1239 fn to_float(&self) -> f64 {
1240 Number::to_float(*self)
1241 }
1242}
1243
1244impl Encode<()> for Number {
1245 fn encode<W: std::io::Write>(
1246 &self,
1247 w: &mut storekey::Writer<W>,
1248 ) -> std::result::Result<(), storekey::EncodeError> {
1249 let slice = self.as_decimal_buf();
1250 w.write_slice(&slice)?;
1251 let kind = match self {
1252 Number::Int(_) => NumberKind::Int,
1253 Number::Float(_) => NumberKind::Float,
1254 Number::Decimal(_) => NumberKind::Decimal,
1255 };
1256 Encode::<()>::encode(&kind, w)?;
1257 Ok(())
1258 }
1259}
1260
1261impl<'de> BorrowDecode<'de, ()> for Number {
1262 fn borrow_decode(
1263 r: &mut storekey::BorrowReader<'de>,
1264 ) -> std::result::Result<Self, storekey::DecodeError> {
1265 let slice = r.read_cow()?;
1266 let kind: NumberKind = BorrowDecode::<'de, ()>::borrow_decode(r)?;
1267 Number::from_decimal_buf_kind(slice.as_ref(), kind)
1268 .map_err(|_| storekey::DecodeError::InvalidFormat)
1269 }
1270}
1271
1272impl Encode<IndexFormat> for Number {
1273 fn encode<W: std::io::Write>(
1274 &self,
1275 w: &mut storekey::Writer<W>,
1276 ) -> std::result::Result<(), storekey::EncodeError> {
1277 let slice = self.as_decimal_buf();
1278 w.write_slice(&slice)
1279 }
1280}
1281
1282impl<'de> BorrowDecode<'de, IndexFormat> for Number {
1283 fn borrow_decode(
1284 r: &mut storekey::BorrowReader<'de>,
1285 ) -> std::result::Result<Self, storekey::DecodeError> {
1286 let slice = r.read_cow()?;
1287 Number::from_decimal_buf(slice.as_ref()).map_err(|_| storekey::DecodeError::InvalidFormat)
1288 }
1289}
1290
1291pub trait ToFloat {
1295 fn to_float(&self) -> f64;
1296}
1297
1298impl ToFloat for f64 {
1299 #[inline]
1300 fn to_float(&self) -> f64 {
1301 *self
1302 }
1303}
1304
1305impl ToFloat for f32 {
1306 #[inline]
1307 fn to_float(&self) -> f64 {
1308 *self as f64
1309 }
1310}
1311
1312impl ToFloat for half::f16 {
1313 #[inline]
1314 fn to_float(&self) -> f64 {
1315 f64::from(*self)
1316 }
1317}
1318
1319impl ToFloat for i64 {
1320 #[inline]
1321 fn to_float(&self) -> f64 {
1322 *self as f64
1323 }
1324}
1325
1326impl ToFloat for i32 {
1327 #[inline]
1328 fn to_float(&self) -> f64 {
1329 *self as f64
1330 }
1331}
1332
1333impl ToFloat for i16 {
1334 #[inline]
1335 fn to_float(&self) -> f64 {
1336 *self as f64
1337 }
1338}
1339
1340impl ToFloat for i8 {
1341 #[inline]
1342 fn to_float(&self) -> f64 {
1343 *self as f64
1344 }
1345}
1346
1347impl ToFloat for u8 {
1348 #[inline]
1349 fn to_float(&self) -> f64 {
1350 *self as f64
1351 }
1352}
1353
1354#[cfg(test)]
1355mod tests {
1356 use std::cmp::Ordering;
1357
1358 use ahash::HashSet;
1359 use common::decimal::DecimalExt;
1360 use rand::Rng;
1361 use rand::seq::SliceRandom;
1362 use rust_decimal::Decimal;
1363 use rust_decimal::prelude::ToPrimitive;
1364
1365 use super::*;
1366
1367 #[test]
1368 fn test_decimal_ext_from_str_normalized() {
1369 let decimal = Decimal::from_str_normalized("0.0").unwrap();
1370 assert_eq!(decimal.to_string(), "0");
1371 assert_eq!(decimal.to_i64(), Some(0));
1372 assert_eq!(decimal.to_f64(), Some(0.0));
1373
1374 let decimal = Decimal::from_str_normalized("123.456").unwrap();
1375 assert_eq!(decimal.to_string(), "123.456");
1376 assert_eq!(decimal.to_i64(), Some(123));
1377 assert_eq!(decimal.to_f64(), Some(123.456));
1378
1379 let decimal =
1380 Decimal::from_str_normalized("13.5719384719384719385639856394139476937756394756")
1381 .unwrap();
1382 assert_eq!(decimal.to_string(), "13.571938471938471938563985639");
1383 assert_eq!(decimal.to_i64(), Some(13));
1384 assert_eq!(decimal.to_f64(), Some(13.571_938_471_938_472));
1385 }
1386
1387 #[test]
1388 fn test_try_float_div() {
1389 let (sum_one, count_one) = (Number::Int(5), Number::Int(2));
1390 assert_eq!(sum_one.try_float_div(count_one).unwrap(), Number::Float(2.5));
1391 let (sum_two, count_two) = (Number::Int(10), Number::Int(5));
1394 assert_eq!(sum_two.try_float_div(count_two).unwrap(), Number::Int(2));
1395
1396 let (sum_three, count_three) = (Number::Float(6.3), Number::Int(3));
1397 assert_eq!(sum_three.try_float_div(count_three).unwrap(), Number::Float(2.1));
1398 }
1399
1400 #[test]
1401 fn ord_test() {
1402 let a = Number::Float(-f64::NAN);
1403 let b = Number::Float(-f64::INFINITY);
1404 let c = Number::Float(1f64);
1405 let d = Number::Decimal(
1406 Decimal::from_str_normalized("1.0000000000000000000000000002").unwrap(),
1407 );
1408 let e = Number::Decimal(Decimal::from_str_normalized("1.1").unwrap());
1409 let f = Number::Float(1.1f64);
1410 let g = Number::Float(1.5f64);
1411 let h = Number::Decimal(Decimal::from_str_normalized("1.5").unwrap());
1412 let i = Number::Float(f64::INFINITY);
1413 let j = Number::Float(f64::NAN);
1414 let original = vec![a, b, c, d, e, f, g, h, i, j];
1415 let mut copy = original.clone();
1416 let mut rng = rand::rng();
1417 copy.shuffle(&mut rng);
1418 copy.sort();
1419 assert_eq!(original, copy);
1420 }
1421
1422 #[test]
1423 fn ord_fuzz() {
1424 fn random_number() -> Number {
1425 let mut rng = rand::rng();
1426 match rng.random_range(0..3) {
1427 0 => Number::Int(rng.random()),
1428 1 => Number::Float(f64::from_bits(rng.random())),
1429 _ => Number::Decimal(Number::Float(f64::from_bits(rng.random())).as_decimal()),
1430 }
1431 }
1432
1433 fn random_permutation(number: Number) -> Number {
1434 let mut rng = rand::rng();
1435 let value = match rng.random_range(0..4) {
1436 0 => number + Number::from(rng.random::<f64>()),
1437 1 if !matches!(number, Number::Int(i64::MIN)) => number * Number::from(-1),
1438 2 => Number::Float(number.as_float().next_down()),
1439 _ => number,
1440 };
1441 match rng.random_range(0..3) {
1442 0 => Number::Int(value.as_int()),
1443 1 => Number::Float(value.as_float()),
1444 _ => Number::Decimal(value.as_decimal()),
1445 }
1446 }
1447
1448 fn assert_partial_ord(x: Number, y: Number) {
1449 assert_eq!(x == y, x.partial_cmp(&y) == Some(Ordering::Equal), "{x:?} {y:?}");
1451
1452 assert_eq!(x.partial_cmp(&y), Some(x.cmp(&y)), "{x:?} {y:?}");
1454 }
1455
1456 fn assert_consistent(a: Number, b: Number, c: Number) {
1457 assert_partial_ord(a, b);
1458 assert_partial_ord(b, c);
1459 assert_partial_ord(c, a);
1460
1461 if a == b && b == c {
1463 assert_eq!(a, c, "{a:?} {b:?} {c:?}");
1464 }
1465 if a != b && b == c {
1466 assert_ne!(a, c, "{a:?} {b:?} {c:?}");
1467 }
1468 if a < b && b < c {
1469 assert!(a < c, "{a:?} {b:?} {c:?}");
1470 }
1471 if a > b && b > c {
1472 assert!(a > c, "{a:?} {b:?} {c:?}");
1473 }
1474
1475 assert_eq!(a == b, b == a, "{a:?} {b:?}");
1477 assert_eq!(a < b, b > a, "{a:?} {b:?}");
1478 }
1479
1480 for _ in 0..100000 {
1481 let base = random_number();
1482 let a = random_permutation(base);
1483 let b = random_permutation(a);
1484 let c = random_permutation(b);
1485 assert_consistent(a, b, c);
1486 }
1487 }
1488
1489 #[test]
1490 fn serialised_ord_test() {
1491 let ordering = [
1492 Number::from(f64::NEG_INFINITY),
1493 Number::from(f64::MIN),
1494 Number::Int(i64::MIN),
1495 Number::from(-1000),
1496 Number::from(-100),
1497 Number::from(-10),
1498 Number::from(-1.5),
1499 Number::from(-1),
1500 Number::from(0),
1501 Number::from(1),
1502 Number::from(1.5),
1503 Number::from(2),
1504 Number::from(10),
1505 Number::from(100),
1506 Number::from(1000),
1507 Number::from(i64::MAX),
1508 Number::from(f64::MAX),
1509 Number::from(f64::INFINITY),
1510 Number::from(f64::NAN),
1511 ];
1512 for window in ordering.windows(2) {
1513 let n1 = &window[0];
1514 let n2 = &window[1];
1515 assert!(n1 < n2, "{n1:?} < {n2:?} (before serialization)");
1516 let b1 = n1.as_decimal_buf();
1517 let b2 = n2.as_decimal_buf();
1518 assert!(b1 < b2, "{n1:?} < {n2:?} (after serialization) - {b1:?} < {b2:?}");
1519 let r1 = Number::from_decimal_buf(&b1).unwrap();
1520 let r2 = Number::from_decimal_buf(&b2).unwrap();
1521 assert!(r1.eq(n1), "{r1:?} = {n1:?} (after deserialization)");
1522 assert!(r2.eq(n2), "{r2:?} = {n2:?} (after deserialization)");
1523 }
1524 }
1525
1526 #[test]
1527 fn serialised_test() {
1528 let check = |numbers: &[Number]| {
1529 let mut buffers = HashSet::default();
1530 for n1 in numbers {
1531 let b = n1.as_decimal_buf();
1532 let n2 = Number::from_decimal_buf(&b).unwrap();
1533 buffers.insert(b);
1534 assert!(n1.eq(&n2), "{n1:?} = {n2:?} (after deserialization)");
1535 }
1536 assert_eq!(buffers.len(), 1, "{numbers:?}");
1537 };
1538 check(&[Number::Int(0), Number::Float(0.0), Number::Decimal(Decimal::ZERO)]);
1539 check(&[Number::Int(1), Number::Float(1.0), Number::Decimal(Decimal::ONE)]);
1540 check(&[Number::Int(-1), Number::Float(-1.0), Number::Decimal(Decimal::NEGATIVE_ONE)]);
1541 check(&[Number::Float(1.5), Number::Decimal(Decimal::from_str_normalized("1.5").unwrap())]);
1542 }
1543
1544 #[test]
1545 fn as_int_lossless_accepts_valid() {
1546 assert_eq!(Number::Int(0).as_int_lossless(), Some(0));
1547 assert_eq!(Number::Int(i64::MIN).as_int_lossless(), Some(i64::MIN));
1548 assert_eq!(Number::Int(i64::MAX).as_int_lossless(), Some(i64::MAX));
1549 assert_eq!(Number::Float(0.0).as_int_lossless(), Some(0));
1550 assert_eq!(Number::Float(-0.0).as_int_lossless(), Some(0));
1551 assert_eq!(Number::Float(7.0).as_int_lossless(), Some(7));
1552 assert_eq!(Number::Float(i64::MIN as f64).as_int_lossless(), Some(i64::MIN));
1554 assert_eq!(Number::Decimal(Decimal::ZERO).as_int_lossless(), Some(0));
1555 assert_eq!(Number::Decimal(Decimal::ONE).as_int_lossless(), Some(1));
1556 assert_eq!(Number::Decimal(Decimal::NEGATIVE_ONE).as_int_lossless(), Some(-1));
1557 }
1558
1559 #[test]
1560 fn as_int_lossless_rejects_invalid() {
1561 assert_eq!(Number::Float(1.5).as_int_lossless(), None);
1562 assert_eq!(Number::Float(-1.5).as_int_lossless(), None);
1563 assert_eq!(Number::Float(f64::NAN).as_int_lossless(), None);
1564 assert_eq!(Number::Float(f64::INFINITY).as_int_lossless(), None);
1565 assert_eq!(Number::Float(f64::NEG_INFINITY).as_int_lossless(), None);
1566 assert_eq!(Number::Float(i64::MAX as f64).as_int_lossless(), None);
1569 assert_eq!(Number::Float(1e30).as_int_lossless(), None);
1570 assert_eq!(Number::Float(-1e30).as_int_lossless(), None);
1571 assert_eq!(
1572 Number::Decimal(Decimal::from_str_normalized("1.5").unwrap()).as_int_lossless(),
1573 None,
1574 );
1575 }
1576
1577 #[test]
1578 fn as_array_index_accepts_valid() {
1579 assert_eq!(Number::Int(0).as_array_index(), Some(0));
1580 assert_eq!(Number::Int(7).as_array_index(), Some(7));
1581 assert_eq!(Number::Float(0.0).as_array_index(), Some(0));
1582 assert_eq!(Number::Float(-0.0).as_array_index(), Some(0));
1583 assert_eq!(Number::Float(3.0).as_array_index(), Some(3));
1584 assert_eq!(Number::Decimal(Decimal::ZERO).as_array_index(), Some(0));
1585 assert_eq!(Number::Decimal(Decimal::ONE).as_array_index(), Some(1));
1586 }
1587
1588 #[test]
1589 fn as_array_index_rejects_invalid() {
1590 assert_eq!(Number::Int(-1).as_array_index(), None);
1591 assert_eq!(Number::Int(i64::MIN).as_array_index(), None);
1592 assert_eq!(Number::Float(-1.0).as_array_index(), None);
1593 assert_eq!(Number::Float(1.5).as_array_index(), None);
1594 assert_eq!(Number::Float(f64::NAN).as_array_index(), None);
1595 assert_eq!(Number::Float(f64::INFINITY).as_array_index(), None);
1596 assert_eq!(Number::Float(f64::NEG_INFINITY).as_array_index(), None);
1597 assert_eq!(Number::Float(1e30).as_array_index(), None);
1599 assert_eq!(Number::Decimal(Decimal::NEGATIVE_ONE).as_array_index(), None);
1600 assert_eq!(
1601 Number::Decimal(Decimal::from_str_normalized("1.5").unwrap()).as_array_index(),
1602 None,
1603 );
1604 }
1605
1606 #[test]
1607 fn fixed_int_is_unchanged_regardless_of_precision() {
1608 assert_eq!(Number::Int(101).fixed(0), Number::Int(101));
1609 assert_eq!(Number::Int(101).fixed(2), Number::Int(101));
1610 assert_eq!(Number::Int(101).fixed(319), Number::Int(101));
1611 assert_eq!(Number::Int(-7).fixed(5), Number::Int(-7));
1612 }
1613
1614 #[test]
1615 fn fixed_float_rounds_to_requested_precision() {
1616 assert_eq!(Number::Float(101.5).fixed(2), Number::Float(101.5));
1617 assert_eq!(Number::Float(101.1111111).fixed(2), Number::Float(101.11));
1618 assert_eq!(
1622 Number::Float(2.2250738585072014e-308).fixed(319),
1623 Number::Float(2.22507385851e-308),
1624 );
1625 }
1626
1627 #[test]
1628 fn fixed_float_preserves_non_finite() {
1629 let Number::Float(nan) = Number::Float(f64::NAN).fixed(2) else {
1634 panic!("expected Number::Float(NaN)");
1635 };
1636 assert!(nan.is_nan());
1637 assert_eq!(Number::Float(f64::INFINITY).fixed(2), Number::Float(f64::INFINITY));
1638 assert_eq!(Number::Float(f64::NEG_INFINITY).fixed(2), Number::Float(f64::NEG_INFINITY));
1639 }
1640
1641 #[test]
1642 fn fixed_decimal_uses_round_dp() {
1643 let d = Decimal::from_str_normalized("1.2345").unwrap();
1644 assert_eq!(
1645 Number::Decimal(d).fixed(2),
1646 Number::Decimal(Decimal::from_str_normalized("1.23").unwrap()),
1647 );
1648 }
1649
1650 fn through_record_key(n: &Number) -> (Vec<u8>, Number) {
1652 let key = storekey::encode_vec(n).unwrap();
1653 let back = storekey::decode_borrow::<Number>(&key)
1654 .unwrap_or_else(|e| panic!("the key of {n:?} does not decode: {e}"));
1655 (key, back)
1656 }
1657
1658 fn assert_float_key_round_trips(f: f64) {
1662 let (key, back) = through_record_key(&Number::Float(f));
1663 let Number::Float(g) = back else {
1664 panic!("{f:e} decoded as {back:?}, not a float");
1665 };
1666 let same =
1668 g.to_bits() == f.to_bits() || (f == 0.0 && g == 0.0) || (f.is_nan() && g.is_nan());
1669 assert!(same, "{f:e} decoded as {g:e}");
1670 assert_eq!(
1671 through_record_key(&Number::Float(g)).0,
1672 key,
1673 "{f:e} does not re-encode to its key"
1674 );
1675 }
1676
1677 #[test]
1678 fn a_float_key_decodes_to_the_float_it_was_written_from() {
1679 for f in [
1680 0.0,
1681 -0.0,
1682 0.1,
1683 0.2 + 0.1,
1684 1.5,
1685 5.0,
1686 1.6330027767028172,
1687 std::f64::consts::PI,
1688 9007199254740994.0,
1689 f64::EPSILON,
1690 f64::INFINITY,
1691 f64::NEG_INFINITY,
1692 f64::NAN,
1693 1e28,
1695 7.9e28,
1696 1e29,
1697 1e30,
1698 -1e30,
1699 1e300,
1700 f64::MAX,
1701 f64::MIN,
1702 1e-6,
1704 1e-7,
1705 5.6527459748369866e-8,
1706 1e-20,
1707 1e-28,
1708 1e-29,
1709 1e-300,
1710 f64::MIN_POSITIVE,
1711 5e-324,
1712 ] {
1713 assert_float_key_round_trips(f);
1714 }
1715 for e in -324..=308 {
1717 for m in ["1", "9.999999999999999", "1.2345678901234567", "5", "7.1"] {
1718 if let Ok(f) = format!("{m}e{e}").parse::<f64>() {
1719 assert_float_key_round_trips(f);
1720 assert_float_key_round_trips(-f);
1721 }
1722 }
1723 }
1724 let mut rng = rand::rng();
1725 for _ in 0..20_000 {
1726 assert_float_key_round_trips(f64::from_bits(rng.random()));
1727 assert_float_key_round_trips(rng.random::<f64>());
1728 assert_float_key_round_trips(
1729 rng.random::<f64>() * 10f64.powi(rng.random_range(-30..30)),
1730 );
1731 }
1732 }
1733
1734 #[test]
1735 fn a_decimal_key_decodes_to_the_decimal_it_was_written_from() {
1736 fn assert_round_trips(d: Decimal) {
1737 let (key, back) = through_record_key(&Number::Decimal(d));
1738 assert!(matches!(back, Number::Decimal(g) if g == d), "{d} decoded as {back:?}");
1739 assert_eq!(through_record_key(&back).0, key, "{d} does not re-encode to its key");
1740 }
1741 for d in [
1742 "0",
1743 "1",
1744 "-1",
1745 "1.5",
1746 "1.50",
1747 "100.000",
1748 "1000000",
1749 "0.0000001",
1751 "-0.0000000121",
1752 "0.0000000000000000000000000001",
1753 "7.9228162514264337593543950335",
1754 "79228162514264337593543950335",
1755 "-79228162514264337593543950335",
1756 ] {
1757 assert_round_trips(d.parse().unwrap());
1758 }
1759 assert_round_trips(Decimal::MAX);
1760 assert_round_trips(Decimal::MIN);
1761 let mut rng = rand::rng();
1762 for _ in 0..20_000 {
1763 let mantissa = (rng.random::<u128>() >> rng.random_range(32..128)) as i128;
1764 let mantissa = if rng.random() {
1765 -mantissa
1766 } else {
1767 mantissa
1768 };
1769 assert_round_trips(Decimal::from_i128_with_scale(mantissa, rng.random_range(0..=28)));
1770 }
1771 }
1772
1773 #[test]
1774 fn an_int_key_decodes_to_the_int_it_was_written_from() {
1775 let mut ints = vec![0, 1, -1, i64::MAX, i64::MIN];
1776 for e in 0..19 {
1777 let p = 10i64.pow(e);
1778 ints.extend([p, -p, p - 1, p + 1, 5 * p]);
1779 }
1780 for i in ints {
1781 let (key, back) = through_record_key(&Number::Int(i));
1782 assert!(matches!(back, Number::Int(g) if g == i), "{i} decoded as {back:?}");
1783 assert_eq!(through_record_key(&back).0, key);
1784 }
1785 }
1786
1787 #[test]
1791 fn the_stored_bytes_of_a_numeric_key_are_frozen() {
1792 fn hex(b: &[u8]) -> String {
1793 b.iter().map(|b| format!("{b:02x}")).collect()
1794 }
1795 for (n, stored) in [
1796 (Number::Float(1e30), "a01937211111111111111112a995735949767001000003"),
1797 (Number::Float(0.1), "a01918211111111111111116662226234236893813229001000003"),
1798 (Number::Float(5e-324), "a017d35a51767569523576552876798a3979332483480f01000003"),
1799 (Number::Decimal("0.0000001".parse().unwrap()), "a019122001000004"),
1800 (Number::Int(1000), "a0191c21110f01000002"),
1801 ] {
1802 let key = storekey::encode_vec(&n).unwrap();
1803 assert_eq!(hex(&key), stored, "{n:?}");
1804 }
1805 }
1806}