authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-29 17:21:29-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-29 17:21:29-05:00
log7ebc624a15c5a01d6bee8eaf9c7487b30ed1904c
treee4db4340a18e9a116f7e39e48ca9dc990f811575
parentd448c3d38af9f8f70daaa2817a5834e30da4b8ca
parentf97b398b654aecdb679a054d9078b92cb70ba3b5
signaturelock-open Commit is signed but in an unrecognized format.

Merge branch 'LemonBoy-fix-4259'


2 files changed, 105 insertions(+), 32 deletions(-)

src/ir.cpp+63-20
......@@ -11161,6 +11161,38 @@ void float_read_ieee597(ZigValue *val, uint8_t *buf, bool is_big_endian) {
1116111161 }
1116211162}
1116311163
11164static void value_to_bigfloat(BigFloat *out, ZigValue *val) {
11165 switch (val->type->id) {
11166 case ZigTypeIdInt:
11167 case ZigTypeIdComptimeInt:
11168 bigfloat_init_bigint(out, &val->data.x_bigint);
11169 return;
11170 case ZigTypeIdComptimeFloat:
11171 *out = val->data.x_bigfloat;
11172 return;
11173 case ZigTypeIdFloat: switch (val->type->data.floating.bit_count) {
11174 case 16:
11175 bigfloat_init_16(out, val->data.x_f16);
11176 return;
11177 case 32:
11178 bigfloat_init_32(out, val->data.x_f32);
11179 return;
11180 case 64:
11181 bigfloat_init_64(out, val->data.x_f64);
11182 return;
11183 case 80:
11184 zig_panic("TODO");
11185 case 128:
11186 bigfloat_init_128(out, val->data.x_f128);
11187 return;
11188 default:
11189 zig_unreachable();
11190 }
11191 default:
11192 zig_unreachable();
11193 }
11194}
11195
1116411196static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstGen *instruction, ZigType *other_type,
1116511197 bool explicit_cast)
1116611198{
......@@ -15815,33 +15847,44 @@ never_mind_just_calculate_it_normally:
1581515847 bool op1_is_int = op1_val->type->id == ZigTypeIdInt || op1_val->type->id == ZigTypeIdComptimeInt;
1581615848 bool op2_is_int = op2_val->type->id == ZigTypeIdInt || op2_val->type->id == ZigTypeIdComptimeInt;
1581715849
15818 BigInt *op1_bigint;
15819 BigInt *op2_bigint;
15820 bool need_to_free_op1_bigint = false;
15821 bool need_to_free_op2_bigint = false;
15822 if (op1_is_float) {
15823 op1_bigint = allocate<BigInt>(1, "BigInt");
15824 need_to_free_op1_bigint = true;
15825 float_init_bigint(op1_bigint, op1_val);
15826 } else {
15827 assert(op1_is_int);
15828 op1_bigint = &op1_val->data.x_bigint;
15850 if (op1_is_int && op2_is_int) {
15851 Cmp cmp_result = bigint_cmp(&op1_val->data.x_bigint, &op2_val->data.x_bigint);
15852 out_val->special = ConstValSpecialStatic;
15853 out_val->data.x_bool = resolve_cmp_op_id(op_id, cmp_result);
15854
15855 return nullptr;
1582915856 }
15830 if (op2_is_float) {
15831 op2_bigint = allocate<BigInt>(1, "BigInt");
15832 need_to_free_op2_bigint = true;
15833 float_init_bigint(op2_bigint, op2_val);
15857
15858 // Handle the case where one of the two operands is a fp value and the other
15859 // is an integer value
15860 ZigValue *float_val;
15861 if (op1_is_int && op2_is_float) {
15862 float_val = op2_val;
15863 } else if (op1_is_float && op2_is_int) {
15864 float_val = op1_val;
1583415865 } else {
15835 assert(op2_is_int);
15836 op2_bigint = &op2_val->data.x_bigint;
15866 zig_unreachable();
1583715867 }
1583815868
15839 Cmp cmp_result = bigint_cmp(op1_bigint, op2_bigint);
15869 // They can never be equal if the fp value has a non-zero decimal part
15870 if (op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq) {
15871 if (float_has_fraction(float_val)) {
15872 out_val->special = ConstValSpecialStatic;
15873 out_val->data.x_bool = op_id == IrBinOpCmpNotEq;
15874 return nullptr;
15875 }
15876 }
15877
15878 // Cast the integer operand into a fp value to perform the comparison
15879 BigFloat op1_bigfloat;
15880 BigFloat op2_bigfloat;
15881 value_to_bigfloat(&op1_bigfloat, op1_val);
15882 value_to_bigfloat(&op2_bigfloat, op2_val);
15883
15884 Cmp cmp_result = bigfloat_cmp(&op1_bigfloat, &op2_bigfloat);
1584015885 out_val->special = ConstValSpecialStatic;
1584115886 out_val->data.x_bool = resolve_cmp_op_id(op_id, cmp_result);
1584215887
15843 if (need_to_free_op1_bigint) destroy(op1_bigint, "BigInt");
15844 if (need_to_free_op2_bigint) destroy(op2_bigint, "BigInt");
1584515888 return nullptr;
1584615889}
1584715890
test/stage1/behavior/floatop.zig+42-12
......@@ -36,7 +36,7 @@ fn testSqrt() void {
3636 // expect(@sqrt(a) == 7);
3737 //}
3838 {
39 var v: @Vector(4, f32) = [_]f32{1.1, 2.2, 3.3, 4.4};
39 var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
4040 var result = @sqrt(v);
4141 expect(math.approxEq(f32, @sqrt(@as(f32, 1.1)), result[0], epsilon));
4242 expect(math.approxEq(f32, @sqrt(@as(f32, 2.2)), result[1], epsilon));
......@@ -86,7 +86,7 @@ fn testSin() void {
8686 expect(@sin(a) == 0);
8787 }
8888 {
89 var v: @Vector(4, f32) = [_]f32{1.1, 2.2, 3.3, 4.4};
89 var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
9090 var result = @sin(v);
9191 expect(math.approxEq(f32, @sin(@as(f32, 1.1)), result[0], epsilon));
9292 expect(math.approxEq(f32, @sin(@as(f32, 2.2)), result[1], epsilon));
......@@ -116,7 +116,7 @@ fn testCos() void {
116116 expect(@cos(a) == 1);
117117 }
118118 {
119 var v: @Vector(4, f32) = [_]f32{1.1, 2.2, 3.3, 4.4};
119 var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
120120 var result = @cos(v);
121121 expect(math.approxEq(f32, @cos(@as(f32, 1.1)), result[0], epsilon));
122122 expect(math.approxEq(f32, @cos(@as(f32, 2.2)), result[1], epsilon));
......@@ -146,7 +146,7 @@ fn testExp() void {
146146 expect(@exp(a) == 1);
147147 }
148148 {
149 var v: @Vector(4, f32) = [_]f32{1.1, 2.2, 0.3, 0.4};
149 var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
150150 var result = @exp(v);
151151 expect(math.approxEq(f32, @exp(@as(f32, 1.1)), result[0], epsilon));
152152 expect(math.approxEq(f32, @exp(@as(f32, 2.2)), result[1], epsilon));
......@@ -176,7 +176,7 @@ fn testExp2() void {
176176 expect(@exp2(a) == 4);
177177 }
178178 {
179 var v: @Vector(4, f32) = [_]f32{1.1, 2.2, 0.3, 0.4};
179 var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
180180 var result = @exp2(v);
181181 expect(math.approxEq(f32, @exp2(@as(f32, 1.1)), result[0], epsilon));
182182 expect(math.approxEq(f32, @exp2(@as(f32, 2.2)), result[1], epsilon));
......@@ -208,7 +208,7 @@ fn testLog() void {
208208 expect(@log(a) == 1 or @log(a) == @bitCast(f64, @as(u64, 0x3ff0000000000000)));
209209 }
210210 {
211 var v: @Vector(4, f32) = [_]f32{1.1, 2.2, 0.3, 0.4};
211 var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
212212 var result = @log(v);
213213 expect(math.approxEq(f32, @log(@as(f32, 1.1)), result[0], epsilon));
214214 expect(math.approxEq(f32, @log(@as(f32, 2.2)), result[1], epsilon));
......@@ -238,7 +238,7 @@ fn testLog2() void {
238238 expect(@log2(a) == 2);
239239 }
240240 {
241 var v: @Vector(4, f32) = [_]f32{1.1, 2.2, 0.3, 0.4};
241 var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
242242 var result = @log2(v);
243243 expect(math.approxEq(f32, @log2(@as(f32, 1.1)), result[0], epsilon));
244244 expect(math.approxEq(f32, @log2(@as(f32, 2.2)), result[1], epsilon));
......@@ -268,7 +268,7 @@ fn testLog10() void {
268268 expect(@log10(a) == 3);
269269 }
270270 {
271 var v: @Vector(4, f32) = [_]f32{1.1, 2.2, 0.3, 0.4};
271 var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
272272 var result = @log10(v);
273273 expect(math.approxEq(f32, @log10(@as(f32, 1.1)), result[0], epsilon));
274274 expect(math.approxEq(f32, @log10(@as(f32, 2.2)), result[1], epsilon));
......@@ -304,7 +304,7 @@ fn testFabs() void {
304304 expect(@fabs(b) == 2.5);
305305 }
306306 {
307 var v: @Vector(4, f32) = [_]f32{1.1, -2.2, 0.3, -0.4};
307 var v: @Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
308308 var result = @fabs(v);
309309 expect(math.approxEq(f32, @fabs(@as(f32, 1.1)), result[0], epsilon));
310310 expect(math.approxEq(f32, @fabs(@as(f32, -2.2)), result[1], epsilon));
......@@ -334,7 +334,7 @@ fn testFloor() void {
334334 expect(@floor(a) == 3);
335335 }
336336 {
337 var v: @Vector(4, f32) = [_]f32{1.1, -2.2, 0.3, -0.4};
337 var v: @Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
338338 var result = @floor(v);
339339 expect(math.approxEq(f32, @floor(@as(f32, 1.1)), result[0], epsilon));
340340 expect(math.approxEq(f32, @floor(@as(f32, -2.2)), result[1], epsilon));
......@@ -364,7 +364,7 @@ fn testCeil() void {
364364 expect(@ceil(a) == 4);
365365 }
366366 {
367 var v: @Vector(4, f32) = [_]f32{1.1, -2.2, 0.3, -0.4};
367 var v: @Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
368368 var result = @ceil(v);
369369 expect(math.approxEq(f32, @ceil(@as(f32, 1.1)), result[0], epsilon));
370370 expect(math.approxEq(f32, @ceil(@as(f32, -2.2)), result[1], epsilon));
......@@ -394,7 +394,7 @@ fn testTrunc() void {
394394 expect(@trunc(a) == -3);
395395 }
396396 {
397 var v: @Vector(4, f32) = [_]f32{1.1, -2.2, 0.3, -0.4};
397 var v: @Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
398398 var result = @trunc(v);
399399 expect(math.approxEq(f32, @trunc(@as(f32, 1.1)), result[0], epsilon));
400400 expect(math.approxEq(f32, @trunc(@as(f32, -2.2)), result[1], epsilon));
......@@ -403,6 +403,36 @@ fn testTrunc() void {
403403 }
404404}
405405
406test "floating point comparisons" {
407 testFloatComparisons();
408 comptime testFloatComparisons();
409}
410
411fn testFloatComparisons() void {
412 inline for ([_]type{ f16, f32, f64, f128 }) |ty| {
413 // No decimal part
414 {
415 const x: ty = 1.0;
416 expect(x == 1);
417 expect(x != 0);
418 expect(x > 0);
419 expect(x < 2);
420 expect(x >= 1);
421 expect(x <= 1);
422 }
423 // Non-zero decimal part
424 {
425 const x: ty = 1.5;
426 expect(x != 1);
427 expect(x != 2);
428 expect(x > 1);
429 expect(x < 2);
430 expect(x >= 1);
431 expect(x <= 2);
432 }
433 }
434}
435
406436// TODO This is waiting on library support for the Windows build (not sure why the other's don't need it)
407437//test "@nearbyint" {
408438// comptime testNearbyInt();