| 1 | const std = @import("std"); |
| 2 | const testing = std.testing; |
| 3 | |
| 4 | const impl = @import("truncf.zig"); |
| 5 | |
| 6 | const f16_floatCast_f32 = impl.f16_floatCast_f32; |
| 7 | const f16_floatCast_f64 = impl.f16_floatCast_f64; |
| 8 | const f16_floatCast_f80 = impl.f16_floatCast_f80; |
| 9 | const f16_floatCast_f128 = impl.f16_floatCast_f128; |
| 10 | |
| 11 | const f32_floatCast_f64 = impl.f32_floatCast_f64; |
| 12 | const f32_floatCast_f80 = impl.f32_floatCast_f80; |
| 13 | const f32_floatCast_f128 = impl.f32_floatCast_f128; |
| 14 | |
| 15 | const f64_floatCast_f80 = impl.f64_floatCast_f80; |
| 16 | const f64_floatCast_f128 = impl.f64_floatCast_f128; |
| 17 | |
| 18 | const f80_floatCast_f128 = impl.f80_floatCast_f128; |
| 19 | |
| 20 | fn test_f16_floatCast_f32(a: u32, expected: u16) !void { |
| 21 | const actual: u16 = @bitCast(f16_floatCast_f32(@bitCast(a))); |
| 22 | try testing.expect(actual == expected); |
| 23 | } |
| 24 | |
| 25 | test f16_floatCast_f32 { |
| 26 | try test_f16_floatCast_f32(0x7fc00000, 0x7e00); // qNaN |
| 27 | try test_f16_floatCast_f32(0x7fe00000, 0x7f00); // sNaN |
| 28 | |
| 29 | try test_f16_floatCast_f32(0, 0); // 0 |
| 30 | try test_f16_floatCast_f32(0x80000000, 0x8000); // -0 |
| 31 | |
| 32 | try test_f16_floatCast_f32(0x7f800000, 0x7c00); // inf |
| 33 | try test_f16_floatCast_f32(0xff800000, 0xfc00); // -inf |
| 34 | |
| 35 | try test_f16_floatCast_f32(0x477ff000, 0x7c00); // 65520 -> inf |
| 36 | try test_f16_floatCast_f32(0xc77ff000, 0xfc00); // -65520 -> -inf |
| 37 | |
| 38 | try test_f16_floatCast_f32(0x71cc3892, 0x7c00); // 0x1.987124876876324p+100 -> inf |
| 39 | try test_f16_floatCast_f32(0xf1cc3892, 0xfc00); // -0x1.987124876876324p+100 -> -inf |
| 40 | |
| 41 | try test_f16_floatCast_f32(0x38800000, 0x0400); // normal (min), 2**-14 |
| 42 | try test_f16_floatCast_f32(0xb8800000, 0x8400); // normal (min), -2**-14 |
| 43 | |
| 44 | try test_f16_floatCast_f32(0x477fe000, 0x7bff); // normal (max), 65504 |
| 45 | try test_f16_floatCast_f32(0xc77fe000, 0xfbff); // normal (max), -65504 |
| 46 | |
| 47 | try test_f16_floatCast_f32(0x477fe100, 0x7bff); // normal, 65505 -> 65504 |
| 48 | try test_f16_floatCast_f32(0xc77fe100, 0xfbff); // normal, -65505 -> -65504 |
| 49 | |
| 50 | try test_f16_floatCast_f32(0x477fef00, 0x7bff); // normal, 65519 -> 65504 |
| 51 | try test_f16_floatCast_f32(0xc77fef00, 0xfbff); // normal, -65519 -> -65504 |
| 52 | |
| 53 | try test_f16_floatCast_f32(0x3f802000, 0x3c01); // normal, 1 + 2**-10 |
| 54 | try test_f16_floatCast_f32(0xbf802000, 0xbc01); // normal, -1 - 2**-10 |
| 55 | |
| 56 | try test_f16_floatCast_f32(0x3eaaa000, 0x3555); // normal, approx. 1/3 |
| 57 | try test_f16_floatCast_f32(0xbeaaa000, 0xb555); // normal, approx. -1/3 |
| 58 | |
| 59 | try test_f16_floatCast_f32(0x40490fdb, 0x4248); // normal, 3.1415926535 |
| 60 | try test_f16_floatCast_f32(0xc0490fdb, 0xc248); // normal, -3.1415926535 |
| 61 | |
| 62 | try test_f16_floatCast_f32(0x45cc3892, 0x6e62); // normal, 0x1.987124876876324p+12 |
| 63 | |
| 64 | try test_f16_floatCast_f32(0x3f800000, 0x3c00); // normal, 1 |
| 65 | try test_f16_floatCast_f32(0x38800000, 0x0400); // normal, 0x1.0p-14 |
| 66 | |
| 67 | try test_f16_floatCast_f32(0x33800000, 0x0001); // denormal (min), 2**-24 |
| 68 | try test_f16_floatCast_f32(0xb3800000, 0x8001); // denormal (min), -2**-24 |
| 69 | |
| 70 | try test_f16_floatCast_f32(0x387fc000, 0x03ff); // denormal (max), 2**-14 - 2**-24 |
| 71 | try test_f16_floatCast_f32(0xb87fc000, 0x83ff); // denormal (max), -2**-14 + 2**-24 |
| 72 | |
| 73 | try test_f16_floatCast_f32(0x35800000, 0x0010); // denormal, 0x1.0p-20 |
| 74 | try test_f16_floatCast_f32(0x33280000, 0x0001); // denormal, 0x1.5p-25 -> 0x1.0p-24 |
| 75 | try test_f16_floatCast_f32(0x33000000, 0x0000); // 0x1.0p-25 -> zero |
| 76 | } |
| 77 | |
| 78 | fn test_f16_floatCast_f64(a: f64, expected: u16) !void { |
| 79 | const rep: u16 = @bitCast(f16_floatCast_f64(a)); |
| 80 | |
| 81 | if (rep == expected) { |
| 82 | return; |
| 83 | } |
| 84 | // test other possible NaN representation(signal NaN) |
| 85 | else if (expected == 0x7e00) { |
| 86 | if ((rep & 0x7c00) == 0x7c00 and (rep & 0x3ff) > 0) { |
| 87 | return; |
| 88 | } |
| 89 | } |
| 90 | return error.TestFailure; |
| 91 | } |
| 92 | |
| 93 | fn test_f16_floatCast_f64_raw(a: u64, expected: u16) !void { |
| 94 | const actual: u16 = @bitCast(f16_floatCast_f64(@bitCast(a))); |
| 95 | try testing.expect(actual == expected); |
| 96 | } |
| 97 | |
| 98 | test f16_floatCast_f64 { |
| 99 | try test_f16_floatCast_f64_raw(0x7ff8000000000000, 0x7e00); // qNaN |
| 100 | try test_f16_floatCast_f64_raw(0x7ff0000000008000, 0x7e00); // NaN |
| 101 | |
| 102 | try test_f16_floatCast_f64_raw(0x7ff0000000000000, 0x7c00); //inf |
| 103 | try test_f16_floatCast_f64_raw(0xfff0000000000000, 0xfc00); // -inf |
| 104 | |
| 105 | try test_f16_floatCast_f64(0.0, 0x0); // zero |
| 106 | try test_f16_floatCast_f64_raw(0x80000000 << 32, 0x8000); // -zero |
| 107 | |
| 108 | try test_f16_floatCast_f64(3.1415926535, 0x4248); |
| 109 | try test_f16_floatCast_f64(-3.1415926535, 0xc248); |
| 110 | |
| 111 | try test_f16_floatCast_f64(0x1.987124876876324p+1000, 0x7c00); |
| 112 | try test_f16_floatCast_f64(0x1.987124876876324p+12, 0x6e62); |
| 113 | try test_f16_floatCast_f64(0x1.0p+0, 0x3c00); |
| 114 | try test_f16_floatCast_f64(0x1.0p-14, 0x0400); |
| 115 | |
| 116 | // denormal |
| 117 | try test_f16_floatCast_f64(0x1.0p-20, 0x0010); |
| 118 | try test_f16_floatCast_f64(0x1.0p-24, 0x0001); |
| 119 | try test_f16_floatCast_f64(-0x1.0p-24, 0x8001); |
| 120 | try test_f16_floatCast_f64(0x1.5p-25, 0x0001); |
| 121 | |
| 122 | // and back to zero |
| 123 | try test_f16_floatCast_f64(0x1.0p-25, 0x0000); |
| 124 | try test_f16_floatCast_f64(-0x1.0p-25, 0x8000); |
| 125 | |
| 126 | // max (precise) |
| 127 | try test_f16_floatCast_f64(65504.0, 0x7bff); |
| 128 | |
| 129 | // max (rounded) |
| 130 | try test_f16_floatCast_f64(65519.0, 0x7bff); |
| 131 | |
| 132 | // max (to +inf) |
| 133 | try test_f16_floatCast_f64(65520.0, 0x7c00); |
| 134 | try test_f16_floatCast_f64(-65520.0, 0xfc00); |
| 135 | try test_f16_floatCast_f64(65536.0, 0x7c00); |
| 136 | } |
| 137 | |
| 138 | fn test_f32_floatCast_f128(a: f128, expected: u32) !void { |
| 139 | const x = f32_floatCast_f128(a); |
| 140 | |
| 141 | const rep: u32 = @bitCast(x); |
| 142 | if (rep == expected) { |
| 143 | return; |
| 144 | } |
| 145 | // test other possible NaN representation(signal NaN) |
| 146 | else if (expected == 0x7fc00000) { |
| 147 | if ((rep & 0x7f800000) == 0x7f800000 and (rep & 0x7fffff) > 0) { |
| 148 | return; |
| 149 | } |
| 150 | } |
| 151 | return error.TestFailure; |
| 152 | } |
| 153 | |
| 154 | test f32_floatCast_f128 { |
| 155 | // qnan |
| 156 | try test_f32_floatCast_f128(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7fc00000); |
| 157 | // nan |
| 158 | try test_f32_floatCast_f128(@bitCast(@as(u128, (0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7fc08000); |
| 159 | // inf |
| 160 | try test_f32_floatCast_f128(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7f800000); |
| 161 | // zero |
| 162 | try test_f32_floatCast_f128(0.0, 0x0); |
| 163 | |
| 164 | try test_f32_floatCast_f128(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x4211d156); |
| 165 | try test_f32_floatCast_f128(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x3b71e9e2); |
| 166 | try test_f32_floatCast_f128(0x1.234eebb5faa678f4488693abcdefp+4534, 0x7f800000); |
| 167 | try test_f32_floatCast_f128(0x1.edcba9bb8c76a5a43dd21f334634p-435, 0x0); |
| 168 | } |
| 169 | |
| 170 | fn test_f64_floatCast_f128(a: f128, expected: u64) !void { |
| 171 | const x = f64_floatCast_f128(a); |
| 172 | |
| 173 | const rep: u64 = @bitCast(x); |
| 174 | if (rep == expected) { |
| 175 | return; |
| 176 | } |
| 177 | // test other possible NaN representation(signal NaN) |
| 178 | else if (expected == 0x7ff8000000000000) { |
| 179 | if ((rep & 0x7ff0000000000000) == 0x7ff0000000000000 and (rep & 0xfffffffffffff) > 0) { |
| 180 | return; |
| 181 | } |
| 182 | } |
| 183 | return error.TestFailure; |
| 184 | } |
| 185 | |
| 186 | test f64_floatCast_f128 { |
| 187 | // qnan |
| 188 | try test_f64_floatCast_f128(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7ff8000000000000); |
| 189 | // nan |
| 190 | try test_f64_floatCast_f128(@bitCast(@as(u128, (0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7ff8100000000000); |
| 191 | // inf |
| 192 | try test_f64_floatCast_f128(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7ff0000000000000); |
| 193 | // zero |
| 194 | try test_f64_floatCast_f128(0.0, 0x0); |
| 195 | |
| 196 | try test_f64_floatCast_f128(0x1.af23456789bbaaab347645365cdep+5, 0x404af23456789bbb); |
| 197 | try test_f64_floatCast_f128(0x1.dedafcff354b6ae9758763545432p-9, 0x3f6dedafcff354b7); |
| 198 | try test_f64_floatCast_f128(0x1.2f34dd5f437e849b4baab754cdefp+4534, 0x7ff0000000000000); |
| 199 | try test_f64_floatCast_f128(0x1.edcbff8ad76ab5bf46463233214fp-435, 0x24cedcbff8ad76ab); |
| 200 | } |
| 201 | |
| 202 | fn test_f32_floatCast_f64(a: f64, expected: u32) !void { |
| 203 | const x = f32_floatCast_f64(a); |
| 204 | |
| 205 | const rep: u32 = @bitCast(x); |
| 206 | if (rep == expected) { |
| 207 | return; |
| 208 | } |
| 209 | // test other possible NaN representation(signal NaN) |
| 210 | else if (expected == 0x7fc00000) { |
| 211 | if ((rep & 0x7f800000) == 0x7f800000 and (rep & 0x7fffff) > 0) { |
| 212 | return; |
| 213 | } |
| 214 | } |
| 215 | return error.TestFailure; |
| 216 | } |
| 217 | |
| 218 | test f32_floatCast_f64 { |
| 219 | // nan & qnan |
| 220 | try test_f32_floatCast_f64(@bitCast(@as(u64, 0x7ff8000000000000)), 0x7fc00000); |
| 221 | try test_f32_floatCast_f64(@bitCast(@as(u64, 0x7ff0000000000001)), 0x7fc00000); |
| 222 | // inf |
| 223 | try test_f32_floatCast_f64(@bitCast(@as(u64, 0x7ff0000000000000)), 0x7f800000); |
| 224 | try test_f32_floatCast_f64(@bitCast(@as(u64, 0xfff0000000000000)), 0xff800000); |
| 225 | |
| 226 | try test_f32_floatCast_f64(0.0, 0x0); |
| 227 | try test_f32_floatCast_f64(1.0, 0x3f800000); |
| 228 | try test_f32_floatCast_f64(-1.0, 0xbf800000); |
| 229 | |
| 230 | // huge number becomes inf |
| 231 | try test_f32_floatCast_f64(340282366920938463463374607431768211456.0, 0x7f800000); |
| 232 | } |
| 233 | |
| 234 | fn test_f16_floatCast_f128(a: f128, expected: u16) !void { |
| 235 | const x = f16_floatCast_f128(a); |
| 236 | |
| 237 | const rep: u16 = @bitCast(x); |
| 238 | try testing.expect(rep == expected); |
| 239 | } |
| 240 | |
| 241 | test f16_floatCast_f128 { |
| 242 | // qNaN |
| 243 | try test_f16_floatCast_f128(@bitCast(@as(u128, 0x7fff8000000000000000000000000000)), 0x7e00); |
| 244 | // NaN |
| 245 | try test_f16_floatCast_f128(@bitCast(@as(u128, 0x7fff0000000000000000000000000001)), 0x7e00); |
| 246 | // inf |
| 247 | try test_f16_floatCast_f128(@bitCast(@as(u128, 0x7fff0000000000000000000000000000)), 0x7c00); |
| 248 | try test_f16_floatCast_f128(-@as(f128, @bitCast(@as(u128, 0x7fff0000000000000000000000000000))), 0xfc00); |
| 249 | // zero |
| 250 | try test_f16_floatCast_f128(0.0, 0x0); |
| 251 | try test_f16_floatCast_f128(-0.0, 0x8000); |
| 252 | |
| 253 | try test_f16_floatCast_f128(3.1415926535, 0x4248); |
| 254 | try test_f16_floatCast_f128(-3.1415926535, 0xc248); |
| 255 | try test_f16_floatCast_f128(0x1.987124876876324p+100, 0x7c00); |
| 256 | try test_f16_floatCast_f128(0x1.987124876876324p+12, 0x6e62); |
| 257 | try test_f16_floatCast_f128(0x1.0p+0, 0x3c00); |
| 258 | try test_f16_floatCast_f128(0x1.0p-14, 0x0400); |
| 259 | // denormal |
| 260 | try test_f16_floatCast_f128(0x1.0p-20, 0x0010); |
| 261 | try test_f16_floatCast_f128(0x1.0p-24, 0x0001); |
| 262 | try test_f16_floatCast_f128(-0x1.0p-24, 0x8001); |
| 263 | try test_f16_floatCast_f128(0x1.5p-25, 0x0001); |
| 264 | // and back to zero |
| 265 | try test_f16_floatCast_f128(0x1.0p-25, 0x0000); |
| 266 | try test_f16_floatCast_f128(-0x1.0p-25, 0x8000); |
| 267 | // max (precise) |
| 268 | try test_f16_floatCast_f128(65504.0, 0x7bff); |
| 269 | // max (rounded) |
| 270 | try test_f16_floatCast_f128(65519.0, 0x7bff); |
| 271 | // max (to +inf) |
| 272 | try test_f16_floatCast_f128(65520.0, 0x7c00); |
| 273 | try test_f16_floatCast_f128(65536.0, 0x7c00); |
| 274 | try test_f16_floatCast_f128(-65520.0, 0xfc00); |
| 275 | |
| 276 | try test_f16_floatCast_f128(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x508f); |
| 277 | try test_f16_floatCast_f128(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x1b8f); |
| 278 | try test_f16_floatCast_f128(0x1.234eebb5faa678f4488693abcdefp+453, 0x7c00); |
| 279 | try test_f16_floatCast_f128(0x1.edcba9bb8c76a5a43dd21f334634p-43, 0x0); |
| 280 | } |
| 281 | |
| 282 | fn test_f80_floatCast_f128(a: f128, expected: f80) !void { |
| 283 | const x = f80_floatCast_f128(a); |
| 284 | try testing.expect(x == expected); |
| 285 | } |
| 286 | |
| 287 | test f80_floatCast_f128 { |
| 288 | try test_f80_floatCast_f128(1.5, 1.5); |
| 289 | try test_f80_floatCast_f128(2.5, 2.5); |
| 290 | try test_f80_floatCast_f128(-2.5, -2.5); |
| 291 | try test_f80_floatCast_f128(0.0, 0.0); |
| 292 | } |