malachite_float/conversion/string/
from_string.rs1use crate::Float;
10use alloc::string::{String, ToString};
11use core::str::FromStr;
12use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, NegativeZero, Zero};
13use malachite_base::num::conversion::string::options::FromSciStringOptions;
14use malachite_base::num::conversion::traits::{FromSciString, FromStringBase};
15use malachite_base::rounding_modes::RoundingMode::*;
16use malachite_q::Rational;
17
18fn reduce_exponent_in_hex_string(s: &str) -> Option<(String, i32)> {
19 if let Some(exp_index) = s.find('E') {
20 let tail = &s[exp_index + 1..];
21 let hash_index = tail.find('#').unwrap();
22 let tail = &tail[..hash_index];
23 let original_exponent = i32::from_str(tail).unwrap();
24 if original_exponent.unsigned_abs() < 20 {
25 return None;
26 }
27 let mut new_s = s[..=exp_index].to_string();
28 new_s += "+20";
29 new_s += &s[exp_index + hash_index + 1..];
30 Some((new_s, (original_exponent << 2) - 80))
31 } else {
32 None
33 }
34}
35
36fn from_hex_string(s: &str) -> Float {
37 match s {
38 "NaN" => Float::NAN,
39 "Infinity" => Float::INFINITY,
40 "-Infinity" => Float::NEGATIVE_INFINITY,
41 "0x0.0" => Float::ZERO,
42 "-0x0.0" => Float::NEGATIVE_ZERO,
43 s => {
44 let (s, sign) = if let Some(s) = s.strip_prefix('-') {
45 (s, false)
46 } else {
47 (s, true)
48 };
49 let s = s.strip_prefix("0x").unwrap();
50 let hash_index = s.find('#').unwrap();
51 let precision = u64::from_str(&s[hash_index + 1..]).unwrap();
52 let mut options = FromSciStringOptions::default();
53 options.set_base(16);
54 let x = if let Some((alt_s, exp_offset)) = reduce_exponent_in_hex_string(s) {
55 let hash_index = alt_s.find('#').unwrap();
56 Float::from_rational_prec_round(
57 Rational::from_sci_string_with_options(&alt_s[..hash_index], options).unwrap(),
58 precision,
59 Exact,
60 )
61 .0 << exp_offset
62 } else {
63 Float::from_rational_prec_round(
64 Rational::from_sci_string_with_options(&s[..hash_index], options).unwrap(),
65 precision,
66 Exact,
67 )
68 .0
69 };
70 if sign { x } else { -x }
71 }
72 }
73}
74
75impl FromStringBase for Float {
76 fn from_string_base(base: u8, s: &str) -> Option<Self> {
77 assert_eq!(base, 16);
78 Some(from_hex_string(s))
79 }
80}