/rust/registry/src/index.crates.io-1949cf8c6b5b557f/dtoa-0.4.7/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 std::ops; |
30 | | |
31 | | #[derive(Copy, Clone, Debug)] |
32 | | pub struct DiyFp<F, E> { |
33 | | pub f: F, |
34 | | pub e: E, |
35 | | } |
36 | | |
37 | | impl<F, E> DiyFp<F, E> { |
38 | 243M | pub fn new(f: F, e: E) -> Self { |
39 | 243M | DiyFp { f: f, e: e } |
40 | 243M | } <dtoa::diyfp::DiyFp<u32, i32>>::new Line | Count | Source | 38 | 243M | pub fn new(f: F, e: E) -> Self { | 39 | 243M | DiyFp { f: f, e: e } | 40 | 243M | } |
Unexecuted instantiation: <dtoa::diyfp::DiyFp<u64, isize>>::new |
41 | | } |
42 | | |
43 | | impl ops::Mul for DiyFp<u32, i32> { |
44 | | type Output = Self; |
45 | 182M | fn mul(self, rhs: Self) -> Self { |
46 | 182M | let mut tmp = self.f as u64 * rhs.f as u64; |
47 | 182M | tmp += 1u64 << 31; // mult_round |
48 | 182M | DiyFp { |
49 | 182M | f: (tmp >> 32) as u32, |
50 | 182M | e: self.e + rhs.e + 32, |
51 | 182M | } |
52 | 182M | } |
53 | | } |
54 | | |
55 | | impl ops::Mul for DiyFp<u64, isize> { |
56 | | type Output = Self; |
57 | 0 | fn mul(self, rhs: Self) -> Self { |
58 | 0 | let m32 = 0xFFFFFFFFu64; |
59 | 0 | let a = self.f >> 32; |
60 | 0 | let b = self.f & m32; |
61 | 0 | let c = rhs.f >> 32; |
62 | 0 | let d = rhs.f & m32; |
63 | 0 | let ac = a * c; |
64 | 0 | let bc = b * c; |
65 | 0 | let ad = a * d; |
66 | 0 | let bd = b * d; |
67 | 0 | let mut tmp = (bd >> 32) + (ad & m32) + (bc & m32); |
68 | 0 | tmp += 1u64 << 31; // mult_round |
69 | 0 | DiyFp { |
70 | 0 | f: ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), |
71 | 0 | e: self.e + rhs.e + 64, |
72 | 0 | } |
73 | 0 | } |
74 | | } |
75 | | |
76 | | #[doc(hidden)] |
77 | | #[macro_export] |
78 | | macro_rules! diyfp {( |
79 | | floating_type: $fty:ty, |
80 | | significand_type: $sigty:ty, |
81 | | exponent_type: $expty:ty, |
82 | | |
83 | | diy_significand_size: $diy_significand_size:expr, |
84 | | significand_size: $significand_size:expr, |
85 | | exponent_bias: $exponent_bias:expr, |
86 | | mask_type: $mask_type:ty, |
87 | | exponent_mask: $exponent_mask:expr, |
88 | | significand_mask: $significand_mask:expr, |
89 | | hidden_bit: $hidden_bit:expr, |
90 | | cached_powers_f: $cached_powers_f:expr, |
91 | | cached_powers_e: $cached_powers_e:expr, |
92 | | min_power: $min_power:expr, |
93 | | ) => { |
94 | | |
95 | | type DiyFp = diyfp::DiyFp<$sigty, $expty>; |
96 | | |
97 | | impl DiyFp { |
98 | | // Preconditions: |
99 | | // `d` must have a positive sign and must not be infinity or NaN. |
100 | | /* |
101 | | explicit DiyFp(double d) { |
102 | | union { |
103 | | double d; |
104 | | uint64_t u64; |
105 | | } u = { d }; |
106 | | |
107 | | int biased_e = static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize); |
108 | | uint64_t significand = (u.u64 & kDpSignificandMask); |
109 | | if (biased_e != 0) { |
110 | | f = significand + kDpHiddenBit; |
111 | | e = biased_e - kDpExponentBias; |
112 | | } |
113 | | else { |
114 | | f = significand; |
115 | | e = kDpMinExponent + 1; |
116 | | } |
117 | | } |
118 | | */ |
119 | 60.8M | unsafe fn from(d: $fty) -> Self { |
120 | 60.8M | let u: $mask_type = mem::transmute(d); |
121 | | |
122 | 60.8M | let biased_e = ((u & $exponent_mask) >> $significand_size) as $expty; |
123 | 60.8M | let significand = u & $significand_mask; |
124 | 60.8M | if biased_e != 0 { |
125 | 60.8M | DiyFp { |
126 | 60.8M | f: significand + $hidden_bit, |
127 | 60.8M | e: biased_e - $exponent_bias - $significand_size, |
128 | 60.8M | } |
129 | | } else { |
130 | 17 | DiyFp { |
131 | 17 | f: significand, |
132 | 17 | e: 1 - $exponent_bias - $significand_size, |
133 | 17 | } |
134 | | } |
135 | 60.8M | } <dtoa::diyfp::DiyFp<u32, i32>>::from Line | Count | Source | 119 | 60.8M | unsafe fn from(d: $fty) -> Self { | 120 | 60.8M | let u: $mask_type = mem::transmute(d); | 121 | | | 122 | 60.8M | let biased_e = ((u & $exponent_mask) >> $significand_size) as $expty; | 123 | 60.8M | let significand = u & $significand_mask; | 124 | 60.8M | if biased_e != 0 { | 125 | 60.8M | DiyFp { | 126 | 60.8M | f: significand + $hidden_bit, | 127 | 60.8M | e: biased_e - $exponent_bias - $significand_size, | 128 | 60.8M | } | 129 | | } else { | 130 | 17 | DiyFp { | 131 | 17 | f: significand, | 132 | 17 | e: 1 - $exponent_bias - $significand_size, | 133 | 17 | } | 134 | | } | 135 | 60.8M | } |
Unexecuted instantiation: <dtoa::diyfp::DiyFp<u64, isize>>::from |
136 | | |
137 | | // Normalizes so that the highest bit of the diy significand is 1. |
138 | | /* |
139 | | DiyFp Normalize() const { |
140 | | DiyFp res = *this; |
141 | | while (!(res.f & (static_cast<uint64_t>(1) << 63))) { |
142 | | res.f <<= 1; |
143 | | res.e--; |
144 | | } |
145 | | return res; |
146 | | } |
147 | | */ |
148 | 60.8M | fn normalize(self) -> DiyFp { |
149 | 60.8M | let mut res = self; |
150 | 547M | while (res.f & (1 << ($diy_significand_size - 1))) == 0 { |
151 | 486M | res.f <<= 1; |
152 | 486M | res.e -= 1; |
153 | 486M | } |
154 | 60.8M | res |
155 | 60.8M | } <dtoa::diyfp::DiyFp<u32, i32>>::normalize Line | Count | Source | 148 | 60.8M | fn normalize(self) -> DiyFp { | 149 | 60.8M | let mut res = self; | 150 | 547M | while (res.f & (1 << ($diy_significand_size - 1))) == 0 { | 151 | 486M | res.f <<= 1; | 152 | 486M | res.e -= 1; | 153 | 486M | } | 154 | 60.8M | res | 155 | 60.8M | } |
Unexecuted instantiation: <dtoa::diyfp::DiyFp<u64, isize>>::normalize |
156 | | |
157 | | // Normalizes so that the highest bit of the diy significand is 1. |
158 | | // |
159 | | // Precondition: |
160 | | // `self.f` must be no more than 2 bits longer than the f64 significand. |
161 | | /* |
162 | | DiyFp NormalizeBoundary() const { |
163 | | DiyFp res = *this; |
164 | | while (!(res.f & (kDpHiddenBit << 1))) { |
165 | | res.f <<= 1; |
166 | | res.e--; |
167 | | } |
168 | | res.f <<= (kDiySignificandSize - kDpSignificandSize - 2); |
169 | | res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2); |
170 | | return res; |
171 | | } |
172 | | */ |
173 | 60.8M | fn normalize_boundary(self) -> DiyFp { |
174 | 60.8M | let mut res = self; |
175 | 60.8M | while (res.f & $hidden_bit << 1) == 0 { |
176 | 173 | res.f <<= 1; |
177 | 173 | res.e -= 1; |
178 | 173 | } |
179 | 60.8M | res.f <<= $diy_significand_size - $significand_size - 2; |
180 | 60.8M | res.e -= $diy_significand_size - $significand_size - 2; |
181 | 60.8M | res |
182 | 60.8M | } <dtoa::diyfp::DiyFp<u32, i32>>::normalize_boundary Line | Count | Source | 173 | 60.8M | fn normalize_boundary(self) -> DiyFp { | 174 | 60.8M | let mut res = self; | 175 | 60.8M | while (res.f & $hidden_bit << 1) == 0 { | 176 | 173 | res.f <<= 1; | 177 | 173 | res.e -= 1; | 178 | 173 | } | 179 | 60.8M | res.f <<= $diy_significand_size - $significand_size - 2; | 180 | 60.8M | res.e -= $diy_significand_size - $significand_size - 2; | 181 | 60.8M | res | 182 | 60.8M | } |
Unexecuted instantiation: <dtoa::diyfp::DiyFp<u64, isize>>::normalize_boundary |
183 | | |
184 | | // Normalizes `self - e` and `self + e` where `e` is half of the least |
185 | | // significant digit of `self`. The plus is normalized so that the highest |
186 | | // bit of the diy significand is 1. The minus is normalized so that it has |
187 | | // the same exponent as the plus. |
188 | | // |
189 | | // Preconditions: |
190 | | // `self` must have been returned directly from `DiyFp::from_f64`. |
191 | | // `self.f` must not be zero. |
192 | | /* |
193 | | void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const { |
194 | | DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary(); |
195 | | DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1); |
196 | | mi.f <<= mi.e - pl.e; |
197 | | mi.e = pl.e; |
198 | | *plus = pl; |
199 | | *minus = mi; |
200 | | } |
201 | | */ |
202 | 60.8M | fn normalized_boundaries(self) -> (DiyFp, DiyFp) { |
203 | 60.8M | let pl = DiyFp::new((self.f << 1) + 1, self.e - 1).normalize_boundary(); |
204 | 60.8M | let mut mi = if self.f == $hidden_bit { |
205 | 263k | DiyFp::new((self.f << 2) - 1, self.e - 2) |
206 | | } else { |
207 | 60.5M | DiyFp::new((self.f << 1) - 1, self.e - 1) |
208 | | }; |
209 | 60.8M | mi.f <<= mi.e - pl.e; |
210 | 60.8M | mi.e = pl.e; |
211 | 60.8M | (mi, pl) |
212 | 60.8M | } <dtoa::diyfp::DiyFp<u32, i32>>::normalized_boundaries Line | Count | Source | 202 | 60.8M | fn normalized_boundaries(self) -> (DiyFp, DiyFp) { | 203 | 60.8M | let pl = DiyFp::new((self.f << 1) + 1, self.e - 1).normalize_boundary(); | 204 | 60.8M | let mut mi = if self.f == $hidden_bit { | 205 | 263k | DiyFp::new((self.f << 2) - 1, self.e - 2) | 206 | | } else { | 207 | 60.5M | DiyFp::new((self.f << 1) - 1, self.e - 1) | 208 | | }; | 209 | 60.8M | mi.f <<= mi.e - pl.e; | 210 | 60.8M | mi.e = pl.e; | 211 | 60.8M | (mi, pl) | 212 | 60.8M | } |
Unexecuted instantiation: <dtoa::diyfp::DiyFp<u64, isize>>::normalized_boundaries |
213 | | } |
214 | | |
215 | | impl ops::Sub for DiyFp { |
216 | | type Output = Self; |
217 | 60.8M | fn sub(self, rhs: Self) -> Self { |
218 | 60.8M | DiyFp { |
219 | 60.8M | f: self.f - rhs.f, |
220 | 60.8M | e: self.e, |
221 | 60.8M | } |
222 | 60.8M | } <dtoa::diyfp::DiyFp<u32, i32> as core::ops::arith::Sub>::sub Line | Count | Source | 217 | 60.8M | fn sub(self, rhs: Self) -> Self { | 218 | 60.8M | DiyFp { | 219 | 60.8M | f: self.f - rhs.f, | 220 | 60.8M | e: self.e, | 221 | 60.8M | } | 222 | 60.8M | } |
Unexecuted instantiation: <dtoa::diyfp::DiyFp<u64, isize> as core::ops::arith::Sub>::sub |
223 | | } |
224 | | |
225 | | /* |
226 | | inline DiyFp GetCachedPower(int e, int* K) { |
227 | | //int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374; |
228 | | double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive |
229 | | int k = static_cast<int>(dk); |
230 | | if (dk - k > 0.0) |
231 | | k++; |
232 | | |
233 | | unsigned index = static_cast<unsigned>((k >> 3) + 1); |
234 | | *K = -(-348 + static_cast<int>(index << 3)); // decimal exponent no need lookup table |
235 | | |
236 | | return GetCachedPowerByIndex(index); |
237 | | } |
238 | | */ |
239 | | #[inline] |
240 | 60.8M | fn get_cached_power(e: $expty) -> (DiyFp, isize) { |
241 | 60.8M | let dk = (3 - $diy_significand_size - e) as f64 * 0.30102999566398114f64 - ($min_power + 1) as f64; |
242 | 60.8M | let mut k = dk as isize; |
243 | 60.8M | if dk - k as f64 > 0.0 { |
244 | 60.7M | k += 1; |
245 | 60.7M | } |
246 | | |
247 | 60.8M | let index = ((k >> 3) + 1) as usize; |
248 | 60.8M | let k = -($min_power + (index << 3) as isize); |
249 | | |
250 | 60.8M | (DiyFp::new($cached_powers_f[index], $cached_powers_e[index] as $expty), k) |
251 | 60.8M | } <f32 as dtoa::Floating>::write::get_cached_power Line | Count | Source | 240 | 60.8M | fn get_cached_power(e: $expty) -> (DiyFp, isize) { | 241 | 60.8M | let dk = (3 - $diy_significand_size - e) as f64 * 0.30102999566398114f64 - ($min_power + 1) as f64; | 242 | 60.8M | let mut k = dk as isize; | 243 | 60.8M | if dk - k as f64 > 0.0 { | 244 | 60.7M | k += 1; | 245 | 60.7M | } | 246 | | | 247 | 60.8M | let index = ((k >> 3) + 1) as usize; | 248 | 60.8M | let k = -($min_power + (index << 3) as isize); | 249 | | | 250 | 60.8M | (DiyFp::new($cached_powers_f[index], $cached_powers_e[index] as $expty), k) | 251 | 60.8M | } |
Unexecuted instantiation: <f32 as dtoa::Floating>::write::get_cached_power Unexecuted instantiation: <f64 as dtoa::Floating>::write::get_cached_power |
252 | | |
253 | | }} |