Skip to main content

surrealdb_expr/val/
number.rs

1//! Numeric value type used throughout SurrealDB.
2//!
3//! This module defines Number, a discriminated union over Int (i64), Float (f64),
4//! and Decimal (rust_decimal::Decimal), and implements arithmetic, comparison,
5//! and conversions. For storage in index keys, Numbers are serialized with a
6//! canonical, lexicographic encoding (via expr::decimal::DecimalLexEncoder)
7//! so that byte-wise ordering matches numeric ordering and numerically-equal
8//! values across variants normalize to identical bytes.
9//!
10//! Key points:
11//! - Ordering: PartialOrd/Ord behavior aims to reflect mathematical ordering across variants; for
12//!   index keys we rely on DecimalLexEncoder to preserve ordering at the byte level.
13//! - Normalization in keys: 0 (Int), 0.0 (Float) and 0dec (Decimal) encode to the same byte
14//!   sequence for keys, so UNIQUE indexes treat them as equal.
15//! - Special float values: NaN, +∞ and −∞ are given fixed encodings that fit in the total ordering
16//!   used by keys (see DecimalLexEncoder docs).
17//! - Stream-friendly: the numeric encoding contains an in-band terminator and appends a 0x00 byte,
18//!   allowing concatenation in composite keys without ambiguity during decoding.
19
20use 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	// Add new variants here
56}
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
76// Only integer types that always fit losslessly into an i64 are converted
77// infallibly here. Wider types are handled below so they store the value
78// correctly (as a Decimal when it exceeds i64) instead of truncating.
79from_prim_ints!(i8, i16, i32, i64, isize, u8, u16, u32);
80
81// `u64`/`usize` can exceed i64::MAX but always fit within Decimal's 96-bit
82// mantissa, so the conversion is lossless and infallible: store as an Int when
83// it fits, otherwise as a Decimal.
84impl 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		// usize is at most 64 bits wide on every supported target.
96		Self::from(i as u64)
97	}
98}
99
100// `i128`/`u128` can exceed Decimal's range (2^96), so the conversion is
101// fallible: store as an Int when it fits in i64, otherwise as a Decimal, and
102// error rather than silently truncate when the value is too large for either.
103impl 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		// Attempt to parse as i64
171		match s.parse::<i64>() {
172			// Store it as an i64
173			Ok(v) => Ok(Self::Int(v)),
174			// It wasn't parsed as a i64 so parse as a float
175			_ => match s.parse::<f64>() {
176				// Store it as a float
177				Ok(v) => Ok(Self::Float(v)),
178				// It wasn't parsed as a number
179				_ => Err(()),
180			},
181		}
182	}
183}
184
185macro_rules! try_into_prim {
186	// TODO: switch to one argument per int once https://github.com/rust-lang/rust/issues/29599 is stable
187	($($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					// Special case: Infinity, -Infinity or NaN
252					Some(special) => write_sql!(f, sql_fmt, "{}", special),
253					// Regular float: add f to distinguish between int and float
254					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	// -----------------------------------
264	// Constants
265	// -----------------------------------
266
267	pub const NAN: Number = Number::Float(f64::NAN);
268
269	// -----------------------------------
270	// Simple number detection
271	// -----------------------------------
272
273	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	// -----------------------------------
298	// Simple conversion of number
299	// -----------------------------------
300
301	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	// -----------------------------------
334	// Complex conversion of number
335	// -----------------------------------
336
337	/// Convert to an `i64` only when the value round-trips exactly.
338	///
339	/// Returns `None` for any value that does not represent an exact integer
340	/// within `i64` range — including NaN, infinities, fractional values, and
341	/// out-of-range magnitudes. Lossy `as` casts (which saturate or truncate
342	/// silently) are deliberately avoided so callers can reject the input
343	/// rather than write a wrong value.
344	pub fn as_int_lossless(self) -> Option<i64> {
345		match self {
346			Number::Int(v) => Some(v),
347			Number::Float(v) => {
348				// `i64::MAX as f64` rounds up to 2^63 (the next representable
349				// f64), which is *not* in i64 range. `-(i64::MIN as f64)` is
350				// exactly 2^63 and is the right exclusive upper bound.
351				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	/// Convert to a `usize` suitable for array indexing.
371	///
372	/// Returns `None` for any value that does not represent an exact
373	/// non-negative integer within `usize` range — including negatives,
374	/// NaN, infinities, fractional values, and out-of-range magnitudes.
375	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				// `f64 as usize` saturates above `usize::MAX`; round-trip back
383				// through f64 to reject any value that couldn't be represented
384				// exactly.
385				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	/// The number as an `f64`. Inlined so that per-component loops in other
407	/// crates (the vector functions' norms and distances) compile it into the
408	/// loop whatever link-time optimisation decides.
409	#[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	/// Converts this Number to a lexicographically ordered byte buffer.
427	///
428	/// This serializes the Number using DecimalLexEncoder so that byte-wise
429	/// comparison preserves numeric ordering. This is essential for database
430	/// indexes where key bytes must sort the same way as their numeric values.
431	///
432	/// Ordering guarantees:
433	/// - If `a < b` numerically, then `a.as_decimal_buf() < b.as_decimal_buf()` lexicographically.
434	///
435	/// Encoding format:
436	/// - A leading class/marker byte indicates zero, finite negative, finite positive, negative
437	///   infinity, positive infinity, or NaN.
438	/// - Two bytes encode a biased scale for finite values.
439	/// - Packed base-10 digits follow (2 digits per byte), with an in-band terminator ensured by
440	///   the packing scheme; the encoder also appends a trailing 0x00 terminator byte for
441	///   stream-friendly decoding.
442	///
443	/// Notes:
444	/// - There is no extra "type marker" for Int/Float/Decimal variants; all variants are
445	///   normalized through D128 for ordering.
446	/// - Special float values (NaN/±∞) are mapped to fixed encodings at the extremes to preserve a
447	///   total order.
448	///
449	/// Returns an ordered byte buffer or an error if Decimal conversion fails
450	/// for Decimal variant values.
451	pub fn as_decimal_buf(&self) -> Vec<u8> {
452		match self {
453			Self::Int(v) => {
454				// Convert integer to decimal for consistent encoding across all numeric types
455				DecimalLexEncoder::encode(D128::from(*v))
456			}
457			Self::Float(v) => {
458				// Convert float to decimal for lexicographic encoding
459				DecimalLexEncoder::encode(D128::from_f64(*v))
460			}
461			Self::Decimal(v) => {
462				// Direct encoding of decimal values using lexicographic encoder
463				DecimalLexEncoder::encode(DecimalLexEncoder::to_d128(*v))
464			}
465		}
466	}
467
468	/// Reconstructs a Number from a lexicographically ordered byte buffer.
469	///
470	/// This deserializes a buffer produced by `as_decimal_buf()` using
471	/// DecimalLexEncoder, recovering the numeric value. All Number variants are
472	/// normalized through the same encoding, so the original variant (Int/Float/
473	/// Decimal) is not preserved; only the value (and special cases like NaN/±∞)
474	/// matters for ordering and equality in keys.
475	///
476	/// The decoder recognizes:
477	/// - Zero, finite negatives, finite positives (via marker and biased scale)
478	/// - Negative/positive infinity, NaN (fixed encodings)
479	/// - An explicit in-band terminator added by the encoder, which ensures the mantissa decoder
480	///   stops before any following data in the stream.
481	///
482	/// Returns the reconstructed Number or an error if the buffer is empty or
483	/// cannot be decoded.
484	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	/// Reconstructs a Number of the given kind from a buffer produced by
505	/// `as_decimal_buf()`.
506	///
507	/// This is the inverse of the buffer's encoding for the kind it was written
508	/// with: an `Int` decodes to the same `i64`, a `Decimal` to a `Decimal` of
509	/// the same value, and a `Float` to the same `f64` bit for bit (the sign of a
510	/// zero and the payload of a NaN are not stored). Decoding then encoding
511	/// therefore reproduces the buffer, which a record id read back out of a key
512	/// relies on to address its own record.
513	///
514	/// A float is decoded straight from the decimal digits to the nearest `f64`.
515	/// The buffer holds the float's exact expansion to 34 digits, so that
516	/// conversion lands on the float it was written from at every magnitude,
517	/// including the ones a `Decimal` cannot hold.
518	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	// -----------------------------------
546	//
547	// -----------------------------------
548
549	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			// Truncate via the formatter so subnormals and very large
701			// magnitudes (which would overflow a `10^precision` multiplier)
702			// stay representable; non-finite f64s round-trip too.
703			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				// -0.0 = 0.0
743				Ordering::Equal
744			} else {
745				// Handles NaN's
746				a.total_cmp(&b)
747			}
748		}
749
750		// Pick the greater number depending on whether it's positive.
751		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			// ------------------------------
766			(Number::Int(v), Number::Float(w)) => {
767				// If the float is not finite, we don't need to compare it to the integer.
768				if !w.is_finite() {
769					return greater!(w).reverse();
770				}
771				// Cast int to i128 to avoid saturating.
772				let l = *v as i128;
773				// Cast the integer-part of the float to i128 to avoid saturating.
774				let r = *w as i128;
775				// Compare both integer parts.
776				match l.cmp(&r) {
777					// If the integer parts are equal then we need to compare the mantissa.
778					Ordering::Equal => total_cmp_f64(0.0, w.fract()),
779					// If the integer parts are not equal then we already know the correct ordering.
780					ordering => ordering,
781				}
782			}
783			(v @ Number::Float(_), w @ Number::Int(_)) => w.cmp(v).reverse(),
784			// ------------------------------
785			(Number::Int(v), Number::Decimal(w)) => Decimal::from(*v).cmp(w),
786			(Number::Decimal(v), Number::Int(w)) => v.cmp(&Decimal::from(*w)),
787			// ------------------------------
788			(Number::Float(v), Number::Decimal(w)) => {
789				// Compare fractional parts of the float and decimal.
790				macro_rules! compare_fractions {
791					($l:ident, $r:ident) => {
792						match ($l == 0.0, $r == Decimal::ZERO) {
793							// If both numbers are zero, these are equal.
794							(true, true) => {
795								return Ordering::Equal;
796							}
797							// If only the float is zero, check the decimal's sign.
798							(true, false) => {
799								return greater!($r).reverse();
800							}
801							// If only the decimal is zero, check the float's sign.
802							(false, true) => {
803								return greater!($l);
804							}
805							// If neither is zero, continue checking the rest of the digits.
806							(false, false) => {
807								continue;
808							}
809						}
810					};
811				}
812				// If the float is not finite, we don't need to compare it to the decimal
813				if !v.is_finite() {
814					return greater!(v);
815				}
816				// Cast int to i128 to avoid saturating.
817				let l = *v as i128;
818				// Cast the integer-part of the decimal to i128.
819				let Ok(r) = i128::try_from(*w) else {
820					return greater!(w).reverse();
821				};
822				// Compare both integer parts.
823				match l.cmp(&r) {
824					// If the integer parts are equal then we need to compare the fractional parts.
825					Ordering::Equal => {
826						// We can't compare the fractional parts of floats with decimals reliably.
827						// Instead, we need to compare them as integers. To do this, we need to
828						// multiply the fraction with a number large enough to move some digits
829						// to the integer part of the float or decimal. The number should fit in
830						// 52 bits and be able to multiply f64 fractions between -1 and 1 without
831						// losing precision. Since we may need to do this repeatedly it helps if
832						// the number is as big as possible to reduce the number of
833						// iterations needed.
834						//
835						// This number is roughly 2 ^ 53 with the last digits truncated in order
836						// to make sure the fraction converges to 0 every time we multiply it.
837						// This is a magic number I found through my experiments so don't ask me
838						// the logic behind it :) Before changing this number, please make sure
839						// that the relevant tests aren't flaky after changing it.
840						const SAFE_MULTIPLIER: i64 = 9_007_199_254_740_000;
841						// Get the fractional part of the float.
842						let mut l = v.fract();
843						// Get the fractional part of the decimal.
844						let mut r = w.fract();
845						// Move the digits and compare them.
846						// This is very generous. For example, for our tests to pass we only need
847						// 3 iterations. This should be at least 6 to make sure we cover all
848						// possible decimals and floats.
849						for _ in 0..12 {
850							l *= SAFE_MULTIPLIER as f64;
851							r *= Decimal::new(SAFE_MULTIPLIER, 0);
852							// Cast the integer part of the decimal to i64. The fractions are always
853							// less than 1 so we know this will always be less than SAFE_MULTIPLIER.
854							match r.to_i64() {
855								Some(ref right) => match (l as i64).cmp(right) {
856									// If the integer parts are equal, we need to check the
857									// remaining fractional parts.
858									Ordering::Equal => {
859										// Drop the integer parts we already compared.
860										l = l.fract();
861										r = r.fract();
862										// Compare the fractional parts and decide whether to return
863										// or continue checking the next digits.
864										compare_fractions!(l, r);
865									}
866									ordering => {
867										// If the integer parts are not equal then we already know
868										// the correct ordering.
869										return ordering;
870									}
871								},
872								// This is technically unreachable. Reaching this part likely
873								// indicates a bug in `rust-decimal`'s `to_f64`'s
874								// implementation.
875								None => {
876									// We will assume the decimal is bigger or smaller depending on
877									// its sign.
878									return greater!(w).reverse();
879								}
880							}
881						}
882						// After our iterations, if we still haven't exhausted both fractions we
883						// will just treat them as equal. It should be impossible to reach
884						// this point after at least 6 iterations. We could use an infinite
885						// loop instead but this way we make sure the loop always exits.
886						Ordering::Equal
887					}
888					// If the integer parts are not equal then we already know the correct ordering.
889					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	/// # This hash does not satisfy the `Hash`/`Eq` contract
899	///
900	/// It hashes the decimal buffer encoding, so numerically-equal values with an
901	/// identical decimal expansion agree across variants — `Int(1)`, `Float(1.0)`
902	/// and `Decimal(1)` share a hash. But [`Number`]'s equality is *approximate*
903	/// between `Float` and `Decimal`: it agrees to roughly sixteen significant
904	/// digits and then calls it equal, so `Float(0.1) == Decimal("0.1")` while the
905	/// buffers differ, `D128::from_f64(0.1)` being
906	/// `0.1000000000000000055511151231257827`. (Going the other way,
907	/// `Float(0.11111) != Decimal("0.11111")` — the relation is not even
908	/// transitive across the boundary.)
909	///
910	/// So `a == b` does **not** imply `hash(a) == hash(b)`, and an approximate,
911	/// non-transitive equality admits no canonical form that would fix it. Any
912	/// `HashMap`/`HashSet` keyed on a [`Number`] — or on any value that can hold
913	/// one — will therefore miss entries it contains. Key such structures on `Ord`
914	/// instead, or treat a miss as inconclusive; see
915	/// [`Value::hash_agrees_with_eq`](crate::val::Value::hash_agrees_with_eq) for
916	/// deciding when a miss can still be trusted.
917	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			// ------------------------------
933			(v @ Number::Int(_), w @ Number::Float(_)) => v.cmp(w) == Ordering::Equal,
934			(v @ Number::Float(_), w @ Number::Int(_)) => v.cmp(w) == Ordering::Equal,
935			// ------------------------------
936			(Number::Int(v), Number::Decimal(w)) => Decimal::from(*v).eq(w),
937			(Number::Decimal(v), Number::Int(w)) => v.eq(&Decimal::from(*w)),
938			// ------------------------------
939			(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					// 0^(-x)
990					Ordering::Less => bail!(Error::TryPow(v.to_string(), p.to_string())),
991					// 0^0
992					Ordering::Equal => 1,
993					// 0^x
994					Ordering::Greater => 0,
995				},
996				// 1^p
997				1 => 1,
998				-1 => {
999					if p % 2 == 0 {
1000						// (-1)^even
1001						1
1002					} else {
1003						// (-1)^odd
1004						-1
1005					}
1006				}
1007				// try_into may cause an error, which would be wrong for the above cases.
1008				_ => 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
1184// ------------------------------
1185
1186impl 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
1291/// Conversion to `f64`. The implementations are marked `#[inline]` so that the
1292/// per-component loops of the vector functions, in other crates, compile them
1293/// into the loop whatever link-time optimisation decides.
1294pub 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		// i64::MIN
1392
1393		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			// PartialOrd requirements
1450			assert_eq!(x == y, x.partial_cmp(&y) == Some(Ordering::Equal), "{x:?} {y:?}");
1451
1452			// Ord consistent with PartialOrd
1453			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			// Transitive property (without the fix, these can fail)
1462			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			// Duality
1476			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		// `i64::MIN` is exactly representable as `f64` and is the inclusive lower bound.
1553		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		// `i64::MAX as f64` rounds up to 2^63, which is *not* in `i64` range —
1567		// the exclusive upper bound is `-(i64::MIN as f64)`.
1568		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		// 1e30 is far beyond usize::MAX and not exactly representable as usize.
1598		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		// Subnormal at precision past f64's significant-digit range: the
1619		// trailing digits get truncated, producing a smaller-but-finite
1620		// neighbour rather than 0, inf, or NaN.
1621		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		// The Float arm relies on `format!`/`parse` round-tripping every
1630		// f64 — including NaN and ±inf. Pin that invariant here so a future
1631		// change to the formatter cannot silently break the `expect` in
1632		// `Number::fixed`.
1633		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	/// A number as a record key stores it, and as a scan reads it back.
1651	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	/// A record id read out of a key is used to fetch the record again, which
1659	/// re-encodes it, so decoding must give back the value the key was written
1660	/// from: the same float bit for bit, not a neighbour of it, and not an error.
1661	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		// The sign of a zero and the payload of a NaN are not stored.
1667		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			// Past the largest magnitude a `Decimal` holds, ~7.9e28.
1694			1e28,
1695			7.9e28,
1696			1e29,
1697			1e30,
1698			-1e30,
1699			1e300,
1700			f64::MAX,
1701			f64::MIN,
1702			// Below the smallest scale a `Decimal` holds, and the subnormals.
1703			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		// Every decimal exponent, over mantissas of every length.
1716		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			// A scale of 7 or more is printed in scientific notation by `D128`.
1750			"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	/// What a released binary stored for these numbers. The bytes are the format
1788	/// of every record id and key that holds one, so they must not change: a
1789	/// scan on a newer release decodes exactly these.
1790	#[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}