fixed/
from_str.rs

1// Copyright © 2018–2025 Trevor Spiteri
2
3// This library is free software: you can redistribute it and/or
4// modify it under the terms of either
5//
6//   * the Apache License, Version 2.0 or
7//   * the MIT License
8//
9// at your option.
10//
11// You should have recieved copies of the Apache License and the MIT
12// License along with the library. If not, see
13// <https://www.apache.org/licenses/LICENSE-2.0> and
14// <https://opensource.org/licenses/MIT>.
15
16use crate::bytes::{DigitsExp, DigitsUnds};
17use crate::types::extra::{LeEqU8, LeEqU16, LeEqU32, LeEqU64, LeEqU128};
18use crate::{
19    FixedI8, FixedI16, FixedI32, FixedI64, FixedI128, FixedU8, FixedU16, FixedU32, FixedU64,
20    FixedU128,
21};
22use core::error::Error;
23use core::fmt::{Display, Formatter, Result as FmtResult};
24use core::num::NonZeroU32;
25use core::str::FromStr;
26
27// NOTE ON dec_to_bin
28//
29// dec_to_bin: Decode fractional decimal digits into nbits fractional bits.
30//
31// For an output with BIN = 8 bits, we can take DEC = 3 decimal digits.
32//
33//     0 ≤ val ≤ 999, 0 ≤ nbits ≤ 8
34//
35// In general,
36//
37//     0 ≤ val ≤ 10^DEC - 1, 0 ≤ nbits ≤ BIN
38//
39// We can either floor the result or round to the nearest, with ties rounded to
40// even. If rounding results in more than nbits bits, returns None.
41//
42// Examples: (for DEC = 3, BIN = 8)
43//
44//    dec_to_bin(999, 8, Round::Floor) -> floor(999 × 256 / 1000) -> 255 -> Some(255)
45//    dec_to_bin(999, 8, Round::Nearest) -> floor(999 × 256 / 1000 + 0.5) -> 256 -> None
46//    dec_to_bin(999, 5, Round::Floor) -> floor(999 × 32 / 1000) -> 31 -> Some(31)
47//    dec_to_bin(999, 5, Round::Nearest) -> floor(999 × 32 / 1000 + 0.5) -> 32 -> None
48//    dec_to_bin(499, 0, Round::Floor) -> floor(499 / 1000) -> 0 -> Some(0)
49//    dec_to_bin(499, 0, Round::Nearest) -> floor(499 / 1000 + 0.5) -> 0 -> Some(0)
50//    dec_to_bin(500, 0, Round::Nearest) -> floor(500 / 1000 + 0.5) -> 1 -> None
51//
52// For flooring:
53//
54//     floor(val × 2^nbits / 10^3) = floor(val × 2^(nbits - 3) / 5^3)
55//
56// For rounding:
57//
58//     floor(val × 2^nbits / 10^3 + 0.5) = floor((val × 2^(nbits - 2) + 5^3) / (2 × 5^3))
59//
60// Using integer arithmetic, this is equal to:
61//
62//     ((val << 6 >> (8 - nbits)) + if rounding { 125 } else { 0 }) / 250
63//
64// Note that val << 6 cannot overflow u16, as val < 1000 and 1000 × 2^6 < 2^16.
65//
66// In general:
67//
68//     ((val << (BIN - DEC + 1) >> (8 - nbits)) + if rounding { 5^DEC } else { 0 }) / (2 × 5^DEC)
69//
70// And we ensure that 10^DEC × 2^(BIN - DEC + 1) < 2^(2 × BIN), which simplifies to
71//
72//     5^DEC × 2 < 2^BIN
73//
74// From this it also follows that val << (BIN - DEC + 1) never overflows a (2 × BIN)-bit number.
75//
76// So for u8, BIN = 8, DEC ≤ 3
77// So for u16, BIN = 16, DEC ≤ 6
78// So for u32, BIN = 32, DEC ≤ 13
79// So for u64, BIN = 64, DEC ≤ 27
80// So for u128, BIN = 128, DEC ≤ 54
81//
82// END NOTE ON dec_to_bin
83
84// Expanded on all signed and unsigned integers.
85// This should be expanded in a module named like the integer.
86//
87//   * Defines:
88//       - pub const fn from_str_radix
89//       - pub const fn saturating_from_str_radix
90//       - pub const fn wrapping_from_str_radix
91//       - pub const fn overflowing_from_str_radix
92macro_rules! all {
93    ($Single:ident) => {
94        use crate::from_str::{ParseErrorKind, ParseFixedError, Sep};
95
96        #[inline]
97        pub const fn from_str_radix(
98            s: &[u8],
99            radix: u32,
100            frac_nbits: u32,
101        ) -> Result<$Single, ParseFixedError> {
102            match overflowing_from_str_radix(s, radix, frac_nbits) {
103                Ok((val, false)) => Ok(val),
104                Ok((_, true)) => Err(ParseFixedError {
105                    kind: ParseErrorKind::Overflow,
106                }),
107                Err(e) => Err(e),
108            }
109        }
110
111        #[inline]
112        pub const fn saturating_from_str_radix(
113            s: &[u8],
114            radix: u32,
115            frac_nbits: u32,
116        ) -> Result<$Single, ParseFixedError> {
117            match overflowing_from_str_radix(s, radix, frac_nbits) {
118                Ok((val, false)) => Ok(val),
119                Ok((_, true)) => {
120                    let starts_with_minus = match s.first() {
121                        Some(byte) => *byte == b'-',
122                        None => false,
123                    };
124                    if starts_with_minus {
125                        Ok($Single::MIN)
126                    } else {
127                        Ok($Single::MAX)
128                    }
129                }
130                Err(e) => Err(e),
131            }
132        }
133
134        #[inline]
135        pub const fn wrapping_from_str_radix(
136            s: &[u8],
137            radix: u32,
138            frac_nbits: u32,
139        ) -> Result<$Single, ParseFixedError> {
140            match overflowing_from_str_radix(s, radix, frac_nbits) {
141                Ok((val, _)) => Ok(val),
142                Err(e) => Err(e),
143            }
144        }
145
146        #[inline]
147        pub const fn overflowing_from_str_radix(
148            s: &[u8],
149            radix: u32,
150            frac_nbits: u32,
151        ) -> Result<($Single, bool), ParseFixedError> {
152            match from_str(s, radix, Sep::Error, frac_nbits) {
153                Ok(val) => Ok(val),
154                Err(kind) => Err(ParseFixedError { kind }),
155            }
156        }
157    };
158}
159
160// Expanded on all signed integers.
161//
162//   * Creates a module named like the integer.
163//   * Expands `all` macro.
164//   * Defines:
165//       - pub const fn from_str
166//       - pub const fn lit
167macro_rules! signed {
168    ($Single:ident, $Uns:ident) => {
169        pub mod $Single {
170            all! { $Single }
171
172            pub(super) const fn from_str(
173                bytes: &[u8],
174                radix: u32,
175                sep: Sep,
176                frac_nbits: u32,
177            ) -> Result<($Single, bool), ParseErrorKind> {
178                let (neg, abs, mut overflow) = match crate::from_str::$Uns::get_int_frac(
179                    bytes,
180                    radix,
181                    sep,
182                    $Single::BITS - frac_nbits,
183                    frac_nbits,
184                ) {
185                    Ok((neg, abs, overflow)) => (neg, abs, overflow),
186                    Err(e) => return Err(e),
187                };
188                let bound = if !neg { $Single::MAX } else { $Single::MIN };
189                if abs > bound.unsigned_abs() {
190                    overflow = true;
191                }
192                let abs = if neg { abs.wrapping_neg() } else { abs } as $Single;
193                Ok((abs, overflow))
194            }
195
196            pub const fn lit(mut s: &[u8], frac_nbits: u32) -> Result<$Single, ParseFixedError> {
197                if s.is_empty() {
198                    return Err(ParseFixedError {
199                        kind: ParseErrorKind::NoDigits,
200                    });
201                }
202                let neg = if s[0] == b'-' {
203                    s = s.split_at(1).1;
204                    true
205                } else {
206                    false
207                };
208                let abs = match crate::from_str::$Uns::lit_no_sign(s, frac_nbits) {
209                    Ok(val) => val,
210                    Err(kind) => return Err(ParseFixedError { kind }),
211                };
212                let bound = if !neg { $Single::MAX } else { $Single::MIN };
213                if abs > bound.unsigned_abs() {
214                    return Err(ParseFixedError {
215                        kind: ParseErrorKind::Overflow,
216                    });
217                }
218                let val = if neg { abs.wrapping_neg() } else { abs } as $Single;
219                Ok(val)
220            }
221        }
222    };
223}
224
225signed! { i8, u8 }
226signed! { i16, u16 }
227signed! { i32, u32 }
228signed! { i64, u64 }
229signed! { i128, u128 }
230
231// Expanded on all unsigned integers.
232//
233//   * Expands `all` macro.
234//   * Defines:
235//       - pub(super) const fn from_str
236//       - pub const fn lit
237//       - pub(super) const fn lit_no_sign
238//       - pub(super) const fn get_int_frac
239//       - pub(super) const fn get_int
240//       - pub(super) const fn get_frac
241//       - const fn bin_str_int_to_bin
242//       - const fn bin_str_frac_to_bin
243//       - const fn oct_str_int_to_bin
244//       - const fn oct_str_frac_to_bin
245//       - const fn hex_str_int_to_bin
246//       - const fn hex_str_frac_to_bin
247//       - pub(super) const fn dec_str_int_to_bin
248//       - const fn dec_str_frac_to_bin
249//       - const fn from_byte
250//       - pub(super) const fn is_odd
251macro_rules! unsigned {
252    ($Uns:ident $(, $Half:ident)?) => {
253        use crate::from_str::{
254            frac_is_half, parse_bounds, unchecked_hex_digit, BitExp, DigitsExp, Parse, Round,
255        };
256
257        all! { $Uns }
258
259        pub(super) const fn from_str(
260            bytes: &[u8],
261            radix: u32,
262            sep: Sep,
263            frac_nbits: u32,
264        ) -> Result<($Uns, bool), ParseErrorKind> {
265            let (neg, abs, mut overflow) =
266                match get_int_frac(bytes, radix, sep, $Uns::BITS - frac_nbits, frac_nbits) {
267                    Ok((neg, abs, overflow)) => (neg, abs, overflow),
268                    Err(e) => return Err(e),
269                };
270            if neg && abs > 0 {
271                overflow = true;
272            }
273            let abs = if neg { abs.wrapping_neg() } else { abs };
274            Ok((abs, overflow))
275        }
276
277        #[inline]
278        pub const fn lit(s: &[u8], frac_nbits: u32) -> Result<$Uns, ParseFixedError> {
279            match lit_no_sign(s, frac_nbits) {
280                Ok(val) => Ok(val),
281                Err(kind) => Err(ParseFixedError { kind }),
282            }
283        }
284
285        pub(super) const fn lit_no_sign(
286            mut bytes: &[u8],
287            frac_nbits: u32,
288        ) -> Result<$Uns, ParseErrorKind> {
289            if bytes.is_empty() {
290                return Err(ParseErrorKind::NoDigits);
291            }
292            let radix = if bytes.len() >= 2 && bytes[0] == b'0' {
293                match bytes[1] {
294                    b'b' => 2,
295                    b'o' => 8,
296                    b'x' => 16,
297                    _ => 10,
298                }
299            } else {
300                10
301            };
302            if radix != 10 {
303                bytes = bytes.split_at(2).1;
304                while let Some((b'_', rest)) = bytes.split_first() {
305                    bytes = rest;
306                }
307            }
308            if let Some((b'-' | b'+', _)) = bytes.split_first() {
309                return Err(ParseErrorKind::MisplacedSign);
310            }
311            match from_str(bytes, radix, Sep::Skip, frac_nbits) {
312                Ok((val, false)) => Ok(val),
313                Ok((_, true)) => Err(ParseErrorKind::Overflow),
314                Err(e) => Err(e),
315            }
316        }
317
318        pub(super) const fn get_int_frac(
319            bytes: &[u8],
320            radix: u32,
321            sep: Sep,
322            int_nbits: u32,
323            frac_nbits: u32,
324        ) -> Result<(bool, $Uns, bool), ParseErrorKind> {
325            let Parse {
326                neg,
327                int,
328                frac,
329                bit_exp,
330            } = match parse_bounds(bytes, radix, sep) {
331                Ok(o) => o,
332                Err(e) => return Err(e),
333            };
334            let (int_val, mut overflow) = get_int(int, radix, int_nbits, bit_exp);
335            let (frac_val, frac_overflow) = match get_frac(frac, radix, frac_nbits, bit_exp) {
336                Some(val) => (val, false),
337                None => (0, true),
338            };
339            let mut val = int_val | frac_val;
340            // frac_overflow does not catch the case where:
341            //  1. int is odd
342            //  2. frac_nbits is 0
343            //  3. frac_bytes is exactly half, e.g. "5" for decimal
344            // In this case, get_frac returns 0.5 rounded to even 0.0,
345            // as it does not have a way to know that int is odd.
346            if frac_overflow || (is_odd(int_val) && frac_nbits == 0 && frac_is_half(frac, radix)) {
347                let (new_val, new_overflow) = if int_nbits == 0 {
348                    (val, true)
349                } else {
350                    val.overflowing_add(1 << frac_nbits)
351                };
352                if new_overflow {
353                    overflow = true;
354                }
355                val = new_val;
356            }
357            Ok((neg, val, overflow))
358        }
359
360        pub(super) const fn get_int(
361            int: DigitsExp,
362            radix: u32,
363            nbits: u32,
364            bit_exp: Option<BitExp>,
365        ) -> ($Uns, bool) {
366            $(
367                if nbits <= $Half::BITS {
368                    let (half, overflow) =
369                        crate::from_str::$Half::get_int(int, radix, nbits, bit_exp);
370                    return ((half as $Uns) << $Half::BITS, overflow);
371                }
372            )?
373
374            if int.is_empty() && bit_exp.is_none() {
375                return (0, false);
376            }
377            let (mut parsed_int, mut overflow): ($Uns, bool) = match radix {
378                2 => bin_str_int_to_bin(int),
379                8 => oct_str_int_to_bin(int, bit_exp),
380                16 => hex_str_int_to_bin(int, bit_exp),
381                _ => {
382                    debug_assert!(radix == 10);
383                    dec_str_int_to_bin(int)
384                }
385            };
386            let remove_bits = $Uns::BITS - nbits;
387            if nbits == 0 {
388                overflow = true;
389                parsed_int = 0;
390            } else if remove_bits > 0 {
391                if (parsed_int >> nbits) != 0 {
392                    overflow = true;
393                }
394                parsed_int <<= remove_bits;
395            }
396            (parsed_int, overflow)
397        }
398
399        pub(super) const fn get_frac(
400            frac: DigitsExp,
401            radix: u32,
402            nbits: u32,
403            bit_exp: Option<BitExp>,
404        ) -> Option<$Uns> {
405            $(
406                if nbits <= $Half::BITS {
407                    return match crate::from_str::$Half::get_frac(frac, radix, nbits, bit_exp) {
408                        Some(half) => Some(half as $Uns),
409                        None => None,
410                    };
411                }
412            )?
413
414            if frac.is_empty() {
415                return Some(0);
416            }
417            match radix {
418                2 => bin_str_frac_to_bin(frac, nbits),
419                8 => oct_str_frac_to_bin(frac, nbits, bit_exp),
420                16 => hex_str_frac_to_bin(frac, nbits, bit_exp),
421                _ => {
422                    debug_assert!(radix == 10);
423                    dec_str_frac_to_bin(frac, nbits)
424                }
425            }
426        }
427
428        const fn bin_str_int_to_bin(digits: DigitsExp) -> ($Uns, bool) {
429            let max_len = $Uns::BITS as usize;
430            let (digits, overflow) = if digits.len() > max_len {
431                let (_, last_max_len) = digits.split_at(digits.len() - max_len);
432                (last_max_len, true)
433            } else {
434                (digits, false)
435            };
436            let mut acc = 0;
437            let mut rem_digits = digits;
438            while let Some((digit, rem)) = rem_digits.split_first() {
439                rem_digits = rem;
440
441                acc = (acc << 1) + from_byte(digit - b'0');
442            }
443            (acc, overflow)
444        }
445
446        const fn bin_str_frac_to_bin(digits: DigitsExp, nbits: u32) -> Option<$Uns> {
447            let mut rem_bits = nbits;
448            let mut acc = 0;
449            let mut rem_digits = digits;
450            while let Some((digit, rem)) = rem_digits.split_first() {
451                rem_digits = rem;
452
453                let val = digit - b'0';
454                if rem_bits < 1 {
455                    if val != 0 {
456                        // half bit is true, round up if we have more
457                        // significant bits or currently acc is odd
458                        if !rem_digits.is_empty() || is_odd(acc) {
459                            acc = match acc.checked_add(1) {
460                                Some(acc) => acc,
461                                None => return None,
462                            };
463                        }
464                    }
465                    if nbits != $Uns::BITS && acc >> nbits != 0 {
466                        return None;
467                    }
468                    return Some(acc);
469                }
470                acc = (acc << 1) + from_byte(val);
471                rem_bits -= 1;
472            }
473            Some(acc << rem_bits)
474        }
475
476        const fn oct_str_int_to_bin(digits: DigitsExp, bit_exp: Option<BitExp>) -> ($Uns, bool) {
477            let (exp, exp_extra_digit) = match bit_exp {
478                Some(s) => (s.exp.get(), s.first_frac_digit),
479                None => (0, 0),
480            };
481            // handle condition where exp_extra_digit is only digit we have
482            if digits.is_empty() {
483                let val = (from_byte(exp_extra_digit - b'0')) >> (3 - exp);
484                return (val, false)
485            }
486            // max_digits does not count exp_extra_digit, which holds exp bits we'll use.
487            let max_digits = ($Uns::BITS - exp).div_ceil(3) as usize;
488            let (digits, mut overflow) = if digits.len() > max_digits {
489                let (_, last_max_digits) = digits.split_at(digits.len() - max_digits);
490                (last_max_digits, true)
491            } else {
492                (digits, false)
493            };
494            let Some((first_digit, mut rem_digits)) = digits.split_first() else {
495                unreachable!();
496            };
497            let mut acc = from_byte(first_digit - b'0');
498            if digits.len() == max_digits {
499                let first_max_bits = $Uns::BITS - exp - (max_digits as u32 - 1) * 3;
500                let first_max = (from_byte(1) << first_max_bits) - 1;
501                if acc > first_max {
502                    overflow = true;
503                }
504            }
505            while let Some((digit, rem)) = rem_digits.split_first() {
506                rem_digits = rem;
507
508                acc = (acc << 3) + from_byte(digit - b'0');
509            }
510            if bit_exp.is_some() {
511                let val = (exp_extra_digit - b'0') >> (3 - exp);
512                acc = (acc << exp) + from_byte(val);
513            }
514            (acc, overflow)
515        }
516
517        const fn oct_str_frac_to_bin(
518            digits: DigitsExp,
519            nbits: u32,
520            bit_exp: Option<BitExp>,
521        ) -> Option<$Uns> {
522            let mut rem_bits = nbits;
523            let mut acc = 0;
524            let mut rem_digits = digits;
525            let mut val_bits = match bit_exp {
526                Some(s) => 3 - s.exp.get(),
527                None => 3,
528            };
529            while let Some((digit, rem)) = rem_digits.split_first() {
530                rem_digits = rem;
531
532                // If val_bits is not 3, we need to skip some bits
533                let val = if val_bits != 3 {
534                    let first_digit_mask = (1 << val_bits) - 1;
535                    (digit - b'0') & first_digit_mask
536                } else {
537                    digit - b'0'
538                };
539                if rem_bits < val_bits {
540                    acc = (acc << rem_bits) + from_byte(val >> (3 - rem_bits));
541                    let half = 1 << (2 - rem_bits);
542                    if val & half != 0 {
543                        // half bit is true, round up if we have more
544                        // significant bits or currently acc is odd
545                        if val & (half - 1) != 0 || !rem_digits.is_empty() || is_odd(acc) {
546                            acc = match acc.checked_add(1) {
547                                Some(acc) => acc,
548                                None => return None,
549                            };
550                        }
551                    }
552                    if nbits != $Uns::BITS && acc >> nbits != 0 {
553                        return None;
554                    }
555                    return Some(acc);
556                }
557                acc = (acc << 3) + from_byte(val);
558                rem_bits -= val_bits;
559                val_bits = 3;
560            }
561            Some(acc << rem_bits)
562        }
563
564        const fn hex_str_int_to_bin(digits: DigitsExp, bit_exp: Option<BitExp>) -> ($Uns, bool) {
565            let (exp, exp_extra_digit) = match bit_exp {
566                Some(s) => (s.exp.get(), s.first_frac_digit),
567                None => (0, 0),
568            };
569            // handle condition where exp_extra_digit is only digit we have
570            if digits.is_empty() {
571                let val = (from_byte(exp_extra_digit - b'0')) >> (3 - exp);
572                return (val, false)
573            }
574            // max_digits does not count exp_extra_digit, which holds exp bits we'll use.
575            let max_digits = ($Uns::BITS - exp).div_ceil(4) as usize;
576            let (digits, mut overflow) = if digits.len() > max_digits {
577                let (_, last_max_digits) = digits.split_at(digits.len() - max_digits);
578                (last_max_digits, true)
579            } else {
580                (digits, false)
581            };
582            let Some((first_digit, mut rem_digits)) = digits.split_first() else {
583                unreachable!();
584            };
585            let mut acc = from_byte(unchecked_hex_digit(first_digit));
586            if digits.len() == max_digits {
587                let first_max_bits = $Uns::BITS - exp - (max_digits as u32 - 1) * 4;
588                let first_max = (from_byte(1) << first_max_bits) - 1;
589                if acc > first_max {
590                    overflow = true;
591                }
592            }
593            while let Some((digit, rem)) = rem_digits.split_first() {
594                rem_digits = rem;
595
596                acc = (acc << 4) + from_byte(unchecked_hex_digit(digit));
597            }
598            if bit_exp.is_some() {
599                let val = unchecked_hex_digit(exp_extra_digit) >> (4 - exp);
600                acc = (acc << exp) + from_byte(val);
601            }
602            (acc, overflow)
603        }
604
605        const fn hex_str_frac_to_bin(
606            digits: DigitsExp,
607            nbits: u32,
608            bit_exp: Option<BitExp>,
609        ) -> Option<$Uns> {
610            let mut rem_bits = nbits;
611            let mut acc = 0;
612            let mut rem_digits = digits;
613            let mut val_bits = match bit_exp {
614                Some(s) => 4 - s.exp.get(),
615                None => 4,
616            };
617            while let Some((digit, rem)) = rem_digits.split_first() {
618                rem_digits = rem;
619
620                // If val_bits is not 4, we need to skip some bits
621                let val = if val_bits != 4 {
622                    let first_digit_mask = (1 << val_bits) - 1;
623                    unchecked_hex_digit(digit) & first_digit_mask
624                } else {
625                    unchecked_hex_digit(digit)
626                };
627                if rem_bits < val_bits {
628                    acc = (acc << rem_bits) + from_byte(val >> (4 - rem_bits));
629                    let half = 1 << (3 - rem_bits);
630                    if val & half != 0 {
631                        // half bit is true, round up if we have more
632                        // significant bits or currently acc is odd
633                        if val & (half - 1) != 0 || !rem_digits.is_empty() || is_odd(acc) {
634                            acc = match acc.checked_add(1) {
635                                Some(acc) => acc,
636                                None => return None,
637                            };
638                        }
639                    }
640                    if nbits != $Uns::BITS && acc >> nbits != 0 {
641                        return None;
642                    }
643                    return Some(acc);
644                }
645                acc = (acc << 4) + from_byte(val);
646                rem_bits -= val_bits;
647                val_bits = 4;
648            }
649            Some(acc << rem_bits)
650        }
651
652        pub(super) const fn dec_str_int_to_bin(digits: DigitsExp) -> ($Uns, bool) {
653            let max_effective_len = $Uns::BITS as usize;
654            let (digits, mut overflow) = if digits.len() > max_effective_len {
655                let (_, last_max_effective_len) = digits.split_at(digits.len() - max_effective_len);
656                (last_max_effective_len, true)
657            } else {
658                (digits, false)
659            };
660            let mut acc = 0;
661            let mut rem_digits = digits;
662            while let Some((digit, rem)) = rem_digits.split_first() {
663                rem_digits = rem;
664
665                let (prod, mul_overflow) = mul10_overflow(acc);
666                let (add, add_overflow) = prod.overflowing_add(from_byte(digit - b'0'));
667                acc = add;
668                overflow = overflow || mul_overflow != 0 || add_overflow;
669            }
670            (acc, overflow)
671        }
672
673        const fn dec_str_frac_to_bin(digits: DigitsExp, nbits: u32) -> Option<$Uns> {
674            let (val, is_short) = parse_is_short(digits);
675            let one: $Uns = 1;
676            let dump_bits = $Uns::BITS - nbits;
677            // if is_short, dec_to_bin can round and give correct answer immediately
678            let round = if is_short {
679                Round::Nearest
680            } else {
681                Round::Floor
682            };
683            let Some(floor) = dec_to_bin(val, nbits, round) else {
684                return None;
685            };
686            if is_short {
687                return Some(floor);
688            }
689            // since !is_short, we have a floor and we have to check whether
690            // we need to increment
691
692            // add_5 is to add rounding when all bits are used
693            let (mut boundary, mut add_5) = if nbits == 0 {
694                (one << ($Uns::BITS - 1), false)
695            } else if dump_bits == 0 {
696                (floor, true)
697            } else {
698                ((floor << dump_bits) + (one << (dump_bits - 1)), false)
699            };
700            let mut tie = true;
701            let mut rem_digits = digits;
702            while let Some((digit, rem)) = rem_digits.split_first() {
703                rem_digits = rem;
704
705                if !add_5 && boundary == 0 {
706                    // since zeros are trimmed, there must be some digit > 0 eventually
707                    tie = false;
708                    break;
709                }
710                let (prod, mut boundary_digit) = mul10_overflow(boundary);
711                boundary = prod;
712                if add_5 {
713                    let (wrapped, overflow) = boundary.overflowing_add(5);
714                    boundary = wrapped;
715                    if overflow {
716                        boundary_digit += 1;
717                    }
718                    add_5 = false;
719                }
720                if digit - b'0' < boundary_digit {
721                    return Some(floor);
722                }
723                if digit - b'0' > boundary_digit {
724                    tie = false;
725                    break;
726                }
727            }
728            if tie && !is_odd(floor) {
729                return Some(floor);
730            }
731            let Some(next_up) = floor.checked_add(1) else  {
732                return None;
733            };
734            if dump_bits != 0 && next_up >> nbits != 0 {
735                None
736            } else {
737                Some(next_up)
738            }
739        }
740
741        const fn from_byte(b: u8) -> $Uns {
742            b as $Uns
743        }
744
745        pub(super) const fn is_odd(val: $Uns) -> bool {
746            val & 1 != 0
747        }
748    };
749}
750
751// Expanded on all unsigned integers except u128.
752//
753//   * Creates a module named like the integer.
754//   * Expands `unsigned` macro.
755//   * Defines:
756//       - const fn mul10_overflow
757//       - pub(super) const fn dec_to_bin
758//       - const fn parse_is_short
759macro_rules! unsigned_not_u128 {
760    ($Single:ident $(, $Half:ident)?; $Double:ident, $dec:expr, $bin:expr) => {
761        pub mod $Single {
762            unsigned! { $Single $(, $Half)? }
763
764            #[inline]
765            const fn mul10_overflow(x: $Single) -> ($Single, u8) {
766                let prod = (x as $Double) * 10;
767                (prod as $Single, (prod >> <$Single>::BITS) as u8)
768            }
769
770            pub(super) const fn dec_to_bin(
771                val: $Double,
772                nbits: u32,
773                round: Round,
774            ) -> Option<$Single> {
775                debug_assert!(val < $Double::pow(10, $dec));
776                debug_assert!(nbits <= $bin);
777                let fives = $Double::pow(5, $dec);
778                let denom = fives * 2;
779                let mut numer = val << ($bin - $dec + 1) >> ($bin - nbits);
780                match round {
781                    Round::Nearest => {
782                        // Round up, then round back down if we had a tie and the result is odd.
783                        numer += fives;
784                        // If unrounded division == 1 exactly, we actually have a tie at upper
785                        // bound, which is rounded up to 1.0. This is even in all cases except
786                        // when nbits == 0, in which case we must round it back down to 0.
787                        if numer >> nbits >= denom {
788                            // 0.5 exactly is 10^$dec / 2 = 5^dec * 2^dec / 2 = fives << ($dec - 1)
789                            return if nbits == 0 && val == fives << ($dec - 1) {
790                                Some(0)
791                            } else {
792                                None
793                            };
794                        }
795                    }
796                    Round::Floor => {}
797                }
798                let (mut div, tie) = (numer / denom, numer % denom == 0);
799                if tie && crate::from_str::$Double::is_odd(div) {
800                    div -= 1;
801                }
802                Some(div as $Single)
803            }
804
805            const fn parse_is_short(digits: DigitsExp) -> ($Double, bool) {
806                let (is_short, slice, pad) =
807                    if let Some(rem) = usize::checked_sub($dec, digits.len()) {
808                        (true, digits, $Double::pow(10, rem as u32))
809                    } else {
810                        let (short, _) = digits.split_at($dec);
811                        (false, short, 1)
812                    };
813                let val = crate::from_str::$Double::dec_str_int_to_bin(slice).0 * pad;
814                (val, is_short)
815            }
816        }
817    };
818}
819
820unsigned_not_u128! { u8; u16, 3, 8 }
821unsigned_not_u128! { u16, u8; u32, 6, 16 }
822unsigned_not_u128! { u32, u16; u64, 13, 32 }
823unsigned_not_u128! { u64, u32; u128, 27, 64 }
824
825pub mod u128 {
826    unsigned! { u128, u64 }
827
828    use crate::int256;
829    use crate::int256::U256;
830    use core::num::NonZeroU128;
831
832    #[inline]
833    const fn mul10_overflow(x: u128) -> (u128, u8) {
834        const LO_MASK: u128 = !(!0 << 64);
835        let hi = (x >> 64) * 10;
836        let lo = (x & LO_MASK) * 10;
837        // Generates better code than:
838        //     let (wrapped, overflow) = (hi << 64).overflowing_add(lo);
839        //     ((hi >> 64) as u8 + u8::from(overflow), wrapped)
840        let (hi_lo, hi_hi) = (hi as u64, (hi >> 64) as u64);
841        let (lo_lo, lo_hi) = (lo as u64, (lo >> 64) as u64);
842        let (wrapped, overflow) = hi_lo.overflowing_add(lo_hi);
843        (
844            ((wrapped as u128) << 64) | (lo_lo as u128),
845            (hi_hi as u8) + (overflow as u8),
846        )
847    }
848
849    pub(super) const fn dec_to_bin(
850        (hi, lo): (u128, u128),
851        nbits: u32,
852        round: Round,
853    ) -> Option<u128> {
854        debug_assert!(hi < 10u128.pow(27));
855        debug_assert!(lo < 10u128.pow(27));
856        debug_assert!(nbits <= 128);
857        let fives = 5u128.pow(54);
858        let denom = fives * 2;
859        let Some(denom) = NonZeroU128::new(denom) else {
860            unreachable!();
861        };
862        // we need to combine (10^27*hi + lo) << (128 - 54 + 1)
863        let hi_e27 = int256::wide_mul_u128(hi, 10u128.pow(27));
864        let (val_lo, overflow) = hi_e27.lo.overflowing_add(lo);
865        let val_hi = hi_e27.hi + (overflow as u128);
866        let (mut numer_lo, mut numer_hi) = (val_lo, val_hi);
867        if nbits < (54 - 1) {
868            let shr = (54 - 1) - nbits;
869            numer_lo = (numer_lo >> shr) | (numer_hi << (128 - shr));
870            numer_hi >>= shr;
871        } else if nbits > (54 - 1) {
872            let shl = nbits - (54 - 1);
873            numer_hi = (numer_hi << shl) | (numer_lo >> (128 - shl));
874            numer_lo <<= shl;
875        }
876        match round {
877            Round::Nearest => {
878                // Round up, then round back down if we had a tie and the result is odd.
879                let (wrapped, overflow) = numer_lo.overflowing_add(fives);
880                numer_lo = wrapped;
881                if overflow {
882                    numer_hi += 1;
883                }
884                let check_overflow = if nbits == 128 {
885                    numer_hi
886                } else if nbits == 0 {
887                    numer_lo
888                } else {
889                    (numer_lo >> nbits) | (numer_hi << (128 - nbits))
890                };
891                // If unrounded division == 1 exactly, we actually have a tie at upper
892                // bound, which is rounded up to 1.0. This is even in all cases except
893                // when nbits == 0, in which case we must round it back down to 0.
894                if check_overflow >= denom.get() {
895                    // 0.5 exactly is 10^$dec / 2 = 5^dec * 2^dec / 2 = fives << ($dec - 1)
896                    let half_hi = fives >> (128 - (54 - 1));
897                    let half_lo = fives << (54 - 1);
898                    return if nbits == 0 && val_hi == half_hi && val_lo == half_lo {
899                        Some(0)
900                    } else {
901                        None
902                    };
903                }
904            }
905            Round::Floor => {}
906        }
907        let (mut div, tie) = div_tie(numer_hi, numer_lo, denom);
908        if tie && is_odd(div) {
909            div -= 1;
910        }
911        Some(div)
912    }
913
914    const fn parse_is_short(digits: DigitsExp) -> ((u128, u128), bool) {
915        if let Some(rem) = 27usize.checked_sub(digits.len()) {
916            let hi = dec_str_int_to_bin(digits).0 * 10u128.pow(rem as u32);
917            ((hi, 0), true)
918        } else {
919            let (begin, end) = digits.split_at(27);
920            let hi = dec_str_int_to_bin(begin).0;
921
922            let (is_short, slice, pad) = if let Some(rem) = 54usize.checked_sub(digits.len()) {
923                (true, end, 10u128.pow(rem as u32))
924            } else {
925                let (mid, _) = end.split_at(27);
926                (false, mid, 1)
927            };
928            let lo = dec_str_int_to_bin(slice).0 * pad;
929            ((hi, lo), is_short)
930        }
931    }
932
933    const fn div_tie(dividend_hi: u128, dividend_lo: u128, divisor: NonZeroU128) -> (u128, bool) {
934        let dividend = U256 {
935            lo: dividend_lo,
936            hi: dividend_hi,
937        };
938        let (quot, rem) = int256::div_rem_u256_u128(dividend, divisor);
939        (quot.lo, rem == 0)
940    }
941}
942
943const fn unchecked_hex_digit(byte: u8) -> u8 {
944    // We know that byte is a valid hex:
945    //   * b'0'..=b'9' (0x30..=0x39) => byte & 0x0f
946    //   * b'A'..=b'F' (0x41..=0x46) => byte & 0x0f + 9
947    //   * b'a'..=b'f' (0x61..=0x66) => byte & 0x0f + 9
948    (byte & 0x0f) + if byte >= 0x40 { 9 } else { 0 }
949}
950
951#[derive(Clone, Copy, Debug)]
952pub enum Round {
953    Nearest,
954    Floor,
955}
956
957#[derive(Clone, Copy, Debug)]
958struct BitExp {
959    exp: NonZeroU32,
960    first_frac_digit: u8,
961}
962
963impl BitExp {
964    const fn new(bit_exp: u32, frac: DigitsExp) -> Option<BitExp> {
965        let Some(exp) = NonZeroU32::new(bit_exp) else {
966            return None;
967        };
968        let first_frac_digit = match frac.split_first() {
969            Some((digit, _)) => digit,
970            None => b'0',
971        };
972        Some(BitExp {
973            exp,
974            first_frac_digit,
975        })
976    }
977}
978
979//   * bit_exp.exp can be {1,2} for octal or {1,2,3} for hex.
980//   * For all other cases, bit_exp is None.
981#[derive(Clone, Copy, Debug)]
982struct Parse<'a> {
983    neg: bool,
984    int: DigitsExp<'a>,
985    frac: DigitsExp<'a>,
986    bit_exp: Option<BitExp>,
987}
988
989#[derive(Clone, Copy, Debug)]
990pub enum Sep {
991    Skip,
992    Error,
993}
994
995/**
996An error which can be returned when parsing a fixed-point number.
997
998# Examples
999
1000```rust
1001use fixed::types::I16F16;
1002use fixed::ParseFixedError;
1003// This string is not a fixed-point number.
1004let s = "something completely different (_!_!_)";
1005let error: ParseFixedError = match s.parse::<I16F16>() {
1006    Ok(_) => unreachable!(),
1007    Err(error) => error,
1008};
1009println!("Parse error: {error}");
1010```
1011*/
1012#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1013pub struct ParseFixedError {
1014    kind: ParseErrorKind,
1015}
1016
1017#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1018enum ParseErrorKind {
1019    InvalidDigit,
1020    MisplacedSign,
1021    MisplacedUnderscore,
1022    NoDigits,
1023    TooManyPoints,
1024    Overflow,
1025    ExpInvalidDigit,
1026    ExpNoDigits,
1027    TooManyExp,
1028    ExpOverflow,
1029}
1030
1031impl ParseFixedError {
1032    #[inline]
1033    #[track_caller]
1034    pub(crate) const fn lit_message(self) -> &'static str {
1035        use self::ParseErrorKind::*;
1036        match self.kind {
1037            InvalidDigit => "invalid literal: invalid digit found in string",
1038            MisplacedSign => "invalid literal: misplaced sign found in string",
1039            MisplacedUnderscore => "invalid literal: misplaced underscore found in string",
1040            NoDigits => "invalid literal: string has no digits",
1041            TooManyPoints => "invalid literal: more than one point found in string",
1042            Overflow => "invalid literal: overflow",
1043            ExpInvalidDigit => "invalid literal: invalid digit found in exponent",
1044            ExpNoDigits => "invalid literal: exponent has no digits",
1045            TooManyExp => "invalid literal: more than one exponent found",
1046            ExpOverflow => "invalid literal: exponent overflow",
1047        }
1048    }
1049
1050    #[inline]
1051    pub(crate) const fn message(self) -> &'static str {
1052        use self::ParseErrorKind::*;
1053        match self.kind {
1054            InvalidDigit => "invalid digit found in string",
1055            MisplacedSign => "misplaced sign found in string",
1056            MisplacedUnderscore => "misplaced underscore found in string",
1057            NoDigits => "string has no digits",
1058            TooManyPoints => "more than one point found in string",
1059            Overflow => "overflow",
1060            ExpInvalidDigit => "invalid digit found in exponent",
1061            ExpNoDigits => "exponent has no digits",
1062            TooManyExp => "more than one exponent found",
1063            ExpOverflow => "exponent overflow",
1064        }
1065    }
1066}
1067
1068impl Display for ParseFixedError {
1069    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
1070        Display::fmt(self.message(), f)
1071    }
1072}
1073
1074impl Error for ParseFixedError {
1075    fn description(&self) -> &str {
1076        self.message()
1077    }
1078}
1079
1080// Zeros at start of int and at end of frac are trimmed.
1081// Leading underscores for either int or frac are never accepted, even for Sep::Skip.
1082const fn parse_bounds(bytes: &[u8], radix: u32, sep: Sep) -> Result<Parse<'_>, ParseErrorKind> {
1083    let mut sign: Option<bool> = None;
1084    let mut int_start: Option<usize> = None;
1085    let mut point: Option<usize> = None;
1086    let mut frac_end: Option<usize> = None;
1087    let mut has_int_digit = false;
1088    let mut has_frac_digit = false;
1089    let mut exp_sep: Option<usize> = None;
1090    let mut exp_sign: Option<bool> = None;
1091    let mut exp: i32 = 0;
1092    let mut has_exp_digit = false;
1093    let mut exp_is_bit = false;
1094
1095    let mut next_index = 0;
1096    let mut rem_bytes = bytes;
1097    while let Some((&byte, rem)) = rem_bytes.split_first() {
1098        let index = next_index;
1099        next_index += 1;
1100        rem_bytes = rem;
1101
1102        match (byte, radix) {
1103            (b'+', _) => {
1104                if exp_sep.is_none() {
1105                    if sign.is_some() || has_int_digit || point.is_some() {
1106                        return Err(ParseErrorKind::MisplacedSign);
1107                    }
1108                    sign = Some(false);
1109                } else {
1110                    if exp_sign.is_some() || has_exp_digit {
1111                        return Err(ParseErrorKind::MisplacedSign);
1112                    }
1113                    exp_sign = Some(false);
1114                }
1115            }
1116            (b'-', _) => {
1117                if exp_sep.is_none() {
1118                    if sign.is_some() || has_int_digit || point.is_some() {
1119                        return Err(ParseErrorKind::MisplacedSign);
1120                    }
1121                    sign = Some(true);
1122                } else {
1123                    if exp_sign.is_some() || has_exp_digit {
1124                        return Err(ParseErrorKind::MisplacedSign);
1125                    }
1126                    exp_sign = Some(true);
1127                }
1128            }
1129            (b'.', _) => {
1130                if exp_sep.is_some() {
1131                    return Err(ParseErrorKind::ExpInvalidDigit);
1132                }
1133                if point.is_some() {
1134                    return Err(ParseErrorKind::TooManyPoints);
1135                }
1136                point = Some(index);
1137                frac_end = Some(index + 1);
1138            }
1139            (b'_', _) => {
1140                if matches!(sep, Sep::Error) {
1141                    if exp_sep.is_some() {
1142                        return Err(ParseErrorKind::ExpInvalidDigit);
1143                    }
1144                    return Err(ParseErrorKind::InvalidDigit);
1145                };
1146                if (point.is_none() && exp_sep.is_none() && !has_int_digit)
1147                    || (point.is_some() && exp_sep.is_none() && !has_frac_digit)
1148                    || (exp_sep.is_some() && !has_exp_digit)
1149                {
1150                    return Err(ParseErrorKind::MisplacedUnderscore);
1151                }
1152            }
1153            (b'e' | b'E', 2 | 8 | 10) | (b'@', _) => {
1154                if exp_sep.is_some() {
1155                    return Err(ParseErrorKind::TooManyExp);
1156                }
1157                exp_sep = Some(index);
1158            }
1159            (b'p' | b'P', 2 | 8 | 16) => {
1160                if exp_sep.is_some() {
1161                    return Err(ParseErrorKind::TooManyExp);
1162                }
1163                exp_sep = Some(index);
1164                exp_is_bit = true;
1165            }
1166            (b'0'..=b'1', 2)
1167            | (b'0'..=b'7', 8)
1168            | (b'0'..=b'9', 10)
1169            | (b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F', 16)
1170                if exp_sep.is_none() =>
1171            {
1172                if point.is_none() {
1173                    has_int_digit = true;
1174                    if int_start.is_none() && byte != b'0' {
1175                        int_start = Some(index);
1176                    }
1177                } else {
1178                    has_frac_digit = true;
1179                    if byte != b'0' {
1180                        frac_end = Some(index + 1);
1181                    }
1182                }
1183            }
1184            (b'0'..=b'9', _) if exp_sep.is_some() => {
1185                exp = match exp.checked_mul(10) {
1186                    Some(s) => s,
1187                    None => {
1188                        return Err(ParseErrorKind::ExpOverflow);
1189                    }
1190                };
1191                let add = match exp_sign {
1192                    Some(true) => -((byte - b'0') as i32),
1193                    Some(false) | None => (byte - b'0') as i32,
1194                };
1195                exp = match exp.checked_add(add) {
1196                    Some(s) => s,
1197                    None => {
1198                        return Err(ParseErrorKind::ExpOverflow);
1199                    }
1200                };
1201                has_exp_digit = true;
1202            }
1203            _ => {
1204                if exp_sep.is_some() {
1205                    return Err(ParseErrorKind::ExpInvalidDigit);
1206                }
1207                return Err(ParseErrorKind::InvalidDigit);
1208            }
1209        }
1210    }
1211    if !has_int_digit && !has_frac_digit {
1212        return Err(ParseErrorKind::NoDigits);
1213    }
1214    if exp_sep.is_some() && !has_exp_digit {
1215        return Err(ParseErrorKind::ExpNoDigits);
1216    }
1217    // workaround for https://github.com/rust-lang/rust-clippy/issues/12568
1218    #[allow(unknown_lints, clippy::manual_unwrap_or_default)]
1219    let neg = match sign {
1220        Some(s) => s,
1221        None => false,
1222    };
1223    let int = match (int_start, point, exp_sep) {
1224        (Some(begin), Some(end), _) | (Some(begin), None, Some(end)) => {
1225            let (up_to_end, _) = bytes.split_at(end);
1226            let (_, from_begin) = up_to_end.split_at(begin);
1227            DigitsUnds::new(from_begin)
1228        }
1229        (Some(begin), None, None) => {
1230            let (_, from_begin) = bytes.split_at(begin);
1231            DigitsUnds::new(from_begin)
1232        }
1233        (None, _, _) => DigitsUnds::EMPTY,
1234    };
1235    let frac = match (point, frac_end) {
1236        (Some(point), Some(end)) => {
1237            let (up_to_end, _) = bytes.split_at(end);
1238            let (_, from_after_point) = up_to_end.split_at(point + 1);
1239            DigitsUnds::new(from_after_point)
1240        }
1241        _ => DigitsUnds::EMPTY,
1242    };
1243    let bit_exp = if exp_is_bit {
1244        match radix {
1245            2 => 0,
1246            8 => {
1247                let (q, r) = (exp.div_euclid(3), exp.rem_euclid(3));
1248                exp = q;
1249                r.unsigned_abs()
1250            }
1251            16 => {
1252                let (q, r) = (exp.div_euclid(4), exp.rem_euclid(4));
1253                exp = q;
1254                r.unsigned_abs()
1255            }
1256            _ => unreachable!(),
1257        }
1258    } else {
1259        0
1260    };
1261    let Some((int, frac)) = DigitsExp::new_int_frac(int, frac, exp) else {
1262        return Err(ParseErrorKind::ExpOverflow);
1263    };
1264    let bit_exp = BitExp::new(bit_exp, frac);
1265    Ok(Parse {
1266        neg,
1267        int,
1268        frac,
1269        bit_exp,
1270    })
1271}
1272
1273const fn frac_is_half(digits: DigitsExp, radix: u32) -> bool {
1274    // since zeros are trimmed, when the value is one half there has to be
1275    // exatly one digit, and rest has to be empty
1276    match digits.split_first() {
1277        Some((digit, rest)) => digit - b'0' == (radix as u8) / 2 && rest.is_empty(),
1278        None => false,
1279    }
1280}
1281
1282macro_rules! impl_from_str {
1283    ($Fixed:ident, $LeEqU:ident) => {
1284        impl<Frac: $LeEqU> FromStr for $Fixed<Frac> {
1285            type Err = ParseFixedError;
1286            /// Parses a string slice to return a fixed-point number.
1287            ///
1288            /// Rounding is to the nearest, with ties rounded to even.
1289            #[inline]
1290            fn from_str(s: &str) -> Result<Self, Self::Err> {
1291                Self::from_str(s)
1292            }
1293        }
1294    };
1295}
1296impl_from_str! { FixedI8, LeEqU8 }
1297impl_from_str! { FixedI16, LeEqU16 }
1298impl_from_str! { FixedI32, LeEqU32 }
1299impl_from_str! { FixedI64, LeEqU64 }
1300impl_from_str! { FixedI128, LeEqU128 }
1301impl_from_str! { FixedU8, LeEqU8 }
1302impl_from_str! { FixedU16, LeEqU16 }
1303impl_from_str! { FixedU32, LeEqU32 }
1304impl_from_str! { FixedU64, LeEqU64 }
1305impl_from_str! { FixedU128, LeEqU128 }
1306
1307#[cfg(test)]
1308mod tests {
1309    use crate::bytes::DigitsExp;
1310    use crate::from_str;
1311    use crate::from_str::{Parse, ParseErrorKind, ParseFixedError, Round, Sep, parse_bounds};
1312    use crate::types::*;
1313    use std::format;
1314    #[cfg(not(feature = "std"))]
1315    use std::string::{String, ToString};
1316
1317    #[test]
1318    fn overflowing() {
1319        let overflow = ParseFixedError {
1320            kind: ParseErrorKind::Overflow,
1321        };
1322        assert_eq!(
1323            U4F4::overflowing_from_str("15.5"),
1324            Ok((U4F4::from_bits(0xF8), false))
1325        );
1326        assert_eq!(U4F4::from_str("15.5"), Ok(U4F4::from_bits(0xF8)));
1327        assert_eq!(
1328            U4F4::overflowing_from_str("31.5"),
1329            Ok((U4F4::from_bits(0xF8), true))
1330        );
1331        assert_eq!(U4F4::from_str("31.5"), Err(overflow));
1332        assert_eq!(
1333            U4F4::overflowing_from_str("271.5"),
1334            Ok((U4F4::from_bits(0xF8), true))
1335        );
1336        assert_eq!(
1337            U8F0::overflowing_from_str("271"),
1338            Ok((U8F0::from_bits(0x0F), true))
1339        );
1340        let longer_than_8 = format!("{}", (1 << 30) + 15);
1341        assert_eq!(
1342            U8F0::overflowing_from_str(&longer_than_8),
1343            Ok((U8F0::from_bits(0x0F), true))
1344        );
1345
1346        assert_eq!(
1347            U4F4::overflowing_from_str_binary("1111.1000"),
1348            Ok((U4F4::from_bits(0xF8), false))
1349        );
1350        assert_eq!(
1351            U4F4::from_str_binary("1111.1000"),
1352            Ok(U4F4::from_bits(0xF8))
1353        );
1354        assert_eq!(
1355            U4F4::overflowing_from_str_binary("11111.1000"),
1356            Ok((U4F4::from_bits(0xF8), true))
1357        );
1358        assert_eq!(U4F4::from_str_binary("11111.1000"), Err(overflow));
1359        assert_eq!(
1360            U8F0::overflowing_from_str_binary("100001111"),
1361            Ok((U8F0::from_bits(0x0F), true))
1362        );
1363
1364        assert_eq!(
1365            U4F4::overflowing_from_str_octal("17.7"),
1366            Ok((U4F4::from_bits(0xFE), false))
1367        );
1368        assert_eq!(U4F4::from_str_octal("17.7"), Ok(U4F4::from_bits(0xFE)));
1369        assert_eq!(
1370            U4F4::overflowing_from_str_octal("77.7"),
1371            Ok((U4F4::from_bits(0xFE), true))
1372        );
1373        assert_eq!(U4F4::from_str_octal("77.7"), Err(overflow));
1374        assert_eq!(
1375            U4F4::overflowing_from_str_octal("707.7"),
1376            Ok((U4F4::from_bits(0x7E), true))
1377        );
1378        assert_eq!(
1379            U8F0::overflowing_from_str_octal("1307"),
1380            Ok((U8F0::from_bits(0o307), true))
1381        );
1382
1383        assert_eq!(
1384            U6F10::overflowing_from_str_hex("3F.8"),
1385            Ok((U6F10::from_bits(0xFE00), false))
1386        );
1387        assert_eq!(U6F10::from_str_hex("3F.8"), Ok(U6F10::from_bits(0xFE00)));
1388        assert_eq!(
1389            U6F10::overflowing_from_str_hex("FF.8"),
1390            Ok((U6F10::from_bits(0xFE00), true))
1391        );
1392        assert_eq!(U6F10::from_str_hex("FF.8"), Err(overflow));
1393        assert_eq!(
1394            U6F10::overflowing_from_str_hex("F0F.8"),
1395            Ok((U6F10::from_bits(0x3E00), true))
1396        );
1397        assert_eq!(
1398            U16F0::overflowing_from_str_hex("100FF"),
1399            Ok((U16F0::from_bits(0x00FF), true))
1400        );
1401    }
1402
1403    #[test]
1404    fn check_dec_8() {
1405        let two_pow = 8f64.exp2();
1406        let limit = 1000;
1407        for i in 0..limit {
1408            let ans = from_str::u8::dec_to_bin(i, 8, Round::Nearest);
1409            let approx = two_pow * f64::from(i) / f64::from(limit);
1410            let error = (ans.map_or(two_pow, f64::from) - approx).abs();
1411            assert!(
1412                error <= 0.5,
1413                "i {i} ans {ans:?}  approx {approx} error {error}"
1414            );
1415        }
1416    }
1417
1418    #[test]
1419    fn check_dec_16() {
1420        let two_pow = 16f64.exp2();
1421        let limit = 1_000_000;
1422        for i in 0..limit {
1423            let ans = from_str::u16::dec_to_bin(i, 16, Round::Nearest);
1424            let approx = two_pow * f64::from(i) / f64::from(limit);
1425            let error = (ans.map_or(two_pow, f64::from) - approx).abs();
1426            assert!(
1427                error <= 0.5,
1428                "i {i} ans {ans:?}  approx {approx} error {error}"
1429            );
1430        }
1431    }
1432
1433    #[test]
1434    fn check_dec_32() {
1435        let two_pow = 32f64.exp2();
1436        let limit = 10_000_000_000_000;
1437        for iter in 0..1_000_000 {
1438            for &i in &[
1439                iter,
1440                limit / 4 - 1 - iter,
1441                limit / 4 + iter,
1442                limit / 3 - 1 - iter,
1443                limit / 3 + iter,
1444                limit / 2 - 1 - iter,
1445                limit / 2 + iter,
1446                limit - iter - 1,
1447            ] {
1448                let ans = from_str::u32::dec_to_bin(i, 32, Round::Nearest);
1449                let approx = two_pow * i as f64 / limit as f64;
1450                let error = (ans.map_or(two_pow, f64::from) - approx).abs();
1451                assert!(
1452                    error <= 0.5,
1453                    "i {i} ans {ans:?}  approx {approx} error {error}"
1454                );
1455            }
1456        }
1457    }
1458
1459    #[test]
1460    fn check_dec_64() {
1461        let two_pow = 64f64.exp2();
1462        let limit = 1_000_000_000_000_000_000_000_000_000;
1463        for iter in 0..200_000 {
1464            for &i in &[
1465                iter,
1466                limit / 4 - 1 - iter,
1467                limit / 4 + iter,
1468                limit / 3 - 1 - iter,
1469                limit / 3 + iter,
1470                limit / 2 - 1 - iter,
1471                limit / 2 + iter,
1472                limit - iter - 1,
1473            ] {
1474                let ans = from_str::u64::dec_to_bin(i, 64, Round::Nearest);
1475                let approx = two_pow * i as f64 / limit as f64;
1476                let error = (ans.map_or(two_pow, |x| x as f64) - approx).abs();
1477                assert!(
1478                    error <= 0.5,
1479                    "i {i} ans {ans:?}  approx {approx} error {error}"
1480                );
1481            }
1482        }
1483    }
1484
1485    #[test]
1486    fn check_dec_128() {
1487        let nines = 10u128.pow(27) - 1;
1488        let zeros = 0;
1489        let too_big = from_str::u128::dec_to_bin((nines, nines), 128, Round::Nearest);
1490        assert_eq!(too_big, None);
1491        let big = from_str::u128::dec_to_bin((nines, zeros), 128, Round::Nearest);
1492        assert_eq!(
1493            big,
1494            Some(340_282_366_920_938_463_463_374_607_091_485_844_535)
1495        );
1496        let small = from_str::u128::dec_to_bin((zeros, nines), 128, Round::Nearest);
1497        assert_eq!(small, Some(340_282_366_921));
1498        let zero = from_str::u128::dec_to_bin((zeros, zeros), 128, Round::Nearest);
1499        assert_eq!(zero, Some(0));
1500        let x = from_str::u128::dec_to_bin(
1501            (
1502                123_456_789_012_345_678_901_234_567,
1503                987_654_321_098_765_432_109_876_543,
1504            ),
1505            128,
1506            Round::Nearest,
1507        );
1508        assert_eq!(x, Some(42_010_168_377_579_896_403_540_037_811_203_677_112));
1509
1510        let eights = 888_888_888_888_888_888_888_888_888;
1511        let narrow = from_str::u128::dec_to_bin((eights, zeros), 40, Round::Nearest);
1512        assert_eq!(narrow, Some(977_343_669_134));
1513    }
1514
1515    fn digits_eq_bytes(mut digits: DigitsExp, bytes: &[u8]) -> bool {
1516        let mut bytes = bytes.iter().copied();
1517        while let Some((digit, rem)) = digits.split_first() {
1518            digits = rem;
1519            match bytes.next() {
1520                Some(byte) => {
1521                    if byte != digit {
1522                        return false;
1523                    }
1524                }
1525                None => return false,
1526            }
1527        }
1528        bytes.next().is_none()
1529    }
1530
1531    #[track_caller]
1532    fn check_parse_bounds_ok(bytes: &str, radix: u32, sep: Sep, check: (bool, &str, &str, u32)) {
1533        let bytes = bytes.as_bytes();
1534        let Parse {
1535            neg,
1536            int,
1537            frac,
1538            bit_exp,
1539        } = parse_bounds(bytes, radix, sep).unwrap();
1540        assert_eq!(neg, check.0);
1541        assert!(digits_eq_bytes(int, check.1.as_bytes()));
1542        assert!(digits_eq_bytes(frac, check.2.as_bytes()));
1543        match bit_exp {
1544            Some(bit_exp) => {
1545                assert_eq!(bit_exp.exp.get(), check.3);
1546                assert_eq!(
1547                    bit_exp.first_frac_digit,
1548                    frac.split_first().map_or(b'0', |x| x.0)
1549                );
1550            }
1551            None => assert_eq!(0, check.3),
1552        }
1553    }
1554
1555    #[track_caller]
1556    fn check_parse_bounds_err(bytes: &str, radix: u32, sep: Sep, check: ParseErrorKind) {
1557        let bytes = bytes.as_bytes();
1558        let kind = parse_bounds(bytes, radix, sep).unwrap_err();
1559        assert_eq!(kind, check);
1560    }
1561
1562    #[test]
1563    fn check_parse_bounds() {
1564        let sep = Sep::Error;
1565
1566        check_parse_bounds_ok("-12.34", 10, sep, (true, "12", "34", 0));
1567        check_parse_bounds_ok("012.", 10, sep, (false, "12", "", 0));
1568        check_parse_bounds_ok("+.340", 10, sep, (false, "", "34", 0));
1569        check_parse_bounds_ok("0", 10, sep, (false, "", "", 0));
1570        check_parse_bounds_ok("-.C1A0", 16, sep, (true, "", "C1A", 0));
1571        check_parse_bounds_ok("-.C1A0@1", 16, sep, (true, "C", "1A", 0));
1572        check_parse_bounds_ok("-.C1A0@+1", 16, sep, (true, "C", "1A", 0));
1573        check_parse_bounds_ok("-.C1A0@-1", 16, sep, (true, "", "0C1A", 0));
1574        check_parse_bounds_ok("-C1A0@-2", 16, sep, (true, "C1", "A", 0));
1575        check_parse_bounds_ok("-.C1A0p5", 16, sep, (true, "C", "1A", 1));
1576        check_parse_bounds_ok("-C1A0P-2", 16, sep, (true, "C1A", "", 2));
1577
1578        check_parse_bounds_err("0 ", 10, sep, ParseErrorKind::InvalidDigit);
1579        check_parse_bounds_err("+-", 10, sep, ParseErrorKind::MisplacedSign);
1580        check_parse_bounds_err("1+2", 10, sep, ParseErrorKind::MisplacedSign);
1581        check_parse_bounds_err("1-2", 10, sep, ParseErrorKind::MisplacedSign);
1582        check_parse_bounds_err("+.", 10, sep, ParseErrorKind::NoDigits);
1583        check_parse_bounds_err(".1.", 10, sep, ParseErrorKind::TooManyPoints);
1584        check_parse_bounds_err("C1A0@2F", 16, sep, ParseErrorKind::ExpInvalidDigit);
1585        check_parse_bounds_err("12.34E", 10, sep, ParseErrorKind::ExpNoDigits);
1586        check_parse_bounds_err("C1A0@1P1", 16, sep, ParseErrorKind::TooManyExp);
1587        check_parse_bounds_err("1E3000000000", 10, sep, ParseErrorKind::ExpOverflow);
1588
1589        check_parse_bounds_err("-_12.34", 10, sep, ParseErrorKind::InvalidDigit);
1590        check_parse_bounds_err("-1_2.34", 10, sep, ParseErrorKind::InvalidDigit);
1591        check_parse_bounds_err("-12_.34", 10, sep, ParseErrorKind::InvalidDigit);
1592        check_parse_bounds_err("-12._34", 10, sep, ParseErrorKind::InvalidDigit);
1593        check_parse_bounds_err("-12.3_4", 10, sep, ParseErrorKind::InvalidDigit);
1594        check_parse_bounds_err("-123E4_", 10, sep, ParseErrorKind::ExpInvalidDigit);
1595        check_parse_bounds_err("-12.34_", 10, sep, ParseErrorKind::InvalidDigit);
1596        check_parse_bounds_err(
1597            "-0_1__2___.3____4_____0",
1598            10,
1599            sep,
1600            ParseErrorKind::InvalidDigit,
1601        );
1602        check_parse_bounds_err("-1_2__.3_4__e+0___5", 10, sep, ParseErrorKind::InvalidDigit);
1603        check_parse_bounds_err("-1_2__.3_4__E-0___5", 10, sep, ParseErrorKind::InvalidDigit);
1604    }
1605
1606    #[test]
1607    fn check_parse_bounds_underscore() {
1608        let sep = Sep::Skip;
1609
1610        check_parse_bounds_ok("-12.34", 10, sep, (true, "12", "34", 0));
1611        check_parse_bounds_ok("012.", 10, sep, (false, "12", "", 0));
1612        check_parse_bounds_ok("+.340", 10, sep, (false, "", "34", 0));
1613        check_parse_bounds_ok("0", 10, sep, (false, "", "", 0));
1614        check_parse_bounds_ok("-.C1A0", 16, sep, (true, "", "C1A", 0));
1615        check_parse_bounds_ok("-.C1A0@1", 16, sep, (true, "C", "1A", 0));
1616        check_parse_bounds_ok("-.C1A0@+1", 16, sep, (true, "C", "1A", 0));
1617        check_parse_bounds_ok("-.C1A0@-1", 16, sep, (true, "", "0C1A", 0));
1618        check_parse_bounds_ok("-C1A0@-2", 16, sep, (true, "C1", "A", 0));
1619        check_parse_bounds_ok("-.C1A0p5", 16, sep, (true, "C", "1A", 1));
1620        check_parse_bounds_ok("-C1A0P-2", 16, sep, (true, "C1A", "", 2));
1621
1622        check_parse_bounds_err("0 ", 10, sep, ParseErrorKind::InvalidDigit);
1623        check_parse_bounds_err("+-", 10, sep, ParseErrorKind::MisplacedSign);
1624        check_parse_bounds_err("1+2", 10, sep, ParseErrorKind::MisplacedSign);
1625        check_parse_bounds_err("1-2", 10, sep, ParseErrorKind::MisplacedSign);
1626        check_parse_bounds_err("+.", 10, sep, ParseErrorKind::NoDigits);
1627        check_parse_bounds_err(".1.", 10, sep, ParseErrorKind::TooManyPoints);
1628        check_parse_bounds_err("C1A0@2F", 16, sep, ParseErrorKind::ExpInvalidDigit);
1629        check_parse_bounds_err("12.34E", 10, sep, ParseErrorKind::ExpNoDigits);
1630        check_parse_bounds_err("C1A0@1P1", 16, sep, ParseErrorKind::TooManyExp);
1631        check_parse_bounds_err("1E3000000000", 10, sep, ParseErrorKind::ExpOverflow);
1632
1633        check_parse_bounds_err("-_12.34", 10, sep, ParseErrorKind::MisplacedUnderscore);
1634        check_parse_bounds_ok("-1_2.34", 10, sep, (true, "12", "34", 0));
1635        check_parse_bounds_ok("-12_.34", 10, sep, (true, "12", "34", 0));
1636        check_parse_bounds_err("-12._34", 10, sep, ParseErrorKind::MisplacedUnderscore);
1637        check_parse_bounds_ok("-12.3_4", 10, sep, (true, "12", "34", 0));
1638        check_parse_bounds_ok("-12.34_", 10, sep, (true, "12", "34", 0));
1639        check_parse_bounds_ok("-123E4_", 10, sep, (true, "1230000", "", 0));
1640        check_parse_bounds_ok("-0_1__2___.3____4_____0", 10, sep, (true, "12", "34", 0));
1641        check_parse_bounds_ok("-1_2__.3_4__e+0___5", 10, sep, (true, "1234000", "", 0));
1642        check_parse_bounds_ok("-1_2__.3_4__E-0___5", 10, sep, (true, "", "0001234", 0));
1643    }
1644
1645    macro_rules! assert_ok {
1646        ($T:ty, $str:expr, $radix:expr, $bits:expr, $overflow:expr) => {
1647            let m = match $radix {
1648                2 => <$T>::overflowing_from_str_binary($str),
1649                8 => <$T>::overflowing_from_str_octal($str),
1650                10 => <$T>::overflowing_from_str($str),
1651                16 => <$T>::overflowing_from_str_hex($str),
1652                _ => unreachable!(),
1653            };
1654            match m {
1655                Ok((f, o)) => {
1656                    assert_eq!(f.to_bits(), $bits, "{} -> ({f}, {o})", $str);
1657                    assert_eq!(o, $overflow, "{} -> ({f}, {o})", $str);
1658                }
1659                Err(e) => panic!("could not parse {}: {e}", $str),
1660            }
1661        };
1662    }
1663
1664    #[test]
1665    fn check_i8_u8_from_str() {
1666        assert_ok!(I0F8, "-1", 10, 0x00, true);
1667        assert_ok!(I0F8, "-0.502", 10, 0x7F, true);
1668        assert_ok!(I0F8, "-0.501", 10, -0x80, false);
1669        assert_ok!(I0F8, "0.498", 10, 0x7F, false);
1670        assert_ok!(I0F8, "0.499", 10, -0x80, true);
1671        assert_ok!(I0F8, "1", 10, 0x00, true);
1672
1673        assert_ok!(I4F4, "-8.04", 10, 0x7F, true);
1674        assert_ok!(I4F4, "-8.03", 10, -0x80, false);
1675        assert_ok!(I4F4, "7.96", 10, 0x7F, false);
1676        assert_ok!(I4F4, "7.97", 10, -0x80, true);
1677
1678        assert_ok!(I8F0, "-128.501", 10, 0x7F, true);
1679        // exact tie, round up to even
1680        assert_ok!(I8F0, "-128.5", 10, -0x80, false);
1681        assert_ok!(I8F0, "127.499", 10, 0x7F, false);
1682        // exact tie, round up to even
1683        assert_ok!(I8F0, "127.5", 10, -0x80, true);
1684
1685        assert_ok!(U0F8, "-0", 10, 0x00, false);
1686        assert_ok!(U0F8, "0.498", 10, 0x7F, false);
1687        assert_ok!(U0F8, "0.499", 10, 0x80, false);
1688        assert_ok!(U0F8, "0.998", 10, 0xFF, false);
1689        assert_ok!(U0F8, "0.999", 10, 0x00, true);
1690        assert_ok!(U0F8, "1", 10, 0x00, true);
1691
1692        assert_ok!(U4F4, "7.96", 10, 0x7F, false);
1693        assert_ok!(U4F4, "7.97", 10, 0x80, false);
1694        assert_ok!(U4F4, "15.96", 10, 0xFF, false);
1695        assert_ok!(U4F4, "15.97", 10, 0x00, true);
1696
1697        assert_ok!(U8F0, "127.499", 10, 0x7F, false);
1698        // exact tie, round up to even
1699        assert_ok!(U8F0, "127.5", 10, 0x80, false);
1700        assert_ok!(U8F0, "255.499", 10, 0xFF, false);
1701        // exact tie, round up to even
1702        assert_ok!(U8F0, "255.5", 10, 0x00, true);
1703    }
1704
1705    #[test]
1706    fn check_i16_u16_from_str() {
1707        assert_ok!(I0F16, "-1", 10, 0x00, true);
1708        assert_ok!(I0F16, "-0.500008", 10, 0x7FFF, true);
1709        assert_ok!(I0F16, "-0.500007", 10, -0x8000, false);
1710        assert_ok!(I0F16, "+0.499992", 10, 0x7FFF, false);
1711        assert_ok!(I0F16, "+0.499993", 10, -0x8000, true);
1712        assert_ok!(I0F16, "1", 10, 0x0000, true);
1713
1714        assert_ok!(I8F8, "-128.002", 10, 0x7FFF, true);
1715        assert_ok!(I8F8, "-128.001", 10, -0x8000, false);
1716        assert_ok!(I8F8, "+127.998", 10, 0x7FFF, false);
1717        assert_ok!(I8F8, "+127.999", 10, -0x8000, true);
1718
1719        assert_ok!(I16F0, "-32768.500001", 10, 0x7FFF, true);
1720        // exact tie, round up to even
1721        assert_ok!(I16F0, "-32768.5", 10, -0x8000, false);
1722        assert_ok!(I16F0, "+32767.499999", 10, 0x7FFF, false);
1723        // exact tie, round up to even
1724        assert_ok!(I16F0, "+32767.5", 10, -0x8000, true);
1725
1726        assert_ok!(U0F16, "-0", 10, 0x0000, false);
1727        assert_ok!(U0F16, "0.499992", 10, 0x7FFF, false);
1728        assert_ok!(U0F16, "0.499993", 10, 0x8000, false);
1729        assert_ok!(U0F16, "0.999992", 10, 0xFFFF, false);
1730        assert_ok!(U0F16, "0.999993", 10, 0x0000, true);
1731        assert_ok!(U0F16, "1", 10, 0x0000, true);
1732
1733        assert_ok!(U8F8, "127.998", 10, 0x7FFF, false);
1734        assert_ok!(U8F8, "127.999", 10, 0x8000, false);
1735        assert_ok!(U8F8, "255.998", 10, 0xFFFF, false);
1736        assert_ok!(U8F8, "255.999", 10, 0x0000, true);
1737
1738        assert_ok!(U16F0, "32767.499999", 10, 0x7FFF, false);
1739        // exact tie, round up to even
1740        assert_ok!(U16F0, "32767.5", 10, 0x8000, false);
1741        assert_ok!(U16F0, "65535.499999", 10, 0xFFFF, false);
1742        // exact tie, round up to even
1743        assert_ok!(U16F0, "65535.5", 10, 0x0000, true);
1744    }
1745
1746    #[test]
1747    fn check_i32_u32_from_str() {
1748        assert_ok!(I0F32, "-1", 10, 0x0000_0000, true);
1749        assert_ok!(I0F32, "-0.5000000002", 10, 0x7FFF_FFFF, true);
1750        assert_ok!(I0F32, "-0.5000000001", 10, -0x8000_0000, false);
1751        assert_ok!(I0F32, "0.4999999998", 10, 0x7FFF_FFFF, false);
1752        assert_ok!(I0F32, "0.4999999999", 10, -0x8000_0000, true);
1753        assert_ok!(I0F32, "1", 10, 0x0000_0000, true);
1754
1755        assert_ok!(I16F16, "-32768.000008", 10, 0x7FFF_FFFF, true);
1756        assert_ok!(I16F16, "-32768.000007", 10, -0x8000_0000, false);
1757        assert_ok!(I16F16, "32767.999992", 10, 0x7FFF_FFFF, false);
1758        assert_ok!(I16F16, "32767.999993", 10, -0x8000_0000, true);
1759
1760        assert_ok!(I32F0, "-2147483648.5000000001", 10, 0x7FFF_FFFF, true);
1761        // exact tie, round up to even
1762        assert_ok!(I32F0, "-2147483648.5", 10, -0x8000_0000, false);
1763        assert_ok!(I32F0, "2147483647.4999999999", 10, 0x7FFF_FFFF, false);
1764        // exact tie, round up to even
1765        assert_ok!(I32F0, "2147483647.5", 10, -0x8000_0000, true);
1766
1767        assert_ok!(U0F32, "-0", 10, 0x0000_0000, false);
1768        assert_ok!(U0F32, "0.4999999998", 10, 0x7FFF_FFFF, false);
1769        assert_ok!(U0F32, "0.4999999999", 10, 0x8000_0000, false);
1770        assert_ok!(U0F32, "0.9999999998", 10, 0xFFFF_FFFF, false);
1771        assert_ok!(U0F32, "0.9999999999", 10, 0x0000_0000, true);
1772        assert_ok!(U0F32, "1", 10, 0x0000_0000, true);
1773
1774        assert_ok!(U16F16, "32767.999992", 10, 0x7FFF_FFFF, false);
1775        assert_ok!(U16F16, "32767.999993", 10, 0x8000_0000, false);
1776        assert_ok!(U16F16, "65535.999992", 10, 0xFFFF_FFFF, false);
1777        assert_ok!(U16F16, "65535.999993", 10, 0x0000_0000, true);
1778
1779        assert_ok!(U32F0, "2147483647.4999999999", 10, 0x7FFF_FFFF, false);
1780        // exact tie, round up to even
1781        assert_ok!(U32F0, "2147483647.5", 10, 0x8000_0000, false);
1782        assert_ok!(U32F0, "4294967295.4999999999", 10, 0xFFFF_FFFF, false);
1783        // exact tie, round up to even
1784        assert_ok!(U32F0, "4294967295.5", 10, 0x0000_0000, true);
1785    }
1786
1787    #[test]
1788    fn check_i64_u64_from_str() {
1789        assert_ok!(I0F64, "-1", 10, 0x0000_0000_0000_0000, true);
1790        assert_ok!(
1791            I0F64,
1792            "-0.50000000000000000003",
1793            10,
1794            0x7FFF_FFFF_FFFF_FFFF,
1795            true
1796        );
1797        assert_ok!(
1798            I0F64,
1799            "-0.50000000000000000002",
1800            10,
1801            -0x8000_0000_0000_0000,
1802            false
1803        );
1804        assert_ok!(
1805            I0F64,
1806            "+0.49999999999999999997",
1807            10,
1808            0x7FFF_FFFF_FFFF_FFFF,
1809            false
1810        );
1811        assert_ok!(
1812            I0F64,
1813            "+0.49999999999999999998",
1814            10,
1815            -0x8000_0000_0000_0000,
1816            true
1817        );
1818        assert_ok!(I0F64, "1", 10, 0x0000_0000_0000_0000, true);
1819
1820        assert_ok!(
1821            I32F32,
1822            "-2147483648.0000000002",
1823            10,
1824            0x7FFF_FFFF_FFFF_FFFF,
1825            true
1826        );
1827        assert_ok!(
1828            I32F32,
1829            "-2147483648.0000000001",
1830            10,
1831            -0x8000_0000_0000_0000,
1832            false
1833        );
1834        assert_ok!(
1835            I32F32,
1836            "2147483647.9999999998",
1837            10,
1838            0x7FFF_FFFF_FFFF_FFFF,
1839            false
1840        );
1841        assert_ok!(
1842            I32F32,
1843            "2147483647.9999999999",
1844            10,
1845            -0x8000_0000_0000_0000,
1846            true
1847        );
1848
1849        assert_ok!(
1850            I64F0,
1851            "-9223372036854775808.50000000000000000001",
1852            10,
1853            0x7FFF_FFFF_FFFF_FFFF,
1854            true
1855        );
1856        // exact tie, round up to even
1857        assert_ok!(
1858            I64F0,
1859            "-9223372036854775808.5",
1860            10,
1861            -0x8000_0000_0000_0000,
1862            false
1863        );
1864        assert_ok!(
1865            I64F0,
1866            "9223372036854775807.49999999999999999999",
1867            10,
1868            0x7FFF_FFFF_FFFF_FFFF,
1869            false
1870        );
1871        // exact tie, round up to even
1872        assert_ok!(
1873            I64F0,
1874            "9223372036854775807.5",
1875            10,
1876            -0x8000_0000_0000_0000,
1877            true
1878        );
1879
1880        assert_ok!(U0F64, "-0", 10, 0x0000_0000_0000_0000, false);
1881        assert_ok!(
1882            U0F64,
1883            "0.49999999999999999997",
1884            10,
1885            0x7FFF_FFFF_FFFF_FFFF,
1886            false
1887        );
1888        assert_ok!(
1889            U0F64,
1890            "0.49999999999999999998",
1891            10,
1892            0x8000_0000_0000_0000,
1893            false
1894        );
1895        assert_ok!(
1896            U0F64,
1897            "0.99999999999999999997",
1898            10,
1899            0xFFFF_FFFF_FFFF_FFFF,
1900            false
1901        );
1902        assert_ok!(
1903            U0F64,
1904            "0.99999999999999999998",
1905            10,
1906            0x0000_0000_0000_0000,
1907            true
1908        );
1909        assert_ok!(U0F64, "1", 10, 0x0000_0000_0000_0000, true);
1910
1911        assert_ok!(
1912            U32F32,
1913            "2147483647.9999999998",
1914            10,
1915            0x7FFF_FFFF_FFFF_FFFF,
1916            false
1917        );
1918        assert_ok!(
1919            U32F32,
1920            "2147483647.9999999999",
1921            10,
1922            0x8000_0000_0000_0000,
1923            false
1924        );
1925        assert_ok!(
1926            U32F32,
1927            "4294967295.9999999998",
1928            10,
1929            0xFFFF_FFFF_FFFF_FFFF,
1930            false
1931        );
1932        assert_ok!(
1933            U32F32,
1934            "4294967295.9999999999",
1935            10,
1936            0x0000_0000_0000_0000,
1937            true
1938        );
1939
1940        assert_ok!(
1941            U64F0,
1942            "9223372036854775807.49999999999999999999",
1943            10,
1944            0x7FFF_FFFF_FFFF_FFFF,
1945            false
1946        );
1947        // exact tie, round up to even
1948        assert_ok!(
1949            U64F0,
1950            "9223372036854775807.5",
1951            10,
1952            0x8000_0000_0000_0000,
1953            false
1954        );
1955        assert_ok!(
1956            U64F0,
1957            "18446744073709551615.49999999999999999999",
1958            10,
1959            0xFFFF_FFFF_FFFF_FFFF,
1960            false
1961        );
1962        // exact tie, round up to even
1963        assert_ok!(
1964            U64F0,
1965            "18446744073709551615.5",
1966            10,
1967            0x0000_0000_0000_0000,
1968            true
1969        );
1970    }
1971
1972    #[test]
1973    fn check_i128_u128_from_str() {
1974        assert_ok!(
1975            I0F128,
1976            "-1",
1977            10,
1978            0x0000_0000_0000_0000_0000_0000_0000_0000,
1979            true
1980        );
1981        assert_ok!(
1982            I0F128,
1983            "-0.500000000000000000000000000000000000002",
1984            10,
1985            0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
1986            true
1987        );
1988        assert_ok!(
1989            I0F128,
1990            "-0.500000000000000000000000000000000000001",
1991            10,
1992            -0x8000_0000_0000_0000_0000_0000_0000_0000,
1993            false
1994        );
1995        assert_ok!(
1996            I0F128,
1997            "0.499999999999999999999999999999999999998",
1998            10,
1999            0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
2000            false
2001        );
2002        assert_ok!(
2003            I0F128,
2004            "0.499999999999999999999999999999999999999",
2005            10,
2006            -0x8000_0000_0000_0000_0000_0000_0000_0000,
2007            true
2008        );
2009        assert_ok!(
2010            I0F128,
2011            "1",
2012            10,
2013            0x0000_0000_0000_0000_0000_0000_0000_0000,
2014            true
2015        );
2016
2017        assert_ok!(
2018            I64F64,
2019            "-9223372036854775808.00000000000000000003",
2020            10,
2021            0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
2022            true
2023        );
2024        assert_ok!(
2025            I64F64,
2026            "-9223372036854775808.00000000000000000002",
2027            10,
2028            -0x8000_0000_0000_0000_0000_0000_0000_0000,
2029            false
2030        );
2031        assert_ok!(
2032            I64F64,
2033            "9223372036854775807.99999999999999999997",
2034            10,
2035            0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
2036            false
2037        );
2038        assert_ok!(
2039            I64F64,
2040            "9223372036854775807.99999999999999999998",
2041            10,
2042            -0x8000_0000_0000_0000_0000_0000_0000_0000,
2043            true
2044        );
2045
2046        assert_ok!(
2047            I128F0,
2048            "-170141183460469231731687303715884105728.5000000000000000000000000000000000000001",
2049            10,
2050            0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
2051            true
2052        );
2053        // exact tie, round up to even
2054        assert_ok!(
2055            I128F0,
2056            "-170141183460469231731687303715884105728.5",
2057            10,
2058            -0x8000_0000_0000_0000_0000_0000_0000_0000,
2059            false
2060        );
2061        assert_ok!(
2062            I128F0,
2063            "170141183460469231731687303715884105727.4999999999999999999999999999999999999999",
2064            10,
2065            0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
2066            false
2067        );
2068        // exact tie, round up to even
2069        assert_ok!(
2070            I128F0,
2071            "170141183460469231731687303715884105727.5",
2072            10,
2073            -0x8000_0000_0000_0000_0000_0000_0000_0000,
2074            true
2075        );
2076
2077        assert_ok!(
2078            U0F128,
2079            "-0",
2080            10,
2081            0x0000_0000_0000_0000_0000_0000_0000_0000,
2082            false
2083        );
2084        assert_ok!(
2085            U0F128,
2086            "0.499999999999999999999999999999999999998",
2087            10,
2088            0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
2089            false
2090        );
2091        assert_ok!(
2092            U0F128,
2093            "0.499999999999999999999999999999999999999",
2094            10,
2095            0x8000_0000_0000_0000_0000_0000_0000_0000,
2096            false
2097        );
2098        assert_ok!(
2099            U0F128,
2100            "0.999999999999999999999999999999999999998",
2101            10,
2102            0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
2103            false
2104        );
2105        assert_ok!(
2106            U0F128,
2107            "0.999999999999999999999999999999999999999",
2108            10,
2109            0x0000_0000_0000_0000_0000_0000_0000_0000,
2110            true
2111        );
2112        assert_ok!(
2113            U0F128,
2114            "1",
2115            10,
2116            0x0000_0000_0000_0000_0000_0000_0000_0000,
2117            true
2118        );
2119
2120        assert_ok!(
2121            U64F64,
2122            "9223372036854775807.99999999999999999997",
2123            10,
2124            0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
2125            false
2126        );
2127        assert_ok!(
2128            U64F64,
2129            "9223372036854775807.99999999999999999998",
2130            10,
2131            0x8000_0000_0000_0000_0000_0000_0000_0000,
2132            false
2133        );
2134        assert_ok!(
2135            U64F64,
2136            "18446744073709551615.99999999999999999997",
2137            10,
2138            0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
2139            false
2140        );
2141        assert_ok!(
2142            U64F64,
2143            "18446744073709551615.99999999999999999998",
2144            10,
2145            0x0000_0000_0000_0000_0000_0000_0000_0000,
2146            true
2147        );
2148
2149        assert_ok!(
2150            U128F0,
2151            "170141183460469231731687303715884105727.4999999999999999999999999999999999999999",
2152            10,
2153            0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
2154            false
2155        );
2156        // exact tie(ound up to even
2157        assert_ok!(
2158            U128F0,
2159            "170141183460469231731687303715884105727.5",
2160            10,
2161            0x8000_0000_0000_0000_0000_0000_0000_0000,
2162            false
2163        );
2164        assert_ok!(
2165            U128F0,
2166            "340282366920938463463374607431768211455.4999999999999999999999999999999999999999",
2167            10,
2168            0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
2169            false
2170        );
2171        // exact tie, round up to even
2172        assert_ok!(
2173            U128F0,
2174            "340282366920938463463374607431768211455.5",
2175            10,
2176            0x0000_0000_0000_0000_0000_0000_0000_0000,
2177            true
2178        );
2179    }
2180
2181    #[test]
2182    fn check_i16_u16_from_str_binary() {
2183        assert_ok!(I0F16, "-1", 2, 0x0000, true);
2184        assert_ok!(I0F16, "-0.100000000000000011", 2, 0x7FFF, true);
2185        assert_ok!(I0F16, "-0.100000000000000010", 2, -0x8000, false);
2186        assert_ok!(I0F16, "-0.011111111111111110", 2, -0x8000, false);
2187        assert_ok!(I0F16, "+0.011111111111111101", 2, 0x7FFF, false);
2188        assert_ok!(I0F16, "+0.011111111111111110", 2, -0x8000, true);
2189        assert_ok!(I0F16, "1", 2, 0x0000, true);
2190
2191        assert_ok!(I8F8, "-10000000.0000000011", 2, 0x7FFF, true);
2192        assert_ok!(I8F8, "-10000000.0000000010", 2, -0x8000, false);
2193        assert_ok!(I8F8, "-01111111.1111111110", 2, -0x8000, false);
2194        assert_ok!(I8F8, "+01111111.1111111101", 2, 0x7FFF, false);
2195        assert_ok!(I8F8, "+01111111.1111111110", 2, -0x8000, true);
2196
2197        assert_ok!(I16F0, "-1000000000000000.11", 2, 0x7FFF, true);
2198        assert_ok!(I16F0, "-1000000000000000.10", 2, -0x8000, false);
2199        assert_ok!(I16F0, "-0111111111111111.10", 2, -0x8000, false);
2200        assert_ok!(I16F0, "+0111111111111111.01", 2, 0x7FFF, false);
2201        assert_ok!(I16F0, "+0111111111111111.10", 2, -0x8000, true);
2202
2203        assert_ok!(U0F16, "-0", 2, 0x0000, false);
2204        assert_ok!(U0F16, "0.011111111111111101", 2, 0x7FFF, false);
2205        assert_ok!(U0F16, "0.011111111111111110", 2, 0x8000, false);
2206        assert_ok!(U0F16, "0.111111111111111101", 2, 0xFFFF, false);
2207        assert_ok!(U0F16, "0.111111111111111110", 2, 0x0000, true);
2208        assert_ok!(U0F16, "1", 2, 0x0000, true);
2209
2210        assert_ok!(U8F8, "01111111.1111111101", 2, 0x7FFF, false);
2211        assert_ok!(U8F8, "01111111.1111111110", 2, 0x8000, false);
2212        assert_ok!(U8F8, "11111111.1111111101", 2, 0xFFFF, false);
2213        assert_ok!(U8F8, "11111111.1111111110", 2, 0x0000, true);
2214
2215        assert_ok!(U16F0, "0111111111111111.01", 2, 0x7FFF, false);
2216        assert_ok!(U16F0, "0111111111111111.10", 2, 0x8000, false);
2217        assert_ok!(U16F0, "1111111111111111.01", 2, 0xFFFF, false);
2218        assert_ok!(U16F0, "1111111111111111.10", 2, 0x0000, true);
2219
2220        assert_ok!(U0F16, "00111.11111111111101e-4", 2, 0x7FFF, false);
2221        assert_ok!(U16F0, "011111111111.111101e4", 2, 0x7FFF, false);
2222        assert_ok!(U8F8, "011.110P3", 2, 0x1E00, false);
2223        assert_ok!(U8F8, "011.110P-3", 2, 0x0078, false);
2224    }
2225
2226    #[test]
2227    fn check_i16_u16_from_str_octal() {
2228        assert_ok!(I0F16, "-1", 8, 0x0000, true);
2229        assert_ok!(I0F16, "-0.400003", 8, 0x7FFF, true);
2230        assert_ok!(I0F16, "-0.400002", 8, -0x8000, false);
2231        assert_ok!(I0F16, "-0.377776", 8, -0x8000, false);
2232        assert_ok!(I0F16, "+0.377775", 8, 0x7FFF, false);
2233        assert_ok!(I0F16, "+0.377776", 8, -0x8000, true);
2234        assert_ok!(I0F16, "1", 8, 0x0000, true);
2235
2236        assert_ok!(I8F8, "-200.0011", 8, 0x7FFF, true);
2237        assert_ok!(I8F8, "-200.0010", 8, -0x8000, false);
2238        assert_ok!(I8F8, "-177.7770", 8, -0x8000, false);
2239        assert_ok!(I8F8, "+177.7767", 8, 0x7FFF, false);
2240        assert_ok!(I8F8, "+177.7770", 8, -0x8000, true);
2241
2242        assert_ok!(I16F0, "-100000.5", 8, 0x7FFF, true);
2243        assert_ok!(I16F0, "-100000.4", 8, -0x8000, false);
2244        assert_ok!(I16F0, "-077777.4", 8, -0x8000, false);
2245        assert_ok!(I16F0, "+077777.3", 8, 0x7FFF, false);
2246        assert_ok!(I16F0, "+077777.4", 8, -0x8000, true);
2247
2248        assert_ok!(U0F16, "-0", 8, 0x0000, false);
2249        assert_ok!(U0F16, "0.377775", 8, 0x7FFF, false);
2250        assert_ok!(U0F16, "0.377776", 8, 0x8000, false);
2251        assert_ok!(U0F16, "0.777775", 8, 0xFFFF, false);
2252        assert_ok!(U0F16, "0.777776", 8, 0x0000, true);
2253        assert_ok!(U0F16, "1", 8, 0x0000, true);
2254
2255        assert_ok!(U8F8, "177.7767", 8, 0x7FFF, false);
2256        assert_ok!(U8F8, "177.7770", 8, 0x8000, false);
2257        assert_ok!(U8F8, "377.7767", 8, 0xFFFF, false);
2258        assert_ok!(U8F8, "377.7770", 8, 0x0000, true);
2259
2260        assert_ok!(U16F0, "077777.3", 8, 0x7FFF, false);
2261        assert_ok!(U16F0, "077777.4", 8, 0x8000, false);
2262        assert_ok!(U16F0, "177777.3", 8, 0xFFFF, false);
2263        assert_ok!(U16F0, "177777.4", 8, 0x0000, true);
2264
2265        assert_ok!(U0F16, "037.7775e-2", 8, 0x7FFF, false);
2266        assert_ok!(U16F0, "0777.773e2", 8, 0x7FFF, false);
2267        assert_ok!(U8F8, "037.450P4", 8, 0xF940, true);
2268        assert_ok!(U8F8, "037.450P3", 8, 0xFCA0, false);
2269        assert_ok!(U8F8, "037.450P2", 8, 0x7E50, false);
2270        assert_ok!(U8F8, "037.450P1", 8, 0x3F28, false);
2271        assert_ok!(U8F8, "037.450P0", 8, 0x1F94, false);
2272        assert_ok!(U8F8, "037.450P-1", 8, 0x0FCA, false);
2273        assert_ok!(U8F8, "037.450P-2", 8, 0x07E5, false);
2274        assert_ok!(U8F8, "037.450P-3", 8, 0x03F2, false);
2275        assert_ok!(U8F8, "037.450P-4", 8, 0x01F9, false);
2276    }
2277
2278    #[test]
2279    fn check_i16_u16_from_str_hex() {
2280        assert_ok!(I0F16, "-1", 16, 0x0000, true);
2281        assert_ok!(I0F16, "-0.80009", 16, 0x7FFF, true);
2282        assert_ok!(I0F16, "-0.80008", 16, -0x8000, false);
2283        assert_ok!(I0F16, "-0.7FFF8", 16, -0x8000, false);
2284        assert_ok!(I0F16, "+0.7FFF7", 16, 0x7FFF, false);
2285        assert_ok!(I0F16, "+0.7FFF8", 16, -0x8000, true);
2286        assert_ok!(I0F16, "1", 16, 0x0000, true);
2287
2288        assert_ok!(I8F8, "-80.009", 16, 0x7FFF, true);
2289        assert_ok!(I8F8, "-80.008", 16, -0x8000, false);
2290        assert_ok!(I8F8, "-7F.FF8", 16, -0x8000, false);
2291        assert_ok!(I8F8, "+7F.FF7", 16, 0x7FFF, false);
2292        assert_ok!(I8F8, "+7F.FF8", 16, -0x8000, true);
2293
2294        assert_ok!(I16F0, "-8000.9", 16, 0x7FFF, true);
2295        assert_ok!(I16F0, "-8000.8", 16, -0x8000, false);
2296        assert_ok!(I16F0, "-7FFF.8", 16, -0x8000, false);
2297        assert_ok!(I16F0, "+7FFF.7", 16, 0x7FFF, false);
2298        assert_ok!(I16F0, "+7FFF.8", 16, -0x8000, true);
2299
2300        assert_ok!(U0F16, "-0", 16, 0x0000, false);
2301        assert_ok!(U0F16, "0.7FFF7", 16, 0x7FFF, false);
2302        assert_ok!(U0F16, "0.7FFF8", 16, 0x8000, false);
2303        assert_ok!(U0F16, "0.FFFF7", 16, 0xFFFF, false);
2304        assert_ok!(U0F16, "0.FFFF8", 16, 0x0000, true);
2305        assert_ok!(U0F16, "1", 16, 0x0000, true);
2306
2307        assert_ok!(U8F8, "7F.FF7", 16, 0x7FFF, false);
2308        assert_ok!(U8F8, "7F.FF8", 16, 0x8000, false);
2309        assert_ok!(U8F8, "FF.FF7", 16, 0xFFFF, false);
2310        assert_ok!(U8F8, "FF.FF8", 16, 0x0000, true);
2311
2312        assert_ok!(U16F0, "7FFF.7", 16, 0x7FFF, false);
2313        assert_ok!(U16F0, "7FFF.8", 16, 0x8000, false);
2314        assert_ok!(U16F0, "FFFF.7", 16, 0xFFFF, false);
2315        assert_ok!(U16F0, "FFFF.8", 16, 0x0000, true);
2316
2317        assert_ok!(U0F16, "07F.FF7@-2", 16, 0x7FFF, false);
2318        assert_ok!(U16F0, "7F.FF7@2", 16, 0x7FFF, false);
2319        assert_ok!(U8F8, "13.B8P4", 16, 0x3B80, true);
2320        assert_ok!(U8F8, "13.B8P3", 16, 0x9DC0, false);
2321        assert_ok!(U8F8, "13.B8P2", 16, 0x4EE0, false);
2322        assert_ok!(U8F8, "13.B8P1", 16, 0x2770, false);
2323        assert_ok!(U8F8, "13.B8P0", 16, 0x13B8, false);
2324        assert_ok!(U8F8, "13.B8P-1", 16, 0x09DC, false);
2325        assert_ok!(U8F8, "13.B8P-2", 16, 0x04EE, false);
2326        assert_ok!(U8F8, "13.B8P-3", 16, 0x0277, false);
2327        assert_ok!(U8F8, "13.B8P-4", 16, 0x013C, false);
2328    }
2329
2330    #[test]
2331    fn check_i128_u128_from_str_hex() {
2332        assert_ok!(
2333            I0F128,
2334            "-1",
2335            16,
2336            0x0000_0000_0000_0000_0000_0000_0000_0000,
2337            true
2338        );
2339        assert_ok!(
2340            I0F128,
2341            "-0.800000000000000000000000000000009",
2342            16,
2343            0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
2344            true
2345        );
2346        assert_ok!(
2347            I0F128,
2348            "-0.800000000000000000000000000000008",
2349            16,
2350            -0x8000_0000_0000_0000_0000_0000_0000_0000,
2351            false
2352        );
2353        assert_ok!(
2354            I0F128,
2355            "-0.7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8",
2356            16,
2357            -0x8000_0000_0000_0000_0000_0000_0000_0000,
2358            false
2359        );
2360        assert_ok!(
2361            I0F128,
2362            "+0.7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7",
2363            16,
2364            0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
2365            false
2366        );
2367        assert_ok!(
2368            I0F128,
2369            "+0.7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8",
2370            16,
2371            -0x8000_0000_0000_0000_0000_0000_0000_0000,
2372            true
2373        );
2374        assert_ok!(
2375            I0F128,
2376            "1",
2377            16,
2378            0x0000_0000_0000_0000_0000_0000_0000_0000,
2379            true
2380        );
2381
2382        assert_ok!(
2383            I64F64,
2384            "-8000000000000000.00000000000000009",
2385            16,
2386            0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
2387            true
2388        );
2389        assert_ok!(
2390            I64F64,
2391            "-8000000000000000.00000000000000008",
2392            16,
2393            -0x8000_0000_0000_0000_0000_0000_0000_0000,
2394            false
2395        );
2396        assert_ok!(
2397            I64F64,
2398            "-7FFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF8",
2399            16,
2400            -0x8000_0000_0000_0000_0000_0000_0000_0000,
2401            false
2402        );
2403        assert_ok!(
2404            I64F64,
2405            "+7FFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF7",
2406            16,
2407            0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
2408            false
2409        );
2410        assert_ok!(
2411            I64F64,
2412            "+7FFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF8",
2413            16,
2414            -0x8000_0000_0000_0000_0000_0000_0000_0000,
2415            true
2416        );
2417
2418        assert_ok!(
2419            I128F0,
2420            "-80000000000000000000000000000000.9",
2421            16,
2422            0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
2423            true
2424        );
2425        assert_ok!(
2426            I128F0,
2427            "-80000000000000000000000000000000.8",
2428            16,
2429            -0x8000_0000_0000_0000_0000_0000_0000_0000,
2430            false
2431        );
2432        assert_ok!(
2433            I128F0,
2434            "-7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF.8",
2435            16,
2436            -0x8000_0000_0000_0000_0000_0000_0000_0000,
2437            false
2438        );
2439        assert_ok!(
2440            I128F0,
2441            "+7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF.7",
2442            16,
2443            0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
2444            false
2445        );
2446        assert_ok!(
2447            I128F0,
2448            "+7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF.8",
2449            16,
2450            -0x8000_0000_0000_0000_0000_0000_0000_0000,
2451            true
2452        );
2453
2454        assert_ok!(
2455            U0F128,
2456            "-0",
2457            16,
2458            0x0000_0000_0000_0000_0000_0000_0000_0000,
2459            false
2460        );
2461        assert_ok!(
2462            U0F128,
2463            "0.7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7",
2464            16,
2465            0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
2466            false
2467        );
2468        assert_ok!(
2469            U0F128,
2470            "0.7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8",
2471            16,
2472            0x8000_0000_0000_0000_0000_0000_0000_0000,
2473            false
2474        );
2475        assert_ok!(
2476            U0F128,
2477            "0.FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7",
2478            16,
2479            0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
2480            false
2481        );
2482        assert_ok!(
2483            U0F128,
2484            "0.FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8",
2485            16,
2486            0x0000_0000_0000_0000_0000_0000_0000_0000,
2487            true
2488        );
2489        assert_ok!(
2490            U0F128,
2491            "1",
2492            16,
2493            0x0000_0000_0000_0000_0000_0000_0000_0000,
2494            true
2495        );
2496
2497        assert_ok!(
2498            U64F64,
2499            "7FFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF7",
2500            16,
2501            0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
2502            false
2503        );
2504        assert_ok!(
2505            U64F64,
2506            "7FFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF8",
2507            16,
2508            0x8000_0000_0000_0000_0000_0000_0000_0000,
2509            false
2510        );
2511        assert_ok!(
2512            U64F64,
2513            "FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF7",
2514            16,
2515            0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
2516            false
2517        );
2518        assert_ok!(
2519            U64F64,
2520            "FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF8",
2521            16,
2522            0x0000_0000_0000_0000_0000_0000_0000_0000,
2523            true
2524        );
2525
2526        assert_ok!(
2527            U128F0,
2528            "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF.7",
2529            16,
2530            0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
2531            false
2532        );
2533        assert_ok!(
2534            U128F0,
2535            "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF.8",
2536            16,
2537            0x8000_0000_0000_0000_0000_0000_0000_0000,
2538            false
2539        );
2540        assert_ok!(
2541            U128F0,
2542            "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF.7",
2543            16,
2544            0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
2545            false
2546        );
2547        assert_ok!(
2548            U128F0,
2549            "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF.8",
2550            16,
2551            0x0000_0000_0000_0000_0000_0000_0000_0000,
2552            true
2553        );
2554    }
2555
2556    // For an odd prefix, e.g. eps = 0.125
2557    // zero = 0.125
2558    // gt_0 = 0.125000001
2559    // max = max_int.874999999
2560    // overflow = max_int.875
2561    struct Fractions {
2562        zero: String,
2563        gt_0: String,
2564        max: String,
2565        over: String,
2566    }
2567    fn without_last(a: &str) -> &str {
2568        &a[..a.len() - 1]
2569    }
2570    fn make_fraction_strings(max_int: &str, eps_frac: &str) -> Fractions {
2571        let eps_frac_compl: String = eps_frac
2572            .chars()
2573            .map(|digit| (b'0' + b'9' - digit as u8) as char)
2574            .collect();
2575
2576        let zero = String::from("0.") + eps_frac;
2577        let gt_0 = String::from(&*zero) + "000001";
2578        let max = String::from(max_int) + &eps_frac_compl + "999999";
2579        let over = String::from(max_int) + without_last(&eps_frac_compl) + "5";
2580        Fractions {
2581            zero,
2582            gt_0,
2583            max,
2584            over,
2585        }
2586    }
2587
2588    // check that for example for four fractional bits,
2589    //   * 0.03125 (1/32) is parsed as 0
2590    //   * 0.03125000001 (just above 1/32) is parsed as 0.0625 (1/16)
2591    //   * odd.96874999999 (just below 31/32) is parsed as 0.9375 (15/16)
2592    //   * odd.96875 (31/32) is parsed as odd + 1
2593    #[test]
2594    fn check_exact_decimal() {
2595        let max_int_0 = String::from("0.");
2596        let max_int_4 = String::from("15.");
2597        let max_int_8 = format!("{}.", !0u8);
2598        let max_int_16 = format!("{}.", !0u16);
2599        let max_int_28 = format!("{}.", !0u32 >> 4);
2600        let max_int_32 = format!("{}.", !0u32);
2601        let max_int_64 = format!("{}.", !0u64);
2602        let max_int_124 = format!("{}.", !0u128 >> 4);
2603        let max_int_128 = format!("{}.", !0u128);
2604
2605        // Note: fractions can be generated with this:
2606        //
2607        //     use rug::Integer;
2608        //     for &i in &[0, 4, 8, 16, 28, 32, 64, 124, 128] {
2609        //         let eps = Integer::from(Integer::u_pow_u(5, i + 1));
2610        //         println!("let eps_{} = \"{:02$}\";", i, eps, i as usize + 1);
2611        //     }
2612
2613        // eps_0 = 0.5 >> 0 = 0.5
2614        // eps_4 = 0.5 >> 4 = 0.03125
2615        // eps_8 = 0.5 >> 8 = 0.001953125
2616        // etc.
2617        let eps_0 = "5";
2618        let eps_4 = "03125";
2619        let eps_8 = "001953125";
2620        let eps_16 = "00000762939453125";
2621        let eps_28 = "00000000186264514923095703125";
2622        let eps_32 = "000000000116415321826934814453125";
2623        let eps_64 = "00000000000000000002710505431213761085018632002174854278564453125";
2624        let eps_124 = "0000000000000000000000000000000000000235098870164457501593747307\
2625                       4444491355637331113544175043017503412556834518909454345703125";
2626        let eps_128 = "0000000000000000000000000000000000000014693679385278593849609206\
2627                       71527807097273331945965109401885939632848021574318408966064453125";
2628
2629        let frac_0_8 = make_fraction_strings(&max_int_0, eps_8);
2630        assert_ok!(U0F8, &frac_0_8.zero, 10, 0, false);
2631        assert_ok!(U0F8, &frac_0_8.gt_0, 10, 1, false);
2632        assert_ok!(U0F8, &frac_0_8.max, 10, !0, false);
2633        assert_ok!(U0F8, &frac_0_8.over, 10, 0, true);
2634
2635        let frac_4_4 = make_fraction_strings(&max_int_4, eps_4);
2636        assert_ok!(U4F4, &frac_4_4.zero, 10, 0, false);
2637        assert_ok!(U4F4, &frac_4_4.gt_0, 10, 1, false);
2638        assert_ok!(U4F4, &frac_4_4.max, 10, !0, false);
2639        assert_ok!(U4F4, &frac_4_4.over, 10, 0, true);
2640
2641        let frac_8_0 = make_fraction_strings(&max_int_8, eps_0);
2642        assert_ok!(U8F0, &frac_8_0.zero, 10, 0, false);
2643        assert_ok!(U8F0, &frac_8_0.gt_0, 10, 1, false);
2644        assert_ok!(U8F0, &frac_8_0.max, 10, !0, false);
2645        assert_ok!(U8F0, &frac_8_0.over, 10, 0, true);
2646
2647        let frac_0_32 = make_fraction_strings(&max_int_0, eps_32);
2648        assert_ok!(U0F32, &frac_0_32.zero, 10, 0, false);
2649        assert_ok!(U0F32, &frac_0_32.gt_0, 10, 1, false);
2650        assert_ok!(U0F32, &frac_0_32.max, 10, !0, false);
2651        assert_ok!(U0F32, &frac_0_32.over, 10, 0, true);
2652
2653        let frac_4_28 = make_fraction_strings(&max_int_4, eps_28);
2654        assert_ok!(U4F28, &frac_4_28.zero, 10, 0, false);
2655        assert_ok!(U4F28, &frac_4_28.gt_0, 10, 1, false);
2656        assert_ok!(U4F28, &frac_4_28.max, 10, !0, false);
2657        assert_ok!(U4F28, &frac_4_28.over, 10, 0, true);
2658
2659        let frac_16_16 = make_fraction_strings(&max_int_16, eps_16);
2660        assert_ok!(U16F16, &frac_16_16.zero, 10, 0, false);
2661        assert_ok!(U16F16, &frac_16_16.gt_0, 10, 1, false);
2662        assert_ok!(U16F16, &frac_16_16.max, 10, !0, false);
2663        assert_ok!(U16F16, &frac_16_16.over, 10, 0, true);
2664
2665        let frac_28_4 = make_fraction_strings(&max_int_28, eps_4);
2666        assert_ok!(U28F4, &frac_28_4.zero, 10, 0, false);
2667        assert_ok!(U28F4, &frac_28_4.gt_0, 10, 1, false);
2668        assert_ok!(U28F4, &frac_28_4.max, 10, !0, false);
2669        assert_ok!(U28F4, &frac_28_4.over, 10, 0, true);
2670
2671        let frac_32_0 = make_fraction_strings(&max_int_32, eps_0);
2672        assert_ok!(U32F0, &frac_32_0.zero, 10, 0, false);
2673        assert_ok!(U32F0, &frac_32_0.gt_0, 10, 1, false);
2674        assert_ok!(U32F0, &frac_32_0.max, 10, !0, false);
2675        assert_ok!(U32F0, &frac_32_0.over, 10, 0, true);
2676
2677        let frac_0_128 = make_fraction_strings(&max_int_0, eps_128);
2678        assert_ok!(U0F128, &frac_0_128.zero, 10, 0, false);
2679        assert_ok!(U0F128, &frac_0_128.gt_0, 10, 1, false);
2680        assert_ok!(U0F128, &frac_0_128.max, 10, !0, false);
2681        assert_ok!(U0F128, &frac_0_128.over, 10, 0, true);
2682
2683        let frac_4_124 = make_fraction_strings(&max_int_4, eps_124);
2684        assert_ok!(U4F124, &frac_4_124.zero, 10, 0, false);
2685        assert_ok!(U4F124, &frac_4_124.gt_0, 10, 1, false);
2686        assert_ok!(U4F124, &frac_4_124.max, 10, !0, false);
2687        assert_ok!(U4F124, &frac_4_124.over, 10, 0, true);
2688
2689        let frac_64_64 = make_fraction_strings(&max_int_64, eps_64);
2690        assert_ok!(U64F64, &frac_64_64.zero, 10, 0, false);
2691        assert_ok!(U64F64, &frac_64_64.gt_0, 10, 1, false);
2692        assert_ok!(U64F64, &frac_64_64.max, 10, !0, false);
2693        assert_ok!(U64F64, &frac_64_64.over, 10, 0, true);
2694
2695        let frac_124_4 = make_fraction_strings(&max_int_124, eps_4);
2696        assert_ok!(U124F4, &frac_124_4.zero, 10, 0, false);
2697        assert_ok!(U124F4, &frac_124_4.gt_0, 10, 1, false);
2698        assert_ok!(U124F4, &frac_124_4.max, 10, !0, false);
2699        assert_ok!(U124F4, &frac_124_4.over, 10, 0, true);
2700
2701        let frac_128_0 = make_fraction_strings(&max_int_128, eps_0);
2702        assert_ok!(U128F0, &frac_128_0.zero, 10, 0, false);
2703        assert_ok!(U128F0, &frac_128_0.gt_0, 10, 1, false);
2704        assert_ok!(U128F0, &frac_128_0.max, 10, !0, false);
2705        assert_ok!(U128F0, &frac_128_0.over, 10, 0, true);
2706
2707        // some other cases
2708        // 13/32 = 6.5/16, to even 6/16
2709        assert_ok!(
2710            U4F4,
2711            "0.40624999999999999999999999999999999999999999999999",
2712            10,
2713            0x06,
2714            false
2715        );
2716        assert_ok!(U4F4, "0.40625", 10, 0x06, false);
2717        assert_ok!(
2718            U4F4,
2719            "0.40625000000000000000000000000000000000000000000001",
2720            10,
2721            0x07,
2722            false
2723        );
2724        // 14/32 = 7/16
2725        assert_ok!(U4F4, "0.4375", 10, 0x07, false);
2726        // 15/32 = 7.5/16, to even 8/16
2727        assert_ok!(
2728            U4F4,
2729            "0.46874999999999999999999999999999999999999999999999",
2730            10,
2731            0x07,
2732            false
2733        );
2734        assert_ok!(U4F4, "0.46875", 10, 0x08, false);
2735        assert_ok!(
2736            U4F4,
2737            "0.46875000000000000000000000000000000000000000000001",
2738            10,
2739            0x08,
2740            false
2741        );
2742        // 16/32 = 8/16
2743        assert_ok!(U4F4, "0.5", 10, 0x08, false);
2744        // 17/32 = 8.5/16, to even 8/16
2745        assert_ok!(
2746            U4F4,
2747            "0.53124999999999999999999999999999999999999999999999",
2748            10,
2749            0x08,
2750            false
2751        );
2752        assert_ok!(U4F4, "0.53125", 10, 0x08, false);
2753        assert_ok!(
2754            U4F4,
2755            "0.53125000000000000000000000000000000000000000000001",
2756            10,
2757            0x09,
2758            false
2759        );
2760        // 18/32 = 9/16
2761        assert_ok!(U4F4, "0.5625", 10, 0x09, false);
2762    }
2763
2764    #[test]
2765    fn frac4() {
2766        for u in 0..=255u8 {
2767            let (ifix, ufix) = (I4F4::from_bits(u as i8), U4F4::from_bits(u));
2768            let (ifix_str, ufix_str) = (ifix.to_string(), ufix.to_string());
2769            assert_eq!(I4F4::from_str(&ifix_str).unwrap(), ifix);
2770            assert_eq!(U4F4::from_str(&ufix_str).unwrap(), ufix);
2771        }
2772    }
2773
2774    #[test]
2775    fn frac17() {
2776        for u in 0..(1 << 17) {
2777            let fix = U15F17::from_bits(u) + U15F17::from_num(99);
2778            let fix_pos = I15F17::from_num(fix);
2779            let fix_neg = -fix_pos;
2780            let fix_str = fix.to_string();
2781            let fix_pos_str = fix_pos.to_string();
2782            let fix_neg_str = fix_neg.to_string();
2783            assert_eq!(fix_str, fix_pos_str);
2784            if u != 0 {
2785                assert_eq!(&fix_neg_str[..1], "-");
2786                assert_eq!(&fix_neg_str[1..], fix_pos_str);
2787            }
2788            assert_eq!(U15F17::from_str(&fix_str).unwrap(), fix);
2789            assert_eq!(I15F17::from_str(&fix_pos_str).unwrap(), fix_pos);
2790            assert_eq!(I15F17::from_str(&fix_neg_str).unwrap(), fix_neg);
2791
2792            let fix_str3 = format!("{fix:.3}");
2793            let fix_pos_str3 = format!("{fix_pos:.3}");
2794            let fix_neg_str3 = format!("{fix_neg:.3}");
2795            assert_eq!(fix_str3, fix_pos_str3);
2796            if u != 0 {
2797                assert_eq!(&fix_neg_str3[..1], "-");
2798                assert_eq!(&fix_neg_str3[1..], fix_pos_str3);
2799            }
2800            let max_diff = U15F17::from_bits((5 << 17) / 10000 + 1);
2801            let from_fix_str3 = U15F17::from_str(&fix_str3).unwrap();
2802            assert!(from_fix_str3.dist(fix) <= max_diff);
2803            let from_fix_pos_str3 = I15F17::from_str(&fix_pos_str3).unwrap();
2804            assert!(from_fix_pos_str3.dist(fix_pos) <= max_diff);
2805            let from_fix_neg_str3 = I15F17::from_str(&fix_neg_str3).unwrap();
2806            assert!(from_fix_neg_str3.dist(fix_neg) <= max_diff);
2807
2808            let fix_str9 = format!("{fix:.9}");
2809            let fix_pos_str9 = format!("{fix_pos:.9}");
2810            let fix_neg_str9 = format!("{fix_neg:.9}");
2811            assert_eq!(fix_str9, fix_pos_str9);
2812            if u != 0 {
2813                assert_eq!(&fix_neg_str9[..1], "-");
2814                assert_eq!(&fix_neg_str9[1..], fix_pos_str9);
2815            }
2816            assert_eq!(U15F17::from_str(&fix_str9).unwrap(), fix);
2817            assert_eq!(I15F17::from_str(&fix_pos_str9).unwrap(), fix_pos);
2818            assert_eq!(I15F17::from_str(&fix_neg_str9).unwrap(), fix_neg);
2819        }
2820    }
2821}