3 ieee754::FloatEncoding,
4 traits::{Compare, Context, ConvertTo, Float, Select},
7 macro_rules! impl_ilogb {
10 #[prim_signed_bits = $prim_signed_bits:ident]
11 #[ilogb = $ilogb:ident]
12 #[nan = $NAN_RESULT:ident]
13 #[overflow = $OVERFLOW_RESULT:ident]
14 #[underflow = $UNDERFLOW_RESULT:ident]
15 fn $ilogb_extended:ident($vector_float:ident, $scalar_signed_bits:ident) -> $vector_signed_bits:ident;
17 pub const $NAN_RESULT: $prim_signed_bits = $prim_signed_bits::MIN + 1;
18 pub const $OVERFLOW_RESULT: $prim_signed_bits = $prim_signed_bits::MAX;
19 pub const $UNDERFLOW_RESULT: $prim_signed_bits = $prim_signed_bits::MIN;
21 pub fn $ilogb_extended<Ctx: Context>(
23 arg: Ctx::$vector_float,
24 nan_result: Ctx::$scalar_signed_bits,
25 overflow_result: Ctx::$scalar_signed_bits,
26 underflow_result: Ctx::$scalar_signed_bits,
27 ) -> Ctx::$vector_signed_bits {
28 let is_finite = arg.is_finite();
29 let is_zero_subnormal = arg.is_zero_or_subnormal();
30 let is_nan = arg.is_nan();
31 let inf_nan_result: Ctx::$vector_signed_bits =
32 is_nan.select(nan_result.into(), overflow_result.into());
33 let scale_factor: $prim = (1u64 << $prim::MANTISSA_FIELD_WIDTH).to();
34 let scaled = arg * ctx.make(scale_factor);
35 let scaled_exponent = scaled.extract_exponent_unbiased();
36 let exponent = arg.extract_exponent_unbiased();
37 let normal_inf_nan_result = is_finite.select(exponent, inf_nan_result);
38 let is_zero = arg.eq(ctx.make($prim::from(0u8)));
39 let zero_subnormal_result = is_zero.select(
40 underflow_result.into(),
41 scaled_exponent - ctx.make($prim::MANTISSA_FIELD_WIDTH.to()),
43 is_zero_subnormal.select(zero_subnormal_result, normal_inf_nan_result)
46 pub fn $ilogb<Ctx: Context>(ctx: Ctx, arg: Ctx::$vector_float) -> Ctx::$vector_signed_bits {
50 ctx.make($NAN_RESULT),
51 ctx.make($OVERFLOW_RESULT),
52 ctx.make($UNDERFLOW_RESULT),
60 #[prim_signed_bits = i16]
62 #[nan = ILOGB_NAN_RESULT_F16]
63 #[overflow = ILOGB_OVERFLOW_RESULT_F16]
64 #[underflow = ILOGB_UNDERFLOW_RESULT_F16]
65 fn ilogb_f16_extended(VecF16, I16) -> VecI16;
70 #[prim_signed_bits = i32]
72 #[nan = ILOGB_NAN_RESULT_F32]
73 #[overflow = ILOGB_OVERFLOW_RESULT_F32]
74 #[underflow = ILOGB_UNDERFLOW_RESULT_F32]
75 fn ilogb_f32_extended(VecF32, I32) -> VecI32;
80 #[prim_signed_bits = i64]
82 #[nan = ILOGB_NAN_RESULT_F64]
83 #[overflow = ILOGB_OVERFLOW_RESULT_F64]
84 #[underflow = ILOGB_UNDERFLOW_RESULT_F64]
85 fn ilogb_f64_extended(VecF64, I64) -> VecI64;
91 use crate::scalar::Scalar;
96 should_panic(expected = "f16 feature is not enabled")
99 fn ilogb(arg: f32) -> i16 {
100 let arg: F16 = arg.to();
101 ilogb_f16(Scalar, arg)
103 assert_eq!(ilogb(0.), ILOGB_UNDERFLOW_RESULT_F16);
104 assert_eq!(ilogb(1.), 0);
105 assert_eq!(ilogb(2.), 1);
106 assert_eq!(ilogb(3.), 1);
107 assert_eq!(ilogb(3.998), 1);
108 assert_eq!(ilogb(0.5), -1);
109 assert_eq!(ilogb(0.5f32.powi(20)), -20);
110 assert_eq!(ilogb(f32::INFINITY), ILOGB_OVERFLOW_RESULT_F16);
111 assert_eq!(ilogb(f32::NAN), ILOGB_NAN_RESULT_F16);
115 fn test_ilogb_f32() {
116 assert_eq!(ilogb_f32(Scalar, 0f32), ILOGB_UNDERFLOW_RESULT_F32);
117 assert_eq!(ilogb_f32(Scalar, 1f32), 0);
118 assert_eq!(ilogb_f32(Scalar, 2f32), 1);
119 assert_eq!(ilogb_f32(Scalar, 3f32), 1);
120 assert_eq!(ilogb_f32(Scalar, 3.99999f32), 1);
121 assert_eq!(ilogb_f32(Scalar, 0.5f32), -1);
122 assert_eq!(ilogb_f32(Scalar, 0.5f32.powi(130)), -130);
123 assert_eq!(ilogb_f32(Scalar, f32::INFINITY), ILOGB_OVERFLOW_RESULT_F32);
124 assert_eq!(ilogb_f32(Scalar, f32::NAN), ILOGB_NAN_RESULT_F32);
128 fn test_ilogb_f64() {
129 assert_eq!(ilogb_f64(Scalar, 0f64), ILOGB_UNDERFLOW_RESULT_F64);
130 assert_eq!(ilogb_f64(Scalar, 1f64), 0);
131 assert_eq!(ilogb_f64(Scalar, 2f64), 1);
132 assert_eq!(ilogb_f64(Scalar, 3f64), 1);
133 assert_eq!(ilogb_f64(Scalar, 3.99999f64), 1);
134 assert_eq!(ilogb_f64(Scalar, 0.5f64), -1);
135 assert_eq!(ilogb_f64(Scalar, 0.5f64.powi(1030)), -1030);
136 assert_eq!(ilogb_f64(Scalar, f64::INFINITY), ILOGB_OVERFLOW_RESULT_F64);
137 assert_eq!(ilogb_f64(Scalar, f64::NAN), ILOGB_NAN_RESULT_F64);