Skip to content

Commit 44c32fa

Browse files
committed
Make conv more generic
1 parent 1a3639e commit 44c32fa

File tree

3 files changed

+66
-72
lines changed

3 files changed

+66
-72
lines changed

src/float/conv.rs

Lines changed: 47 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
use crate::int::{CastFrom, CastInto, Int, MinInt};
2+
3+
use super::Float;
4+
15
/// Conversions from integers to floats.
26
///
37
/// These are hand-optimized bit twiddling code,
@@ -142,102 +146,73 @@ intrinsics! {
142146
}
143147
}
144148

149+
fn float_to_unsigned_int<F, U>(f: F) -> U
150+
where
151+
F: Float,
152+
U: Int,
153+
u32: CastInto<F::Int>,
154+
u32: CastFrom<F::Int>,
155+
F::Int: CastInto<U>,
156+
F::Int: CastFrom<u32>,
157+
{
158+
let uint_max_exp: u32 = F::EXPONENT_BIAS + U::BITS;
159+
let fbits = f.repr();
160+
161+
if fbits < F::ONE.repr() {
162+
// >= 0.0, < 1.0 (< 0.0 are > 1.0 in int repr)
163+
U::ZERO
164+
} else if fbits < F::Int::cast_from(uint_max_exp) << F::SIGNIFICAND_BITS {
165+
// >= 1, < U::max
166+
let mantissa = if U::BITS >= F::Int::BITS {
167+
U::cast_from(fbits) << (U::BITS - F::SIGNIFICAND_BITS - 1)
168+
} else {
169+
U::cast_from(fbits >> 21)
170+
};
171+
172+
// Set the implicit 1-bit.
173+
let m: U = U::ONE << (U::BITS - 1) | mantissa;
174+
// Shift based on the exponent and bias.
175+
let s: u32 = (uint_max_exp - 1) - u32::cast_from(fbits >> F::SIGNIFICAND_BITS);
176+
177+
m >> s
178+
} else if fbits <= F::EXPONENT_MASK {
179+
// >= max (incl. inf)
180+
U::MAX
181+
} else {
182+
U::ZERO
183+
}
184+
}
185+
145186
// Conversions from floats to unsigned integers.
146187
intrinsics! {
147188
#[arm_aeabi_alias = __aeabi_f2uiz]
148189
pub extern "C" fn __fixunssfsi(f: f32) -> u32 {
149-
let fbits = f.to_bits();
150-
if fbits < 127 << 23 { // >= 0, < 1
151-
0
152-
} else if fbits < 159 << 23 { // >= 1, < max
153-
let m = 1 << 31 | fbits << 8; // Mantissa and the implicit 1-bit.
154-
let s = 158 - (fbits >> 23); // Shift based on the exponent and bias.
155-
m >> s
156-
} else if fbits <= 255 << 23 { // >= max (incl. inf)
157-
u32::MAX
158-
} else { // Negative or NaN
159-
0
160-
}
190+
float_to_unsigned_int(f)
161191
}
162192

163193
#[arm_aeabi_alias = __aeabi_f2ulz]
164194
pub extern "C" fn __fixunssfdi(f: f32) -> u64 {
165-
let fbits = f.to_bits();
166-
if fbits < 127 << 23 { // >= 0, < 1
167-
0
168-
} else if fbits < 191 << 23 { // >= 1, < max
169-
let m = 1 << 63 | (fbits as u64) << 40; // Mantissa and the implicit 1-bit.
170-
let s = 190 - (fbits >> 23); // Shift based on the exponent and bias.
171-
m >> s
172-
} else if fbits <= 255 << 23 { // >= max (incl. inf)
173-
u64::MAX
174-
} else { // Negative or NaN
175-
0
176-
}
195+
float_to_unsigned_int(f)
177196
}
178197

179198
#[win64_128bit_abi_hack]
180199
pub extern "C" fn __fixunssfti(f: f32) -> u128 {
181-
let fbits = f.to_bits();
182-
if fbits < 127 << 23 { // >= 0, < 1
183-
0
184-
} else if fbits < 255 << 23 { // >= 1, < inf
185-
let m = 1 << 127 | (fbits as u128) << 104; // Mantissa and the implicit 1-bit.
186-
let s = 254 - (fbits >> 23); // Shift based on the exponent and bias.
187-
m >> s
188-
} else if fbits == 255 << 23 { // == inf
189-
u128::MAX
190-
} else { // Negative or NaN
191-
0
192-
}
200+
float_to_unsigned_int(f)
193201
}
194202

195203
#[arm_aeabi_alias = __aeabi_d2uiz]
196204
pub extern "C" fn __fixunsdfsi(f: f64) -> u32 {
197-
let fbits = f.to_bits();
198-
if fbits < 1023 << 52 { // >= 0, < 1
199-
0
200-
} else if fbits < 1055 << 52 { // >= 1, < max
201-
let m = 1 << 31 | (fbits >> 21) as u32; // Mantissa and the implicit 1-bit.
202-
let s = 1054 - (fbits >> 52); // Shift based on the exponent and bias.
203-
m >> s
204-
} else if fbits <= 2047 << 52 { // >= max (incl. inf)
205-
u32::MAX
206-
} else { // Negative or NaN
207-
0
208-
}
205+
float_to_unsigned_int(f)
209206
}
210207

211208
#[arm_aeabi_alias = __aeabi_d2ulz]
212209
pub extern "C" fn __fixunsdfdi(f: f64) -> u64 {
213-
let fbits = f.to_bits();
214-
if fbits < 1023 << 52 { // >= 0, < 1
215-
0
216-
} else if fbits < 1087 << 52 { // >= 1, < max
217-
let m = 1 << 63 | fbits << 11; // Mantissa and the implicit 1-bit.
218-
let s = 1086 - (fbits >> 52); // Shift based on the exponent and bias.
219-
m >> s
220-
} else if fbits <= 2047 << 52 { // >= max (incl. inf)
221-
u64::MAX
222-
} else { // Negative or NaN
223-
0
224-
}
210+
float_to_unsigned_int(f)
225211
}
226212

227213
#[win64_128bit_abi_hack]
228214
pub extern "C" fn __fixunsdfti(f: f64) -> u128 {
229-
let fbits = f.to_bits();
230-
if fbits < 1023 << 52 { // >= 0, < 1
231-
0
232-
} else if fbits < 1151 << 52 { // >= 1, < max
233-
let m = 1 << 127 | (fbits as u128) << 75; // Mantissa and the implicit 1-bit.
234-
let s = 1150 - (fbits >> 52); // Shift based on the exponent and bias.
235-
m >> s
236-
} else if fbits <= 2047 << 52 { // >= max (incl. inf)
237-
u128::MAX
238-
} else { // Negative or NaN
239-
0
240-
}
215+
float_to_unsigned_int(f)
241216
}
242217
}
243218

src/int/mod.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ pub(crate) trait Int: MinInt
102102
fn rotate_left(self, other: u32) -> Self;
103103
fn overflowing_add(self, other: Self) -> (Self, bool);
104104
fn leading_zeros(self) -> u32;
105+
fn ilog2(self) -> u32;
105106
}
106107
}
107108

@@ -200,6 +201,10 @@ macro_rules! int_impl_common {
200201
fn leading_zeros(self) -> u32 {
201202
<Self>::leading_zeros(self)
202203
}
204+
205+
fn ilog2(self) -> u32 {
206+
<Self>::ilog2(self)
207+
}
203208
};
204209
}
205210

@@ -380,6 +385,16 @@ public_test_dep! {
380385
pub(crate) trait CastInto<T: Copy>: Copy {
381386
fn cast(self) -> T;
382387
}
388+
389+
pub(crate) trait CastFrom<T: Copy>:Copy {
390+
fn cast_from(value: T) -> Self;
391+
}
392+
}
393+
394+
impl<T: Copy, U: CastInto<T> + Copy> CastFrom<U> for T {
395+
fn cast_from(value: U) -> Self {
396+
value.cast()
397+
}
383398
}
384399

385400
macro_rules! cast_into {

testcrate/tests/conv.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ fn float_to_int() {
118118
__fixdfdi, __fixdfsi, __fixdfti, __fixsfdi, __fixsfsi, __fixsfti, __fixunsdfdi,
119119
__fixunsdfsi, __fixunsdfti, __fixunssfdi, __fixunssfsi, __fixunssfti,
120120
};
121+
println!("bias {}", f32::EXPONENT_BIAS);
122+
println!("bits {}", f32::SIGNIFICAND_BITS);
123+
println!("bias {}", f64::EXPONENT_BIAS);
124+
println!("bits {}", f64::SIGNIFICAND_BITS);
121125

122126
fuzz_float(N, |x: f32| {
123127
f_to_i!(x,

0 commit comments

Comments
 (0)