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