| author | |
| committer | |
| log | 5919b10048be6efa8c0ca6bcb259706098b2d5ec |
| tree | 307c504b85c9aee16602e667db1a5db5c25e1fff |
| parent | cb3b1dd6ddee65d1811fb4058b5cc0f2c06d0139 |
| parent | b2a1b4c085b93d508c51307f40444252b8cd4d52 |
| signature |
stage2 float fixes13 files changed, 394 insertions(+), 128 deletions(-)
doc/langref.html.in+36-31| ... | ... | @@ -2515,13 +2515,14 @@ test "null terminated array" { |
| 2515 | 2515 | |
| 2516 | 2516 | {#header_open|Vectors#} |
| 2517 | 2517 | <p> |
| 2518 | A vector is a group of booleans, {#link|Integers#}, {#link|Floats#}, or {#link|Pointers#} which are operated on | |
| 2519 | in parallel using SIMD instructions. Vector types are created with the builtin function {#link|@Type#}, | |
| 2520 | or using the shorthand function {#syntax#}std.meta.Vector{#endsyntax#}. | |
| 2518 | A vector is a group of booleans, {#link|Integers#}, {#link|Floats#}, or | |
| 2519 | {#link|Pointers#} which are operated on in parallel, using SIMD instructions if possible. | |
| 2520 | Vector types are created with the builtin function {#link|@Vector#}. | |
| 2521 | 2521 | </p> |
| 2522 | 2522 | <p> |
| 2523 | Vectors support the same builtin operators as their underlying base types. These operations are performed | |
| 2524 | element-wise, and return a vector of the same length as the input vectors. This includes: | |
| 2523 | Vectors support the same builtin operators as their underlying base types. | |
| 2524 | These operations are performed element-wise, and return a vector of the same length | |
| 2525 | as the input vectors. This includes: | |
| 2525 | 2526 | </p> |
| 2526 | 2527 | <ul> |
| 2527 | 2528 | <li>Arithmetic ({#syntax#}+{#endsyntax#}, {#syntax#}-{#endsyntax#}, {#syntax#}/{#endsyntax#}, {#syntax#}*{#endsyntax#}, |
| ... | ... | @@ -2532,10 +2533,11 @@ test "null terminated array" { |
| 2532 | 2533 | <li>Comparison operators ({#syntax#}<{#endsyntax#}, {#syntax#}>{#endsyntax#}, {#syntax#}=={#endsyntax#}, etc.)</li> |
| 2533 | 2534 | </ul> |
| 2534 | 2535 | <p> |
| 2535 | It is prohibited to use a math operator on a mixture of scalars (individual numbers) and vectors. | |
| 2536 | Zig provides the {#link|@splat#} builtin to easily convert from scalars to vectors, and it supports {#link|@reduce#} | |
| 2537 | and array indexing syntax to convert from vectors to scalars. Vectors also support assignment to and from | |
| 2538 | fixed-length arrays with comptime known length. | |
| 2536 | It is prohibited to use a math operator on a mixture of scalars (individual numbers) | |
| 2537 | and vectors. Zig provides the {#link|@splat#} builtin to easily convert from scalars | |
| 2538 | to vectors, and it supports {#link|@reduce#} and array indexing syntax to convert | |
| 2539 | from vectors to scalars. Vectors also support assignment to and from fixed-length | |
| 2540 | arrays with comptime known length. | |
| 2539 | 2541 | </p> |
| 2540 | 2542 | <p> |
| 2541 | 2543 | For rearranging elements within and between vectors, Zig provides the {#link|@shuffle#} and {#link|@select#} functions. |
| ... | ... | @@ -2550,16 +2552,14 @@ test "null terminated array" { |
| 2550 | 2552 | </p> |
| 2551 | 2553 | {#code_begin|test|vector_example#} |
| 2552 | 2554 | const std = @import("std"); |
| 2553 | const Vector = std.meta.Vector; | |
| 2554 | 2555 | const expectEqual = std.testing.expectEqual; |
| 2555 | 2556 | |
| 2556 | 2557 | test "Basic vector usage" { |
| 2557 | // Vectors have a compile-time known length and base type, | |
| 2558 | // and can be assigned to using array literal syntax | |
| 2559 | const a: Vector(4, i32) = [_]i32{ 1, 2, 3, 4 }; | |
| 2560 | const b: Vector(4, i32) = [_]i32{ 5, 6, 7, 8 }; | |
| 2558 | // Vectors have a compile-time known length and base type. | |
| 2559 | const a = @Vector(4, i32){ 1, 2, 3, 4 }; | |
| 2560 | const b = @Vector(4, i32){ 5, 6, 7, 8 }; | |
| 2561 | 2561 | |
| 2562 | // Math operations take place element-wise | |
| 2562 | // Math operations take place element-wise. | |
| 2563 | 2563 | const c = a + b; |
| 2564 | 2564 | |
| 2565 | 2565 | // Individual vector elements can be accessed using array indexing syntax. |
| ... | ... | @@ -2572,19 +2572,19 @@ test "Basic vector usage" { |
| 2572 | 2572 | test "Conversion between vectors, arrays, and slices" { |
| 2573 | 2573 | // Vectors and fixed-length arrays can be automatically assigned back and forth |
| 2574 | 2574 | var arr1: [4]f32 = [_]f32{ 1.1, 3.2, 4.5, 5.6 }; |
| 2575 | var vec: Vector(4, f32) = arr1; | |
| 2575 | var vec: @Vector(4, f32) = arr1; | |
| 2576 | 2576 | var arr2: [4]f32 = vec; |
| 2577 | 2577 | try expectEqual(arr1, arr2); |
| 2578 | 2578 | |
| 2579 | 2579 | // You can also assign from a slice with comptime-known length to a vector using .* |
| 2580 | const vec2: Vector(2, f32) = arr1[1..3].*; | |
| 2580 | const vec2: @Vector(2, f32) = arr1[1..3].*; | |
| 2581 | 2581 | |
| 2582 | 2582 | var slice: []const f32 = &arr1; |
| 2583 | 2583 | var offset: u32 = 1; |
| 2584 | 2584 | // To extract a comptime-known length from a runtime-known offset, |
| 2585 | 2585 | // first extract a new slice from the starting offset, then an array of |
| 2586 | 2586 | // comptime known length |
| 2587 | const vec3: Vector(2, f32) = slice[offset..][0..2].*; | |
| 2587 | const vec3: @Vector(2, f32) = slice[offset..][0..2].*; | |
| 2588 | 2588 | try expectEqual(slice[offset], vec2[0]); |
| 2589 | 2589 | try expectEqual(slice[offset + 1], vec2[1]); |
| 2590 | 2590 | try expectEqual(vec2, vec3); |
| ... | ... | @@ -9084,7 +9084,7 @@ pub const PrefetchOptions = struct { |
| 9084 | 9084 | {#header_close#} |
| 9085 | 9085 | |
| 9086 | 9086 | {#header_open|@select#} |
| 9087 | <pre>{#syntax#}@select(comptime T: type, pred: std.meta.Vector(len, bool), a: std.meta.Vector(len, T), b: std.meta.Vector(len, T)) std.meta.Vector(len, T){#endsyntax#}</pre> | |
| 9087 | <pre>{#syntax#}@select(comptime T: type, pred: @Vector(len, bool), a: @Vector(len, T), b: @Vector(len, T)) @Vector(len, T){#endsyntax#}</pre> | |
| 9088 | 9088 | <p> |
| 9089 | 9089 | Selects values element-wise from {#syntax#}a{#endsyntax#} or {#syntax#}b{#endsyntax#} based on {#syntax#}pred{#endsyntax#}. If {#syntax#}pred[i]{#endsyntax#} is {#syntax#}true{#endsyntax#}, the corresponding element in the result will be {#syntax#}a[i]{#endsyntax#} and otherwise {#syntax#}b[i]{#endsyntax#}. |
| 9090 | 9090 | </p> |
| ... | ... | @@ -9252,7 +9252,7 @@ test "@setRuntimeSafety" { |
| 9252 | 9252 | {#header_close#} |
| 9253 | 9253 | |
| 9254 | 9254 | {#header_open|@shuffle#} |
| 9255 | <pre>{#syntax#}@shuffle(comptime E: type, a: std.meta.Vector(a_len, E), b: std.meta.Vector(b_len, E), comptime mask: std.meta.Vector(mask_len, i32)) std.meta.Vector(mask_len, E){#endsyntax#}</pre> | |
| 9255 | <pre>{#syntax#}@shuffle(comptime E: type, a: @Vector(a_len, E), b: @Vector(b_len, E), comptime mask: @Vector(mask_len, i32)) @Vector(mask_len, E){#endsyntax#}</pre> | |
| 9256 | 9256 | <p> |
| 9257 | 9257 | Constructs a new {#link|vector|Vectors#} by selecting elements from {#syntax#}a{#endsyntax#} and |
| 9258 | 9258 | {#syntax#}b{#endsyntax#} based on {#syntax#}mask{#endsyntax#}. |
| ... | ... | @@ -9287,22 +9287,21 @@ test "@setRuntimeSafety" { |
| 9287 | 9287 | </p> |
| 9288 | 9288 | {#code_begin|test|vector_shuffle#} |
| 9289 | 9289 | const std = @import("std"); |
| 9290 | const Vector = std.meta.Vector; | |
| 9291 | 9290 | const expect = std.testing.expect; |
| 9292 | 9291 | |
| 9293 | 9292 | test "vector @shuffle" { |
| 9294 | const a: Vector(7, u8) = [_]u8{ 'o', 'l', 'h', 'e', 'r', 'z', 'w' }; | |
| 9295 | const b: Vector(4, u8) = [_]u8{ 'w', 'd', '!', 'x' }; | |
| 9293 | const a = @Vector(7, u8){ 'o', 'l', 'h', 'e', 'r', 'z', 'w' }; | |
| 9294 | const b = @Vector(4, u8){ 'w', 'd', '!', 'x' }; | |
| 9296 | 9295 | |
| 9297 | 9296 | // To shuffle within a single vector, pass undefined as the second argument. |
| 9298 | 9297 | // Notice that we can re-order, duplicate, or omit elements of the input vector |
| 9299 | const mask1: Vector(5, i32) = [_]i32{ 2, 3, 1, 1, 0 }; | |
| 9300 | const res1: Vector(5, u8) = @shuffle(u8, a, undefined, mask1); | |
| 9298 | const mask1 = @Vector(5, i32){ 2, 3, 1, 1, 0 }; | |
| 9299 | const res1: @Vector(5, u8) = @shuffle(u8, a, undefined, mask1); | |
| 9301 | 9300 | try expect(std.mem.eql(u8, &@as([5]u8, res1), "hello")); |
| 9302 | 9301 | |
| 9303 | 9302 | // Combining two vectors |
| 9304 | const mask2: Vector(6, i32) = [_]i32{ -1, 0, 4, 1, -2, -3 }; | |
| 9305 | const res2: Vector(6, u8) = @shuffle(u8, a, b, mask2); | |
| 9303 | const mask2 = @Vector(6, i32){ -1, 0, 4, 1, -2, -3 }; | |
| 9304 | const res2: @Vector(6, u8) = @shuffle(u8, a, b, mask2); | |
| 9306 | 9305 | try expect(std.mem.eql(u8, &@as([6]u8, res2), "world!")); |
| 9307 | 9306 | } |
| 9308 | 9307 | {#code_end#} |
| ... | ... | @@ -9329,7 +9328,7 @@ test "vector @shuffle" { |
| 9329 | 9328 | {#header_close#} |
| 9330 | 9329 | |
| 9331 | 9330 | {#header_open|@splat#} |
| 9332 | <pre>{#syntax#}@splat(comptime len: u32, scalar: anytype) std.meta.Vector(len, @TypeOf(scalar)){#endsyntax#}</pre> | |
| 9331 | <pre>{#syntax#}@splat(comptime len: u32, scalar: anytype) @Vector(len, @TypeOf(scalar)){#endsyntax#}</pre> | |
| 9333 | 9332 | <p> |
| 9334 | 9333 | Produces a vector of length {#syntax#}len{#endsyntax#} where each element is the value |
| 9335 | 9334 | {#syntax#}scalar{#endsyntax#}: |
| ... | ... | @@ -9341,7 +9340,7 @@ const expect = std.testing.expect; |
| 9341 | 9340 | test "vector @splat" { |
| 9342 | 9341 | const scalar: u32 = 5; |
| 9343 | 9342 | const result = @splat(4, scalar); |
| 9344 | comptime try expect(@TypeOf(result) == std.meta.Vector(4, u32)); | |
| 9343 | comptime try expect(@TypeOf(result) == @Vector(4, u32)); | |
| 9345 | 9344 | try expect(std.mem.eql(u32, &@as([4]u32, result), &[_]u32{ 5, 5, 5, 5 })); |
| 9346 | 9345 | } |
| 9347 | 9346 | {#code_end#} |
| ... | ... | @@ -9381,10 +9380,10 @@ const std = @import("std"); |
| 9381 | 9380 | const expect = std.testing.expect; |
| 9382 | 9381 | |
| 9383 | 9382 | test "vector @reduce" { |
| 9384 | const value: std.meta.Vector(4, i32) = [_]i32{ 1, -1, 1, -1 }; | |
| 9383 | const value = @Vector(4, i32){ 1, -1, 1, -1 }; | |
| 9385 | 9384 | const result = value > @splat(4, @as(i32, 0)); |
| 9386 | 9385 | // result is { true, false, true, false }; |
| 9387 | comptime try expect(@TypeOf(result) == std.meta.Vector(4, bool)); | |
| 9386 | comptime try expect(@TypeOf(result) == @Vector(4, bool)); | |
| 9388 | 9387 | const is_all_true = @reduce(.And, result); |
| 9389 | 9388 | comptime try expect(@TypeOf(is_all_true) == bool); |
| 9390 | 9389 | try expect(is_all_true == false); |
| ... | ... | @@ -9743,6 +9742,12 @@ fn foo(comptime T: type, ptr: *T) T { |
| 9743 | 9742 | {#syntax#}@unionInit{#endsyntax#} forwards its {#link|result location|Result Location Semantics#} to {#syntax#}init_expr{#endsyntax#}. |
| 9744 | 9743 | </p> |
| 9745 | 9744 | {#header_close#} |
| 9745 | ||
| 9746 | ||
| 9747 | {#header_open|@Vector#} | |
| 9748 | <pre>{#syntax#}@Vector(len: comptime_int, Element: type) type{#endsyntax#}</pre> | |
| 9749 | <p>Creates {#link|Vectors#}.</p> | |
| 9750 | {#header_close#} | |
| 9746 | 9751 | {#header_close#} |
| 9747 | 9752 | |
| 9748 | 9753 | {#header_open|Build Mode#} |
lib/std/math/round.zig+4| ... | ... | @@ -20,6 +20,10 @@ pub fn round(x: anytype) @TypeOf(x) { |
| 20 | 20 | f32 => round32(x), |
| 21 | 21 | f64 => round64(x), |
| 22 | 22 | f128 => round128(x), |
| 23 | ||
| 24 | // TODO this is not correct for some targets | |
| 25 | c_longdouble => @floatCast(c_longdouble, round128(x)), | |
| 26 | ||
| 23 | 27 | else => @compileError("round not implemented for " ++ @typeName(T)), |
| 24 | 28 | }; |
| 25 | 29 | } |
lib/std/meta.zig+1| ... | ... | @@ -930,6 +930,7 @@ test "std.meta.Float" { |
| 930 | 930 | try testing.expectEqual(f128, Float(128)); |
| 931 | 931 | } |
| 932 | 932 | |
| 933 | /// Deprecated. Use `@Vector`. | |
| 933 | 934 | pub fn Vector(comptime len: u32, comptime child: type) type { |
| 934 | 935 | return @Type(.{ |
| 935 | 936 | .Vector = .{ |
lib/std/multi_array_list.zig+1-1| ... | ... | @@ -421,7 +421,7 @@ pub fn MultiArrayList(comptime S: type) type { |
| 421 | 421 | } |
| 422 | 422 | |
| 423 | 423 | fn capacityInBytes(capacity: usize) usize { |
| 424 | const sizes_vector: std.meta.Vector(sizes.bytes.len, usize) = sizes.bytes; | |
| 424 | const sizes_vector: @Vector(sizes.bytes.len, usize) = sizes.bytes; | |
| 425 | 425 | const capacity_vector = @splat(sizes.bytes.len, capacity); |
| 426 | 426 | return @reduce(.Add, capacity_vector * sizes_vector); |
| 427 | 427 | } |
lib/std/special/c.zig+9-1| ... | ... | @@ -98,6 +98,7 @@ comptime { |
| 98 | 98 | |
| 99 | 99 | @export(round, .{ .name = "round", .linkage = .Strong }); |
| 100 | 100 | @export(roundf, .{ .name = "roundf", .linkage = .Strong }); |
| 101 | @export(roundl, .{ .name = "roundl", .linkage = .Strong }); | |
| 101 | 102 | |
| 102 | 103 | @export(fmin, .{ .name = "fmin", .linkage = .Strong }); |
| 103 | 104 | @export(fminf, .{ .name = "fminf", .linkage = .Strong }); |
| ... | ... | @@ -575,11 +576,18 @@ fn fabsf(a: f32) callconv(.C) f32 { |
| 575 | 576 | return math.fabs(a); |
| 576 | 577 | } |
| 577 | 578 | |
| 579 | fn roundf(a: f32) callconv(.C) f32 { | |
| 580 | return math.round(a); | |
| 581 | } | |
| 582 | ||
| 578 | 583 | fn round(a: f64) callconv(.C) f64 { |
| 579 | 584 | return math.round(a); |
| 580 | 585 | } |
| 581 | 586 | |
| 582 | fn roundf(a: f32) callconv(.C) f32 { | |
| 587 | fn roundl(a: c_longdouble) callconv(.C) c_longdouble { | |
| 588 | if (!long_double_is_f128) { | |
| 589 | @panic("TODO implement this"); | |
| 590 | } | |
| 583 | 591 | return math.round(a); |
| 584 | 592 | } |
| 585 | 593 |
src/Sema.zig+59-3| ... | ... | @@ -4195,7 +4195,15 @@ fn zirDbgVar( |
| 4195 | 4195 | const str_op = sema.code.instructions.items(.data)[inst].str_op; |
| 4196 | 4196 | const operand = sema.resolveInst(str_op.operand); |
| 4197 | 4197 | const operand_ty = sema.typeOf(operand); |
| 4198 | if (!(try sema.typeHasRuntimeBits(block, sema.src, operand_ty))) return; | |
| 4198 | switch (air_tag) { | |
| 4199 | .dbg_var_ptr => { | |
| 4200 | if (!(try sema.typeHasRuntimeBits(block, sema.src, operand_ty.childType()))) return; | |
| 4201 | }, | |
| 4202 | .dbg_var_val => { | |
| 4203 | if (!(try sema.typeHasRuntimeBits(block, sema.src, operand_ty))) return; | |
| 4204 | }, | |
| 4205 | else => unreachable, | |
| 4206 | } | |
| 4199 | 4207 | const name = str_op.getStr(sema.code); |
| 4200 | 4208 | |
| 4201 | 4209 | // Add the name to the AIR. |
| ... | ... | @@ -13268,7 +13276,7 @@ fn checkFloatType( |
| 13268 | 13276 | ty: Type, |
| 13269 | 13277 | ) CompileError!void { |
| 13270 | 13278 | switch (ty.zigTypeTag()) { |
| 13271 | .ComptimeFloat, .Float => {}, | |
| 13279 | .ComptimeInt, .ComptimeFloat, .Float => {}, | |
| 13272 | 13280 | else => return sema.fail(block, ty_src, "expected float type, found '{}'", .{ty}), |
| 13273 | 13281 | } |
| 13274 | 13282 | } |
| ... | ... | @@ -17169,10 +17177,25 @@ fn storePtr2( |
| 17169 | 17177 | return; |
| 17170 | 17178 | } |
| 17171 | 17179 | |
| 17180 | // TODO do the same thing for anon structs as for tuples above. | |
| 17181 | ||
| 17182 | // Detect if we are storing an array operand to a bitcasted vector pointer. | |
| 17183 | // If so, we instead reach through the bitcasted pointer to the vector pointer, | |
| 17184 | // bitcast the array operand to a vector, and then lower this as a store of | |
| 17185 | // a vector value to a vector pointer. This generally results in better code, | |
| 17186 | // as well as working around an LLVM bug: | |
| 17187 | // https://github.com/ziglang/zig/issues/11154 | |
| 17188 | if (sema.obtainBitCastedVectorPtr(ptr)) |vector_ptr| { | |
| 17189 | const vector_ty = sema.typeOf(vector_ptr).childType(); | |
| 17190 | const vector = try sema.coerce(block, vector_ty, uncasted_operand, operand_src); | |
| 17191 | try sema.storePtr2(block, src, vector_ptr, ptr_src, vector, operand_src, .store); | |
| 17192 | return; | |
| 17193 | } | |
| 17194 | ||
| 17172 | 17195 | const operand = try sema.coerce(block, elem_ty, uncasted_operand, operand_src); |
| 17196 | const maybe_operand_val = try sema.resolveMaybeUndefVal(block, operand_src, operand); | |
| 17173 | 17197 | |
| 17174 | 17198 | const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: { |
| 17175 | const maybe_operand_val = try sema.resolveMaybeUndefVal(block, operand_src, operand); | |
| 17176 | 17199 | const operand_val = maybe_operand_val orelse { |
| 17177 | 17200 | try sema.checkPtrIsNotComptimeMutable(block, ptr_val, ptr_src, operand_src); |
| 17178 | 17201 | break :rs operand_src; |
| ... | ... | @@ -17195,6 +17218,39 @@ fn storePtr2( |
| 17195 | 17218 | _ = try block.addBinOp(air_tag, ptr, operand); |
| 17196 | 17219 | } |
| 17197 | 17220 | |
| 17221 | /// Traverse an arbitrary number of bitcasted pointers and return the underyling vector | |
| 17222 | /// pointer. Only if the final element type matches the vector element type, and the | |
| 17223 | /// lengths match. | |
| 17224 | fn obtainBitCastedVectorPtr(sema: *Sema, ptr: Air.Inst.Ref) ?Air.Inst.Ref { | |
| 17225 | const array_ty = sema.typeOf(ptr).childType(); | |
| 17226 | if (array_ty.zigTypeTag() != .Array) return null; | |
| 17227 | var ptr_inst = Air.refToIndex(ptr) orelse return null; | |
| 17228 | const air_datas = sema.air_instructions.items(.data); | |
| 17229 | const air_tags = sema.air_instructions.items(.tag); | |
| 17230 | const prev_ptr = while (air_tags[ptr_inst] == .bitcast) { | |
| 17231 | const prev_ptr = air_datas[ptr_inst].ty_op.operand; | |
| 17232 | const prev_ptr_ty = sema.typeOf(prev_ptr); | |
| 17233 | const prev_ptr_child_ty = switch (prev_ptr_ty.tag()) { | |
| 17234 | .single_mut_pointer => prev_ptr_ty.castTag(.single_mut_pointer).?.data, | |
| 17235 | .pointer => prev_ptr_ty.castTag(.pointer).?.data.pointee_type, | |
| 17236 | else => return null, | |
| 17237 | }; | |
| 17238 | if (prev_ptr_child_ty.zigTypeTag() == .Vector) break prev_ptr; | |
| 17239 | ptr_inst = Air.refToIndex(prev_ptr) orelse return null; | |
| 17240 | } else return null; | |
| 17241 | ||
| 17242 | // We have a pointer-to-array and a pointer-to-vector. If the elements and | |
| 17243 | // lengths match, return the result. | |
| 17244 | const vector_ty = sema.typeOf(prev_ptr).childType(); | |
| 17245 | if (array_ty.childType().eql(vector_ty.childType()) and | |
| 17246 | array_ty.arrayLen() == vector_ty.vectorLen()) | |
| 17247 | { | |
| 17248 | return prev_ptr; | |
| 17249 | } else { | |
| 17250 | return null; | |
| 17251 | } | |
| 17252 | } | |
| 17253 | ||
| 17198 | 17254 | /// Call when you have Value objects rather than Air instructions, and you want to |
| 17199 | 17255 | /// assert the store must be done at comptime. |
| 17200 | 17256 | fn storePtrVal( |
src/codegen/llvm.zig+4-2| ... | ... | @@ -3709,10 +3709,11 @@ pub const FuncGen = struct { |
| 3709 | 3709 | |
| 3710 | 3710 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 3711 | 3711 | const operand = try self.resolveInst(ty_op.operand); |
| 3712 | const operand_ty = self.air.typeOf(ty_op.operand); | |
| 3712 | 3713 | const dest_ty = self.air.typeOfIndex(inst); |
| 3713 | 3714 | const dest_llvm_ty = try self.dg.llvmType(dest_ty); |
| 3714 | 3715 | |
| 3715 | if (dest_ty.isSignedInt()) { | |
| 3716 | if (operand_ty.isSignedInt()) { | |
| 3716 | 3717 | return self.builder.buildSIToFP(operand, dest_llvm_ty, ""); |
| 3717 | 3718 | } else { |
| 3718 | 3719 | return self.builder.buildUIToFP(operand, dest_llvm_ty, ""); |
| ... | ... | @@ -3984,13 +3985,14 @@ pub const FuncGen = struct { |
| 3984 | 3985 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 3985 | 3986 | const operand = try self.resolveInst(pl_op.operand); |
| 3986 | 3987 | const name = self.air.nullTerminatedString(pl_op.payload); |
| 3988 | const ptr_ty = self.air.typeOf(pl_op.operand); | |
| 3987 | 3989 | |
| 3988 | 3990 | const di_local_var = dib.createAutoVariable( |
| 3989 | 3991 | self.di_scope.?, |
| 3990 | 3992 | name.ptr, |
| 3991 | 3993 | self.di_file.?, |
| 3992 | 3994 | self.prev_dbg_line, |
| 3993 | try self.dg.lowerDebugType(self.air.typeOf(pl_op.operand)), | |
| 3995 | try self.dg.lowerDebugType(ptr_ty.childType()), | |
| 3994 | 3996 | true, // always preserve |
| 3995 | 3997 | 0, // flags |
| 3996 | 3998 | ); |
src/type.zig+4-5| ... | ... | @@ -2573,15 +2573,14 @@ pub const Type = extern union { |
| 2573 | 2573 | .array_u8_sentinel_0 => self.castTag(.array_u8_sentinel_0).?.data + 1, |
| 2574 | 2574 | .array, .vector => { |
| 2575 | 2575 | const payload = self.cast(Payload.Array).?.data; |
| 2576 | const elem_size = @maximum(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target)); | |
| 2576 | const elem_size = payload.elem_type.abiSize(target); | |
| 2577 | assert(elem_size >= payload.elem_type.abiAlignment(target)); | |
| 2577 | 2578 | return payload.len * elem_size; |
| 2578 | 2579 | }, |
| 2579 | 2580 | .array_sentinel => { |
| 2580 | 2581 | const payload = self.castTag(.array_sentinel).?.data; |
| 2581 | const elem_size = std.math.max( | |
| 2582 | payload.elem_type.abiAlignment(target), | |
| 2583 | payload.elem_type.abiSize(target), | |
| 2584 | ); | |
| 2582 | const elem_size = payload.elem_type.abiSize(target); | |
| 2583 | assert(elem_size >= payload.elem_type.abiAlignment(target)); | |
| 2585 | 2584 | return (payload.len + 1) * elem_size; |
| 2586 | 2585 | }, |
| 2587 | 2586 | .i16, .u16 => return 2, |
src/value.zig+2-17| ... | ... | @@ -3931,15 +3931,12 @@ pub const Value = extern union { |
| 3931 | 3931 | }, |
| 3932 | 3932 | 80 => { |
| 3933 | 3933 | if (true) { |
| 3934 | @panic("TODO implement compiler_rt fabs for f80"); | |
| 3934 | @panic("TODO implement compiler_rt fabs for f80 (__fabsx)"); | |
| 3935 | 3935 | } |
| 3936 | 3936 | const f = val.toFloat(f80); |
| 3937 | 3937 | return Value.Tag.float_80.create(arena, @fabs(f)); |
| 3938 | 3938 | }, |
| 3939 | 3939 | 128 => { |
| 3940 | if (true) { | |
| 3941 | @panic("TODO implement compiler_rt fabs for f128"); | |
| 3942 | } | |
| 3943 | 3940 | const f = val.toFloat(f128); |
| 3944 | 3941 | return Value.Tag.float_128.create(arena, @fabs(f)); |
| 3945 | 3942 | }, |
| ... | ... | @@ -3963,15 +3960,12 @@ pub const Value = extern union { |
| 3963 | 3960 | }, |
| 3964 | 3961 | 80 => { |
| 3965 | 3962 | if (true) { |
| 3966 | @panic("TODO implement compiler_rt floor for f80"); | |
| 3963 | @panic("TODO implement compiler_rt floor for f80 (__floorx)"); | |
| 3967 | 3964 | } |
| 3968 | 3965 | const f = val.toFloat(f80); |
| 3969 | 3966 | return Value.Tag.float_80.create(arena, @floor(f)); |
| 3970 | 3967 | }, |
| 3971 | 3968 | 128 => { |
| 3972 | if (true) { | |
| 3973 | @panic("TODO implement compiler_rt floor for f128"); | |
| 3974 | } | |
| 3975 | 3969 | const f = val.toFloat(f128); |
| 3976 | 3970 | return Value.Tag.float_128.create(arena, @floor(f)); |
| 3977 | 3971 | }, |
| ... | ... | @@ -4001,9 +3995,6 @@ pub const Value = extern union { |
| 4001 | 3995 | return Value.Tag.float_80.create(arena, @ceil(f)); |
| 4002 | 3996 | }, |
| 4003 | 3997 | 128 => { |
| 4004 | if (true) { | |
| 4005 | @panic("TODO implement compiler_rt ceil for f128"); | |
| 4006 | } | |
| 4007 | 3998 | const f = val.toFloat(f128); |
| 4008 | 3999 | return Value.Tag.float_128.create(arena, @ceil(f)); |
| 4009 | 4000 | }, |
| ... | ... | @@ -4033,9 +4024,6 @@ pub const Value = extern union { |
| 4033 | 4024 | return Value.Tag.float_80.create(arena, @round(f)); |
| 4034 | 4025 | }, |
| 4035 | 4026 | 128 => { |
| 4036 | if (true) { | |
| 4037 | @panic("TODO implement compiler_rt round for f128"); | |
| 4038 | } | |
| 4039 | 4027 | const f = val.toFloat(f128); |
| 4040 | 4028 | return Value.Tag.float_128.create(arena, @round(f)); |
| 4041 | 4029 | }, |
| ... | ... | @@ -4065,9 +4053,6 @@ pub const Value = extern union { |
| 4065 | 4053 | return Value.Tag.float_80.create(arena, @trunc(f)); |
| 4066 | 4054 | }, |
| 4067 | 4055 | 128 => { |
| 4068 | if (true) { | |
| 4069 | @panic("TODO implement compiler_rt trunc for f128"); | |
| 4070 | } | |
| 4071 | 4056 | const f = val.toFloat(f128); |
| 4072 | 4057 | return Value.Tag.float_128.create(arena, @trunc(f)); |
| 4073 | 4058 | }, |
test/behavior/cast.zig+22-3| ... | ... | @@ -95,8 +95,29 @@ test "comptime_int @intToFloat" { |
| 95 | 95 | } |
| 96 | 96 | } |
| 97 | 97 | |
| 98 | test "@intToFloat" { | |
| 99 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 100 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 101 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 102 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 103 | ||
| 104 | const S = struct { | |
| 105 | fn doTheTest() !void { | |
| 106 | try testIntToFloat(-2); | |
| 107 | } | |
| 108 | ||
| 109 | fn testIntToFloat(k: i32) !void { | |
| 110 | const f = @intToFloat(f32, k); | |
| 111 | const i = @floatToInt(i32, f); | |
| 112 | try expect(i == k); | |
| 113 | } | |
| 114 | }; | |
| 115 | try S.doTheTest(); | |
| 116 | comptime try S.doTheTest(); | |
| 117 | } | |
| 118 | ||
| 98 | 119 | test "@floatToInt" { |
| 99 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 120 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 100 | 121 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 101 | 122 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 102 | 123 | |
| ... | ... | @@ -1007,8 +1028,6 @@ test "peer type resolve array pointer and unknown pointer" { |
| 1007 | 1028 | } |
| 1008 | 1029 | |
| 1009 | 1030 | test "comptime float casts" { |
| 1010 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 1011 | ||
| 1012 | 1031 | const a = @intToFloat(comptime_float, 1); |
| 1013 | 1032 | try expect(a == 1); |
| 1014 | 1033 | try expect(@TypeOf(a) == comptime_float); |
test/behavior/floatop.zig+124-21| ... | ... | @@ -333,7 +333,6 @@ fn testLog() !void { |
| 333 | 333 | } |
| 334 | 334 | |
| 335 | 335 | test "@log with vectors" { |
| 336 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO | |
| 337 | 336 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 338 | 337 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 339 | 338 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -343,15 +342,19 @@ test "@log with vectors" { |
| 343 | 342 | { |
| 344 | 343 | var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; |
| 345 | 344 | var result = @log(v); |
| 346 | try expect(math.approxEqAbs(f32, @log(@as(f32, 1.1)), result[0], epsilon)); | |
| 347 | try expect(math.approxEqAbs(f32, @log(@as(f32, 2.2)), result[1], epsilon)); | |
| 345 | try expect(@log(@as(f32, 1.1)) == result[0]); | |
| 346 | try expect(@log(@as(f32, 2.2)) == result[1]); | |
| 348 | 347 | try expect(@log(@as(f32, 0.3)) == result[2]); |
| 349 | try expect(math.approxEqAbs(f32, @log(@as(f32, 0.4)), result[3], epsilon)); | |
| 348 | try expect(@log(@as(f32, 0.4)) == result[3]); | |
| 350 | 349 | } |
| 351 | 350 | } |
| 352 | 351 | |
| 353 | 352 | test "@log2" { |
| 354 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 353 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 354 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 355 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 356 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 357 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 355 | 358 | |
| 356 | 359 | comptime try testLog2(); |
| 357 | 360 | try testLog2(); |
| ... | ... | @@ -368,15 +371,19 @@ fn testLog2() !void { |
| 368 | 371 | { |
| 369 | 372 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; |
| 370 | 373 | var result = @log2(v); |
| 371 | try expect(math.approxEqAbs(f32, @log2(@as(f32, 1.1)), result[0], epsilon)); | |
| 372 | try expect(math.approxEqAbs(f32, @log2(@as(f32, 2.2)), result[1], epsilon)); | |
| 373 | try expect(math.approxEqAbs(f32, @log2(@as(f32, 0.3)), result[2], epsilon)); | |
| 374 | try expect(math.approxEqAbs(f32, @log2(@as(f32, 0.4)), result[3], epsilon)); | |
| 374 | try expect(@log2(@as(f32, 1.1)) == result[0]); | |
| 375 | try expect(@log2(@as(f32, 2.2)) == result[1]); | |
| 376 | try expect(@log2(@as(f32, 0.3)) == result[2]); | |
| 377 | try expect(@log2(@as(f32, 0.4)) == result[3]); | |
| 375 | 378 | } |
| 376 | 379 | } |
| 377 | 380 | |
| 378 | 381 | test "@log10" { |
| 379 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 382 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 383 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 384 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 385 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 386 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 380 | 387 | |
| 381 | 388 | comptime try testLog10(); |
| 382 | 389 | try testLog10(); |
| ... | ... | @@ -393,10 +400,10 @@ fn testLog10() !void { |
| 393 | 400 | { |
| 394 | 401 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; |
| 395 | 402 | var result = @log10(v); |
| 396 | try expect(math.approxEqAbs(f32, @log10(@as(f32, 1.1)), result[0], epsilon)); | |
| 397 | try expect(math.approxEqAbs(f32, @log10(@as(f32, 2.2)), result[1], epsilon)); | |
| 398 | try expect(math.approxEqAbs(f32, @log10(@as(f32, 0.3)), result[2], epsilon)); | |
| 399 | try expect(math.approxEqAbs(f32, @log10(@as(f32, 0.4)), result[3], epsilon)); | |
| 403 | try expect(@log10(@as(f32, 1.1)) == result[0]); | |
| 404 | try expect(@log10(@as(f32, 2.2)) == result[1]); | |
| 405 | try expect(@log10(@as(f32, 0.3)) == result[2]); | |
| 406 | try expect(@log10(@as(f32, 0.4)) == result[3]); | |
| 400 | 407 | } |
| 401 | 408 | } |
| 402 | 409 | |
| ... | ... | @@ -537,7 +544,71 @@ fn testTrunc() !void { |
| 537 | 544 | } |
| 538 | 545 | } |
| 539 | 546 | |
| 540 | test "negation" { | |
| 547 | test "negation f16" { | |
| 548 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 549 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 550 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 551 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 552 | ||
| 553 | if (builtin.os.tag == .freebsd) { | |
| 554 | // TODO file issue to track this failure | |
| 555 | return error.SkipZigTest; | |
| 556 | } | |
| 557 | ||
| 558 | const S = struct { | |
| 559 | fn doTheTest() !void { | |
| 560 | var a: f16 = 1; | |
| 561 | a = -a; | |
| 562 | try expect(a == -1); | |
| 563 | a = -a; | |
| 564 | try expect(a == 1); | |
| 565 | } | |
| 566 | }; | |
| 567 | ||
| 568 | try S.doTheTest(); | |
| 569 | comptime try S.doTheTest(); | |
| 570 | } | |
| 571 | ||
| 572 | test "negation f32" { | |
| 573 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 574 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 575 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 576 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 577 | ||
| 578 | const S = struct { | |
| 579 | fn doTheTest() !void { | |
| 580 | var a: f32 = 1; | |
| 581 | a = -a; | |
| 582 | try expect(a == -1); | |
| 583 | a = -a; | |
| 584 | try expect(a == 1); | |
| 585 | } | |
| 586 | }; | |
| 587 | ||
| 588 | try S.doTheTest(); | |
| 589 | comptime try S.doTheTest(); | |
| 590 | } | |
| 591 | ||
| 592 | test "negation f64" { | |
| 593 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 594 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 595 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 596 | ||
| 597 | const S = struct { | |
| 598 | fn doTheTest() !void { | |
| 599 | var a: f64 = 1; | |
| 600 | a = -a; | |
| 601 | try expect(a == -1); | |
| 602 | a = -a; | |
| 603 | try expect(a == 1); | |
| 604 | } | |
| 605 | }; | |
| 606 | ||
| 607 | try S.doTheTest(); | |
| 608 | comptime try S.doTheTest(); | |
| 609 | } | |
| 610 | ||
| 611 | test "negation f80" { | |
| 541 | 612 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO |
| 542 | 613 | |
| 543 | 614 | if (builtin.os.tag == .freebsd) { |
| ... | ... | @@ -547,11 +618,37 @@ test "negation" { |
| 547 | 618 | |
| 548 | 619 | const S = struct { |
| 549 | 620 | fn doTheTest() !void { |
| 550 | inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| { | |
| 551 | var a: T = 1; | |
| 552 | a = -a; | |
| 553 | try expect(a == -1); | |
| 554 | } | |
| 621 | var a: f80 = 1; | |
| 622 | a = -a; | |
| 623 | try expect(a == -1); | |
| 624 | a = -a; | |
| 625 | try expect(a == 1); | |
| 626 | } | |
| 627 | }; | |
| 628 | ||
| 629 | try S.doTheTest(); | |
| 630 | comptime try S.doTheTest(); | |
| 631 | } | |
| 632 | ||
| 633 | test "negation f128" { | |
| 634 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 635 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 636 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 637 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 638 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 639 | ||
| 640 | if (builtin.os.tag == .freebsd) { | |
| 641 | // TODO file issue to track this failure | |
| 642 | return error.SkipZigTest; | |
| 643 | } | |
| 644 | ||
| 645 | const S = struct { | |
| 646 | fn doTheTest() !void { | |
| 647 | var a: f128 = 1; | |
| 648 | a = -a; | |
| 649 | try expect(a == -1); | |
| 650 | a = -a; | |
| 651 | try expect(a == 1); | |
| 555 | 652 | } |
| 556 | 653 | }; |
| 557 | 654 | |
| ... | ... | @@ -583,7 +680,13 @@ test "float literal at compile time not lossy" { |
| 583 | 680 | } |
| 584 | 681 | |
| 585 | 682 | test "f128 at compile time is lossy" { |
| 586 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 683 | if (builtin.zig_backend != .stage1) { | |
| 684 | // this one is happening because we represent comptime-known f128 integers with | |
| 685 | // Value.Tag.bigint and only convert to f128 representation if it stops being an | |
| 686 | // integer. Is this something we want? need to have a lang spec discussion on this | |
| 687 | // topic. | |
| 688 | return error.SkipZigTest; // TODO | |
| 689 | } | |
| 587 | 690 | |
| 588 | 691 | try expect(@as(f128, 10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0); |
| 589 | 692 | } |
test/behavior/math.zig+126-43| ... | ... | @@ -6,7 +6,6 @@ const expectEqualSlices = std.testing.expectEqualSlices; |
| 6 | 6 | const maxInt = std.math.maxInt; |
| 7 | 7 | const minInt = std.math.minInt; |
| 8 | 8 | const mem = std.mem; |
| 9 | const has_f80_rt = builtin.cpu.arch == .x86_64; | |
| 10 | 9 | |
| 11 | 10 | test "assignment operators" { |
| 12 | 11 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -1046,12 +1045,14 @@ fn testSqrt(comptime T: type, x: T) !void { |
| 1046 | 1045 | } |
| 1047 | 1046 | |
| 1048 | 1047 | test "@fabs" { |
| 1049 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 1048 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 1049 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 1050 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 1051 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 1052 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 1050 | 1053 | |
| 1051 | 1054 | try testFabs(f128, 12.0); |
| 1052 | 1055 | comptime try testFabs(f128, 12.0); |
| 1053 | if (has_f80_rt) try testFabs(f80, 12.0); | |
| 1054 | // comptime try testFabs(f80, 12.0); | |
| 1055 | 1056 | try testFabs(f64, 12.0); |
| 1056 | 1057 | comptime try testFabs(f64, 12.0); |
| 1057 | 1058 | try testFabs(f32, 12.0); |
| ... | ... | @@ -1065,20 +1066,25 @@ test "@fabs" { |
| 1065 | 1066 | comptime try expectEqual(x, z); |
| 1066 | 1067 | } |
| 1067 | 1068 | |
| 1069 | test "@fabs f80" { | |
| 1070 | if (true) { | |
| 1071 | // https://github.com/ziglang/zig/issues/11030 | |
| 1072 | return error.SkipZigTest; | |
| 1073 | } | |
| 1074 | ||
| 1075 | try testFabs(f80, 12.0); | |
| 1076 | comptime try testFabs(f80, 12.0); | |
| 1077 | } | |
| 1078 | ||
| 1068 | 1079 | fn testFabs(comptime T: type, x: T) !void { |
| 1069 | 1080 | const y = -x; |
| 1070 | 1081 | const z = @fabs(y); |
| 1071 | try expectEqual(x, z); | |
| 1082 | try expect(x == z); | |
| 1072 | 1083 | } |
| 1073 | 1084 | |
| 1074 | 1085 | test "@floor" { |
| 1075 | 1086 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO |
| 1076 | 1087 | |
| 1077 | // FIXME: Generates a floorl function call | |
| 1078 | // testFloor(f128, 12.0); | |
| 1079 | comptime try testFloor(f128, 12.0); | |
| 1080 | // try testFloor(f80, 12.0); | |
| 1081 | comptime try testFloor(f80, 12.0); | |
| 1082 | 1088 | try testFloor(f64, 12.0); |
| 1083 | 1089 | comptime try testFloor(f64, 12.0); |
| 1084 | 1090 | try testFloor(f32, 12.0); |
| ... | ... | @@ -1089,23 +1095,39 @@ test "@floor" { |
| 1089 | 1095 | const x = 14.0; |
| 1090 | 1096 | const y = x + 0.7; |
| 1091 | 1097 | const z = @floor(y); |
| 1092 | comptime try expectEqual(x, z); | |
| 1098 | comptime try expect(x == z); | |
| 1099 | } | |
| 1100 | ||
| 1101 | test "@floor f80" { | |
| 1102 | if (true) { | |
| 1103 | // https://github.com/ziglang/zig/issues/11030 | |
| 1104 | return error.SkipZigTest; | |
| 1105 | } | |
| 1106 | try testFloor(f80, 12.0); | |
| 1107 | comptime try testFloor(f80, 12.0); | |
| 1108 | } | |
| 1109 | ||
| 1110 | test "@floor f128" { | |
| 1111 | if (builtin.zig_backend == .stage1) { | |
| 1112 | // Fails because it incorrectly lowers to a floorl function call. | |
| 1113 | return error.SkipZigTest; | |
| 1114 | } | |
| 1115 | ||
| 1116 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 1117 | ||
| 1118 | testFloor(f128, 12.0); | |
| 1119 | comptime try testFloor(f128, 12.0); | |
| 1093 | 1120 | } |
| 1094 | 1121 | |
| 1095 | 1122 | fn testFloor(comptime T: type, x: T) !void { |
| 1096 | 1123 | const y = x + 0.6; |
| 1097 | 1124 | const z = @floor(y); |
| 1098 | try expectEqual(x, z); | |
| 1125 | try expect(x == z); | |
| 1099 | 1126 | } |
| 1100 | 1127 | |
| 1101 | 1128 | test "@ceil" { |
| 1102 | 1129 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO |
| 1103 | 1130 | |
| 1104 | // FIXME: Generates a ceill function call | |
| 1105 | //testCeil(f128, 12.0); | |
| 1106 | comptime try testCeil(f128, 12.0); | |
| 1107 | // try testCeil(f80, 12.0); | |
| 1108 | comptime try testCeil(f80, 12.0); | |
| 1109 | 1131 | try testCeil(f64, 12.0); |
| 1110 | 1132 | comptime try testCeil(f64, 12.0); |
| 1111 | 1133 | try testCeil(f32, 12.0); |
| ... | ... | @@ -1116,29 +1138,40 @@ test "@ceil" { |
| 1116 | 1138 | const x = 14.0; |
| 1117 | 1139 | const y = x - 0.7; |
| 1118 | 1140 | const z = @ceil(y); |
| 1119 | comptime try expectEqual(x, z); | |
| 1141 | comptime try expect(x == z); | |
| 1142 | } | |
| 1143 | ||
| 1144 | test "@ceil f80" { | |
| 1145 | if (true) { | |
| 1146 | // https://github.com/ziglang/zig/issues/11030 | |
| 1147 | return error.SkipZigTest; | |
| 1148 | } | |
| 1149 | ||
| 1150 | try testCeil(f80, 12.0); | |
| 1151 | comptime try testCeil(f80, 12.0); | |
| 1152 | } | |
| 1153 | ||
| 1154 | test "@ceil f128" { | |
| 1155 | if (builtin.zig_backend == .stage1) { | |
| 1156 | // Fails because it incorrectly lowers to a ceill function call. | |
| 1157 | return error.SkipZigTest; | |
| 1158 | } | |
| 1159 | ||
| 1160 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 1161 | ||
| 1162 | testCeil(f128, 12.0); | |
| 1163 | comptime try testCeil(f128, 12.0); | |
| 1120 | 1164 | } |
| 1121 | 1165 | |
| 1122 | 1166 | fn testCeil(comptime T: type, x: T) !void { |
| 1123 | 1167 | const y = x - 0.8; |
| 1124 | 1168 | const z = @ceil(y); |
| 1125 | try expectEqual(x, z); | |
| 1169 | try expect(x == z); | |
| 1126 | 1170 | } |
| 1127 | 1171 | |
| 1128 | 1172 | test "@trunc" { |
| 1129 | 1173 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO |
| 1130 | 1174 | |
| 1131 | // FIXME: Generates a truncl function call | |
| 1132 | //testTrunc(f128, 12.0); | |
| 1133 | comptime try testTrunc(f128, 12.0); | |
| 1134 | // try testTrunc(f80, 12.0); | |
| 1135 | // comptime try testTrunc(f80, 12.0); | |
| 1136 | comptime { | |
| 1137 | const x: f80 = 12.0; | |
| 1138 | const y = x + 0.8; | |
| 1139 | const z = @trunc(y); | |
| 1140 | try expectEqual(x, z); | |
| 1141 | } | |
| 1142 | 1175 | try testTrunc(f64, 12.0); |
| 1143 | 1176 | comptime try testTrunc(f64, 12.0); |
| 1144 | 1177 | try testTrunc(f32, 12.0); |
| ... | ... | @@ -1149,31 +1182,54 @@ test "@trunc" { |
| 1149 | 1182 | const x = 14.0; |
| 1150 | 1183 | const y = x + 0.7; |
| 1151 | 1184 | const z = @trunc(y); |
| 1152 | comptime try expectEqual(x, z); | |
| 1185 | comptime try expect(x == z); | |
| 1186 | } | |
| 1187 | ||
| 1188 | test "@trunc f80" { | |
| 1189 | if (true) { | |
| 1190 | // https://github.com/ziglang/zig/issues/11030 | |
| 1191 | return error.SkipZigTest; | |
| 1192 | } | |
| 1193 | ||
| 1194 | try testTrunc(f80, 12.0); | |
| 1195 | comptime try testTrunc(f80, 12.0); | |
| 1196 | comptime { | |
| 1197 | const x: f80 = 12.0; | |
| 1198 | const y = x + 0.8; | |
| 1199 | const z = @trunc(y); | |
| 1200 | try expect(x == z); | |
| 1201 | } | |
| 1202 | } | |
| 1203 | ||
| 1204 | test "@trunc f128" { | |
| 1205 | if (builtin.zig_backend == .stage1) { | |
| 1206 | // Fails because it incorrectly lowers to a truncl function call. | |
| 1207 | return error.SkipZigTest; | |
| 1208 | } | |
| 1209 | ||
| 1210 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 1211 | ||
| 1212 | testTrunc(f128, 12.0); | |
| 1213 | comptime try testTrunc(f128, 12.0); | |
| 1153 | 1214 | } |
| 1154 | 1215 | |
| 1155 | 1216 | fn testTrunc(comptime T: type, x: T) !void { |
| 1156 | 1217 | { |
| 1157 | 1218 | const y = x + 0.8; |
| 1158 | 1219 | const z = @trunc(y); |
| 1159 | try expectEqual(x, z); | |
| 1220 | try expect(x == z); | |
| 1160 | 1221 | } |
| 1161 | 1222 | |
| 1162 | 1223 | { |
| 1163 | 1224 | const y = -x - 0.8; |
| 1164 | 1225 | const z = @trunc(y); |
| 1165 | try expectEqual(-x, z); | |
| 1226 | try expect(-x == z); | |
| 1166 | 1227 | } |
| 1167 | 1228 | } |
| 1168 | 1229 | |
| 1169 | 1230 | test "@round" { |
| 1170 | 1231 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO |
| 1171 | 1232 | |
| 1172 | // FIXME: Generates a roundl function call | |
| 1173 | //testRound(f128, 12.0); | |
| 1174 | comptime try testRound(f128, 12.0); | |
| 1175 | // try testRound(f80, 12.0); | |
| 1176 | comptime try testRound(f80, 12.0); | |
| 1177 | 1233 | try testRound(f64, 12.0); |
| 1178 | 1234 | comptime try testRound(f64, 12.0); |
| 1179 | 1235 | try testRound(f32, 12.0); |
| ... | ... | @@ -1184,13 +1240,35 @@ test "@round" { |
| 1184 | 1240 | const x = 14.0; |
| 1185 | 1241 | const y = x + 0.4; |
| 1186 | 1242 | const z = @round(y); |
| 1187 | comptime try expectEqual(x, z); | |
| 1243 | comptime try expect(x == z); | |
| 1244 | } | |
| 1245 | ||
| 1246 | test "@round f80" { | |
| 1247 | if (true) { | |
| 1248 | // https://github.com/ziglang/zig/issues/11030 | |
| 1249 | return error.SkipZigTest; | |
| 1250 | } | |
| 1251 | ||
| 1252 | try testRound(f80, 12.0); | |
| 1253 | comptime try testRound(f80, 12.0); | |
| 1254 | } | |
| 1255 | ||
| 1256 | test "@round f128" { | |
| 1257 | if (builtin.zig_backend == .stage1) { | |
| 1258 | // Fails because it incorrectly lowers to a roundl function call. | |
| 1259 | return error.SkipZigTest; | |
| 1260 | } | |
| 1261 | ||
| 1262 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 1263 | ||
| 1264 | testRound(f128, 12.0); | |
| 1265 | comptime try testRound(f128, 12.0); | |
| 1188 | 1266 | } |
| 1189 | 1267 | |
| 1190 | 1268 | fn testRound(comptime T: type, x: T) !void { |
| 1191 | 1269 | const y = x - 0.5; |
| 1192 | 1270 | const z = @round(y); |
| 1193 | try expectEqual(x, z); | |
| 1271 | try expect(x == z); | |
| 1194 | 1272 | } |
| 1195 | 1273 | |
| 1196 | 1274 | test "vector integer addition" { |
| ... | ... | @@ -1225,10 +1303,15 @@ test "NaN comparison" { |
| 1225 | 1303 | comptime try testNanEqNan(f32); |
| 1226 | 1304 | comptime try testNanEqNan(f64); |
| 1227 | 1305 | comptime try testNanEqNan(f128); |
| 1306 | } | |
| 1228 | 1307 | |
| 1229 | // TODO https://github.com/ziglang/zig/issues/11030 | |
| 1230 | // try testNanEqNan(f80); | |
| 1231 | // comptime try testNanEqNan(f80); | |
| 1308 | test "NaN comparison f80" { | |
| 1309 | if (true) { | |
| 1310 | // https://github.com/ziglang/zig/issues/11030 | |
| 1311 | return error.SkipZigTest; | |
| 1312 | } | |
| 1313 | try testNanEqNan(f80); | |
| 1314 | comptime try testNanEqNan(f80); | |
| 1232 | 1315 | } |
| 1233 | 1316 | |
| 1234 | 1317 | fn testNanEqNan(comptime F: type) !void { |
test/cases.zig+2-1| ... | ... | @@ -16,5 +16,6 @@ pub fn addCases(ctx: *TestContext) !void { |
| 16 | 16 | try @import("stage2/riscv64.zig").addCases(ctx); |
| 17 | 17 | try @import("stage2/plan9.zig").addCases(ctx); |
| 18 | 18 | try @import("stage2/x86_64.zig").addCases(ctx); |
| 19 | try @import("stage2/nvptx.zig").addCases(ctx); | |
| 19 | // https://github.com/ziglang/zig/issues/10968 | |
| 20 | //try @import("stage2/nvptx.zig").addCases(ctx); | |
| 20 | 21 | } |