2 prim::{PrimFloat, PrimUInt},
3 traits::{Context, ConvertTo, Float, Make, Select, UInt},
8 VecF: Float<PrimFloat = PrimF> + Make<Context = Ctx>,
9 PrimF: PrimFloat<BitsType = PrimU>,
15 VecF::from_bits(x.to_bits() & ctx.make(!PrimF::SIGN_FIELD_MASK))
20 VecF: Float<PrimFloat = PrimF> + Make<Context = Ctx>,
21 PrimF: PrimFloat<BitsType = PrimU>,
28 let mag_bits = mag.to_bits() & ctx.make(!PrimF::SIGN_FIELD_MASK);
29 let sign_bit = sign.to_bits() & ctx.make(PrimF::SIGN_FIELD_MASK);
30 VecF::from_bits(mag_bits | sign_bit)
35 VecF: Float<PrimFloat = PrimF, BitsType = VecU> + Make<Context = Ctx>,
36 VecU: UInt<PrimUInt = PrimU> + Make<Context = Ctx>,
37 PrimF: PrimFloat<BitsType = PrimU>,
43 let big_limit: VecF = ctx.make(PrimF::IMPLICIT_MANTISSA_BIT.to());
44 let big = !v.abs().lt(big_limit); // use `lt` so nans are counted as big
45 let small = v.abs().lt(ctx.make(PrimF::cvt_from(1)));
46 let out_of_range = big | small;
47 let small_value = ctx.make::<VecF>(0.to()).copy_sign(v);
48 let out_of_range_value = small.select(small_value, v);
49 let exponent_field = v.extract_exponent_field();
50 let right_shift_amount: VecU = exponent_field - ctx.make(PrimF::EXPONENT_BIAS_UNSIGNED);
51 let mut mask: VecU = ctx.make(PrimF::MANTISSA_FIELD_MASK);
52 mask >>= right_shift_amount;
53 let in_range_value = VecF::from_bits(v.to_bits() & !mask);
54 out_of_range.select(out_of_range_value, in_range_value)
57 pub fn round_to_nearest_ties_to_even<
59 VecF: Float<PrimFloat = PrimF, BitsType = VecU> + Make<Context = Ctx>,
60 VecU: UInt<PrimUInt = PrimU> + Make<Context = Ctx>,
61 PrimF: PrimFloat<BitsType = PrimU>,
67 let big_limit: VecF = ctx.make(PrimF::IMPLICIT_MANTISSA_BIT.to());
68 let big = !v.abs().lt(big_limit); // use `lt` so nans are counted as big
69 let small = v.abs().le(ctx.make(PrimF::cvt_from(0.5)));
70 let out_of_range = big | small;
71 let small_value = ctx.make::<VecF>(0.to()).copy_sign(v);
72 let out_of_range_value = small.select(small_value, v);
73 let offset = ctx.make((PrimU::cvt_from(1) << PrimF::MANTISSA_FIELD_WIDTH).to());
74 let offset_value: VecF = v.abs() + offset;
75 let in_range_value = (offset_value - offset).copy_sign(v);
76 out_of_range.select(out_of_range_value, in_range_value)
85 scalar::{Scalar, Value},
92 should_panic(expected = "f16 feature is not enabled")
95 for bits in 0..=u16::MAX {
96 let v = F16::from_bits(bits);
97 let expected = v.abs();
98 let result = abs(Scalar, Value(v)).0;
99 assert_eq!(expected.to_bits(), result.to_bits());
105 for bits in (0..=u32::MAX).step_by(10001) {
106 let v = f32::from_bits(bits);
107 let expected = v.abs();
108 let result = abs(Scalar, Value(v)).0;
109 assert_eq!(expected.to_bits(), result.to_bits());
115 for bits in (0..=u64::MAX).step_by(100_000_000_000_001) {
116 let v = f64::from_bits(bits);
117 let expected = v.abs();
118 let result = abs(Scalar, Value(v)).0;
119 assert_eq!(expected.to_bits(), result.to_bits());
125 not(feature = "f16"),
126 should_panic(expected = "f16 feature is not enabled")
128 fn test_copy_sign_f16() {
130 fn check(mag_bits: u16, sign_bits: u16) {
131 let mag = F16::from_bits(mag_bits);
132 let sign = F16::from_bits(sign_bits);
133 let expected = mag.copysign(sign);
134 let result = copy_sign(Scalar, Value(mag), Value(sign)).0;
135 assert_eq!(expected.to_bits(), result.to_bits());
137 for mag_low_bits in 0..16 {
138 for mag_high_bits in 0..16 {
139 for sign_low_bits in 0..16 {
140 for sign_high_bits in 0..16 {
142 mag_low_bits | (mag_high_bits << (16 - 4)),
143 sign_low_bits | (sign_high_bits << (16 - 4)),
152 fn test_copy_sign_f32() {
154 fn check(mag_bits: u32, sign_bits: u32) {
155 let mag = f32::from_bits(mag_bits);
156 let sign = f32::from_bits(sign_bits);
157 let expected = mag.copysign(sign);
158 let result = copy_sign(Scalar, Value(mag), Value(sign)).0;
159 assert_eq!(expected.to_bits(), result.to_bits());
161 for mag_low_bits in 0..16 {
162 for mag_high_bits in 0..16 {
163 for sign_low_bits in 0..16 {
164 for sign_high_bits in 0..16 {
166 mag_low_bits | (mag_high_bits << (32 - 4)),
167 sign_low_bits | (sign_high_bits << (32 - 4)),
176 fn test_copy_sign_f64() {
178 fn check(mag_bits: u64, sign_bits: u64) {
179 let mag = f64::from_bits(mag_bits);
180 let sign = f64::from_bits(sign_bits);
181 let expected = mag.copysign(sign);
182 let result = copy_sign(Scalar, Value(mag), Value(sign)).0;
183 assert_eq!(expected.to_bits(), result.to_bits());
185 for mag_low_bits in 0..16 {
186 for mag_high_bits in 0..16 {
187 for sign_low_bits in 0..16 {
188 for sign_high_bits in 0..16 {
190 mag_low_bits | (mag_high_bits << (64 - 4)),
191 sign_low_bits | (sign_high_bits << (64 - 4)),
199 fn same<F: PrimFloat>(a: F, b: F) -> bool {
200 if a.is_finite() && b.is_finite() {
203 a == b || (a.is_nan() && b.is_nan())
209 not(feature = "f16"),
210 should_panic(expected = "f16 feature is not enabled")
212 fn test_trunc_f16() {
213 for bits in 0..=u16::MAX {
214 let v = F16::from_bits(bits);
215 let expected = v.trunc();
216 let result = trunc(Scalar, Value(v)).0;
218 same(expected, result),
219 "case failed: v={v}, v_bits={v_bits:#X}, expected={expected}, expected_bits={expected_bits:#X}, result={result}, result_bits={result_bits:#X}",
223 expected_bits=expected.to_bits(),
225 result_bits=result.to_bits(),
231 fn test_trunc_f32() {
232 for bits in (0..=u32::MAX).step_by(0x10000) {
233 let v = f32::from_bits(bits);
234 let expected = v.trunc();
235 let result = trunc(Scalar, Value(v)).0;
237 same(expected, result),
238 "case failed: v={v}, v_bits={v_bits:#X}, expected={expected}, expected_bits={expected_bits:#X}, result={result}, result_bits={result_bits:#X}",
242 expected_bits=expected.to_bits(),
244 result_bits=result.to_bits(),
250 fn test_trunc_f64() {
251 for bits in (0..=u64::MAX).step_by(1 << 48) {
252 let v = f64::from_bits(bits);
253 let expected = v.trunc();
254 let result = trunc(Scalar, Value(v)).0;
256 same(expected, result),
257 "case failed: v={v}, v_bits={v_bits:#X}, expected={expected}, expected_bits={expected_bits:#X}, result={result}, result_bits={result_bits:#X}",
261 expected_bits=expected.to_bits(),
263 result_bits=result.to_bits(),
268 fn reference_round_to_nearest_ties_to_even<
269 F: PrimFloat<BitsType = U, SignedBitsType = S>,
271 S: PrimSInt + ConvertFrom<F>,
275 if v.abs() < F::cvt_from(S::MAX) {
276 let int_value: S = v.to();
277 let int_value_f: F = int_value.to();
278 let remainder: F = v - int_value_f;
279 if remainder.abs() < 0.5.to()
280 || (int_value % 2.to() == 0.to() && remainder.abs() == 0.5.to())
282 int_value_f.copy_sign(v)
283 } else if remainder < 0.0.to() {
284 int_value_f - 1.0.to()
286 int_value_f + 1.0.to()
294 fn test_reference_round_to_nearest_ties_to_even() {
296 fn case(v: f32, expected: f32) {
297 let result = reference_round_to_nearest_ties_to_even(v);
298 let same = if expected.is_nan() {
301 expected.to_bits() == result.to_bits()
305 "case failed: v={v}, v_bits={v_bits:#X}, expected={expected}, expected_bits={expected_bits:#X}, result={result}, result_bits={result_bits:#X}",
309 expected_bits=expected.to_bits(),
311 result_bits=result.to_bits(),
338 case(f32::INFINITY, f32::INFINITY);
339 case(-f32::INFINITY, -f32::INFINITY);
340 case(f32::NAN, f32::NAN);
343 let i32_max = i32::MAX as f32;
344 let i32_max_prev = f32::from_bits(i32_max.to_bits() - 1);
345 let i32_max_next = f32::from_bits(i32_max.to_bits() + 1);
346 case(i32_max, i32_max);
347 case(-i32_max, -i32_max);
348 case(i32_max_prev, i32_max_prev);
349 case(-i32_max_prev, -i32_max_prev);
350 case(i32_max_next, i32_max_next);
351 case(-i32_max_next, -i32_max_next);
356 not(feature = "f16"),
357 should_panic(expected = "f16 feature is not enabled")
359 fn test_round_to_nearest_ties_to_even_f16() {
360 for bits in 0..=u16::MAX {
361 let v = F16::from_bits(bits);
362 let expected = reference_round_to_nearest_ties_to_even(v);
363 let result = round_to_nearest_ties_to_even(Scalar, Value(v)).0;
365 same(expected, result),
366 "case failed: v={v}, v_bits={v_bits:#X}, expected={expected}, expected_bits={expected_bits:#X}, result={result}, result_bits={result_bits:#X}",
370 expected_bits=expected.to_bits(),
372 result_bits=result.to_bits(),
378 fn test_round_to_nearest_ties_to_even_f32() {
379 for bits in (0..=u32::MAX).step_by(0x10000) {
380 let v = f32::from_bits(bits);
381 let expected = reference_round_to_nearest_ties_to_even(v);
382 let result = round_to_nearest_ties_to_even(Scalar, Value(v)).0;
384 same(expected, result),
385 "case failed: v={v}, v_bits={v_bits:#X}, expected={expected}, expected_bits={expected_bits:#X}, result={result}, result_bits={result_bits:#X}",
389 expected_bits=expected.to_bits(),
391 result_bits=result.to_bits(),
397 fn test_round_to_nearest_ties_to_even_f64() {
398 for bits in (0..=u64::MAX).step_by(1 << 48) {
399 let v = f64::from_bits(bits);
400 let expected = reference_round_to_nearest_ties_to_even(v);
401 let result = round_to_nearest_ties_to_even(Scalar, Value(v)).0;
403 same(expected, result),
404 "case failed: v={v}, v_bits={v_bits:#X}, expected={expected}, expected_bits={expected_bits:#X}, result={result}, result_bits={result_bits:#X}",
408 expected_bits=expected.to_bits(),
410 result_bits=result.to_bits(),