json_joxit_fork/
number.rs

1use std::{ ops, fmt, f32, f64 };
2use std::num::FpCategory;
3use crate::util::grisu2;
4use crate::util::print_dec;
5
6/// NaN value represented in `Number` type. NaN is equal to itself.
7pub 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/// Number representation used inside `JsonValue`. You can easily convert
18/// the `Number` type into native Rust number types and back, or use the
19/// equality operator with another number type.
20///
21/// ```
22/// # use json::number::Number;
23/// let foo: Number = 3.14.into();
24/// let bar: f64 = foo.into();
25///
26/// assert_eq!(foo, 3.14);
27/// assert_eq!(bar, 3.14);
28/// ```
29///
30/// More often than not you will deal with `JsonValue::Number` variant that
31/// wraps around this type, instead of using the methods here directly.
32#[derive(Copy, Clone, Debug)]
33pub struct Number {
34    // A byte describing the sign and NaN-ness of the number.
35    //
36    // category == 0 (NEGATIVE constant)         -> negative sign
37    // category == 1 (POSITIVE constant)         -> positive sign
38    // category >  1 (matches NAN_MASK constant) -> NaN
39    category: u8,
40
41    // Decimal exponent, analog to `e` notation in string form.
42    exponent: i16,
43
44    // Integer base before sing and exponent applied.
45    mantissa: u64,
46}
47
48impl Number {
49    /// Construct a new `Number` from parts. This can't create a NaN value.
50    ///
51    /// ```
52    /// # use json::number::Number;
53    /// let pi = unsafe { Number::from_parts_unchecked(true, 3141592653589793, -15) };
54    ///
55    /// assert_eq!(pi, 3.141592653589793);
56    /// ```
57    ///
58    /// While this method is marked unsafe, it doesn't actually perform any unsafe operations.
59    /// THe goal of the 'unsafe' is to deter from using this method in favor of its safe equivalent
60    /// `from_parts`, at least in context when the associated performance cost is negligible.
61    #[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    /// Construct a new `Number` from parts, stripping unnecessary trailing zeroes.
71    /// This can't create a NaN value.
72    ///
73    /// ```
74    /// # use json::number::Number;
75    /// let one = Number::from_parts(true, 1000, -3);
76    /// let (positive, mantissa, exponent) = one.as_parts();
77    ///
78    /// assert_eq!(true, positive);
79    /// assert_eq!(1, mantissa);
80    /// assert_eq!(0, exponent);
81    /// ```
82    #[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    /// Reverse to `from_parts` - obtain parts from an existing `Number`.
92    ///
93    /// ```
94    /// # use json::number::Number;
95    /// let pi = Number::from(3.141592653589793);
96    /// let (positive, mantissa, exponent) = pi.as_parts();
97    ///
98    /// assert_eq!(positive, true);
99    /// assert_eq!(mantissa, 3141592653589793);
100    /// assert_eq!(exponent, -15);
101    /// ```
102    #[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    /// Test if the number is NaN or has a zero value.
123    #[inline]
124    pub fn is_empty(&self) -> bool {
125        self.mantissa == 0 || self.is_nan()
126    }
127
128    /// Obtain an integer at a fixed decimal point. This is useful for
129    /// converting monetary values and doing arithmetic on them without
130    /// rounding errors introduced by floating point operations.
131    ///
132    /// Will return `None` if `Number` is negative or a NaN.
133    ///
134    /// ```
135    /// # use json::number::Number;
136    /// let price_a = Number::from(5.99);
137    /// let price_b = Number::from(7);
138    /// let price_c = Number::from(10.2);
139    ///
140    /// assert_eq!(price_a.as_fixed_point_u64(2), Some(599));
141    /// assert_eq!(price_b.as_fixed_point_u64(2), Some(700));
142    /// assert_eq!(price_c.as_fixed_point_u64(2), Some(1020));
143    /// ```
144    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    /// Analog to `as_fixed_point_u64`, except returning a signed
161    /// `i64`, properly handling negative numbers.
162    ///
163    /// ```
164    /// # use json::number::Number;
165    /// let balance_a = Number::from(-1.49);
166    /// let balance_b = Number::from(42);
167    ///
168    /// assert_eq!(balance_a.as_fixed_point_i64(2), Some(-149));
169    /// assert_eq!(balance_b.as_fixed_point_i64(2), Some(4200));
170    /// ```
171    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                    // This may overflow, which is fine
443                    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// Commented out for now - not doing math ops for 0.10.0
483// -----------------------------------------------------
484//
485// impl ops::Mul for Number {
486//     type Output = Number;
487
488//     #[inline]
489//     fn mul(self, other: Number) -> Number {
490//         // If either is a NaN, return a NaN
491//         if (self.category | other.category) & NAN_MASK != 0 {
492//             NAN
493//         } else {
494//             Number {
495//                 // If both signs are the same, xoring will produce 0.
496//                 // If they are different, xoring will produce 1.
497//                 // Xor again with 1 to get a proper proper sign!
498//                 // Xor all the things!                              ^ _ ^
499
500//                 category: self.category ^ other.category ^ POSITIVE,
501//                 exponent: self.exponent + other.exponent,
502//                 mantissa: self.mantissa * other.mantissa,
503//             }
504//         }
505//     }
506// }
507
508// impl ops::MulAssign for Number {
509//     #[inline]
510//     fn mul_assign(&mut self, other: Number) {
511//         *self = *self * other;
512//     }
513// }
514
515#[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}