1#[derive(Clone, Debug, PartialEq)]
3pub enum Number {
4 Basic(BasicNumber),
5 Scientific(ScientificNumber),
6}
7
8impl std::fmt::Display for Number {
9 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10 match self {
11 Self::Basic(num) => write!(f, "{}", num),
12 Self::Scientific(ex) => write!(f, "{}", ex),
13 }
14 }
15}
16
17impl Number {
18 pub fn new(value: f64, unit: Option<String>) -> Self {
22 Number::Basic(BasicNumber::new(value, unit))
23 }
24
25 pub fn new_unitless(value: f64) -> Self {
27 Self::new(value, None)
28 }
29
30 pub fn new_scientific(
34 significand: f64,
35 exponent: i32,
36 unit: Option<String>,
37 ) -> Option<Self> {
38 Some(Number::Scientific(ScientificNumber::new(
39 significand,
40 exponent,
41 unit,
42 )?))
43 }
44
45 pub fn new_scientific_unitless(
47 significand: f64,
48 exponent: i32,
49 ) -> Option<Self> {
50 Self::new_scientific(significand, exponent, None)
51 }
52
53 pub fn as_number(&self) -> Option<&BasicNumber> {
55 match self {
56 Self::Basic(number) => Some(number),
57 _ => None,
58 }
59 }
60
61 pub fn as_scientific_number(&self) -> Option<&ScientificNumber> {
64 match self {
65 Self::Scientific(ex) => Some(ex),
66 _ => None,
67 }
68 }
69
70 pub fn unit(&self) -> Option<&str> {
72 match self {
73 Self::Basic(num) => num.unit(),
74 Self::Scientific(ex) => ex.unit(),
75 }
76 }
77
78 pub fn to_axon_code(&self) -> String {
80 match self {
81 Self::Basic(num) => num.to_axon_code(),
82 Self::Scientific(ex) => ex.to_axon_code(),
83 }
84 }
85}
86
87#[derive(Clone, Debug, PartialEq)]
91pub struct BasicNumber {
92 value: f64,
93 unit: Option<String>,
94}
95
96impl BasicNumber {
97 pub fn new(value: f64, unit: Option<String>) -> Self {
101 Self { value, unit }
102 }
103
104 pub fn new_unitless(value: f64) -> Self {
106 Self::new(value, None)
107 }
108
109 pub fn value(&self) -> f64 {
111 self.value
112 }
113
114 pub fn unit(&self) -> Option<&str> {
116 self.unit.as_ref().map(|unit| unit.as_ref())
117 }
118
119 pub fn to_axon_code(&self) -> String {
121 let value = self.value();
122 if let Some(unit) = self.unit() {
123 if value.is_nan() {
124 format!("nan().as(\"{}\")", unit)
125 } else if value.is_infinite() && value.is_sign_positive() {
126 format!("posInf().as(\"{}\")", unit)
127 } else if value.is_infinite() && value.is_sign_negative() {
128 format!("negInf().as(\"{}\")", unit)
129 } else {
130 format!("{}{}", value, unit)
131 }
132 } else {
133 if value.is_nan() {
134 "nan()".to_owned()
135 } else if value.is_infinite() && value.is_sign_positive() {
136 "posInf()".to_owned()
137 } else if value.is_infinite() && value.is_sign_negative() {
138 "negInf()".to_owned()
139 } else {
140 format!("{}", value)
141 }
142 }
143 }
144}
145
146impl std::fmt::Display for BasicNumber {
147 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
148 let value = self.value();
149 if value.is_nan() {
150 if let Some(unit) = self.unit() {
151 write!(f, "NaN {}", unit)
152 } else {
153 write!(f, "NaN")
154 }
155 } else if value.is_infinite() && value.is_sign_positive() {
156 if let Some(unit) = self.unit() {
157 write!(f, "INF {}", unit)
158 } else {
159 write!(f, "INF")
160 }
161 } else if value.is_infinite() && value.is_sign_negative() {
162 if let Some(unit) = self.unit() {
163 write!(f, "-INF {}", unit)
164 } else {
165 write!(f, "-INF")
166 }
167 } else if let Some(unit) = self.unit() {
168 write!(f, "{} {}", value, unit)
169 } else {
170 write!(f, "{}", value)
171 }
172 }
173}
174
175#[derive(Clone, Debug, PartialEq)]
179pub struct ScientificNumber {
180 significand: f64,
181 exponent: i32,
182 unit: Option<String>,
183}
184
185impl ScientificNumber {
186 pub fn new(
191 significand: f64,
192 exponent: i32,
193 unit: Option<String>,
194 ) -> Option<Self> {
195 if significand.is_nan() || significand.is_infinite() {
196 None
197 } else {
198 Some(Self {
199 significand,
200 exponent,
201 unit,
202 })
203 }
204 }
205
206 pub fn new_unitless(significand: f64, exponent: i32) -> Option<Self> {
209 Self::new(significand, exponent, None)
210 }
211
212 pub fn significand(&self) -> f64 {
214 self.significand
215 }
216
217 pub fn exponent(&self) -> i32 {
219 self.exponent
220 }
221
222 pub fn unit(&self) -> Option<&str> {
224 self.unit.as_ref().map(|unit| unit.as_ref())
225 }
226
227 pub fn to_axon_code(&self) -> String {
229 let exp = self.exponent();
230 let sig = self.significand();
231 if let Some(unit) = self.unit() {
232 format!("{}e{}{}", sig, exp, unit)
233 } else {
234 format!("{}e{}", sig, exp)
235 }
236 }
237}
238
239impl std::fmt::Display for ScientificNumber {
240 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
241 let exp = self.exponent();
242 let sig = self.significand();
243 if let Some(unit) = self.unit() {
244 write!(f, "{}e{} {}", sig, exp, unit)
245 } else {
246 write!(f, "{}e{}", sig, exp)
247 }
248 }
249}