Coverage Report

Created: 2026-03-31 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/dtoa-1.0.10/src/diyfp.rs
Line
Count
Source
1
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
2
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
3
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
4
// option. This file may not be copied, modified, or distributed
5
// except according to those terms.
6
//
7
// ---
8
//
9
// The C++ implementation preserved here in comments is licensed as follows:
10
//
11
// Tencent is pleased to support the open source community by making RapidJSON
12
// available.
13
//
14
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All
15
// rights reserved.
16
//
17
// Licensed under the MIT License (the "License"); you may not use this file
18
// except in compliance with the License. You may obtain a copy of the License
19
// at
20
//
21
// http://opensource.org/licenses/MIT
22
//
23
// Unless required by applicable law or agreed to in writing, software
24
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
25
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
26
// License for the specific language governing permissions and limitations under
27
// the License.
28
29
use core::ops::{Mul, Sub};
30
#[cfg(feature = "no-panic")]
31
use no_panic::no_panic;
32
33
#[derive(Copy, Clone, Debug)]
34
pub struct DiyFp<F, E> {
35
    pub f: F,
36
    pub e: E,
37
}
38
39
impl<F, E> DiyFp<F, E> {
40
    #[cfg_attr(feature = "no-panic", no_panic)]
41
0
    pub fn new(f: F, e: E) -> Self {
42
0
        DiyFp { f, e }
43
0
    }
Unexecuted instantiation: <dtoa::diyfp::DiyFp<u32, i32>>::new
Unexecuted instantiation: <dtoa::diyfp::DiyFp<u64, isize>>::new
44
}
45
46
impl<F, E> Sub for DiyFp<F, E>
47
where
48
    F: Sub<F, Output = F>,
49
{
50
    type Output = Self;
51
52
    #[cfg_attr(feature = "no-panic", no_panic)]
53
0
    fn sub(self, rhs: Self) -> Self {
54
0
        DiyFp {
55
0
            f: self.f - rhs.f,
56
0
            e: self.e,
57
0
        }
58
0
    }
Unexecuted instantiation: <dtoa::diyfp::DiyFp<u32, i32> as core::ops::arith::Sub>::sub
Unexecuted instantiation: <dtoa::diyfp::DiyFp<_, _> as core::ops::arith::Sub>::sub
59
}
60
61
impl Mul for DiyFp<u32, i32> {
62
    type Output = Self;
63
64
    #[cfg_attr(feature = "no-panic", no_panic)]
65
0
    fn mul(self, rhs: Self) -> Self {
66
0
        let mut tmp = self.f as u64 * rhs.f as u64;
67
0
        tmp += 1u64 << 31; // mult_round
68
0
        DiyFp {
69
0
            f: (tmp >> 32) as u32,
70
0
            e: self.e + rhs.e + 32,
71
0
        }
72
0
    }
73
}
74
75
impl Mul for DiyFp<u64, isize> {
76
    type Output = Self;
77
78
    #[cfg_attr(feature = "no-panic", no_panic)]
79
0
    fn mul(self, rhs: Self) -> Self {
80
0
        let m32 = 0xFFFFFFFFu64;
81
0
        let a = self.f >> 32;
82
0
        let b = self.f & m32;
83
0
        let c = rhs.f >> 32;
84
0
        let d = rhs.f & m32;
85
0
        let ac = a * c;
86
0
        let bc = b * c;
87
0
        let ad = a * d;
88
0
        let bd = b * d;
89
0
        let mut tmp = (bd >> 32) + (ad & m32) + (bc & m32);
90
0
        tmp += 1u64 << 31; // mult_round
91
0
        DiyFp {
92
0
            f: ac + (ad >> 32) + (bc >> 32) + (tmp >> 32),
93
0
            e: self.e + rhs.e + 64,
94
0
        }
95
0
    }
96
}
97
98
macro_rules! diyfp {
99
    (
100
        floating_type: $fty:ty,
101
        significand_type: $sigty:ty,
102
        exponent_type: $expty:ty,
103
104
        diy_significand_size: $diy_significand_size:expr,
105
        significand_size: $significand_size:expr,
106
        exponent_bias: $exponent_bias:expr,
107
        mask_type: $mask_type:ty,
108
        exponent_mask: $exponent_mask:expr,
109
        significand_mask: $significand_mask:expr,
110
        hidden_bit: $hidden_bit:expr,
111
        cached_powers_f: $cached_powers_f:expr,
112
        cached_powers_e: $cached_powers_e:expr,
113
        min_power: $min_power:expr,
114
    ) => {
115
        type DiyFp = diyfp::DiyFp<$sigty, $expty>;
116
117
        impl DiyFp {
118
            // Preconditions:
119
            // `d` must have a positive sign and must not be infinity or NaN.
120
            /*
121
            explicit DiyFp(double d) {
122
                union {
123
                    double d;
124
                    uint64_t u64;
125
                } u = { d };
126
127
                int biased_e = static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize);
128
                uint64_t significand = (u.u64 & kDpSignificandMask);
129
                if (biased_e != 0) {
130
                    f = significand + kDpHiddenBit;
131
                    e = biased_e - kDpExponentBias;
132
                }
133
                else {
134
                    f = significand;
135
                    e = kDpMinExponent + 1;
136
                }
137
            }
138
            */
139
            #[cfg_attr(feature = "no-panic", no_panic)]
140
0
            unsafe fn from(d: $fty) -> Self {
141
0
                let u: $mask_type = mem::transmute(d);
142
143
0
                let biased_e = ((u & $exponent_mask) >> $significand_size) as $expty;
144
0
                let significand = u & $significand_mask;
145
0
                if biased_e != 0 {
146
0
                    DiyFp {
147
0
                        f: significand + $hidden_bit,
148
0
                        e: biased_e - $exponent_bias - $significand_size,
149
0
                    }
150
                } else {
151
0
                    DiyFp {
152
0
                        f: significand,
153
0
                        e: 1 - $exponent_bias - $significand_size,
154
0
                    }
155
                }
156
0
            }
Unexecuted instantiation: <dtoa::diyfp::DiyFp<u32, i32>>::from
Unexecuted instantiation: <dtoa::diyfp::DiyFp<u64, isize>>::from
157
158
            // Normalizes so that the highest bit of the diy significand is 1.
159
            /*
160
            DiyFp Normalize() const {
161
                DiyFp res = *this;
162
                while (!(res.f & (static_cast<uint64_t>(1) << 63))) {
163
                    res.f <<= 1;
164
                    res.e--;
165
                }
166
                return res;
167
            }
168
            */
169
            #[cfg_attr(feature = "no-panic", no_panic)]
170
0
            fn normalize(self) -> DiyFp {
171
0
                let mut res = self;
172
0
                while (res.f & (1 << ($diy_significand_size - 1))) == 0 {
173
0
                    res.f <<= 1;
174
0
                    res.e -= 1;
175
0
                }
176
0
                res
177
0
            }
Unexecuted instantiation: <dtoa::diyfp::DiyFp<u32, i32>>::normalize
Unexecuted instantiation: <dtoa::diyfp::DiyFp<u64, isize>>::normalize
178
179
            // Normalizes so that the highest bit of the diy significand is 1.
180
            //
181
            // Precondition:
182
            // `self.f` must be no more than 2 bits longer than the f64 significand.
183
            /*
184
            DiyFp NormalizeBoundary() const {
185
                DiyFp res = *this;
186
                while (!(res.f & (kDpHiddenBit << 1))) {
187
                    res.f <<= 1;
188
                    res.e--;
189
                }
190
                res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
191
                res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
192
                return res;
193
            }
194
            */
195
            #[cfg_attr(feature = "no-panic", no_panic)]
196
0
            fn normalize_boundary(self) -> DiyFp {
197
0
                let mut res = self;
198
0
                while (res.f & $hidden_bit << 1) == 0 {
199
0
                    res.f <<= 1;
200
0
                    res.e -= 1;
201
0
                }
202
0
                res.f <<= $diy_significand_size - $significand_size - 2;
203
0
                res.e -= $diy_significand_size - $significand_size - 2;
204
0
                res
205
0
            }
Unexecuted instantiation: <dtoa::diyfp::DiyFp<u32, i32>>::normalize_boundary
Unexecuted instantiation: <dtoa::diyfp::DiyFp<u64, isize>>::normalize_boundary
206
207
            // Normalizes `self - e` and `self + e` where `e` is half of the least
208
            // significant digit of `self`. The plus is normalized so that the highest
209
            // bit of the diy significand is 1. The minus is normalized so that it has
210
            // the same exponent as the plus.
211
            //
212
            // Preconditions:
213
            // `self` must have been returned directly from `DiyFp::from_f64`.
214
            // `self.f` must not be zero.
215
            /*
216
            void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const {
217
                DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
218
                DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
219
                mi.f <<= mi.e - pl.e;
220
                mi.e = pl.e;
221
                *plus = pl;
222
                *minus = mi;
223
            }
224
            */
225
            #[cfg_attr(feature = "no-panic", no_panic)]
226
0
            fn normalized_boundaries(self) -> (DiyFp, DiyFp) {
227
0
                let pl = DiyFp::new((self.f << 1) + 1, self.e - 1).normalize_boundary();
228
0
                let mut mi = if self.f == $hidden_bit {
229
0
                    DiyFp::new((self.f << 2) - 1, self.e - 2)
230
                } else {
231
0
                    DiyFp::new((self.f << 1) - 1, self.e - 1)
232
                };
233
0
                mi.f <<= mi.e - pl.e;
234
0
                mi.e = pl.e;
235
0
                (mi, pl)
236
0
            }
Unexecuted instantiation: <dtoa::diyfp::DiyFp<u32, i32>>::normalized_boundaries
Unexecuted instantiation: <dtoa::diyfp::DiyFp<u64, isize>>::normalized_boundaries
237
        }
238
239
        /*
240
        inline DiyFp GetCachedPower(int e, int* K) {
241
            //int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
242
            double dk = (-61 - e) * 0.30102999566398114 + 347;  // dk must be positive, so can do ceiling in positive
243
            int k = static_cast<int>(dk);
244
            if (dk - k > 0.0)
245
                k++;
246
247
            unsigned index = static_cast<unsigned>((k >> 3) + 1);
248
            *K = -(-348 + static_cast<int>(index << 3));    // decimal exponent no need lookup table
249
250
            return GetCachedPowerByIndex(index);
251
        }
252
        */
253
        #[inline]
254
        #[cfg_attr(feature = "no-panic", no_panic)]
255
0
        fn get_cached_power(e: $expty) -> (DiyFp, isize) {
256
0
            let dk = (3 - $diy_significand_size - e) as f64 * 0.30102999566398114f64
257
0
                - ($min_power + 1) as f64;
258
0
            let mut k = dk as isize;
259
0
            if dk - k as f64 > 0.0 {
260
0
                k += 1;
261
0
            }
262
263
0
            let index = ((k >> 3) + 1) as usize;
264
0
            let k = -($min_power + (index << 3) as isize);
265
266
0
            (
267
0
                DiyFp::new(*unsafe { $cached_powers_f.get_unchecked(index) }, *unsafe {
268
0
                    $cached_powers_e.get_unchecked(index)
269
0
                }
270
0
                    as $expty),
271
0
                k,
272
0
            )
273
0
        }
Unexecuted instantiation: <f32 as dtoa::private::Sealed>::write::get_cached_power
Unexecuted instantiation: <f32 as dtoa::private::Sealed>::write::get_cached_power
Unexecuted instantiation: <f64 as dtoa::private::Sealed>::write::get_cached_power
274
    };
275
}