| 1 | const builtin = @import("builtin"); |
| 2 | const std = @import("std"); |
| 3 | const testing = std.testing; |
| 4 | |
| 5 | const impl = @import("extendf.zig"); |
| 6 | |
| 7 | const f32_floatCast_f16 = impl.f32_floatCast_f16; |
| 8 | const f64_floatCast_f16 = impl.f64_floatCast_f16; |
| 9 | const f80_floatCast_f16 = impl.f80_floatCast_f16; |
| 10 | const f128_floatCast_f16 = impl.f128_floatCast_f16; |
| 11 | |
| 12 | const f64_floatCast_f32 = impl.f64_floatCast_f32; |
| 13 | const f80_floatCast_f32 = impl.f80_floatCast_f32; |
| 14 | const f128_floatCast_f32 = impl.f128_floatCast_f32; |
| 15 | |
| 16 | const f80_floatCast_f64 = impl.f80_floatCast_f64; |
| 17 | const f128_floatCast_f64 = impl.f128_floatCast_f64; |
| 18 | |
| 19 | const f128_floatCast_f80 = impl.f128_floatCast_f80; |
| 20 | |
| 21 | fn test_f80_floatCast_f64(a: f64, expected: u80) !void { |
| 22 | const x = f80_floatCast_f64(a); |
| 23 | |
| 24 | const rep: u80 = @bitCast(x); |
| 25 | if (rep == expected) |
| 26 | return; |
| 27 | // test other possible NaN representation(signal NaN) |
| 28 | if (std.math.isNan(@as(f80, @bitCast(expected))) and std.math.isNan(x)) |
| 29 | return; |
| 30 | return error.TestFailure; |
| 31 | } |
| 32 | |
| 33 | fn test_f128_floatCast_f64(a: f64, expected_hi: u64, expected_lo: u64) !void { |
| 34 | const x = f128_floatCast_f64(a); |
| 35 | |
| 36 | const rep: u128 = @bitCast(x); |
| 37 | const hi: u64 = @intCast(rep >> 64); |
| 38 | const lo: u64 = @truncate(rep); |
| 39 | |
| 40 | if (hi == expected_hi and lo == expected_lo) |
| 41 | return; |
| 42 | // test other possible NaN representation(signal NaN) |
| 43 | if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { |
| 44 | if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and |
| 45 | ((hi & 0xffffffffffff) > 0 or lo > 0)) |
| 46 | { |
| 47 | return; |
| 48 | } |
| 49 | } |
| 50 | return error.TestFailure; |
| 51 | } |
| 52 | |
| 53 | fn test_f32_floatCast_f16(a: u16, expected: u32) !void { |
| 54 | const x = f32_floatCast_f16(@bitCast(a)); |
| 55 | const rep: u32 = @bitCast(x); |
| 56 | |
| 57 | if (rep == expected) { |
| 58 | if (rep & 0x7fffffff > 0x7f800000) { |
| 59 | return; // NaN is always unequal. |
| 60 | } |
| 61 | if (x == @as(f32, @bitCast(expected))) { |
| 62 | return; |
| 63 | } |
| 64 | } |
| 65 | return error.TestFailure; |
| 66 | } |
| 67 | |
| 68 | fn test_f128_floatCast_f32(a: f32, expected_hi: u64, expected_lo: u64) !void { |
| 69 | const x = f128_floatCast_f32(a); |
| 70 | |
| 71 | const rep: u128 = @bitCast(x); |
| 72 | const hi: u64 = @intCast(rep >> 64); |
| 73 | const lo: u64 = @truncate(rep); |
| 74 | |
| 75 | if (hi == expected_hi and lo == expected_lo) |
| 76 | return; |
| 77 | // test other possible NaN representation(signal NaN) |
| 78 | if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { |
| 79 | if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and |
| 80 | ((hi & 0xffffffffffff) > 0 or lo > 0)) |
| 81 | { |
| 82 | return; |
| 83 | } |
| 84 | } |
| 85 | return error.TestFailure; |
| 86 | } |
| 87 | |
| 88 | test f80_floatCast_f64 { |
| 89 | // qNaN |
| 90 | try test_f80_floatCast_f64(makeQNaN64(), 0x7fffc000000000000000); |
| 91 | |
| 92 | // NaN |
| 93 | try test_f80_floatCast_f64(makeNaN64(0x7100000000000), 0x7fffe080000000000000); |
| 94 | // This is bad? |
| 95 | |
| 96 | // inf |
| 97 | try test_f80_floatCast_f64(makeInf64(), 0x7fff8000000000000000); |
| 98 | |
| 99 | // zero |
| 100 | try test_f80_floatCast_f64(0.0, 0x0); |
| 101 | |
| 102 | try test_f80_floatCast_f64(0x0.a3456789abcdefp+6, 0x4004a3456789abcdf000); |
| 103 | |
| 104 | try test_f80_floatCast_f64(0x0.edcba987654321fp-8, 0x3ff6edcba98765432000); |
| 105 | |
| 106 | try test_f80_floatCast_f64(0x0.a3456789abcdefp+46, 0x402ca3456789abcdf000); |
| 107 | |
| 108 | try test_f80_floatCast_f64(0x0.edcba987654321fp-44, 0x3fd2edcba98765432000); |
| 109 | |
| 110 | // subnormal |
| 111 | try test_f80_floatCast_f64(0x1.8000000000001p-1022, 0x3c01c000000000000800); |
| 112 | try test_f80_floatCast_f64(0x1.8000000000002p-1023, 0x3c00c000000000001000); |
| 113 | } |
| 114 | |
| 115 | test f128_floatCast_f64 { |
| 116 | // qNaN |
| 117 | try test_f128_floatCast_f64(makeQNaN64(), 0x7fff800000000000, 0x0); |
| 118 | |
| 119 | // NaN |
| 120 | try test_f128_floatCast_f64(makeNaN64(0x7100000000000), 0x7fff710000000000, 0x0); |
| 121 | |
| 122 | // inf |
| 123 | try test_f128_floatCast_f64(makeInf64(), 0x7fff000000000000, 0x0); |
| 124 | |
| 125 | // zero |
| 126 | try test_f128_floatCast_f64(0.0, 0x0, 0x0); |
| 127 | |
| 128 | try test_f128_floatCast_f64(0x1.23456789abcdefp+5, 0x400423456789abcd, 0xf000000000000000); |
| 129 | |
| 130 | try test_f128_floatCast_f64(0x1.edcba987654321fp-9, 0x3ff6edcba9876543, 0x2000000000000000); |
| 131 | |
| 132 | try test_f128_floatCast_f64(0x1.23456789abcdefp+45, 0x402c23456789abcd, 0xf000000000000000); |
| 133 | |
| 134 | try test_f128_floatCast_f64(0x1.edcba987654321fp-45, 0x3fd2edcba9876543, 0x2000000000000000); |
| 135 | |
| 136 | // subnormal |
| 137 | try test_f128_floatCast_f64(0x1.8p-1022, 0x3c01800000000000, 0x0); |
| 138 | try test_f128_floatCast_f64(0x1.8p-1023, 0x3c00800000000000, 0x0); |
| 139 | } |
| 140 | |
| 141 | test f32_floatCast_f16 { |
| 142 | try test_f32_floatCast_f16(0x7e00, 0x7fc00000); // qNaN |
| 143 | try test_f32_floatCast_f16(0x7f00, 0x7fe00000); // sNaN |
| 144 | // On x86 the NaN becomes quiet because the return is pushed on the x87 |
| 145 | // stack due to ABI requirements |
| 146 | if (builtin.target.cpu.arch != .x86 and builtin.target.os.tag == .windows) |
| 147 | try test_f32_floatCast_f16(0x7c01, 0x7f802000); // sNaN |
| 148 | |
| 149 | try test_f32_floatCast_f16(0, 0); // 0 |
| 150 | try test_f32_floatCast_f16(0x8000, 0x80000000); // -0 |
| 151 | |
| 152 | try test_f32_floatCast_f16(0x7c00, 0x7f800000); // inf |
| 153 | try test_f32_floatCast_f16(0xfc00, 0xff800000); // -inf |
| 154 | |
| 155 | try test_f32_floatCast_f16(0x0001, 0x33800000); // denormal (min), 2**-24 |
| 156 | try test_f32_floatCast_f16(0x8001, 0xb3800000); // denormal (min), -2**-24 |
| 157 | |
| 158 | try test_f32_floatCast_f16(0x03ff, 0x387fc000); // denormal (max), 2**-14 - 2**-24 |
| 159 | try test_f32_floatCast_f16(0x83ff, 0xb87fc000); // denormal (max), -2**-14 + 2**-24 |
| 160 | |
| 161 | try test_f32_floatCast_f16(0x0400, 0x38800000); // normal (min), 2**-14 |
| 162 | try test_f32_floatCast_f16(0x8400, 0xb8800000); // normal (min), -2**-14 |
| 163 | |
| 164 | try test_f32_floatCast_f16(0x7bff, 0x477fe000); // normal (max), 65504 |
| 165 | try test_f32_floatCast_f16(0xfbff, 0xc77fe000); // normal (max), -65504 |
| 166 | |
| 167 | try test_f32_floatCast_f16(0x3c01, 0x3f802000); // normal, 1 + 2**-10 |
| 168 | try test_f32_floatCast_f16(0xbc01, 0xbf802000); // normal, -1 - 2**-10 |
| 169 | |
| 170 | try test_f32_floatCast_f16(0x3555, 0x3eaaa000); // normal, approx. 1/3 |
| 171 | try test_f32_floatCast_f16(0xb555, 0xbeaaa000); // normal, approx. -1/3 |
| 172 | } |
| 173 | |
| 174 | test f128_floatCast_f32 { |
| 175 | // qNaN |
| 176 | try test_f128_floatCast_f32(makeQNaN32(), 0x7fff800000000000, 0x0); |
| 177 | // NaN |
| 178 | try test_f128_floatCast_f32(makeNaN32(0x410000), 0x7fff820000000000, 0x0); |
| 179 | // inf |
| 180 | try test_f128_floatCast_f32(makeInf32(), 0x7fff000000000000, 0x0); |
| 181 | // zero |
| 182 | try test_f128_floatCast_f32(0.0, 0x0, 0x0); |
| 183 | try test_f128_floatCast_f32(0x1.23456p+5, 0x4004234560000000, 0x0); |
| 184 | try test_f128_floatCast_f32(0x1.edcbap-9, 0x3ff6edcba0000000, 0x0); |
| 185 | try test_f128_floatCast_f32(0x1.23456p+45, 0x402c234560000000, 0x0); |
| 186 | try test_f128_floatCast_f32(0x1.edcbap-45, 0x3fd2edcba0000000, 0x0); |
| 187 | } |
| 188 | |
| 189 | fn makeQNaN64() f64 { |
| 190 | return @bitCast(@as(u64, 0x7ff8000000000000)); |
| 191 | } |
| 192 | |
| 193 | fn makeInf64() f64 { |
| 194 | return @bitCast(@as(u64, 0x7ff0000000000000)); |
| 195 | } |
| 196 | |
| 197 | fn makeNaN64(rand: u64) f64 { |
| 198 | return @bitCast(0x7ff0000000000000 | (rand & 0xfffffffffffff)); |
| 199 | } |
| 200 | |
| 201 | fn makeQNaN32() f32 { |
| 202 | return @bitCast(@as(u32, 0x7fc00000)); |
| 203 | } |
| 204 | |
| 205 | fn makeNaN32(rand: u32) f32 { |
| 206 | return @bitCast(0x7f800000 | (rand & 0x7fffff)); |
| 207 | } |
| 208 | |
| 209 | fn makeInf32() f32 { |
| 210 | return @bitCast(@as(u32, 0x7f800000)); |
| 211 | } |
| 212 | |
| 213 | fn test_f128_floatCast_f16(a: u16, expected_hi: u64, expected_lo: u64) !void { |
| 214 | const x = f128_floatCast_f16(@bitCast(a)); |
| 215 | |
| 216 | const rep: u128 = @bitCast(x); |
| 217 | const hi: u64 = @intCast(rep >> 64); |
| 218 | const lo: u64 = @truncate(rep); |
| 219 | |
| 220 | if (hi == expected_hi and lo == expected_lo) |
| 221 | return; |
| 222 | |
| 223 | // test other possible NaN representation(signal NaN) |
| 224 | if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { |
| 225 | if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and |
| 226 | ((hi & 0xffffffffffff) > 0 or lo > 0)) |
| 227 | { |
| 228 | return; |
| 229 | } |
| 230 | } |
| 231 | |
| 232 | return error.TestFailure; |
| 233 | } |
| 234 | |
| 235 | test f128_floatCast_f16 { |
| 236 | // qNaN |
| 237 | try test_f128_floatCast_f16(0x7e00, 0x7fff800000000000, 0x0); |
| 238 | // NaN |
| 239 | try test_f128_floatCast_f16(0x7d00, 0x7fff400000000000, 0x0); |
| 240 | // inf |
| 241 | try test_f128_floatCast_f16(0x7c00, 0x7fff000000000000, 0x0); |
| 242 | try test_f128_floatCast_f16(0xfc00, 0xffff000000000000, 0x0); |
| 243 | // zero |
| 244 | try test_f128_floatCast_f16(0x0000, 0x0000000000000000, 0x0); |
| 245 | try test_f128_floatCast_f16(0x8000, 0x8000000000000000, 0x0); |
| 246 | // denormal |
| 247 | try test_f128_floatCast_f16(0x0010, 0x3feb000000000000, 0x0); |
| 248 | try test_f128_floatCast_f16(0x0001, 0x3fe7000000000000, 0x0); |
| 249 | try test_f128_floatCast_f16(0x8001, 0xbfe7000000000000, 0x0); |
| 250 | |
| 251 | // pi |
| 252 | try test_f128_floatCast_f16(0x4248, 0x4000920000000000, 0x0); |
| 253 | try test_f128_floatCast_f16(0xc248, 0xc000920000000000, 0x0); |
| 254 | |
| 255 | try test_f128_floatCast_f16(0x508c, 0x4004230000000000, 0x0); |
| 256 | try test_f128_floatCast_f16(0x1bb7, 0x3ff6edc000000000, 0x0); |
| 257 | } |