authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-02 16:10:41-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-01-02 16:10:41-05:00
loga90fa45ae146a72e2d54842eed15c4b50062eff1
tree7845fbd8a52ca2f7c6ddf9e157affd9d01c2191a
parentfe21d84c94e16db56cf6f87040a02213615873a4
parent213ff939f18f147b5d9dd164d52ebdd660dab7b4
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #4027 from ziglang/fix-float-ops

fix float ops with respect to vectors

10 files changed, 501 insertions(+), 281 deletions(-)

doc/langref.html.in+82-30
...@@ -8076,94 +8076,146 @@ test "vector @splat" {...@@ -8076,94 +8076,146 @@ test "vector @splat" {
8076 {#header_close#}8076 {#header_close#}
80778077
8078 {#header_open|@sqrt#}8078 {#header_open|@sqrt#}
8079 <pre>{#syntax#}@sqrt(comptime T: type, value: T) T{#endsyntax#}</pre>8079 <pre>{#syntax#}@sqrt(value: var) @TypeOf(value){#endsyntax#}</pre>
8080 <p>8080 <p>
8081 Performs the square root of a floating point number. Uses a dedicated hardware instruction8081 Performs the square root of a floating point number. Uses a dedicated hardware instruction
8082 when available. Supports {#syntax#}f16{#endsyntax#}, {#syntax#}f32{#endsyntax#}, {#syntax#}f64{#endsyntax#}, and {#syntax#}f128{#endsyntax#}, as well as vectors.8082 when available.
8083 </p>
8084 <p>
8085 Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
8086 <a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
8083 </p>8087 </p>
8084 {#header_close#}8088 {#header_close#}
8085 {#header_open|@sin#}8089 {#header_open|@sin#}
8086 <pre>{#syntax#}@sin(comptime T: type, value: T) T{#endsyntax#}</pre>8090 <pre>{#syntax#}@sin(value: var) @TypeOf(value){#endsyntax#}</pre>
8087 <p>8091 <p>
8088 Sine trigometric function on a floating point number. Uses a dedicated hardware instruction8092 Sine trigometric function on a floating point number. Uses a dedicated hardware instruction
8089 when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.8093 when available.
8094 </p>
8095 <p>
8096 Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
8097 <a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
8090 </p>8098 </p>
8091 {#header_close#}8099 {#header_close#}
8092 {#header_open|@cos#}8100 {#header_open|@cos#}
8093 <pre>{#syntax#}@cos(comptime T: type, value: T) T{#endsyntax#}</pre>8101 <pre>{#syntax#}@cos(value: var) @TypeOf(value){#endsyntax#}</pre>
8094 <p>8102 <p>
8095 Cosine trigometric function on a floating point number. Uses a dedicated hardware instruction8103 Cosine trigometric function on a floating point number. Uses a dedicated hardware instruction
8096 when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.8104 when available.
8105 </p>
8106 <p>
8107 Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
8108 <a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
8097 </p>8109 </p>
8098 {#header_close#}8110 {#header_close#}
8099 {#header_open|@exp#}8111 {#header_open|@exp#}
8100 <pre>{#syntax#}@exp(comptime T: type, value: T) T{#endsyntax#}</pre>8112 <pre>{#syntax#}@exp(value: var) @TypeOf(value){#endsyntax#}</pre>
8101 <p>8113 <p>
8102 Base-e exponential function on a floating point number. Uses a dedicated hardware instruction8114 Base-e exponential function on a floating point number. Uses a dedicated hardware instruction
8103 when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.8115 when available.
8116 </p>
8117 <p>
8118 Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
8119 <a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
8104 </p>8120 </p>
8105 {#header_close#}8121 {#header_close#}
8106 {#header_open|@exp2#}8122 {#header_open|@exp2#}
8107 <pre>{#syntax#}@exp2(comptime T: type, value: T) T{#endsyntax#}</pre>8123 <pre>{#syntax#}@exp2(value: var) @TypeOf(value){#endsyntax#}</pre>
8108 <p>8124 <p>
8109 Base-2 exponential function on a floating point number. Uses a dedicated hardware instruction8125 Base-2 exponential function on a floating point number. Uses a dedicated hardware instruction
8110 when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.8126 when available.
8127 </p>
8128 <p>
8129 Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
8130 <a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
8111 </p>8131 </p>
8112 {#header_close#}8132 {#header_close#}
8113 {#header_open|@ln#}8133 {#header_open|@log#}
8114 <pre>{#syntax#}@ln(comptime T: type, value: T) T{#endsyntax#}</pre>8134 <pre>{#syntax#}@log(value: var) @TypeOf(value){#endsyntax#}</pre>
8115 <p>8135 <p>
8116 Returns the natural logarithm of a floating point number. Uses a dedicated hardware instruction8136 Returns the natural logarithm of a floating point number. Uses a dedicated hardware instruction
8117 when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.8137 when available.
8138 </p>
8139 <p>
8140 Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
8141 <a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
8118 </p>8142 </p>
8119 {#header_close#}8143 {#header_close#}
8120 {#header_open|@log2#}8144 {#header_open|@log2#}
8121 <pre>{#syntax#}@log2(comptime T: type, value: T) T{#endsyntax#}</pre>8145 <pre>{#syntax#}@log2(value: var) @TypeOf(value){#endsyntax#}</pre>
8122 <p>8146 <p>
8123 Returns the logarithm to the base 2 of a floating point number. Uses a dedicated hardware instruction8147 Returns the logarithm to the base 2 of a floating point number. Uses a dedicated hardware instruction
8124 when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.8148 when available.
8149 </p>
8150 <p>
8151 Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
8152 <a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
8125 </p>8153 </p>
8126 {#header_close#}8154 {#header_close#}
8127 {#header_open|@log10#}8155 {#header_open|@log10#}
8128 <pre>{#syntax#}@log10(comptime T: type, value: T) T{#endsyntax#}</pre>8156 <pre>{#syntax#}@log10(value: var) @TypeOf(value){#endsyntax#}</pre>
8129 <p>8157 <p>
8130 Returns the logarithm to the base 10 of a floating point number. Uses a dedicated hardware instruction8158 Returns the logarithm to the base 10 of a floating point number. Uses a dedicated hardware instruction
8131 when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.8159 when available.
8160 </p>
8161 <p>
8162 Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
8163 <a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
8132 </p>8164 </p>
8133 {#header_close#}8165 {#header_close#}
8134 {#header_open|@fabs#}8166 {#header_open|@fabs#}
8135 <pre>{#syntax#}@fabs(comptime T: type, value: T) T{#endsyntax#}</pre>8167 <pre>{#syntax#}@fabs(value: var) @TypeOf(value){#endsyntax#}</pre>
8136 <p>8168 <p>
8137 Returns the absolute value of a floating point number. Uses a dedicated hardware instruction8169 Returns the absolute value of a floating point number. Uses a dedicated hardware instruction
8138 when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.8170 when available.
8171 </p>
8172 <p>
8173 Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
8174 <a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
8139 </p>8175 </p>
8140 {#header_close#}8176 {#header_close#}
8141 {#header_open|@floor#}8177 {#header_open|@floor#}
8142 <pre>{#syntax#}@floor(comptime T: type, value: T) T{#endsyntax#}</pre>8178 <pre>{#syntax#}@floor(value: var) @TypeOf(value){#endsyntax#}</pre>
8179 <p>
8180 Returns the largest integral value not greater than the given floating point number.
8181 Uses a dedicated hardware instruction when available.
8182 </p>
8143 <p>8183 <p>
8144 Returns the largest integral value not greater than the given floating point number. Uses a dedicated hardware instruction8184 Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
8145 when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.8185 <a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
8146 </p>8186 </p>
8147 {#header_close#}8187 {#header_close#}
8148 {#header_open|@ceil#}8188 {#header_open|@ceil#}
8149 <pre>{#syntax#}@ceil(comptime T: type, value: T) T{#endsyntax#}</pre>8189 <pre>{#syntax#}@ceil(value: var) @TypeOf(value){#endsyntax#}</pre>
8150 <p>8190 <p>
8151 Returns the largest integral value not less than the given floating point number. Uses a dedicated hardware instruction8191 Returns the largest integral value not less than the given floating point number.
8152 when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.8192 Uses a dedicated hardware instruction when available.
8193 </p>
8194 <p>
8195 Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
8196 <a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
8153 </p>8197 </p>
8154 {#header_close#}8198 {#header_close#}
8155 {#header_open|@trunc#}8199 {#header_open|@trunc#}
8156 <pre>{#syntax#}@trunc(comptime T: type, value: T) T{#endsyntax#}</pre>8200 <pre>{#syntax#}@trunc(value: var) @TypeOf(value){#endsyntax#}</pre>
8201 <p>
8202 Rounds the given floating point number to an integer, towards zero.
8203 Uses a dedicated hardware instruction when available.
8204 </p>
8157 <p>8205 <p>
8158 Rounds the given floating point number to an integer, towards zero. Uses a dedicated hardware instruction8206 Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
8159 when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.8207 <a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
8160 </p>8208 </p>
8161 {#header_close#}8209 {#header_close#}
8162 {#header_open|@round#}8210 {#header_open|@round#}
8163 <pre>{#syntax#}@round(comptime T: type, value: T) T{#endsyntax#}</pre>8211 <pre>{#syntax#}@round(value: var) @TypeOf(value){#endsyntax#}</pre>
8164 <p>8212 <p>
8165 Rounds the given floating point number to an integer, away from zero. Uses a dedicated hardware instruction8213 Rounds the given floating point number to an integer, away from zero. Uses a dedicated hardware instruction
8166 when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.8214 when available.
8215 </p>
8216 <p>
8217 Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
8218 <a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
8167 </p>8219 </p>
8168 {#header_close#}8220 {#header_close#}
81698221
lib/std/math/sqrt.zig+15-78
...@@ -12,12 +12,12 @@ const maxInt = std.math.maxInt;...@@ -12,12 +12,12 @@ const maxInt = std.math.maxInt;
12/// - sqrt(+-0) = +-012/// - sqrt(+-0) = +-0
13/// - sqrt(x) = nan if x < 013/// - sqrt(x) = nan if x < 0
14/// - sqrt(nan) = nan14/// - sqrt(nan) = nan
15pub fn sqrt(x: var) (if (@typeId(@TypeOf(x)) == TypeId.Int) @IntType(false, @TypeOf(x).bit_count / 2) else @TypeOf(x)) {15/// TODO Decide if all this logic should be implemented directly in the @sqrt bultin function.
16pub fn sqrt(x: var) Sqrt(@TypeOf(x)) {
16 const T = @TypeOf(x);17 const T = @TypeOf(x);
17 switch (@typeId(T)) {18 switch (@typeInfo(T)) {
18 TypeId.ComptimeFloat => return @as(T, @sqrt(f64, x)), // TODO upgrade to f12819 .Float, .ComptimeFloat => return @sqrt(x),
19 TypeId.Float => return @sqrt(T, x),20 .ComptimeInt => comptime {
20 TypeId.ComptimeInt => comptime {
21 if (x > maxInt(u128)) {21 if (x > maxInt(u128)) {
22 @compileError("sqrt not implemented for comptime_int greater than 128 bits");22 @compileError("sqrt not implemented for comptime_int greater than 128 bits");
23 }23 }
...@@ -26,83 +26,11 @@ pub fn sqrt(x: var) (if (@typeId(@TypeOf(x)) == TypeId.Int) @IntType(false, @Typ...@@ -26,83 +26,11 @@ pub fn sqrt(x: var) (if (@typeId(@TypeOf(x)) == TypeId.Int) @IntType(false, @Typ
26 }26 }
27 return @as(T, sqrt_int(u128, x));27 return @as(T, sqrt_int(u128, x));
28 },28 },
29 TypeId.Int => return sqrt_int(T, x),29 .Int => return sqrt_int(T, x),
30 else => @compileError("sqrt not implemented for " ++ @typeName(T)),30 else => @compileError("sqrt not implemented for " ++ @typeName(T)),
31 }31 }
32}32}
3333
34test "math.sqrt" {
35 expect(sqrt(@as(f16, 0.0)) == @sqrt(f16, 0.0));
36 expect(sqrt(@as(f32, 0.0)) == @sqrt(f32, 0.0));
37 expect(sqrt(@as(f64, 0.0)) == @sqrt(f64, 0.0));
38}
39
40test "math.sqrt16" {
41 const epsilon = 0.000001;
42
43 expect(@sqrt(f16, 0.0) == 0.0);
44 expect(math.approxEq(f16, @sqrt(f16, 2.0), 1.414214, epsilon));
45 expect(math.approxEq(f16, @sqrt(f16, 3.6), 1.897367, epsilon));
46 expect(@sqrt(f16, 4.0) == 2.0);
47 expect(math.approxEq(f16, @sqrt(f16, 7.539840), 2.745877, epsilon));
48 expect(math.approxEq(f16, @sqrt(f16, 19.230934), 4.385309, epsilon));
49 expect(@sqrt(f16, 64.0) == 8.0);
50 expect(math.approxEq(f16, @sqrt(f16, 64.1), 8.006248, epsilon));
51 expect(math.approxEq(f16, @sqrt(f16, 8942.230469), 94.563370, epsilon));
52}
53
54test "math.sqrt32" {
55 const epsilon = 0.000001;
56
57 expect(@sqrt(f32, 0.0) == 0.0);
58 expect(math.approxEq(f32, @sqrt(f32, 2.0), 1.414214, epsilon));
59 expect(math.approxEq(f32, @sqrt(f32, 3.6), 1.897367, epsilon));
60 expect(@sqrt(f32, 4.0) == 2.0);
61 expect(math.approxEq(f32, @sqrt(f32, 7.539840), 2.745877, epsilon));
62 expect(math.approxEq(f32, @sqrt(f32, 19.230934), 4.385309, epsilon));
63 expect(@sqrt(f32, 64.0) == 8.0);
64 expect(math.approxEq(f32, @sqrt(f32, 64.1), 8.006248, epsilon));
65 expect(math.approxEq(f32, @sqrt(f32, 8942.230469), 94.563370, epsilon));
66}
67
68test "math.sqrt64" {
69 const epsilon = 0.000001;
70
71 expect(@sqrt(f64, 0.0) == 0.0);
72 expect(math.approxEq(f64, @sqrt(f64, 2.0), 1.414214, epsilon));
73 expect(math.approxEq(f64, @sqrt(f64, 3.6), 1.897367, epsilon));
74 expect(@sqrt(f64, 4.0) == 2.0);
75 expect(math.approxEq(f64, @sqrt(f64, 7.539840), 2.745877, epsilon));
76 expect(math.approxEq(f64, @sqrt(f64, 19.230934), 4.385309, epsilon));
77 expect(@sqrt(f64, 64.0) == 8.0);
78 expect(math.approxEq(f64, @sqrt(f64, 64.1), 8.006248, epsilon));
79 expect(math.approxEq(f64, @sqrt(f64, 8942.230469), 94.563367, epsilon));
80}
81
82test "math.sqrt16.special" {
83 expect(math.isPositiveInf(@sqrt(f16, math.inf(f16))));
84 expect(@sqrt(f16, 0.0) == 0.0);
85 expect(@sqrt(f16, -0.0) == -0.0);
86 expect(math.isNan(@sqrt(f16, -1.0)));
87 expect(math.isNan(@sqrt(f16, math.nan(f16))));
88}
89
90test "math.sqrt32.special" {
91 expect(math.isPositiveInf(@sqrt(f32, math.inf(f32))));
92 expect(@sqrt(f32, 0.0) == 0.0);
93 expect(@sqrt(f32, -0.0) == -0.0);
94 expect(math.isNan(@sqrt(f32, -1.0)));
95 expect(math.isNan(@sqrt(f32, math.nan(f32))));
96}
97
98test "math.sqrt64.special" {
99 expect(math.isPositiveInf(@sqrt(f64, math.inf(f64))));
100 expect(@sqrt(f64, 0.0) == 0.0);
101 expect(@sqrt(f64, -0.0) == -0.0);
102 expect(math.isNan(@sqrt(f64, -1.0)));
103 expect(math.isNan(@sqrt(f64, math.nan(f64))));
104}
105
106fn sqrt_int(comptime T: type, value: T) @IntType(false, T.bit_count / 2) {34fn sqrt_int(comptime T: type, value: T) @IntType(false, T.bit_count / 2) {
107 var op = value;35 var op = value;
108 var res: T = 0;36 var res: T = 0;
...@@ -134,3 +62,12 @@ test "math.sqrt_int" {...@@ -134,3 +62,12 @@ test "math.sqrt_int" {
134 expect(sqrt_int(u32, 9) == 3);62 expect(sqrt_int(u32, 9) == 3);
135 expect(sqrt_int(u32, 10) == 3);63 expect(sqrt_int(u32, 10) == 3);
136}64}
65
66/// Returns the return type `sqrt` will return given an operand of type `T`.
67pub fn Sqrt(comptime T: type) type {
68 return switch (@typeInfo(T)) {
69 .Int => |int| @IntType(false, int.bits / 2),
70 else => T,
71 };
72}
73
lib/std/special/c.zig+46
...@@ -728,6 +728,29 @@ export fn sqrt(x: f64) f64 {...@@ -728,6 +728,29 @@ export fn sqrt(x: f64) f64 {
728 return @bitCast(f64, uz);728 return @bitCast(f64, uz);
729}729}
730730
731test "sqrt" {
732 const epsilon = 0.000001;
733
734 std.testing.expect(sqrt(0.0) == 0.0);
735 std.testing.expect(std.math.approxEq(f64, sqrt(2.0), 1.414214, epsilon));
736 std.testing.expect(std.math.approxEq(f64, sqrt(3.6), 1.897367, epsilon));
737 std.testing.expect(sqrt(4.0) == 2.0);
738 std.testing.expect(std.math.approxEq(f64, sqrt(7.539840), 2.745877, epsilon));
739 std.testing.expect(std.math.approxEq(f64, sqrt(19.230934), 4.385309, epsilon));
740 std.testing.expect(sqrt(64.0) == 8.0);
741 std.testing.expect(std.math.approxEq(f64, sqrt(64.1), 8.006248, epsilon));
742 std.testing.expect(std.math.approxEq(f64, sqrt(8942.230469), 94.563367, epsilon));
743}
744
745test "sqrt special" {
746 std.testing.expect(std.math.isPositiveInf(sqrt(std.math.inf(f64))));
747 std.testing.expect(sqrt(0.0) == 0.0);
748 std.testing.expect(sqrt(-0.0) == -0.0);
749 std.testing.expect(std.math.isNan(sqrt(-1.0)));
750 std.testing.expect(std.math.isNan(sqrt(std.math.nan(f64))));
751}
752
753
731export fn sqrtf(x: f32) f32 {754export fn sqrtf(x: f32) f32 {
732 const tiny: f32 = 1.0e-30;755 const tiny: f32 = 1.0e-30;
733 const sign: i32 = @bitCast(i32, @as(u32, 0x80000000));756 const sign: i32 = @bitCast(i32, @as(u32, 0x80000000));
...@@ -803,3 +826,26 @@ export fn sqrtf(x: f32) f32 {...@@ -803,3 +826,26 @@ export fn sqrtf(x: f32) f32 {
803 ix += m << 23;826 ix += m << 23;
804 return @bitCast(f32, ix);827 return @bitCast(f32, ix);
805}828}
829
830test "sqrtf" {
831 const epsilon = 0.000001;
832
833 std.testing.expect(sqrtf(0.0) == 0.0);
834 std.testing.expect(std.math.approxEq(f32, sqrtf(2.0), 1.414214, epsilon));
835 std.testing.expect(std.math.approxEq(f32, sqrtf(3.6), 1.897367, epsilon));
836 std.testing.expect(sqrtf(4.0) == 2.0);
837 std.testing.expect(std.math.approxEq(f32, sqrtf(7.539840), 2.745877, epsilon));
838 std.testing.expect(std.math.approxEq(f32, sqrtf(19.230934), 4.385309, epsilon));
839 std.testing.expect(sqrtf(64.0) == 8.0);
840 std.testing.expect(std.math.approxEq(f32, sqrtf(64.1), 8.006248, epsilon));
841 std.testing.expect(std.math.approxEq(f32, sqrtf(8942.230469), 94.563370, epsilon));
842}
843
844test "sqrtf special" {
845 std.testing.expect(std.math.isPositiveInf(sqrtf(std.math.inf(f32))));
846 std.testing.expect(sqrtf(0.0) == 0.0);
847 std.testing.expect(sqrtf(-0.0) == -0.0);
848 std.testing.expect(std.math.isNan(sqrtf(-1.0)));
849 std.testing.expect(std.math.isNan(sqrtf(std.math.nan(f32))));
850}
851
src/all_types.hpp+3-4
...@@ -1680,7 +1680,7 @@ enum BuiltinFnId {...@@ -1680,7 +1680,7 @@ enum BuiltinFnId {
1680 BuiltinFnIdCos,1680 BuiltinFnIdCos,
1681 BuiltinFnIdExp,1681 BuiltinFnIdExp,
1682 BuiltinFnIdExp2,1682 BuiltinFnIdExp2,
1683 BuiltinFnIdLn,1683 BuiltinFnIdLog,
1684 BuiltinFnIdLog2,1684 BuiltinFnIdLog2,
1685 BuiltinFnIdLog10,1685 BuiltinFnIdLog10,
1686 BuiltinFnIdFabs,1686 BuiltinFnIdFabs,
...@@ -3840,9 +3840,8 @@ struct IrInstructionAddImplicitReturnType {...@@ -3840,9 +3840,8 @@ struct IrInstructionAddImplicitReturnType {
3840struct IrInstructionFloatOp {3840struct IrInstructionFloatOp {
3841 IrInstruction base;3841 IrInstruction base;
38423842
3843 BuiltinFnId op;3843 BuiltinFnId fn_id;
3844 IrInstruction *type;3844 IrInstruction *operand;
3845 IrInstruction *op1;
3846};3845};
38473846
3848struct IrInstructionCheckRuntimeScope {3847struct IrInstructionCheckRuntimeScope {
src/codegen.cpp+18-19
...@@ -764,7 +764,7 @@ static LLVMValueRef get_float_fn(CodeGen *g, ZigType *type_entry, ZigLLVMFnId fn...@@ -764,7 +764,7 @@ static LLVMValueRef get_float_fn(CodeGen *g, ZigType *type_entry, ZigLLVMFnId fn
764 name = "fma";764 name = "fma";
765 num_args = 3;765 num_args = 3;
766 } else if (fn_id == ZigLLVMFnIdFloatOp) {766 } else if (fn_id == ZigLLVMFnIdFloatOp) {
767 name = float_op_to_name(op, true);767 name = float_op_to_name(op);
768 num_args = 1;768 num_args = 1;
769 } else {769 } else {
770 zig_unreachable();770 zig_unreachable();
...@@ -5785,10 +5785,9 @@ static LLVMValueRef ir_render_atomic_store(CodeGen *g, IrExecutable *executable,...@@ -5785,10 +5785,9 @@ static LLVMValueRef ir_render_atomic_store(CodeGen *g, IrExecutable *executable,
5785}5785}
57865786
5787static LLVMValueRef ir_render_float_op(CodeGen *g, IrExecutable *executable, IrInstructionFloatOp *instruction) {5787static LLVMValueRef ir_render_float_op(CodeGen *g, IrExecutable *executable, IrInstructionFloatOp *instruction) {
5788 LLVMValueRef op = ir_llvm_value(g, instruction->op1);5788 LLVMValueRef operand = ir_llvm_value(g, instruction->operand);
5789 assert(instruction->base.value->type->id == ZigTypeIdFloat);5789 LLVMValueRef fn_val = get_float_fn(g, instruction->base.value->type, ZigLLVMFnIdFloatOp, instruction->fn_id);
5790 LLVMValueRef fn_val = get_float_fn(g, instruction->base.value->type, ZigLLVMFnIdFloatOp, instruction->op);5790 return LLVMBuildCall(g->builder, fn_val, &operand, 1, "");
5791 return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
5792}5791}
57935792
5794static LLVMValueRef ir_render_mul_add(CodeGen *g, IrExecutable *executable, IrInstructionMulAdd *instruction) {5793static LLVMValueRef ir_render_mul_add(CodeGen *g, IrExecutable *executable, IrInstructionMulAdd *instruction) {
...@@ -8201,20 +8200,20 @@ static void define_builtin_fns(CodeGen *g) {...@@ -8201,20 +8200,20 @@ static void define_builtin_fns(CodeGen *g) {
8201 create_builtin_fn(g, BuiltinFnIdDivFloor, "divFloor", 2);8200 create_builtin_fn(g, BuiltinFnIdDivFloor, "divFloor", 2);
8202 create_builtin_fn(g, BuiltinFnIdRem, "rem", 2);8201 create_builtin_fn(g, BuiltinFnIdRem, "rem", 2);
8203 create_builtin_fn(g, BuiltinFnIdMod, "mod", 2);8202 create_builtin_fn(g, BuiltinFnIdMod, "mod", 2);
8204 create_builtin_fn(g, BuiltinFnIdSqrt, "sqrt", 2);8203 create_builtin_fn(g, BuiltinFnIdSqrt, "sqrt", 1);
8205 create_builtin_fn(g, BuiltinFnIdSin, "sin", 2);8204 create_builtin_fn(g, BuiltinFnIdSin, "sin", 1);
8206 create_builtin_fn(g, BuiltinFnIdCos, "cos", 2);8205 create_builtin_fn(g, BuiltinFnIdCos, "cos", 1);
8207 create_builtin_fn(g, BuiltinFnIdExp, "exp", 2);8206 create_builtin_fn(g, BuiltinFnIdExp, "exp", 1);
8208 create_builtin_fn(g, BuiltinFnIdExp2, "exp2", 2);8207 create_builtin_fn(g, BuiltinFnIdExp2, "exp2", 1);
8209 create_builtin_fn(g, BuiltinFnIdLn, "ln", 2);8208 create_builtin_fn(g, BuiltinFnIdLog, "log", 1);
8210 create_builtin_fn(g, BuiltinFnIdLog2, "log2", 2);8209 create_builtin_fn(g, BuiltinFnIdLog2, "log2", 1);
8211 create_builtin_fn(g, BuiltinFnIdLog10, "log10", 2);8210 create_builtin_fn(g, BuiltinFnIdLog10, "log10", 1);
8212 create_builtin_fn(g, BuiltinFnIdFabs, "fabs", 2);8211 create_builtin_fn(g, BuiltinFnIdFabs, "fabs", 1);
8213 create_builtin_fn(g, BuiltinFnIdFloor, "floor", 2);8212 create_builtin_fn(g, BuiltinFnIdFloor, "floor", 1);
8214 create_builtin_fn(g, BuiltinFnIdCeil, "ceil", 2);8213 create_builtin_fn(g, BuiltinFnIdCeil, "ceil", 1);
8215 create_builtin_fn(g, BuiltinFnIdTrunc, "trunc", 2);8214 create_builtin_fn(g, BuiltinFnIdTrunc, "trunc", 1);
8216 create_builtin_fn(g, BuiltinFnIdNearbyInt, "nearbyInt", 2);8215 create_builtin_fn(g, BuiltinFnIdNearbyInt, "nearbyInt", 1);
8217 create_builtin_fn(g, BuiltinFnIdRound, "round", 2);8216 create_builtin_fn(g, BuiltinFnIdRound, "round", 1);
8218 create_builtin_fn(g, BuiltinFnIdMulAdd, "mulAdd", 4);8217 create_builtin_fn(g, BuiltinFnIdMulAdd, "mulAdd", 4);
8219 create_builtin_fn(g, BuiltinFnIdNewStackCall, "newStackCall", SIZE_MAX);8218 create_builtin_fn(g, BuiltinFnIdNewStackCall, "newStackCall", SIZE_MAX);
8220 create_builtin_fn(g, BuiltinFnIdAsyncCall, "asyncCall", SIZE_MAX);8219 create_builtin_fn(g, BuiltinFnIdAsyncCall, "asyncCall", SIZE_MAX);
src/ir.cpp+99-85
...@@ -3125,9 +3125,7 @@ static IrInstruction *ir_build_overflow_op(IrBuilder *irb, Scope *scope, AstNode...@@ -3125,9 +3125,7 @@ static IrInstruction *ir_build_overflow_op(IrBuilder *irb, Scope *scope, AstNode
3125//TODO Powi, Pow, minnum, maxnum, maximum, minimum, copysign,3125//TODO Powi, Pow, minnum, maxnum, maximum, minimum, copysign,
3126// lround, llround, lrint, llrint3126// lround, llround, lrint, llrint
3127// So far this is only non-complicated type functions.3127// So far this is only non-complicated type functions.
3128const char *float_op_to_name(BuiltinFnId op, bool llvm_name) {3128const char *float_op_to_name(BuiltinFnId op) {
3129 const bool b = llvm_name;
3130
3131 switch (op) {3129 switch (op) {
3132 case BuiltinFnIdSqrt:3130 case BuiltinFnIdSqrt:
3133 return "sqrt";3131 return "sqrt";
...@@ -3139,8 +3137,8 @@ const char *float_op_to_name(BuiltinFnId op, bool llvm_name) {...@@ -3139,8 +3137,8 @@ const char *float_op_to_name(BuiltinFnId op, bool llvm_name) {
3139 return "exp";3137 return "exp";
3140 case BuiltinFnIdExp2:3138 case BuiltinFnIdExp2:
3141 return "exp2";3139 return "exp2";
3142 case BuiltinFnIdLn:3140 case BuiltinFnIdLog:
3143 return b ? "log" : "ln";3141 return "log";
3144 case BuiltinFnIdLog10:3142 case BuiltinFnIdLog10:
3145 return "log10";3143 return "log10";
3146 case BuiltinFnIdLog2:3144 case BuiltinFnIdLog2:
...@@ -3154,7 +3152,7 @@ const char *float_op_to_name(BuiltinFnId op, bool llvm_name) {...@@ -3154,7 +3152,7 @@ const char *float_op_to_name(BuiltinFnId op, bool llvm_name) {
3154 case BuiltinFnIdTrunc:3152 case BuiltinFnIdTrunc:
3155 return "trunc";3153 return "trunc";
3156 case BuiltinFnIdNearbyInt:3154 case BuiltinFnIdNearbyInt:
3157 return b ? "nearbyint" : "nearbyInt";3155 return "nearbyint";
3158 case BuiltinFnIdRound:3156 case BuiltinFnIdRound:
3159 return "round";3157 return "round";
3160 default:3158 default:
...@@ -3162,14 +3160,14 @@ const char *float_op_to_name(BuiltinFnId op, bool llvm_name) {...@@ -3162,14 +3160,14 @@ const char *float_op_to_name(BuiltinFnId op, bool llvm_name) {
3162 }3160 }
3163}3161}
31643162
3165static IrInstruction *ir_build_float_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op1, BuiltinFnId op) {3163static IrInstruction *ir_build_float_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *operand,
3164 BuiltinFnId fn_id)
3165{
3166 IrInstructionFloatOp *instruction = ir_build_instruction<IrInstructionFloatOp>(irb, scope, source_node);3166 IrInstructionFloatOp *instruction = ir_build_instruction<IrInstructionFloatOp>(irb, scope, source_node);
3167 instruction->type = type;3167 instruction->operand = operand;
3168 instruction->op1 = op1;3168 instruction->fn_id = fn_id;
3169 instruction->op = op;
31703169
3171 if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block);3170 ir_ref_instruction(operand, irb->current_basic_block);
3172 ir_ref_instruction(op1, irb->current_basic_block);
31733171
3174 return &instruction->base;3172 return &instruction->base;
3175}3173}
...@@ -5497,7 +5495,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -5497,7 +5495,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
5497 case BuiltinFnIdCos:5495 case BuiltinFnIdCos:
5498 case BuiltinFnIdExp:5496 case BuiltinFnIdExp:
5499 case BuiltinFnIdExp2:5497 case BuiltinFnIdExp2:
5500 case BuiltinFnIdLn:5498 case BuiltinFnIdLog:
5501 case BuiltinFnIdLog2:5499 case BuiltinFnIdLog2:
5502 case BuiltinFnIdLog10:5500 case BuiltinFnIdLog10:
5503 case BuiltinFnIdFabs:5501 case BuiltinFnIdFabs:
...@@ -5512,13 +5510,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -5512,13 +5510,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
5512 if (arg0_value == irb->codegen->invalid_instruction)5510 if (arg0_value == irb->codegen->invalid_instruction)
5513 return arg0_value;5511 return arg0_value;
55145512
5515 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);5513 IrInstruction *inst = ir_build_float_op(irb, scope, node, arg0_value, builtin_fn->id);
5516 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);5514 return ir_lval_wrap(irb, scope, inst, lval, result_loc);
5517 if (arg1_value == irb->codegen->invalid_instruction)
5518 return arg1_value;
5519
5520 IrInstruction *ir_sqrt = ir_build_float_op(irb, scope, node, arg0_value, arg1_value, builtin_fn->id);
5521 return ir_lval_wrap(irb, scope, ir_sqrt, lval, result_loc);
5522 }5515 }
5523 case BuiltinFnIdTruncate:5516 case BuiltinFnIdTruncate:
5524 {5517 {
...@@ -27643,7 +27636,7 @@ static IrInstruction *ir_analyze_instruction_save_err_ret_addr(IrAnalyze *ira, I...@@ -27643,7 +27636,7 @@ static IrInstruction *ir_analyze_instruction_save_err_ret_addr(IrAnalyze *ira, I
27643 return result;27636 return result;
27644}27637}
2764527638
27646static void ir_eval_float_op(IrAnalyze *ira, IrInstruction *source_instr, BuiltinFnId fop, ZigType *float_type,27639static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, IrInstruction *source_instr, BuiltinFnId fop, ZigType *float_type,
27647 ZigValue *op, ZigValue *out_val)27640 ZigValue *op, ZigValue *out_val)
27648{27641{
27649 assert(ira && source_instr && float_type && out_val && op);27642 assert(ira && source_instr && float_type && out_val && op);
...@@ -27670,24 +27663,49 @@ static void ir_eval_float_op(IrAnalyze *ira, IrInstruction *source_instr, Builti...@@ -27670,24 +27663,49 @@ static void ir_eval_float_op(IrAnalyze *ira, IrInstruction *source_instr, Builti
27670 out_val->data.x_f16 = f16_sqrt(op->data.x_f16);27663 out_val->data.x_f16 = f16_sqrt(op->data.x_f16);
27671 break;27664 break;
27672 case BuiltinFnIdSin:27665 case BuiltinFnIdSin:
27666 out_val->data.x_f16 = zig_double_to_f16(sin(zig_f16_to_double(op->data.x_f16)));
27667 break;
27673 case BuiltinFnIdCos:27668 case BuiltinFnIdCos:
27669 out_val->data.x_f16 = zig_double_to_f16(cos(zig_f16_to_double(op->data.x_f16)));
27670 break;
27674 case BuiltinFnIdExp:27671 case BuiltinFnIdExp:
27672 out_val->data.x_f16 = zig_double_to_f16(exp(zig_f16_to_double(op->data.x_f16)));
27673 break;
27675 case BuiltinFnIdExp2:27674 case BuiltinFnIdExp2:
27676 case BuiltinFnIdLn:27675 out_val->data.x_f16 = zig_double_to_f16(exp2(zig_f16_to_double(op->data.x_f16)));
27676 break;
27677 case BuiltinFnIdLog:
27678 out_val->data.x_f16 = zig_double_to_f16(log(zig_f16_to_double(op->data.x_f16)));
27679 break;
27677 case BuiltinFnIdLog10:27680 case BuiltinFnIdLog10:
27681 out_val->data.x_f16 = zig_double_to_f16(log10(zig_f16_to_double(op->data.x_f16)));
27682 break;
27678 case BuiltinFnIdLog2:27683 case BuiltinFnIdLog2:
27684 out_val->data.x_f16 = zig_double_to_f16(log2(zig_f16_to_double(op->data.x_f16)));
27685 break;
27679 case BuiltinFnIdFabs:27686 case BuiltinFnIdFabs:
27687 out_val->data.x_f16 = zig_double_to_f16(fabs(zig_f16_to_double(op->data.x_f16)));
27688 break;
27680 case BuiltinFnIdFloor:27689 case BuiltinFnIdFloor:
27690 out_val->data.x_f16 = zig_double_to_f16(floor(zig_f16_to_double(op->data.x_f16)));
27691 break;
27681 case BuiltinFnIdCeil:27692 case BuiltinFnIdCeil:
27693 out_val->data.x_f16 = zig_double_to_f16(ceil(zig_f16_to_double(op->data.x_f16)));
27694 break;
27682 case BuiltinFnIdTrunc:27695 case BuiltinFnIdTrunc:
27696 out_val->data.x_f16 = zig_double_to_f16(trunc(zig_f16_to_double(op->data.x_f16)));
27697 break;
27683 case BuiltinFnIdNearbyInt:27698 case BuiltinFnIdNearbyInt:
27699 out_val->data.x_f16 = zig_double_to_f16(nearbyint(zig_f16_to_double(op->data.x_f16)));
27700 break;
27684 case BuiltinFnIdRound:27701 case BuiltinFnIdRound:
27685 zig_panic("unimplemented f16 builtin");27702 out_val->data.x_f16 = zig_double_to_f16(round(zig_f16_to_double(op->data.x_f16)));
27703 break;
27686 default:27704 default:
27687 zig_unreachable();27705 zig_unreachable();
27688 };27706 };
27689 break;27707 break;
27690 };27708 }
27691 case 32: {27709 case 32: {
27692 switch (fop) {27710 switch (fop) {
27693 case BuiltinFnIdSqrt:27711 case BuiltinFnIdSqrt:
...@@ -27705,7 +27723,7 @@ static void ir_eval_float_op(IrAnalyze *ira, IrInstruction *source_instr, Builti...@@ -27705,7 +27723,7 @@ static void ir_eval_float_op(IrAnalyze *ira, IrInstruction *source_instr, Builti
27705 case BuiltinFnIdExp2:27723 case BuiltinFnIdExp2:
27706 out_val->data.x_f32 = exp2f(op->data.x_f32);27724 out_val->data.x_f32 = exp2f(op->data.x_f32);
27707 break;27725 break;
27708 case BuiltinFnIdLn:27726 case BuiltinFnIdLog:
27709 out_val->data.x_f32 = logf(op->data.x_f32);27727 out_val->data.x_f32 = logf(op->data.x_f32);
27710 break;27728 break;
27711 case BuiltinFnIdLog10:27729 case BuiltinFnIdLog10:
...@@ -27736,7 +27754,7 @@ static void ir_eval_float_op(IrAnalyze *ira, IrInstruction *source_instr, Builti...@@ -27736,7 +27754,7 @@ static void ir_eval_float_op(IrAnalyze *ira, IrInstruction *source_instr, Builti
27736 zig_unreachable();27754 zig_unreachable();
27737 };27755 };
27738 break;27756 break;
27739 };27757 }
27740 case 64: {27758 case 64: {
27741 switch (fop) {27759 switch (fop) {
27742 case BuiltinFnIdSqrt:27760 case BuiltinFnIdSqrt:
...@@ -27754,7 +27772,7 @@ static void ir_eval_float_op(IrAnalyze *ira, IrInstruction *source_instr, Builti...@@ -27754,7 +27772,7 @@ static void ir_eval_float_op(IrAnalyze *ira, IrInstruction *source_instr, Builti
27754 case BuiltinFnIdExp2:27772 case BuiltinFnIdExp2:
27755 out_val->data.x_f64 = exp2(op->data.x_f64);27773 out_val->data.x_f64 = exp2(op->data.x_f64);
27756 break;27774 break;
27757 case BuiltinFnIdLn:27775 case BuiltinFnIdLog:
27758 out_val->data.x_f64 = log(op->data.x_f64);27776 out_val->data.x_f64 = log(op->data.x_f64);
27759 break;27777 break;
27760 case BuiltinFnIdLog10:27778 case BuiltinFnIdLog10:
...@@ -27785,7 +27803,11 @@ static void ir_eval_float_op(IrAnalyze *ira, IrInstruction *source_instr, Builti...@@ -27785,7 +27803,11 @@ static void ir_eval_float_op(IrAnalyze *ira, IrInstruction *source_instr, Builti
27785 zig_unreachable();27803 zig_unreachable();
27786 }27804 }
27787 break;27805 break;
27788 };27806 }
27807 case 80:
27808 return ir_add_error(ira, source_instr,
27809 buf_sprintf("compiler bug: TODO: implement '%s' for type '%s'. See https://github.com/ziglang/zig/issues/4026",
27810 float_op_to_name(fop), buf_ptr(&float_type->name)));
27789 case 128: {27811 case 128: {
27790 float128_t *out, *in;27812 float128_t *out, *in;
27791 if (float_type->id == ZigTypeIdComptimeFloat) {27813 if (float_type->id == ZigTypeIdComptimeFloat) {
...@@ -27804,7 +27826,7 @@ static void ir_eval_float_op(IrAnalyze *ira, IrInstruction *source_instr, Builti...@@ -27804,7 +27826,7 @@ static void ir_eval_float_op(IrAnalyze *ira, IrInstruction *source_instr, Builti
27804 case BuiltinFnIdCos:27826 case BuiltinFnIdCos:
27805 case BuiltinFnIdExp:27827 case BuiltinFnIdExp:
27806 case BuiltinFnIdExp2:27828 case BuiltinFnIdExp2:
27807 case BuiltinFnIdLn:27829 case BuiltinFnIdLog:
27808 case BuiltinFnIdLog10:27830 case BuiltinFnIdLog10:
27809 case BuiltinFnIdLog2:27831 case BuiltinFnIdLog2:
27810 case BuiltinFnIdFabs:27832 case BuiltinFnIdFabs:
...@@ -27812,94 +27834,86 @@ static void ir_eval_float_op(IrAnalyze *ira, IrInstruction *source_instr, Builti...@@ -27812,94 +27834,86 @@ static void ir_eval_float_op(IrAnalyze *ira, IrInstruction *source_instr, Builti
27812 case BuiltinFnIdCeil:27834 case BuiltinFnIdCeil:
27813 case BuiltinFnIdTrunc:27835 case BuiltinFnIdTrunc:
27814 case BuiltinFnIdRound:27836 case BuiltinFnIdRound:
27815 zig_panic("unimplemented f128 builtin");27837 return ir_add_error(ira, source_instr,
27838 buf_sprintf("compiler bug: TODO: implement '%s' for type '%s'. See https://github.com/ziglang/zig/issues/4026",
27839 float_op_to_name(fop), buf_ptr(&float_type->name)));
27816 default:27840 default:
27817 zig_unreachable();27841 zig_unreachable();
27818 }27842 }
27819 break;27843 break;
27820 };27844 }
27821 default:27845 default:
27822 zig_unreachable();27846 zig_unreachable();
27823 }27847 }
27848 out_val->special = ConstValSpecialStatic;
27849 return nullptr;
27824}27850}
2782527851
27826static IrInstruction *ir_analyze_float_op(IrAnalyze *ira, IrInstruction *source_instr,27852static IrInstruction *ir_analyze_instruction_float_op(IrAnalyze *ira, IrInstructionFloatOp *instruction) {
27827 ZigType *expr_type, AstNode *expr_type_src_node, IrInstruction *operand, BuiltinFnId op)27853 IrInstruction *operand = instruction->operand->child;
27828{27854 ZigType *operand_type = operand->value->type;
27829 // Only allow float types, and vectors of floats.27855 if (type_is_invalid(operand_type))
27830 ZigType *float_type = (expr_type->id == ZigTypeIdVector) ? expr_type->data.vector.elem_type : expr_type;
27831 if (float_type->id != ZigTypeIdFloat && float_type->id != ZigTypeIdComptimeFloat) {
27832 ir_add_error_node(ira, expr_type_src_node,
27833 buf_sprintf("@%s does not support type '%s'",
27834 float_op_to_name(op, false), buf_ptr(&float_type->name)));
27835 return ira->codegen->invalid_instruction;27856 return ira->codegen->invalid_instruction;
27836 }
2783727857
27838 IrInstruction *casted_op = ir_implicit_cast(ira, operand, float_type);27858 // This instruction accepts floats and vectors of floats.
27839 if (type_is_invalid(casted_op->value->type))27859 ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ?
27840 return ira->codegen->invalid_instruction;27860 operand_type->data.vector.elem_type : operand_type;
2784127861
27842 if (instr_is_comptime(casted_op)) {27862 if (scalar_type->id != ZigTypeIdFloat && scalar_type->id != ZigTypeIdComptimeFloat) {
27843 if ((float_type->id == ZigTypeIdComptimeFloat ||27863 ir_add_error(ira, operand,
27844 float_type->data.floating.bit_count == 16 ||27864 buf_sprintf("expected float type, found '%s'", buf_ptr(&scalar_type->name)));
27845 float_type->data.floating.bit_count == 128) &&27865 return ira->codegen->invalid_instruction;
27846 op != BuiltinFnIdSqrt)27866 }
27847 {
27848 ir_add_error(ira, source_instr,
27849 buf_sprintf("compiler bug: TODO make @%s support type '%s'",
27850 float_op_to_name(op, false), buf_ptr(&float_type->name)));
27851 return ira->codegen->invalid_instruction;
27852 }
2785327867
27854 ZigValue *op1_const = ir_resolve_const(ira, casted_op, UndefBad);27868 if (instr_is_comptime(operand)) {
27855 if (!op1_const)27869 ZigValue *operand_val = ir_resolve_const(ira, operand, UndefOk);
27870 if (operand_val == nullptr)
27856 return ira->codegen->invalid_instruction;27871 return ira->codegen->invalid_instruction;
27872 if (operand_val->special == ConstValSpecialUndef)
27873 return ir_const_undef(ira, &instruction->base, operand_type);
2785727874
27858 IrInstruction *result = ir_const(ira, source_instr, expr_type);27875 IrInstruction *result = ir_const(ira, &instruction->base, operand_type);
27859 ZigValue *out_val = result->value;27876 ZigValue *out_val = result->value;
2786027877
27861 if (expr_type->id == ZigTypeIdVector) {27878 if (operand_type->id == ZigTypeIdVector) {
27862 expand_undef_array(ira->codegen, op1_const);27879 expand_undef_array(ira->codegen, operand_val);
27863 out_val->special = ConstValSpecialUndef;27880 out_val->special = ConstValSpecialUndef;
27864 expand_undef_array(ira->codegen, out_val);27881 expand_undef_array(ira->codegen, out_val);
27865 size_t len = expr_type->data.vector.len;27882 size_t len = operand_type->data.vector.len;
27866 for (size_t i = 0; i < len; i += 1) {27883 for (size_t i = 0; i < len; i += 1) {
27867 ZigValue *float_operand_op1 = &op1_const->data.x_array.data.s_none.elements[i];27884 ZigValue *elem_operand = &operand_val->data.x_array.data.s_none.elements[i];
27868 ZigValue *float_out_val = &out_val->data.x_array.data.s_none.elements[i];27885 ZigValue *float_out_val = &out_val->data.x_array.data.s_none.elements[i];
27869 assert(float_operand_op1->type == float_type);27886 ir_assert(elem_operand->type == scalar_type, &instruction->base);
27870 assert(float_out_val->type == float_type);27887 ir_assert(float_out_val->type == scalar_type, &instruction->base);
27871 ir_eval_float_op(ira, source_instr, op, float_type, op1_const, float_out_val);27888 ErrorMsg *msg = ir_eval_float_op(ira, &instruction->base, instruction->fn_id, scalar_type,
27872 float_out_val->type = float_type;27889 elem_operand, float_out_val);
27890 if (msg != nullptr) {
27891 add_error_note(ira->codegen, msg, instruction->base.source_node,
27892 buf_sprintf("when computing vector element at index %" ZIG_PRI_usize, i));
27893 return ira->codegen->invalid_instruction;
27894 }
27895 float_out_val->type = scalar_type;
27873 }27896 }
27874 out_val->type = expr_type;27897 out_val->type = operand_type;
27875 out_val->special = ConstValSpecialStatic;27898 out_val->special = ConstValSpecialStatic;
27876 } else {27899 } else {
27877 ir_eval_float_op(ira, source_instr, op, float_type, op1_const, out_val);27900 if (ir_eval_float_op(ira, &instruction->base, instruction->fn_id, scalar_type,
27901 operand_val, out_val) != nullptr)
27902 {
27903 return ira->codegen->invalid_instruction;
27904 }
27878 }27905 }
27879 return result;27906 return result;
27880 }27907 }
2788127908
27882 ir_assert(float_type->id == ZigTypeIdFloat, source_instr);27909 ir_assert(scalar_type->id == ZigTypeIdFloat, &instruction->base);
2788327910
27884 IrInstruction *result = ir_build_float_op(&ira->new_irb, source_instr->scope,27911 IrInstruction *result = ir_build_float_op(&ira->new_irb, instruction->base.scope,
27885 source_instr->source_node, nullptr, casted_op, op);27912 instruction->base.source_node, operand, instruction->fn_id);
27886 result->value->type = expr_type;27913 result->value->type = operand_type;
27887 return result;27914 return result;
27888}27915}
2788927916
27890static IrInstruction *ir_analyze_instruction_float_op(IrAnalyze *ira, IrInstructionFloatOp *instruction) {
27891 ZigType *expr_type = ir_resolve_type(ira, instruction->type->child);
27892 if (type_is_invalid(expr_type))
27893 return ira->codegen->invalid_instruction;
27894
27895 IrInstruction *operand = instruction->op1->child;
27896 if (type_is_invalid(operand->value->type))
27897 return ira->codegen->invalid_instruction;
27898
27899 return ir_analyze_float_op(ira, &instruction->base, expr_type, instruction->type->source_node,
27900 operand, instruction->op);
27901}
27902
27903static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstructionBswap *instruction) {27917static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstructionBswap *instruction) {
27904 Error err;27918 Error err;
2790527919
src/ir.hpp+1-1
...@@ -33,7 +33,7 @@ bool ir_has_side_effects(IrInstruction *instruction);...@@ -33,7 +33,7 @@ bool ir_has_side_effects(IrInstruction *instruction);
33struct IrAnalyze;33struct IrAnalyze;
34ZigValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ZigValue *const_val,34ZigValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ZigValue *const_val,
35 AstNode *source_node);35 AstNode *source_node);
36const char *float_op_to_name(BuiltinFnId op, bool llvm_name);36const char *float_op_to_name(BuiltinFnId op);
3737
38// for debugging purposes38// for debugging purposes
39void dbg_ir_break(const char *src_file, uint32_t line);39void dbg_ir_break(const char *src_file, uint32_t line);
src/ir_print.cpp+2-9
...@@ -2005,15 +2005,8 @@ static void ir_print_add_implicit_return_type(IrPrint *irp, IrInstructionAddImpl...@@ -2005,15 +2005,8 @@ static void ir_print_add_implicit_return_type(IrPrint *irp, IrInstructionAddImpl
2005}2005}
20062006
2007static void ir_print_float_op(IrPrint *irp, IrInstructionFloatOp *instruction) {2007static void ir_print_float_op(IrPrint *irp, IrInstructionFloatOp *instruction) {
20082008 fprintf(irp->f, "@%s(", float_op_to_name(instruction->fn_id));
2009 fprintf(irp->f, "@%s(", float_op_to_name(instruction->op, false));2009 ir_print_other_instruction(irp, instruction->operand);
2010 if (instruction->type != nullptr) {
2011 ir_print_other_instruction(irp, instruction->type);
2012 } else {
2013 fprintf(irp->f, "null");
2014 }
2015 fprintf(irp->f, ",");
2016 ir_print_other_instruction(irp, instruction->op1);
2017 fprintf(irp->f, ")");2010 fprintf(irp->f, ")");
2018}2011}
20192012
test/stage1/behavior/floatop.zig+233-53
...@@ -1,6 +1,10 @@...@@ -1,6 +1,10 @@
1const expect = @import("std").testing.expect;1const std = @import("std");
2const pi = @import("std").math.pi;2const expect = std.testing.expect;
3const e = @import("std").math.e;3const math = std.math;
4const pi = std.math.pi;
5const e = std.math.e;
6
7const epsilon = 0.000001;
48
5test "@sqrt" {9test "@sqrt" {
6 comptime testSqrt();10 comptime testSqrt();
...@@ -10,25 +14,55 @@ test "@sqrt" {...@@ -10,25 +14,55 @@ test "@sqrt" {
10fn testSqrt() void {14fn testSqrt() void {
11 {15 {
12 var a: f16 = 4;16 var a: f16 = 4;
13 expect(@sqrt(f16, a) == 2);17 expect(@sqrt(a) == 2);
14 }18 }
15 {19 {
16 var a: f32 = 9;20 var a: f32 = 9;
17 expect(@sqrt(f32, a) == 3);21 expect(@sqrt(a) == 3);
22 var b: f32 = 1.1;
23 expect(math.approxEq(f32, @sqrt(b), 1.0488088481701516, epsilon));
18 }24 }
19 {25 {
20 var a: f64 = 25;26 var a: f64 = 25;
21 expect(@sqrt(f64, a) == 5);27 expect(@sqrt(a) == 5);
22 }28 }
23 {29 {
24 const a: comptime_float = 25.0;30 const a: comptime_float = 25.0;
25 expect(@sqrt(comptime_float, a) == 5.0);31 expect(@sqrt(a) == 5.0);
26 }32 }
27 // Waiting on a c.zig implementation33 // TODO https://github.com/ziglang/zig/issues/4026
28 //{34 //{
29 // var a: f128 = 49;35 // var a: f128 = 49;
30 // expect(@sqrt(f128, a) == 7);36 // expect(@sqrt(a) == 7);
31 //}37 //}
38 {
39 var v: @Vector(4, f32) = [_]f32{1.1, 2.2, 3.3, 4.4};
40 var result = @sqrt(v);
41 expect(math.approxEq(f32, @sqrt(@as(f32, 1.1)), result[0], epsilon));
42 expect(math.approxEq(f32, @sqrt(@as(f32, 2.2)), result[1], epsilon));
43 expect(math.approxEq(f32, @sqrt(@as(f32, 3.3)), result[2], epsilon));
44 expect(math.approxEq(f32, @sqrt(@as(f32, 4.4)), result[3], epsilon));
45 }
46}
47
48test "more @sqrt f16 tests" {
49 // TODO these are not all passing at comptime
50 expect(@sqrt(@as(f16, 0.0)) == 0.0);
51 expect(math.approxEq(f16, @sqrt(@as(f16, 2.0)), 1.414214, epsilon));
52 expect(math.approxEq(f16, @sqrt(@as(f16, 3.6)), 1.897367, epsilon));
53 expect(@sqrt(@as(f16, 4.0)) == 2.0);
54 expect(math.approxEq(f16, @sqrt(@as(f16, 7.539840)), 2.745877, epsilon));
55 expect(math.approxEq(f16, @sqrt(@as(f16, 19.230934)), 4.385309, epsilon));
56 expect(@sqrt(@as(f16, 64.0)) == 8.0);
57 expect(math.approxEq(f16, @sqrt(@as(f16, 64.1)), 8.006248, epsilon));
58 expect(math.approxEq(f16, @sqrt(@as(f16, 8942.230469)), 94.563370, epsilon));
59
60 // special cases
61 expect(math.isPositiveInf(@sqrt(@as(f16, math.inf(f16)))));
62 expect(@sqrt(@as(f16, 0.0)) == 0.0);
63 expect(@sqrt(@as(f16, -0.0)) == -0.0);
64 expect(math.isNan(@sqrt(@as(f16, -1.0))));
65 expect(math.isNan(@sqrt(@as(f16, math.nan(f16)))));
32}66}
3367
34test "@sin" {68test "@sin" {
...@@ -37,26 +71,28 @@ test "@sin" {...@@ -37,26 +71,28 @@ test "@sin" {
37}71}
3872
39fn testSin() void {73fn testSin() void {
40 // TODO - this is actually useful and should be implemented74 // TODO test f128, and c_longdouble
41 // (all the trig functions for f16)75 // https://github.com/ziglang/zig/issues/4026
42 // but will probably wait till self-hosted76 {
43 //{77 var a: f16 = 0;
44 // var a: f16 = pi;78 expect(@sin(a) == 0);
45 // expect(@sin(f16, a/2) == 1);79 }
46 //}
47 {80 {
48 var a: f32 = 0;81 var a: f32 = 0;
49 expect(@sin(f32, a) == 0);82 expect(@sin(a) == 0);
50 }83 }
51 {84 {
52 var a: f64 = 0;85 var a: f64 = 0;
53 expect(@sin(f64, a) == 0);86 expect(@sin(a) == 0);
87 }
88 {
89 var v: @Vector(4, f32) = [_]f32{1.1, 2.2, 3.3, 4.4};
90 var result = @sin(v);
91 expect(math.approxEq(f32, @sin(@as(f32, 1.1)), result[0], epsilon));
92 expect(math.approxEq(f32, @sin(@as(f32, 2.2)), result[1], epsilon));
93 expect(math.approxEq(f32, @sin(@as(f32, 3.3)), result[2], epsilon));
94 expect(math.approxEq(f32, @sin(@as(f32, 4.4)), result[3], epsilon));
54 }95 }
55 // TODO
56 //{
57 // var a: f16 = pi;
58 // expect(@sqrt(f128, a/2) == 1);
59 //}
60}96}
6197
62test "@cos" {98test "@cos" {
...@@ -65,13 +101,27 @@ test "@cos" {...@@ -65,13 +101,27 @@ test "@cos" {
65}101}
66102
67fn testCos() void {103fn testCos() void {
104 // TODO test f128, and c_longdouble
105 // https://github.com/ziglang/zig/issues/4026
106 {
107 var a: f16 = 0;
108 expect(@cos(a) == 1);
109 }
68 {110 {
69 var a: f32 = 0;111 var a: f32 = 0;
70 expect(@cos(f32, a) == 1);112 expect(@cos(a) == 1);
71 }113 }
72 {114 {
73 var a: f64 = 0;115 var a: f64 = 0;
74 expect(@cos(f64, a) == 1);116 expect(@cos(a) == 1);
117 }
118 {
119 var v: @Vector(4, f32) = [_]f32{1.1, 2.2, 3.3, 4.4};
120 var result = @cos(v);
121 expect(math.approxEq(f32, @cos(@as(f32, 1.1)), result[0], epsilon));
122 expect(math.approxEq(f32, @cos(@as(f32, 2.2)), result[1], epsilon));
123 expect(math.approxEq(f32, @cos(@as(f32, 3.3)), result[2], epsilon));
124 expect(math.approxEq(f32, @cos(@as(f32, 4.4)), result[3], epsilon));
75 }125 }
76}126}
77127
...@@ -81,13 +131,27 @@ test "@exp" {...@@ -81,13 +131,27 @@ test "@exp" {
81}131}
82132
83fn testExp() void {133fn testExp() void {
134 // TODO test f128, and c_longdouble
135 // https://github.com/ziglang/zig/issues/4026
136 {
137 var a: f16 = 0;
138 expect(@exp(a) == 1);
139 }
84 {140 {
85 var a: f32 = 0;141 var a: f32 = 0;
86 expect(@exp(f32, a) == 1);142 expect(@exp(a) == 1);
87 }143 }
88 {144 {
89 var a: f64 = 0;145 var a: f64 = 0;
90 expect(@exp(f64, a) == 1);146 expect(@exp(a) == 1);
147 }
148 {
149 var v: @Vector(4, f32) = [_]f32{1.1, 2.2, 0.3, 0.4};
150 var result = @exp(v);
151 expect(math.approxEq(f32, @exp(@as(f32, 1.1)), result[0], epsilon));
152 expect(math.approxEq(f32, @exp(@as(f32, 2.2)), result[1], epsilon));
153 expect(math.approxEq(f32, @exp(@as(f32, 0.3)), result[2], epsilon));
154 expect(math.approxEq(f32, @exp(@as(f32, 0.4)), result[3], epsilon));
91 }155 }
92}156}
93157
...@@ -97,31 +161,59 @@ test "@exp2" {...@@ -97,31 +161,59 @@ test "@exp2" {
97}161}
98162
99fn testExp2() void {163fn testExp2() void {
164 // TODO test f128, and c_longdouble
165 // https://github.com/ziglang/zig/issues/4026
166 {
167 var a: f16 = 2;
168 expect(@exp2(a) == 4);
169 }
100 {170 {
101 var a: f32 = 2;171 var a: f32 = 2;
102 expect(@exp2(f32, a) == 4);172 expect(@exp2(a) == 4);
103 }173 }
104 {174 {
105 var a: f64 = 2;175 var a: f64 = 2;
106 expect(@exp2(f64, a) == 4);176 expect(@exp2(a) == 4);
177 }
178 {
179 var v: @Vector(4, f32) = [_]f32{1.1, 2.2, 0.3, 0.4};
180 var result = @exp2(v);
181 expect(math.approxEq(f32, @exp2(@as(f32, 1.1)), result[0], epsilon));
182 expect(math.approxEq(f32, @exp2(@as(f32, 2.2)), result[1], epsilon));
183 expect(math.approxEq(f32, @exp2(@as(f32, 0.3)), result[2], epsilon));
184 expect(math.approxEq(f32, @exp2(@as(f32, 0.4)), result[3], epsilon));
107 }185 }
108}186}
109187
110test "@ln" {188test "@log" {
111 // Old musl (and glibc?), and our current math.ln implementation do not return 1189 // Old musl (and glibc?), and our current math.ln implementation do not return 1
112 // so also accept those values.190 // so also accept those values.
113 comptime testLn();191 comptime testLog();
114 testLn();192 testLog();
115}193}
116194
117fn testLn() void {195fn testLog() void {
196 // TODO test f128, and c_longdouble
197 // https://github.com/ziglang/zig/issues/4026
198 {
199 var a: f16 = e;
200 expect(math.approxEq(f16, @log(a), 1, epsilon));
201 }
118 {202 {
119 var a: f32 = e;203 var a: f32 = e;
120 expect(@ln(f32, a) == 1 or @ln(f32, a) == @bitCast(f32, @as(u32, 0x3f7fffff)));204 expect(@log(a) == 1 or @log(a) == @bitCast(f32, @as(u32, 0x3f7fffff)));
121 }205 }
122 {206 {
123 var a: f64 = e;207 var a: f64 = e;
124 expect(@ln(f64, a) == 1 or @ln(f64, a) == @bitCast(f64, @as(u64, 0x3ff0000000000000)));208 expect(@log(a) == 1 or @log(a) == @bitCast(f64, @as(u64, 0x3ff0000000000000)));
209 }
210 {
211 var v: @Vector(4, f32) = [_]f32{1.1, 2.2, 0.3, 0.4};
212 var result = @log(v);
213 expect(math.approxEq(f32, @log(@as(f32, 1.1)), result[0], epsilon));
214 expect(math.approxEq(f32, @log(@as(f32, 2.2)), result[1], epsilon));
215 expect(math.approxEq(f32, @log(@as(f32, 0.3)), result[2], epsilon));
216 expect(math.approxEq(f32, @log(@as(f32, 0.4)), result[3], epsilon));
125 }217 }
126}218}
127219
...@@ -131,13 +223,27 @@ test "@log2" {...@@ -131,13 +223,27 @@ test "@log2" {
131}223}
132224
133fn testLog2() void {225fn testLog2() void {
226 // TODO test f128, and c_longdouble
227 // https://github.com/ziglang/zig/issues/4026
228 {
229 var a: f16 = 4;
230 expect(@log2(a) == 2);
231 }
134 {232 {
135 var a: f32 = 4;233 var a: f32 = 4;
136 expect(@log2(f32, a) == 2);234 expect(@log2(a) == 2);
137 }235 }
138 {236 {
139 var a: f64 = 4;237 var a: f64 = 4;
140 expect(@log2(f64, a) == 2);238 expect(@log2(a) == 2);
239 }
240 {
241 var v: @Vector(4, f32) = [_]f32{1.1, 2.2, 0.3, 0.4};
242 var result = @log2(v);
243 expect(math.approxEq(f32, @log2(@as(f32, 1.1)), result[0], epsilon));
244 expect(math.approxEq(f32, @log2(@as(f32, 2.2)), result[1], epsilon));
245 expect(math.approxEq(f32, @log2(@as(f32, 0.3)), result[2], epsilon));
246 expect(math.approxEq(f32, @log2(@as(f32, 0.4)), result[3], epsilon));
141 }247 }
142}248}
143249
...@@ -147,13 +253,27 @@ test "@log10" {...@@ -147,13 +253,27 @@ test "@log10" {
147}253}
148254
149fn testLog10() void {255fn testLog10() void {
256 // TODO test f128, and c_longdouble
257 // https://github.com/ziglang/zig/issues/4026
258 {
259 var a: f16 = 100;
260 expect(@log10(a) == 2);
261 }
150 {262 {
151 var a: f32 = 100;263 var a: f32 = 100;
152 expect(@log10(f32, a) == 2);264 expect(@log10(a) == 2);
153 }265 }
154 {266 {
155 var a: f64 = 1000;267 var a: f64 = 1000;
156 expect(@log10(f64, a) == 3);268 expect(@log10(a) == 3);
269 }
270 {
271 var v: @Vector(4, f32) = [_]f32{1.1, 2.2, 0.3, 0.4};
272 var result = @log10(v);
273 expect(math.approxEq(f32, @log10(@as(f32, 1.1)), result[0], epsilon));
274 expect(math.approxEq(f32, @log10(@as(f32, 2.2)), result[1], epsilon));
275 expect(math.approxEq(f32, @log10(@as(f32, 0.3)), result[2], epsilon));
276 expect(math.approxEq(f32, @log10(@as(f32, 0.4)), result[3], epsilon));
157 }277 }
158}278}
159279
...@@ -163,17 +283,33 @@ test "@fabs" {...@@ -163,17 +283,33 @@ test "@fabs" {
163}283}
164284
165fn testFabs() void {285fn testFabs() void {
286 // TODO test f128, and c_longdouble
287 // https://github.com/ziglang/zig/issues/4026
288 {
289 var a: f16 = -2.5;
290 var b: f16 = 2.5;
291 expect(@fabs(a) == 2.5);
292 expect(@fabs(b) == 2.5);
293 }
166 {294 {
167 var a: f32 = -2.5;295 var a: f32 = -2.5;
168 var b: f32 = 2.5;296 var b: f32 = 2.5;
169 expect(@fabs(f32, a) == 2.5);297 expect(@fabs(a) == 2.5);
170 expect(@fabs(f32, b) == 2.5);298 expect(@fabs(b) == 2.5);
171 }299 }
172 {300 {
173 var a: f64 = -2.5;301 var a: f64 = -2.5;
174 var b: f64 = 2.5;302 var b: f64 = 2.5;
175 expect(@fabs(f64, a) == 2.5);303 expect(@fabs(a) == 2.5);
176 expect(@fabs(f64, b) == 2.5);304 expect(@fabs(b) == 2.5);
305 }
306 {
307 var v: @Vector(4, f32) = [_]f32{1.1, -2.2, 0.3, -0.4};
308 var result = @fabs(v);
309 expect(math.approxEq(f32, @fabs(@as(f32, 1.1)), result[0], epsilon));
310 expect(math.approxEq(f32, @fabs(@as(f32, -2.2)), result[1], epsilon));
311 expect(math.approxEq(f32, @fabs(@as(f32, 0.3)), result[2], epsilon));
312 expect(math.approxEq(f32, @fabs(@as(f32, -0.4)), result[3], epsilon));
177 }313 }
178}314}
179315
...@@ -183,13 +319,27 @@ test "@floor" {...@@ -183,13 +319,27 @@ test "@floor" {
183}319}
184320
185fn testFloor() void {321fn testFloor() void {
322 // TODO test f128, and c_longdouble
323 // https://github.com/ziglang/zig/issues/4026
324 {
325 var a: f16 = 2.1;
326 expect(@floor(a) == 2);
327 }
186 {328 {
187 var a: f32 = 2.1;329 var a: f32 = 2.1;
188 expect(@floor(f32, a) == 2);330 expect(@floor(a) == 2);
189 }331 }
190 {332 {
191 var a: f64 = 3.5;333 var a: f64 = 3.5;
192 expect(@floor(f64, a) == 3);334 expect(@floor(a) == 3);
335 }
336 {
337 var v: @Vector(4, f32) = [_]f32{1.1, -2.2, 0.3, -0.4};
338 var result = @floor(v);
339 expect(math.approxEq(f32, @floor(@as(f32, 1.1)), result[0], epsilon));
340 expect(math.approxEq(f32, @floor(@as(f32, -2.2)), result[1], epsilon));
341 expect(math.approxEq(f32, @floor(@as(f32, 0.3)), result[2], epsilon));
342 expect(math.approxEq(f32, @floor(@as(f32, -0.4)), result[3], epsilon));
193 }343 }
194}344}
195345
...@@ -199,13 +349,27 @@ test "@ceil" {...@@ -199,13 +349,27 @@ test "@ceil" {
199}349}
200350
201fn testCeil() void {351fn testCeil() void {
352 // TODO test f128, and c_longdouble
353 // https://github.com/ziglang/zig/issues/4026
354 {
355 var a: f16 = 2.1;
356 expect(@ceil(a) == 3);
357 }
202 {358 {
203 var a: f32 = 2.1;359 var a: f32 = 2.1;
204 expect(@ceil(f32, a) == 3);360 expect(@ceil(a) == 3);
205 }361 }
206 {362 {
207 var a: f64 = 3.5;363 var a: f64 = 3.5;
208 expect(@ceil(f64, a) == 4);364 expect(@ceil(a) == 4);
365 }
366 {
367 var v: @Vector(4, f32) = [_]f32{1.1, -2.2, 0.3, -0.4};
368 var result = @ceil(v);
369 expect(math.approxEq(f32, @ceil(@as(f32, 1.1)), result[0], epsilon));
370 expect(math.approxEq(f32, @ceil(@as(f32, -2.2)), result[1], epsilon));
371 expect(math.approxEq(f32, @ceil(@as(f32, 0.3)), result[2], epsilon));
372 expect(math.approxEq(f32, @ceil(@as(f32, -0.4)), result[3], epsilon));
209 }373 }
210}374}
211375
...@@ -215,29 +379,45 @@ test "@trunc" {...@@ -215,29 +379,45 @@ test "@trunc" {
215}379}
216380
217fn testTrunc() void {381fn testTrunc() void {
382 // TODO test f128, and c_longdouble
383 // https://github.com/ziglang/zig/issues/4026
384 {
385 var a: f16 = 2.1;
386 expect(@trunc(a) == 2);
387 }
218 {388 {
219 var a: f32 = 2.1;389 var a: f32 = 2.1;
220 expect(@trunc(f32, a) == 2);390 expect(@trunc(a) == 2);
221 }391 }
222 {392 {
223 var a: f64 = -3.5;393 var a: f64 = -3.5;
224 expect(@trunc(f64, a) == -3);394 expect(@trunc(a) == -3);
395 }
396 {
397 var v: @Vector(4, f32) = [_]f32{1.1, -2.2, 0.3, -0.4};
398 var result = @trunc(v);
399 expect(math.approxEq(f32, @trunc(@as(f32, 1.1)), result[0], epsilon));
400 expect(math.approxEq(f32, @trunc(@as(f32, -2.2)), result[1], epsilon));
401 expect(math.approxEq(f32, @trunc(@as(f32, 0.3)), result[2], epsilon));
402 expect(math.approxEq(f32, @trunc(@as(f32, -0.4)), result[3], epsilon));
225 }403 }
226}404}
227405
228// This is waiting on library support for the Windows build (not sure why the other's don't need it)406// TODO This is waiting on library support for the Windows build (not sure why the other's don't need it)
229//test "@nearbyInt" {407//test "@nearbyint" {
230// comptime testNearbyInt();408// comptime testNearbyInt();
231// testNearbyInt();409// testNearbyInt();
232//}410//}
233411
234//fn testNearbyInt() void {412//fn testNearbyInt() void {
413// // TODO test f16, f128, and c_longdouble
414// // https://github.com/ziglang/zig/issues/4026
235// {415// {
236// var a: f32 = 2.1;416// var a: f32 = 2.1;
237// expect(@nearbyInt(f32, a) == 2);417// expect(@nearbyint(a) == 2);
238// }418// }
239// {419// {
240// var a: f64 = -3.75;420// var a: f64 = -3.75;
241// expect(@nearbyInt(f64, a) == -4);421// expect(@nearbyint(a) == -4);
242// }422// }
243//}423//}
test/stage1/behavior/math.zig+2-2
...@@ -587,12 +587,12 @@ test "@sqrt" {...@@ -587,12 +587,12 @@ test "@sqrt" {
587587
588 const x = 14.0;588 const x = 14.0;
589 const y = x * x;589 const y = x * x;
590 const z = @sqrt(@TypeOf(y), y);590 const z = @sqrt(y);
591 comptime expect(z == x);591 comptime expect(z == x);
592}592}
593593
594fn testSqrt(comptime T: type, x: T) void {594fn testSqrt(comptime T: type, x: T) void {
595 expect(@sqrt(T, x * x) == x);595 expect(@sqrt(x * x) == x);
596}596}
597597
598test "comptime_int param and return" {598test "comptime_int param and return" {