1use std::{ ops, fmt, f32, f64 };
2use std::num::FpCategory;
3use crate::util::grisu2;
4use crate::util::print_dec;
5
6pub const NAN: Number = Number {
8 category: NAN_MASK,
9 mantissa: 0,
10 exponent: 0
11};
12
13const NEGATIVE: u8 = 0;
14const POSITIVE: u8 = 1;
15const NAN_MASK: u8 = !1;
16
17#[derive(Copy, Clone, Debug)]
33pub struct Number {
34 category: u8,
40
41 exponent: i16,
43
44 mantissa: u64,
46}
47
48impl Number {
49 #[inline]
62 pub unsafe fn from_parts_unchecked(positive: bool, mantissa: u64, exponent: i16) -> Self {
63 Number {
64 category: positive as u8,
65 exponent: exponent,
66 mantissa: mantissa,
67 }
68 }
69
70 #[inline]
83 pub fn from_parts(positive: bool, mut mantissa: u64, mut exponent: i16) -> Self {
84 while exponent < 0 && mantissa % 10 == 0 {
85 exponent += 1;
86 mantissa /= 10;
87 }
88 unsafe { Number::from_parts_unchecked(positive, mantissa, exponent) }
89 }
90
91 #[inline]
103 pub fn as_parts(&self) -> (bool, u64, i16) {
104 (self.category == POSITIVE, self.mantissa, self.exponent)
105 }
106
107 #[inline]
108 pub fn is_sign_positive(&self) -> bool {
109 self.category == POSITIVE
110 }
111
112 #[inline]
113 pub fn is_zero(&self) -> bool {
114 self.mantissa == 0 && !self.is_nan()
115 }
116
117 #[inline]
118 pub fn is_nan(&self) -> bool {
119 self.category & NAN_MASK != 0
120 }
121
122 #[inline]
124 pub fn is_empty(&self) -> bool {
125 self.mantissa == 0 || self.is_nan()
126 }
127
128 pub fn as_fixed_point_u64(&self, point: u16) -> Option<u64> {
145 if self.category != POSITIVE {
146 return None;
147 }
148
149 let e_diff = point as i16 + self.exponent;
150
151 Some(if e_diff == 0 {
152 self.mantissa
153 } else if e_diff < 0 {
154 self.mantissa.wrapping_div(decimal_power(-e_diff as u16))
155 } else {
156 self.mantissa.wrapping_mul(decimal_power(e_diff as u16))
157 })
158 }
159
160 pub fn as_fixed_point_i64(&self, point: u16) -> Option<i64> {
172 if self.is_nan() {
173 return None;
174 }
175
176 let num = if self.is_sign_positive() {
177 self.mantissa as i64
178 } else {
179 -(self.mantissa as i64)
180 };
181
182 let e_diff = point as i16 + self.exponent;
183
184 Some(if e_diff == 0 {
185 num
186 } else if e_diff < 0 {
187 num.wrapping_div(decimal_power(-e_diff as u16) as i64)
188 } else {
189 num.wrapping_mul(decimal_power(e_diff as u16) as i64)
190 })
191 }
192}
193
194impl PartialEq for Number {
195 #[inline]
196 fn eq(&self, other: &Number) -> bool {
197 if self.is_zero() && other.is_zero()
198 || self.is_nan() && other.is_nan() {
199 return true;
200 }
201
202 if self.category != other.category {
203 return false;
204 }
205
206 let e_diff = self.exponent - other.exponent;
207
208 if e_diff == 0 {
209 return self.mantissa == other.mantissa;
210 } else if e_diff > 0 {
211 let power = decimal_power(e_diff as u16);
212
213 self.mantissa.wrapping_mul(power) == other.mantissa
214 } else {
215 let power = decimal_power(-e_diff as u16);
216
217 self.mantissa == other.mantissa.wrapping_mul(power)
218 }
219
220 }
221}
222
223impl fmt::Display for Number {
224 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
225 unsafe {
226 if self.is_nan() {
227 return f.write_str("nan")
228 }
229 let (positive, mantissa, exponent) = self.as_parts();
230 let mut buf = Vec::new();
231 print_dec::write(&mut buf, positive, mantissa, exponent).unwrap();
232 f.write_str(&String::from_utf8_unchecked(buf))
233 }
234 }
235}
236
237fn exponentiate_f64(n: f64, e: i16) -> f64 {
238 static CACHE_POWERS: [f64; 23] = [
239 1.0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7,
240 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
241 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22
242 ];
243
244 if e >= 0 {
245 let index = e as usize;
246
247 n * if index < 23 {
248 CACHE_POWERS[index]
249 } else {
250 10f64.powf(index as f64)
251 }
252 } else {
253 let index = -e as usize;
254
255 n / if index < 23 {
256 CACHE_POWERS[index]
257 } else {
258 10f64.powf(index as f64)
259 }
260 }
261}
262
263
264fn exponentiate_f32(n: f32, e: i16) -> f32 {
265 static CACHE_POWERS: [f32; 23] = [
266 1.0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7,
267 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
268 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22
269 ];
270
271 if e >= 0 {
272 let index = e as usize;
273
274 n * if index < 23 {
275 CACHE_POWERS[index]
276 } else {
277 10f32.powf(index as f32)
278 }
279 } else {
280 let index = -e as usize;
281
282 n / if index < 23 {
283 CACHE_POWERS[index]
284 } else {
285 10f32.powf(index as f32)
286 }
287 }
288}
289
290impl From<Number> for f64 {
291 fn from(num: Number) -> f64 {
292 if num.is_nan() { return f64::NAN; }
293
294 let mut n = num.mantissa as f64;
295 let mut e = num.exponent;
296
297 if e < -308 {
298 n = exponentiate_f64(n, e + 308);
299 e = -308;
300 }
301
302 let f = exponentiate_f64(n, e);
303 if num.is_sign_positive() { f } else { -f }
304 }
305}
306
307impl From<Number> for f32 {
308 fn from(num: Number) -> f32 {
309 if num.is_nan() { return f32::NAN; }
310
311 let mut n = num.mantissa as f32;
312 let mut e = num.exponent;
313
314 if e < -127 {
315 n = exponentiate_f32(n, e + 127);
316 e = -127;
317 }
318
319 let f = exponentiate_f32(n, e);
320 if num.is_sign_positive() { f } else { -f }
321 }
322}
323
324impl From<f64> for Number {
325 fn from(float: f64) -> Number {
326 match float.classify() {
327 FpCategory::Infinite | FpCategory::Nan => return NAN,
328 _ => {}
329 }
330
331 if !float.is_sign_positive() {
332 let (mantissa, exponent) = grisu2::convert(-float);
333
334 Number::from_parts(false, mantissa, exponent)
335 } else {
336 let (mantissa, exponent) = grisu2::convert(float);
337
338 Number::from_parts(true, mantissa, exponent)
339 }
340 }
341}
342
343impl From<f32> for Number {
344 fn from(float: f32) -> Number {
345 match float.classify() {
346 FpCategory::Infinite | FpCategory::Nan => return NAN,
347 _ => {}
348 }
349
350 if !float.is_sign_positive() {
351 let (mantissa, exponent) = grisu2::convert(-float as f64);
352
353 Number::from_parts(false, mantissa, exponent)
354 } else {
355 let (mantissa, exponent) = grisu2::convert(float as f64);
356
357 Number::from_parts(true, mantissa, exponent)
358 }
359 }
360}
361
362impl PartialEq<f64> for Number {
363 fn eq(&self, other: &f64) -> bool {
364 f64::from(*self) == *other
365 }
366}
367
368impl PartialEq<f32> for Number {
369 fn eq(&self, other: &f32) -> bool {
370 f32::from(*self) == *other
371 }
372}
373
374impl PartialEq<Number> for f64 {
375 fn eq(&self, other: &Number) -> bool {
376 f64::from(*other) == *self
377 }
378}
379
380impl PartialEq<Number> for f32 {
381 fn eq(&self, other: &Number) -> bool {
382 f32::from(*other) == *self
383 }
384}
385
386macro_rules! impl_unsigned {
387 ($( $t:ty ),*) => ($(
388 impl From<$t> for Number {
389 #[inline]
390 fn from(num: $t) -> Number {
391 Number {
392 category: POSITIVE,
393 exponent: 0,
394 mantissa: num as u64,
395 }
396 }
397 }
398
399 impl_integer!($t);
400 )*)
401}
402
403
404macro_rules! impl_signed {
405 ($( $t:ty ),*) => ($(
406 impl From<$t> for Number {
407 fn from(num: $t) -> Number {
408 if num < 0 {
409 Number {
410 category: NEGATIVE,
411 exponent: 0,
412 mantissa: -num as u64,
413 }
414 } else {
415 Number {
416 category: POSITIVE,
417 exponent: 0,
418 mantissa: num as u64,
419 }
420 }
421 }
422 }
423
424 impl_integer!($t);
425 )*)
426}
427
428
429macro_rules! impl_integer {
430 ($t:ty) => {
431 impl From<Number> for $t {
432 fn from(num: Number) -> $t {
433 let (positive, mantissa, exponent) = num.as_parts();
434
435 if exponent <= 0 {
436 if positive {
437 mantissa as $t
438 } else {
439 -(mantissa as i64) as $t
440 }
441 } else {
442 if positive {
444 (mantissa * 10u64.pow(exponent as u32)) as $t
445 } else {
446 (-(mantissa as i64) * 10i64.pow(exponent as u32)) as $t
447 }
448 }
449 }
450 }
451
452 impl PartialEq<$t> for Number {
453 fn eq(&self, other: &$t) -> bool {
454 *self == Number::from(*other)
455 }
456 }
457
458 impl PartialEq<Number> for $t {
459 fn eq(&self, other: &Number) -> bool {
460 Number::from(*self) == *other
461 }
462 }
463 }
464}
465
466impl_signed!(isize, i8, i16, i32, i64);
467impl_unsigned!(usize, u8, u16, u32, u64);
468
469impl ops::Neg for Number {
470 type Output = Number;
471
472 #[inline]
473 fn neg(self) -> Number {
474 Number {
475 category: self.category ^ POSITIVE,
476 exponent: self.exponent,
477 mantissa: self.mantissa,
478 }
479 }
480}
481
482#[inline]
516fn decimal_power(mut e: u16) -> u64 {
517 static CACHED: [u64; 20] = [
518 1,
519 10,
520 100,
521 1000,
522 10000,
523 100000,
524 1000000,
525 10000000,
526 100000000,
527 1000000000,
528 10000000000,
529 100000000000,
530 1000000000000,
531 10000000000000,
532 100000000000000,
533 1000000000000000,
534 10000000000000000,
535 100000000000000000,
536 1000000000000000000,
537 10000000000000000000,
538 ];
539
540 if e < 20 {
541 CACHED[e as usize]
542 } else {
543 let mut pow = 1u64;
544 while e >= 20 {
545 pow = pow.saturating_mul(CACHED[(e % 20) as usize]);
546 e /= 20;
547 }
548
549 pow
550 }
551}