xsd_types/value/
double.rs

1use std::{
2	borrow::Borrow,
3	fmt,
4	ops::{Add, Deref, DerefMut, Div, Mul, Sub},
5	str::FromStr,
6};
7
8use ordered_float::OrderedFloat;
9
10use crate::{
11	lexical::{self, LexicalFormOf},
12	Datatype, ParseXsd, XsdValue,
13};
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
16pub struct Double(OrderedFloat<f64>);
17
18impl Double {
19	pub const NEG_INFINITY: Self = Self(OrderedFloat(f64::NEG_INFINITY));
20	pub const INFINITY: Self = Self(OrderedFloat(f64::INFINITY));
21	pub const MIN: Self = Self(OrderedFloat(f64::MIN));
22	pub const MAX: Self = Self(OrderedFloat(f64::MAX));
23	pub const NAN: Self = Self(OrderedFloat(f64::NAN));
24
25	#[inline(always)]
26	pub fn new(f: f64) -> Self {
27		Self(OrderedFloat(f))
28	}
29
30	/// Returns `true` if this value is NaN.
31	#[inline(always)]
32	pub fn is_nan(&self) -> bool {
33		self.0 .0.is_nan()
34	}
35
36	/// Returns `true` if this number is neither infinite nor NaN.
37	#[inline(always)]
38	pub fn is_finite(&self) -> bool {
39		self.0 .0.is_finite()
40	}
41
42	/// Returns `true` if this value is positive infinity or negative infinity, and `false` otherwise.
43	#[inline(always)]
44	pub fn is_infinite(&self) -> bool {
45		self.0 .0.is_infinite()
46	}
47
48	/// Returns `true` if `self` has a positive sign, including +0.0, NaNs with
49	/// positive sign bit and positive infinity.
50	///
51	/// Note that IEEE 754 doesn't assign any meaning to the sign bit in case
52	/// of a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs
53	/// are conserved over arithmetic operations, the result of
54	/// `is_positive` on a NaN might produce an unexpected result in some
55	/// cases.
56	/// See [explanation of NaN as a special value](https://doc.rust-lang.org/nightly/core/primitive.f32.html)
57	/// for more info.
58	#[inline(always)]
59	pub fn is_positive(&self) -> bool {
60		self.0 .0.is_sign_positive()
61	}
62
63	/// Returns `false` if `self` has a negative sign, including -0.0, NaNs with
64	/// negative sign bit and negative infinity.
65	///
66	/// Note that IEEE 754 doesn't assign any meaning to the sign bit in case
67	/// of a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs
68	/// are conserved over arithmetic operations, the result of
69	/// `is_negative` on a NaN might produce an unexpected result in some
70	/// cases.
71	/// See [explanation of NaN as a special value](https://doc.rust-lang.org/nightly/core/primitive.f32.html)
72	/// for more info.
73	#[inline(always)]
74	pub fn is_negative(&self) -> bool {
75		self.0 .0.is_sign_negative()
76	}
77
78	/// Converts this value into a `f64`.
79	#[inline(always)]
80	pub const fn into_f64(self) -> f64 {
81		self.0 .0
82	}
83}
84
85// <https://www.w3.org/TR/xmlschema11-2/#f-doubleLexmap>
86const XSD_CANONICAL_DOUBLE: pretty_dtoa::FmtFloatConfig = pretty_dtoa::FmtFloatConfig::default()
87	.force_e_notation()
88	.capitalize_e(true);
89
90impl fmt::Display for Double {
91	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92		pretty_dtoa::dtoa(self.0 .0, XSD_CANONICAL_DOUBLE).fmt(f)
93	}
94}
95
96impl XsdValue for Double {
97	fn datatype(&self) -> Datatype {
98		Datatype::Double
99	}
100}
101
102impl ParseXsd for Double {
103	type LexicalForm = lexical::Double;
104}
105
106impl LexicalFormOf<Double> for lexical::Double {
107	type ValueError = std::convert::Infallible;
108
109	fn try_as_value(&self) -> Result<Double, Self::ValueError> {
110		Ok(self.value())
111	}
112}
113
114impl<'a> From<&'a lexical::Double> for Double {
115	fn from(value: &'a lexical::Double) -> Self {
116		Self::new(value.into())
117	}
118}
119
120impl From<lexical::DoubleBuf> for Double {
121	fn from(value: lexical::DoubleBuf) -> Self {
122		Self::new(value.into())
123	}
124}
125
126impl FromStr for Double {
127	type Err = lexical::InvalidDouble;
128
129	fn from_str(s: &str) -> Result<Self, Self::Err> {
130		let l = lexical::Double::new(s)?;
131		Ok(l.into())
132	}
133}
134
135impl From<f32> for Double {
136	fn from(value: f32) -> Self {
137		Self(OrderedFloat(value as f64))
138	}
139}
140
141impl From<f64> for Double {
142	fn from(value: f64) -> Self {
143		Self(OrderedFloat(value))
144	}
145}
146
147impl From<Double> for f64 {
148	fn from(value: Double) -> Self {
149		value.0 .0
150	}
151}
152
153impl AsRef<f64> for Double {
154	fn as_ref(&self) -> &f64 {
155		&self.0
156	}
157}
158
159impl Borrow<f64> for Double {
160	fn borrow(&self) -> &f64 {
161		&self.0
162	}
163}
164
165impl Deref for Double {
166	type Target = f64;
167
168	fn deref(&self) -> &f64 {
169		&self.0
170	}
171}
172
173impl DerefMut for Double {
174	fn deref_mut(&mut self) -> &mut f64 {
175		&mut self.0
176	}
177}
178
179impl Add for Double {
180	type Output = Self;
181
182	fn add(self, rhs: Self) -> Self::Output {
183		Self(OrderedFloat(*self.0 + *rhs.0))
184	}
185}
186
187impl Sub for Double {
188	type Output = Self;
189
190	fn sub(self, rhs: Self) -> Self::Output {
191		Self(OrderedFloat(*self.0 - *rhs.0))
192	}
193}
194
195impl Mul for Double {
196	type Output = Self;
197
198	fn mul(self, rhs: Self) -> Self::Output {
199		Self(OrderedFloat(*self.0 * *rhs.0))
200	}
201}
202
203impl Div for Double {
204	type Output = Self;
205
206	fn div(self, rhs: Self) -> Self::Output {
207		Self(OrderedFloat(*self.0 / *rhs.0))
208	}
209}