| author | |
| committer | |
| log | a90fa45ae146a72e2d54842eed15c4b50062eff1 |
| tree | 7845fbd8a52ca2f7c6ddf9e157affd9d01c2191a |
| parent | fe21d84c94e16db56cf6f87040a02213615873a4 |
| parent | 213ff939f18f147b5d9dd164d52ebdd660dab7b4 |
| signature |
fix float ops with respect to vectors10 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#} |
| 8077 | 8077 | ||
| 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 instruction | 8081 | 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 instruction | 8092 | 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 instruction | 8103 | 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 instruction | 8114 | 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 instruction | 8125 | 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 instruction | 8136 | 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 instruction | 8147 | 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 instruction | 8158 | 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 instruction | 8169 | 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 instruction | 8184 | 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 instruction | 8191 | 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 instruction | 8206 | 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 instruction | 8213 | 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#} |
| 8169 | 8221 |
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) = +-0 | 12 | /// - sqrt(+-0) = +-0 |
| 13 | /// - sqrt(x) = nan if x < 0 | 13 | /// - sqrt(x) = nan if x < 0 |
| 14 | /// - sqrt(nan) = nan | 14 | /// - sqrt(nan) = nan |
| 15 | pub 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. |
| 16 | pub 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 f128 | 19 | .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 | } |
| 33 | 33 | ||
| 34 | test "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 | |||
| 40 | test "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 | |||
| 54 | test "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 | |||
| 68 | test "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 | |||
| 82 | test "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 | |||
| 90 | test "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 | |||
| 98 | test "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 | |||
| 106 | fn sqrt_int(comptime T: type, value: T) @IntType(false, T.bit_count / 2) { | 34 | fn 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`. | ||
| 67 | pub 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 | } |
| 730 | 730 | ||
| 731 | test "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 | |||
| 745 | test "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 | |||
| 731 | export fn sqrtf(x: f32) f32 { | 754 | export 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 | |||
| 830 | test "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 | |||
| 844 | test "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 { |
| 3840 | struct IrInstructionFloatOp { | 3840 | struct IrInstructionFloatOp { |
| 3841 | IrInstruction base; | 3841 | IrInstruction base; |
| 3842 | 3842 | ||
| 3843 | BuiltinFnId op; | 3843 | BuiltinFnId fn_id; |
| 3844 | IrInstruction *type; | 3844 | IrInstruction *operand; |
| 3845 | IrInstruction *op1; | ||
| 3846 | }; | 3845 | }; |
| 3847 | 3846 | ||
| 3848 | struct IrInstructionCheckRuntimeScope { | 3847 | struct 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 | } |
| 5786 | 5786 | ||
| 5787 | static LLVMValueRef ir_render_float_op(CodeGen *g, IrExecutable *executable, IrInstructionFloatOp *instruction) { | 5787 | static 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 | } |
| 5793 | 5792 | ||
| 5794 | static LLVMValueRef ir_render_mul_add(CodeGen *g, IrExecutable *executable, IrInstructionMulAdd *instruction) { | 5793 | static 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, llrint | 3126 | // lround, llround, lrint, llrint |
| 3127 | // So far this is only non-complicated type functions. | 3127 | // So far this is only non-complicated type functions. |
| 3128 | const char *float_op_to_name(BuiltinFnId op, bool llvm_name) { | 3128 | const 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 | } |
| 3164 | 3162 | ||
| 3165 | static IrInstruction *ir_build_float_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op1, BuiltinFnId op) { | 3163 | static 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; | ||
| 3170 | 3169 | ||
| 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); | ||
| 3173 | 3171 | ||
| 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; |
| 5514 | 5512 | ||
| 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 | } |
| 27645 | 27638 | ||
| 27646 | static void ir_eval_float_op(IrAnalyze *ira, IrInstruction *source_instr, BuiltinFnId fop, ZigType *float_type, | 27639 | static 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 | } |
| 27825 | 27851 | ||
| 27826 | static IrInstruction *ir_analyze_float_op(IrAnalyze *ira, IrInstruction *source_instr, | 27852 | static 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 | } | ||
| 27837 | 27857 | ||
| 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; |
| 27841 | 27861 | ||
| 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 | } | ||
| 27853 | 27867 | ||
| 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); | ||
| 27857 | 27874 | ||
| 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; |
| 27860 | 27877 | ||
| 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 | } |
| 27881 | 27908 | ||
| 27882 | ir_assert(float_type->id == ZigTypeIdFloat, source_instr); | 27909 | ir_assert(scalar_type->id == ZigTypeIdFloat, &instruction->base); |
| 27883 | 27910 | ||
| 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 | } |
| 27889 | 27916 | ||
| 27890 | static 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 | |||
| 27903 | static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstructionBswap *instruction) { | 27917 | static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstructionBswap *instruction) { |
| 27904 | Error err; | 27918 | Error err; |
| 27905 | 27919 |
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); |
| 33 | struct IrAnalyze; | 33 | struct IrAnalyze; |
| 34 | ZigValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ZigValue *const_val, | 34 | ZigValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ZigValue *const_val, |
| 35 | AstNode *source_node); | 35 | AstNode *source_node); |
| 36 | const char *float_op_to_name(BuiltinFnId op, bool llvm_name); | 36 | const char *float_op_to_name(BuiltinFnId op); |
| 37 | 37 | ||
| 38 | // for debugging purposes | 38 | // for debugging purposes |
| 39 | void dbg_ir_break(const char *src_file, uint32_t line); | 39 | void 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 | } |
| 2006 | 2006 | ||
| 2007 | static void ir_print_float_op(IrPrint *irp, IrInstructionFloatOp *instruction) { | 2007 | static void ir_print_float_op(IrPrint *irp, IrInstructionFloatOp *instruction) { |
| 2008 | 2008 | 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 | } |
| 2019 | 2012 |
test/stage1/behavior/floatop.zig+233-53| ... | @@ -1,6 +1,10 @@ | ... | @@ -1,6 +1,10 @@ |
| 1 | const expect = @import("std").testing.expect; | 1 | const std = @import("std"); |
| 2 | const pi = @import("std").math.pi; | 2 | const expect = std.testing.expect; |
| 3 | const e = @import("std").math.e; | 3 | const math = std.math; |
| 4 | const pi = std.math.pi; | ||
| 5 | const e = std.math.e; | ||
| 6 | |||
| 7 | const epsilon = 0.000001; | ||
| 4 | 8 | ||
| 5 | test "@sqrt" { | 9 | test "@sqrt" { |
| 6 | comptime testSqrt(); | 10 | comptime testSqrt(); |
| ... | @@ -10,25 +14,55 @@ test "@sqrt" { | ... | @@ -10,25 +14,55 @@ test "@sqrt" { |
| 10 | fn testSqrt() void { | 14 | fn 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 implementation | 33 | // 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 | |||
| 48 | test "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 | } |
| 33 | 67 | ||
| 34 | test "@sin" { | 68 | test "@sin" { |
| ... | @@ -37,26 +71,28 @@ test "@sin" { | ... | @@ -37,26 +71,28 @@ test "@sin" { |
| 37 | } | 71 | } |
| 38 | 72 | ||
| 39 | fn testSin() void { | 73 | fn testSin() void { |
| 40 | // TODO - this is actually useful and should be implemented | 74 | // 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-hosted | 76 | { |
| 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 | } |
| 61 | 97 | ||
| 62 | test "@cos" { | 98 | test "@cos" { |
| ... | @@ -65,13 +101,27 @@ test "@cos" { | ... | @@ -65,13 +101,27 @@ test "@cos" { |
| 65 | } | 101 | } |
| 66 | 102 | ||
| 67 | fn testCos() void { | 103 | fn 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 | } |
| 77 | 127 | ||
| ... | @@ -81,13 +131,27 @@ test "@exp" { | ... | @@ -81,13 +131,27 @@ test "@exp" { |
| 81 | } | 131 | } |
| 82 | 132 | ||
| 83 | fn testExp() void { | 133 | fn 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 | } |
| 93 | 157 | ||
| ... | @@ -97,31 +161,59 @@ test "@exp2" { | ... | @@ -97,31 +161,59 @@ test "@exp2" { |
| 97 | } | 161 | } |
| 98 | 162 | ||
| 99 | fn testExp2() void { | 163 | fn 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 | } |
| 109 | 187 | ||
| 110 | test "@ln" { | 188 | test "@log" { |
| 111 | // Old musl (and glibc?), and our current math.ln implementation do not return 1 | 189 | // 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 | } |
| 116 | 194 | ||
| 117 | fn testLn() void { | 195 | fn 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 | } |
| 127 | 219 | ||
| ... | @@ -131,13 +223,27 @@ test "@log2" { | ... | @@ -131,13 +223,27 @@ test "@log2" { |
| 131 | } | 223 | } |
| 132 | 224 | ||
| 133 | fn testLog2() void { | 225 | fn 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 | } |
| 143 | 249 | ||
| ... | @@ -147,13 +253,27 @@ test "@log10" { | ... | @@ -147,13 +253,27 @@ test "@log10" { |
| 147 | } | 253 | } |
| 148 | 254 | ||
| 149 | fn testLog10() void { | 255 | fn 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 | } |
| 159 | 279 | ||
| ... | @@ -163,17 +283,33 @@ test "@fabs" { | ... | @@ -163,17 +283,33 @@ test "@fabs" { |
| 163 | } | 283 | } |
| 164 | 284 | ||
| 165 | fn testFabs() void { | 285 | fn 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 | } |
| 179 | 315 | ||
| ... | @@ -183,13 +319,27 @@ test "@floor" { | ... | @@ -183,13 +319,27 @@ test "@floor" { |
| 183 | } | 319 | } |
| 184 | 320 | ||
| 185 | fn testFloor() void { | 321 | fn 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 | } |
| 195 | 345 | ||
| ... | @@ -199,13 +349,27 @@ test "@ceil" { | ... | @@ -199,13 +349,27 @@ test "@ceil" { |
| 199 | } | 349 | } |
| 200 | 350 | ||
| 201 | fn testCeil() void { | 351 | fn 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 | } |
| 211 | 375 | ||
| ... | @@ -215,29 +379,45 @@ test "@trunc" { | ... | @@ -215,29 +379,45 @@ test "@trunc" { |
| 215 | } | 379 | } |
| 216 | 380 | ||
| 217 | fn testTrunc() void { | 381 | fn 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 | } |
| 227 | 405 | ||
| 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 | //} |
| 233 | 411 | ||
| 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" { |
| 587 | 587 | ||
| 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 | } |
| 593 | 593 | ||
| 594 | fn testSqrt(comptime T: type, x: T) void { | 594 | fn testSqrt(comptime T: type, x: T) void { |
| 595 | expect(@sqrt(T, x * x) == x); | 595 | expect(@sqrt(x * x) == x); |
| 596 | } | 596 | } |
| 597 | 597 | ||
| 598 | test "comptime_int param and return" { | 598 | test "comptime_int param and return" { |