1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
//! 泛型浮点类型的辅助 trait。

use crate::fmt::{Debug, LowerExp};
use crate::num::FpCategory;
use crate::ops::{Add, Div, Mul, Neg};

/// 一个帮助程序 trait,可以避免基本上复制 `f32` 和 `f64` 的所有转换代码。
///
/// 有关为什么这样做的必要信息,请参见父模块的文档注释。
///
/// **永远不要** 为其他类型实现或在 dec2flt 模块外部使用。
#[doc(hidden)]
pub trait RawFloat:
    Sized
    + Div<Output = Self>
    + Neg<Output = Self>
    + Mul<Output = Self>
    + Add<Output = Self>
    + LowerExp
    + PartialEq
    + PartialOrd
    + Default
    + Clone
    + Copy
    + Debug
{
    const INFINITY: Self;
    const NEG_INFINITY: Self;
    const NAN: Self;
    const NEG_NAN: Self;

    /// 有效位数的位数,*不包括* 隐藏位。
    const MANTISSA_EXPLICIT_BITS: usize;

    // 当 q ≥ −4 在 64 位情况下和 q ≥ -17 在 32 位情况下时,只对 q 的负值进行舍入到偶数。
    //
    // 当 q ≥ 0 时,我们有 5^q ≤ 2m+1。在 64 位情况下,我们有 5^q ≤ 2m+1 ≤ 2^54 或 q ≤ 23。在 32 位的情况下,我们有
    // 5^q ≤ 2m+1 ≤ 2^25 或 q ≤ 10。
    //
    // 当 q < 0 时,我们有 w ≥ (2m+1)×5^−q。我们必须有 w < 2^64,所以 (2m+1)×5^−q < 2^64。
    // 我们有 2m+1 > 2^53 (64 位情况) 或 2m+1 > 2^24 (32 位情况)。
    // 因此,我们必须有 2^53×5^−q < 2^64 (64-bit) 和 2^24×5^−q < 2^64 (32-bit)。
    // 因此,我们有 5^−q < 2^11 或 q ≥ −4 (64 位情况) 和 5^−q < 2^40 或 q ≥ −17 (32-bitcase)。
    //
    // 因此,我们只需要在我们有 q ∈ [−4,23](in the 64-bit case) 或 q∈[−17,10] (在 32 位情况下) 时才需要舍入关系。
    //
    // 在这两种情况下,five(5^|q|) 的功能都适合 64 位字。
    //
    //
    //
    //
    //
    const MIN_EXPONENT_ROUND_TO_EVEN: i32;
    const MAX_EXPONENT_ROUND_TO_EVEN: i32;

    // 快速路径情况下的最小指数,或 `-⌊(MANTISSA_EXPLICIT_BITS+1)/log2(5)⌋`
    const MIN_EXPONENT_FAST_PATH: i64;

    // 快速路径情况下的最大指数,或 `⌊(MANTISSA_EXPLICIT_BITS+1)/log2(5)⌋`
    const MAX_EXPONENT_FAST_PATH: i64;

    // 可以为伪装的快速路径情况表示的最大指数。
    // 这是 `MAX_EXPONENT_FAST_PATH + ⌊(MANTISSA_EXPLICIT_BITS+1)/log2(10)⌋`
    const MAX_EXPONENT_DISGUISED_FAST_PATH: i64;

    // 最小指数值 `-(1 << (EXP_BITS - 1)) + 1`。
    const MINIMUM_EXPONENT: i32;

    // 最大指数值 `(1 << EXP_BITS) - 1`。
    const INFINITE_POWER: i32;

    // 符号的索引 (以位为单位)。
    const SIGN_INDEX: usize;

    // 非零值的最小十进制指数。
    const SMALLEST_POWER_OF_TEN: i32;

    // 非无限值的最大十进制指数。
    const LARGEST_POWER_OF_TEN: i32;

    // 快速路径的最大尾数 (f64 为 `1 << 53`)。
    const MAX_MANTISSA_FAST_PATH: u64 = 2_u64 << Self::MANTISSA_EXPLICIT_BITS;

    /// 通过 as 转换将整数转换为浮点数。
    /// 这仅在快速路径算法中调用,因此不会丢失精度,因为只有当值 <= Self::MAX_MANTISSA_FAST_PATH 时,该值才会始终具有。
    ///
    ///
    fn from_u64(v: u64) -> Self;

    /// 从整数执行原始转换。
    fn from_u64_bits(v: u64) -> Self;

    /// 获得一个小的 10 次幂以进行快速路径乘法。
    fn pow10_fast_path(exponent: usize) -> Self;

    /// 返回此数字所属的类别。
    fn classify(self) -> FpCategory;

    /// 以整数形式返回尾数,指数和符号。
    fn integer_decode(self) -> (u64, i16, i8);
}

impl RawFloat for f32 {
    const INFINITY: Self = f32::INFINITY;
    const NEG_INFINITY: Self = f32::NEG_INFINITY;
    const NAN: Self = f32::NAN;
    const NEG_NAN: Self = -f32::NAN;

    const MANTISSA_EXPLICIT_BITS: usize = 23;
    const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -17;
    const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 10;
    const MIN_EXPONENT_FAST_PATH: i64 = -10; // 假设 FLT_EVAL_METHOD = 0
    const MAX_EXPONENT_FAST_PATH: i64 = 10;
    const MAX_EXPONENT_DISGUISED_FAST_PATH: i64 = 17;
    const MINIMUM_EXPONENT: i32 = -127;
    const INFINITE_POWER: i32 = 0xFF;
    const SIGN_INDEX: usize = 31;
    const SMALLEST_POWER_OF_TEN: i32 = -65;
    const LARGEST_POWER_OF_TEN: i32 = 38;

    #[inline]
    fn from_u64(v: u64) -> Self {
        debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
        v as _
    }

    #[inline]
    fn from_u64_bits(v: u64) -> Self {
        f32::from_bits((v & 0xFFFFFFFF) as u32)
    }

    fn pow10_fast_path(exponent: usize) -> Self {
        #[allow(clippy::use_self)]
        const TABLE: [f32; 16] =
            [1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 0., 0., 0., 0., 0.];
        TABLE[exponent & 15]
    }

    /// 以整数形式返回尾数,指数和符号。
    fn integer_decode(self) -> (u64, i16, i8) {
        let bits = self.to_bits();
        let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 };
        let mut exponent: i16 = ((bits >> 23) & 0xff) as i16;
        let mantissa =
            if exponent == 0 { (bits & 0x7fffff) << 1 } else { (bits & 0x7fffff) | 0x800000 };
        // 指数偏差 + 尾数偏移
        exponent -= 127 + 23;
        (mantissa as u64, exponent, sign)
    }

    fn classify(self) -> FpCategory {
        self.classify()
    }
}

impl RawFloat for f64 {
    const INFINITY: Self = f64::INFINITY;
    const NEG_INFINITY: Self = f64::NEG_INFINITY;
    const NAN: Self = f64::NAN;
    const NEG_NAN: Self = -f64::NAN;

    const MANTISSA_EXPLICIT_BITS: usize = 52;
    const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -4;
    const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 23;
    const MIN_EXPONENT_FAST_PATH: i64 = -22; // 假设 FLT_EVAL_METHOD = 0
    const MAX_EXPONENT_FAST_PATH: i64 = 22;
    const MAX_EXPONENT_DISGUISED_FAST_PATH: i64 = 37;
    const MINIMUM_EXPONENT: i32 = -1023;
    const INFINITE_POWER: i32 = 0x7FF;
    const SIGN_INDEX: usize = 63;
    const SMALLEST_POWER_OF_TEN: i32 = -342;
    const LARGEST_POWER_OF_TEN: i32 = 308;

    #[inline]
    fn from_u64(v: u64) -> Self {
        debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
        v as _
    }

    #[inline]
    fn from_u64_bits(v: u64) -> Self {
        f64::from_bits(v)
    }

    fn pow10_fast_path(exponent: usize) -> Self {
        const TABLE: [f64; 32] = [
            1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
            1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        ];
        TABLE[exponent & 31]
    }

    /// 以整数形式返回尾数,指数和符号。
    fn integer_decode(self) -> (u64, i16, i8) {
        let bits = self.to_bits();
        let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
        let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
        let mantissa = if exponent == 0 {
            (bits & 0xfffffffffffff) << 1
        } else {
            (bits & 0xfffffffffffff) | 0x10000000000000
        };
        // 指数偏差 + 尾数偏移
        exponent -= 1023 + 52;
        (mantissa, exponent, sign)
    }

    fn classify(self) -> FpCategory {
        self.classify()
    }
}