authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-01 23:27:43-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-01 23:27:43-05:00
logcb56b26900dcb563b008cf132aa3ae180d6a205a
tree2b082ecffe7a275bb164870d73197a24f8859b05
parent576320e6d5bf706a0ee03a3e9318c8ef2fd6e76f
signature Commit is signed but in an unrecognized format.

fix float ops with respect to vectors

also remove the redundant type parameter

9 files changed, 289 insertions(+), 254 deletions(-)

doc/langref.html.in+81-29
......@@ -8076,94 +8076,146 @@ test "vector @splat" {
80768076 {#header_close#}
80778077
80788078 {#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>
80808080 <p>
80818081 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>.
80838087 </p>
80848088 {#header_close#}
80858089 {#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>
80878091 <p>
80888092 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>.
80908098 </p>
80918099 {#header_close#}
80928100 {#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>
80948102 <p>
80958103 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>.
80978109 </p>
80988110 {#header_close#}
80998111 {#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>
81018113 <p>
81028114 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>.
81048120 </p>
81058121 {#header_close#}
81068122 {#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>
81088124 <p>
81098125 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>.
81118131 </p>
81128132 {#header_close#}
81138133 {#header_open|@ln#}
8114 <pre>{#syntax#}@ln(comptime T: type, value: T) T{#endsyntax#}</pre>
8134 <pre>{#syntax#}@ln(value: var) @TypeOf(value){#endsyntax#}</pre>
81158135 <p>
81168136 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>.
81188142 </p>
81198143 {#header_close#}
81208144 {#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>
81228146 <p>
81238147 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>.
81258153 </p>
81268154 {#header_close#}
81278155 {#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>
81298157 <p>
81308158 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>.
81328164 </p>
81338165 {#header_close#}
81348166 {#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>
81368168 <p>
81378169 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>.
81398175 </p>
81408176 {#header_close#}
81418177 {#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>
81438183 <p>
8144 Returns the largest integral value not greater than the given floating point number. Uses a dedicated hardware instruction
8145 when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.
8184 Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
8185 <a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
81468186 </p>
81478187 {#header_close#}
81488188 {#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>
81508190 <p>
8151 Returns the largest integral value not less than the given floating point number. Uses a dedicated hardware instruction
8152 when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.
8191 Returns the largest integral value not less than the given floating point number.
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>.
81538197 </p>
81548198 {#header_close#}
81558199 {#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>
81578205 <p>
8158 Rounds the given floating point number to an integer, towards zero. Uses a dedicated hardware instruction
8159 when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.
8206 Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
8207 <a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
81608208 </p>
81618209 {#header_close#}
81628210 {#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>
81648212 <p>
81658213 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>.
81678219 </p>
81688220 {#header_close#}
81698221
lib/std/math/sqrt.zig+15-78
......@@ -12,12 +12,12 @@ const maxInt = std.math.maxInt;
1212/// - sqrt(+-0) = +-0
1313/// - sqrt(x) = nan if x < 0
1414/// - 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)) {
1617 const T = @TypeOf(x);
17 switch (@typeId(T)) {
18 TypeId.ComptimeFloat => return @as(T, @sqrt(f64, x)), // TODO upgrade to f128
19 TypeId.Float => return @sqrt(T, x),
20 TypeId.ComptimeInt => comptime {
18 switch (@typeInfo(T)) {
19 .Float, .ComptimeFloat => return @sqrt(x),
20 .ComptimeInt => comptime {
2121 if (x > maxInt(u128)) {
2222 @compileError("sqrt not implemented for comptime_int greater than 128 bits");
2323 }
......@@ -26,83 +26,11 @@ pub fn sqrt(x: var) (if (@typeId(@TypeOf(x)) == TypeId.Int) @IntType(false, @Typ
2626 }
2727 return @as(T, sqrt_int(u128, x));
2828 },
29 TypeId.Int => return sqrt_int(T, x),
29 .Int => return sqrt_int(T, x),
3030 else => @compileError("sqrt not implemented for " ++ @typeName(T)),
3131 }
3232}
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
10634fn sqrt_int(comptime T: type, value: T) @IntType(false, T.bit_count / 2) {
10735 var op = value;
10836 var res: T = 0;
......@@ -134,3 +62,12 @@ test "math.sqrt_int" {
13462 expect(sqrt_int(u32, 9) == 3);
13563 expect(sqrt_int(u32, 10) == 3);
13664}
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 {
728728 return @bitCast(f64, uz);
729729}
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
731754export fn sqrtf(x: f32) f32 {
732755 const tiny: f32 = 1.0e-30;
733756 const sign: i32 = @bitCast(i32, @as(u32, 0x80000000));
......@@ -803,3 +826,26 @@ export fn sqrtf(x: f32) f32 {
803826 ix += m << 23;
804827 return @bitCast(f32, ix);
805828}
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+2-3
......@@ -3840,9 +3840,8 @@ struct IrInstructionAddImplicitReturnType {
38403840struct IrInstructionFloatOp {
38413841 IrInstruction base;
38423842
3843 BuiltinFnId op;
3844 IrInstruction *type;
3845 IrInstruction *op1;
3843 BuiltinFnId fn_id;
3844 IrInstruction *operand;
38463845};
38473846
38483847struct IrInstructionCheckRuntimeScope {
src/codegen.cpp+17-18
......@@ -5785,10 +5785,9 @@ static LLVMValueRef ir_render_atomic_store(CodeGen *g, IrExecutable *executable,
57855785}
57865786
57875787static LLVMValueRef ir_render_float_op(CodeGen *g, IrExecutable *executable, IrInstructionFloatOp *instruction) {
5788 LLVMValueRef op = ir_llvm_value(g, instruction->op1);
5789 assert(instruction->base.value->type->id == ZigTypeIdFloat);
5790 LLVMValueRef fn_val = get_float_fn(g, instruction->base.value->type, ZigLLVMFnIdFloatOp, instruction->op);
5791 return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
5788 LLVMValueRef operand = ir_llvm_value(g, instruction->operand);
5789 LLVMValueRef fn_val = get_float_fn(g, instruction->base.value->type, ZigLLVMFnIdFloatOp, instruction->fn_id);
5790 return LLVMBuildCall(g->builder, fn_val, &operand, 1, "");
57925791}
57935792
57945793static LLVMValueRef ir_render_mul_add(CodeGen *g, IrExecutable *executable, IrInstructionMulAdd *instruction) {
......@@ -8201,20 +8200,20 @@ static void define_builtin_fns(CodeGen *g) {
82018200 create_builtin_fn(g, BuiltinFnIdDivFloor, "divFloor", 2);
82028201 create_builtin_fn(g, BuiltinFnIdRem, "rem", 2);
82038202 create_builtin_fn(g, BuiltinFnIdMod, "mod", 2);
8204 create_builtin_fn(g, BuiltinFnIdSqrt, "sqrt", 2);
8205 create_builtin_fn(g, BuiltinFnIdSin, "sin", 2);
8206 create_builtin_fn(g, BuiltinFnIdCos, "cos", 2);
8207 create_builtin_fn(g, BuiltinFnIdExp, "exp", 2);
8208 create_builtin_fn(g, BuiltinFnIdExp2, "exp2", 2);
8209 create_builtin_fn(g, BuiltinFnIdLn, "ln", 2);
8210 create_builtin_fn(g, BuiltinFnIdLog2, "log2", 2);
8211 create_builtin_fn(g, BuiltinFnIdLog10, "log10", 2);
8212 create_builtin_fn(g, BuiltinFnIdFabs, "fabs", 2);
8213 create_builtin_fn(g, BuiltinFnIdFloor, "floor", 2);
8214 create_builtin_fn(g, BuiltinFnIdCeil, "ceil", 2);
8215 create_builtin_fn(g, BuiltinFnIdTrunc, "trunc", 2);
8216 create_builtin_fn(g, BuiltinFnIdNearbyInt, "nearbyInt", 2);
8217 create_builtin_fn(g, BuiltinFnIdRound, "round", 2);
8203 create_builtin_fn(g, BuiltinFnIdSqrt, "sqrt", 1);
8204 create_builtin_fn(g, BuiltinFnIdSin, "sin", 1);
8205 create_builtin_fn(g, BuiltinFnIdCos, "cos", 1);
8206 create_builtin_fn(g, BuiltinFnIdExp, "exp", 1);
8207 create_builtin_fn(g, BuiltinFnIdExp2, "exp2", 1);
8208 create_builtin_fn(g, BuiltinFnIdLn, "ln", 1);
8209 create_builtin_fn(g, BuiltinFnIdLog2, "log2", 1);
8210 create_builtin_fn(g, BuiltinFnIdLog10, "log10", 1);
8211 create_builtin_fn(g, BuiltinFnIdFabs, "fabs", 1);
8212 create_builtin_fn(g, BuiltinFnIdFloor, "floor", 1);
8213 create_builtin_fn(g, BuiltinFnIdCeil, "ceil", 1);
8214 create_builtin_fn(g, BuiltinFnIdTrunc, "trunc", 1);
8215 create_builtin_fn(g, BuiltinFnIdNearbyInt, "nearbyInt", 1);
8216 create_builtin_fn(g, BuiltinFnIdRound, "round", 1);
82188217 create_builtin_fn(g, BuiltinFnIdMulAdd, "mulAdd", 4);
82198218 create_builtin_fn(g, BuiltinFnIdNewStackCall, "newStackCall", SIZE_MAX);
82208219 create_builtin_fn(g, BuiltinFnIdAsyncCall, "asyncCall", SIZE_MAX);
src/ir.cpp+40-67
......@@ -3162,14 +3162,14 @@ const char *float_op_to_name(BuiltinFnId op, bool llvm_name) {
31623162 }
31633163}
31643164
3165static IrInstruction *ir_build_float_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op1, BuiltinFnId op) {
3165static IrInstruction *ir_build_float_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *operand,
3166 BuiltinFnId fn_id)
3167{
31663168 IrInstructionFloatOp *instruction = ir_build_instruction<IrInstructionFloatOp>(irb, scope, source_node);
3167 instruction->type = type;
3168 instruction->op1 = op1;
3169 instruction->op = op;
3169 instruction->operand = operand;
3170 instruction->fn_id = fn_id;
31703171
3171 if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block);
3172 ir_ref_instruction(op1, irb->current_basic_block);
3172 ir_ref_instruction(operand, irb->current_basic_block);
31733173
31743174 return &instruction->base;
31753175}
......@@ -5512,13 +5512,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
55125512 if (arg0_value == irb->codegen->invalid_instruction)
55135513 return arg0_value;
55145514
5515 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
5516 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
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);
5515 IrInstruction *inst = ir_build_float_op(irb, scope, node, arg0_value, builtin_fn->id);
5516 return ir_lval_wrap(irb, scope, inst, lval, result_loc);
55225517 }
55235518 case BuiltinFnIdTruncate:
55245519 {
......@@ -27811,83 +27806,61 @@ static void ir_eval_float_op(IrAnalyze *ira, IrInstruction *source_instr, Builti
2781127806 }
2781227807}
2781327808
27814static IrInstruction *ir_analyze_float_op(IrAnalyze *ira, IrInstruction *source_instr,
27815 ZigType *expr_type, AstNode *expr_type_src_node, IrInstruction *operand, BuiltinFnId op)
27816{
27817 // Only allow float types, and vectors of floats.
27818 ZigType *float_type = (expr_type->id == ZigTypeIdVector) ? expr_type->data.vector.elem_type : expr_type;
27819 if (float_type->id != ZigTypeIdFloat && float_type->id != ZigTypeIdComptimeFloat) {
27820 ir_add_error_node(ira, expr_type_src_node,
27821 buf_sprintf("@%s does not support type '%s'",
27822 float_op_to_name(op, false), buf_ptr(&float_type->name)));
27809static IrInstruction *ir_analyze_instruction_float_op(IrAnalyze *ira, IrInstructionFloatOp *instruction) {
27810 IrInstruction *operand = instruction->operand->child;
27811 ZigType *operand_type = operand->value->type;
27812 if (type_is_invalid(operand_type))
2782327813 return ira->codegen->invalid_instruction;
27824 }
2782527814
27826 IrInstruction *casted_op = ir_implicit_cast(ira, operand, float_type);
27827 if (type_is_invalid(casted_op->value->type))
27828 return ira->codegen->invalid_instruction;
27815 // This instruction accepts floats and vectors of floats.
27816 ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ?
27817 operand_type->data.vector.elem_type : operand_type;
2782927818
27830 if (instr_is_comptime(casted_op)) {
27831 if ((float_type->id == ZigTypeIdComptimeFloat ||
27832 float_type->data.floating.bit_count == 16 ||
27833 float_type->data.floating.bit_count == 128) &&
27834 op != BuiltinFnIdSqrt)
27835 {
27836 ir_add_error(ira, source_instr,
27837 buf_sprintf("compiler bug: TODO make @%s support type '%s'",
27838 float_op_to_name(op, false), buf_ptr(&float_type->name)));
27839 return ira->codegen->invalid_instruction;
27840 }
27819 if (scalar_type->id != ZigTypeIdFloat && scalar_type->id != ZigTypeIdComptimeFloat) {
27820 ir_add_error(ira, operand,
27821 buf_sprintf("expected float type, found '%s'", buf_ptr(&scalar_type->name)));
27822 return ira->codegen->invalid_instruction;
27823 }
2784127824
27842 ZigValue *op1_const = ir_resolve_const(ira, casted_op, UndefBad);
27843 if (!op1_const)
27825 if (instr_is_comptime(operand)) {
27826 ZigValue *operand_val = ir_resolve_const(ira, operand, UndefOk);
27827 if (operand_val == nullptr)
2784427828 return ira->codegen->invalid_instruction;
27829 if (operand_val->special == ConstValSpecialUndef)
27830 return ir_const_undef(ira, &instruction->base, operand_type);
2784527831
27846 IrInstruction *result = ir_const(ira, source_instr, expr_type);
27832 IrInstruction *result = ir_const(ira, &instruction->base, operand_type);
2784727833 ZigValue *out_val = result->value;
2784827834
27849 if (expr_type->id == ZigTypeIdVector) {
27850 expand_undef_array(ira->codegen, op1_const);
27835 if (operand_type->id == ZigTypeIdVector) {
27836 expand_undef_array(ira->codegen, operand_val);
2785127837 out_val->special = ConstValSpecialUndef;
2785227838 expand_undef_array(ira->codegen, out_val);
27853 size_t len = expr_type->data.vector.len;
27839 size_t len = operand_type->data.vector.len;
2785427840 for (size_t i = 0; i < len; i += 1) {
27855 ZigValue *float_operand_op1 = &op1_const->data.x_array.data.s_none.elements[i];
27841 ZigValue *float_operand_op1 = &operand_val->data.x_array.data.s_none.elements[i];
2785627842 ZigValue *float_out_val = &out_val->data.x_array.data.s_none.elements[i];
27857 assert(float_operand_op1->type == float_type);
27858 assert(float_out_val->type == float_type);
27859 ir_eval_float_op(ira, source_instr, op, float_type, op1_const, float_out_val);
27860 float_out_val->type = float_type;
27843 ir_assert(float_operand_op1->type == scalar_type, &instruction->base);
27844 ir_assert(float_out_val->type == scalar_type, &instruction->base);
27845 ir_eval_float_op(ira, &instruction->base, instruction->fn_id, scalar_type, operand_val, float_out_val);
27846 float_out_val->type = scalar_type;
2786127847 }
27862 out_val->type = expr_type;
27848 out_val->type = operand_type;
2786327849 out_val->special = ConstValSpecialStatic;
2786427850 } else {
27865 ir_eval_float_op(ira, source_instr, op, float_type, op1_const, out_val);
27851 ir_eval_float_op(ira, &instruction->base, instruction->fn_id, scalar_type, operand_val, out_val);
2786627852 }
2786727853 return result;
2786827854 }
2786927855
27870 ir_assert(float_type->id == ZigTypeIdFloat, source_instr);
27856 ir_assert(scalar_type->id == ZigTypeIdFloat, &instruction->base);
2787127857
27872 IrInstruction *result = ir_build_float_op(&ira->new_irb, source_instr->scope,
27873 source_instr->source_node, nullptr, casted_op, op);
27874 result->value->type = expr_type;
27858 IrInstruction *result = ir_build_float_op(&ira->new_irb, instruction->base.scope,
27859 instruction->base.source_node, operand, instruction->fn_id);
27860 result->value->type = operand_type;
2787527861 return result;
2787627862}
2787727863
27878static IrInstruction *ir_analyze_instruction_float_op(IrAnalyze *ira, IrInstructionFloatOp *instruction) {
27879 ZigType *expr_type = ir_resolve_type(ira, instruction->type->child);
27880 if (type_is_invalid(expr_type))
27881 return ira->codegen->invalid_instruction;
27882
27883 IrInstruction *operand = instruction->op1->child;
27884 if (type_is_invalid(operand->value->type))
27885 return ira->codegen->invalid_instruction;
27886
27887 return ir_analyze_float_op(ira, &instruction->base, expr_type, instruction->type->source_node,
27888 operand, instruction->op);
27889}
27890
2789127864static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstructionBswap *instruction) {
2789227865 Error err;
2789327866
src/ir_print.cpp+2-9
......@@ -2005,15 +2005,8 @@ static void ir_print_add_implicit_return_type(IrPrint *irp, IrInstructionAddImpl
20052005}
20062006
20072007static void ir_print_float_op(IrPrint *irp, IrInstructionFloatOp *instruction) {
2008
2009 fprintf(irp->f, "@%s(", float_op_to_name(instruction->op, false));
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);
2008 fprintf(irp->f, "@%s(", float_op_to_name(instruction->fn_id, false));
2009 ir_print_other_instruction(irp, instruction->operand);
20172010 fprintf(irp->f, ")");
20182011}
20192012
test/stage1/behavior/floatop.zig+84-48
......@@ -1,6 +1,8 @@
1const expect = @import("std").testing.expect;
2const pi = @import("std").math.pi;
3const e = @import("std").math.e;
1const std = @import("std");
2const expect = std.testing.expect;
3const math = std.math;
4const pi = std.math.pi;
5const e = std.math.e;
46
57test "@sqrt" {
68 comptime testSqrt();
......@@ -10,53 +12,65 @@ test "@sqrt" {
1012fn testSqrt() void {
1113 {
1214 var a: f16 = 4;
13 expect(@sqrt(f16, a) == 2);
15 expect(@sqrt(a) == 2);
1416 }
1517 {
1618 var a: f32 = 9;
17 expect(@sqrt(f32, a) == 3);
19 expect(@sqrt(a) == 3);
1820 }
1921 {
2022 var a: f64 = 25;
21 expect(@sqrt(f64, a) == 5);
23 expect(@sqrt(a) == 5);
2224 }
2325 {
2426 const a: comptime_float = 25.0;
25 expect(@sqrt(comptime_float, a) == 5.0);
27 expect(@sqrt(a) == 5.0);
2628 }
27 // Waiting on a c.zig implementation
29 // TODO https://github.com/ziglang/zig/issues/4026
2830 //{
2931 // var a: f128 = 49;
30 // expect(@sqrt(f128, a) == 7);
32 // expect(@sqrt(a) == 7);
3133 //}
3234}
3335
36test "more @sqrt f16 tests" {
37 // TODO these are not all passing at comptime
38 const epsilon = 0.000001;
39
40 expect(@sqrt(@as(f16, 0.0)) == 0.0);
41 expect(math.approxEq(f16, @sqrt(@as(f16, 2.0)), 1.414214, epsilon));
42 expect(math.approxEq(f16, @sqrt(@as(f16, 3.6)), 1.897367, epsilon));
43 expect(@sqrt(@as(f16, 4.0)) == 2.0);
44 expect(math.approxEq(f16, @sqrt(@as(f16, 7.539840)), 2.745877, epsilon));
45 expect(math.approxEq(f16, @sqrt(@as(f16, 19.230934)), 4.385309, epsilon));
46 expect(@sqrt(@as(f16, 64.0)) == 8.0);
47 expect(math.approxEq(f16, @sqrt(@as(f16, 64.1)), 8.006248, epsilon));
48 expect(math.approxEq(f16, @sqrt(@as(f16, 8942.230469)), 94.563370, epsilon));
49
50 // special cases
51 expect(math.isPositiveInf(@sqrt(@as(f16, math.inf(f16)))));
52 expect(@sqrt(@as(f16, 0.0)) == 0.0);
53 expect(@sqrt(@as(f16, -0.0)) == -0.0);
54 expect(math.isNan(@sqrt(@as(f16, -1.0))));
55 expect(math.isNan(@sqrt(@as(f16, math.nan(f16)))));
56}
57
3458test "@sin" {
3559 comptime testSin();
3660 testSin();
3761}
3862
3963fn testSin() void {
40 // TODO - this is actually useful and should be implemented
41 // (all the trig functions for f16)
42 // but will probably wait till self-hosted
43 //{
44 // var a: f16 = pi;
45 // expect(@sin(f16, a/2) == 1);
46 //}
64 // TODO test f16, f128, and c_longdouble
65 // https://github.com/ziglang/zig/issues/4026
4766 {
4867 var a: f32 = 0;
49 expect(@sin(f32, a) == 0);
68 expect(@sin(a) == 0);
5069 }
5170 {
5271 var a: f64 = 0;
53 expect(@sin(f64, a) == 0);
72 expect(@sin(a) == 0);
5473 }
55 // TODO
56 //{
57 // var a: f16 = pi;
58 // expect(@sqrt(f128, a/2) == 1);
59 //}
6074}
6175
6276test "@cos" {
......@@ -65,13 +79,15 @@ test "@cos" {
6579}
6680
6781fn testCos() void {
82 // TODO test f16, f128, and c_longdouble
83 // https://github.com/ziglang/zig/issues/4026
6884 {
6985 var a: f32 = 0;
70 expect(@cos(f32, a) == 1);
86 expect(@cos(a) == 1);
7187 }
7288 {
7389 var a: f64 = 0;
74 expect(@cos(f64, a) == 1);
90 expect(@cos(a) == 1);
7591 }
7692}
7793
......@@ -81,13 +97,15 @@ test "@exp" {
8197}
8298
8399fn testExp() void {
100 // TODO test f16, f128, and c_longdouble
101 // https://github.com/ziglang/zig/issues/4026
84102 {
85103 var a: f32 = 0;
86 expect(@exp(f32, a) == 1);
104 expect(@exp(a) == 1);
87105 }
88106 {
89107 var a: f64 = 0;
90 expect(@exp(f64, a) == 1);
108 expect(@exp(a) == 1);
91109 }
92110}
93111
......@@ -97,13 +115,15 @@ test "@exp2" {
97115}
98116
99117fn testExp2() void {
118 // TODO test f16, f128, and c_longdouble
119 // https://github.com/ziglang/zig/issues/4026
100120 {
101121 var a: f32 = 2;
102 expect(@exp2(f32, a) == 4);
122 expect(@exp2(a) == 4);
103123 }
104124 {
105125 var a: f64 = 2;
106 expect(@exp2(f64, a) == 4);
126 expect(@exp2(a) == 4);
107127 }
108128}
109129
......@@ -115,13 +135,15 @@ test "@ln" {
115135}
116136
117137fn testLn() void {
138 // TODO test f16, f128, and c_longdouble
139 // https://github.com/ziglang/zig/issues/4026
118140 {
119141 var a: f32 = e;
120 expect(@ln(f32, a) == 1 or @ln(f32, a) == @bitCast(f32, @as(u32, 0x3f7fffff)));
142 expect(@ln(a) == 1 or @ln(a) == @bitCast(f32, @as(u32, 0x3f7fffff)));
121143 }
122144 {
123145 var a: f64 = e;
124 expect(@ln(f64, a) == 1 or @ln(f64, a) == @bitCast(f64, @as(u64, 0x3ff0000000000000)));
146 expect(@ln(a) == 1 or @ln(a) == @bitCast(f64, @as(u64, 0x3ff0000000000000)));
125147 }
126148}
127149
......@@ -131,13 +153,15 @@ test "@log2" {
131153}
132154
133155fn testLog2() void {
156 // TODO test f16, f128, and c_longdouble
157 // https://github.com/ziglang/zig/issues/4026
134158 {
135159 var a: f32 = 4;
136 expect(@log2(f32, a) == 2);
160 expect(@log2(a) == 2);
137161 }
138162 {
139163 var a: f64 = 4;
140 expect(@log2(f64, a) == 2);
164 expect(@log2(a) == 2);
141165 }
142166}
143167
......@@ -147,13 +171,15 @@ test "@log10" {
147171}
148172
149173fn testLog10() void {
174 // TODO test f16, f128, and c_longdouble
175 // https://github.com/ziglang/zig/issues/4026
150176 {
151177 var a: f32 = 100;
152 expect(@log10(f32, a) == 2);
178 expect(@log10(a) == 2);
153179 }
154180 {
155181 var a: f64 = 1000;
156 expect(@log10(f64, a) == 3);
182 expect(@log10(a) == 3);
157183 }
158184}
159185
......@@ -163,17 +189,19 @@ test "@fabs" {
163189}
164190
165191fn testFabs() void {
192 // TODO test f16, f128, and c_longdouble
193 // https://github.com/ziglang/zig/issues/4026
166194 {
167195 var a: f32 = -2.5;
168196 var b: f32 = 2.5;
169 expect(@fabs(f32, a) == 2.5);
170 expect(@fabs(f32, b) == 2.5);
197 expect(@fabs(a) == 2.5);
198 expect(@fabs(b) == 2.5);
171199 }
172200 {
173201 var a: f64 = -2.5;
174202 var b: f64 = 2.5;
175 expect(@fabs(f64, a) == 2.5);
176 expect(@fabs(f64, b) == 2.5);
203 expect(@fabs(a) == 2.5);
204 expect(@fabs(b) == 2.5);
177205 }
178206}
179207
......@@ -183,13 +211,15 @@ test "@floor" {
183211}
184212
185213fn testFloor() void {
214 // TODO test f16, f128, and c_longdouble
215 // https://github.com/ziglang/zig/issues/4026
186216 {
187217 var a: f32 = 2.1;
188 expect(@floor(f32, a) == 2);
218 expect(@floor(a) == 2);
189219 }
190220 {
191221 var a: f64 = 3.5;
192 expect(@floor(f64, a) == 3);
222 expect(@floor(a) == 3);
193223 }
194224}
195225
......@@ -199,13 +229,15 @@ test "@ceil" {
199229}
200230
201231fn testCeil() void {
232 // TODO test f16, f128, and c_longdouble
233 // https://github.com/ziglang/zig/issues/4026
202234 {
203235 var a: f32 = 2.1;
204 expect(@ceil(f32, a) == 3);
236 expect(@ceil(a) == 3);
205237 }
206238 {
207239 var a: f64 = 3.5;
208 expect(@ceil(f64, a) == 4);
240 expect(@ceil(a) == 4);
209241 }
210242}
211243
......@@ -215,29 +247,33 @@ test "@trunc" {
215247}
216248
217249fn testTrunc() void {
250 // TODO test f16, f128, and c_longdouble
251 // https://github.com/ziglang/zig/issues/4026
218252 {
219253 var a: f32 = 2.1;
220 expect(@trunc(f32, a) == 2);
254 expect(@trunc(a) == 2);
221255 }
222256 {
223257 var a: f64 = -3.5;
224 expect(@trunc(f64, a) == -3);
258 expect(@trunc(a) == -3);
225259 }
226260}
227261
228// This is waiting on library support for the Windows build (not sure why the other's don't need it)
262// TODO This is waiting on library support for the Windows build (not sure why the other's don't need it)
229263//test "@nearbyInt" {
230264// comptime testNearbyInt();
231265// testNearbyInt();
232266//}
233267
234268//fn testNearbyInt() void {
269// // TODO test f16, f128, and c_longdouble
270// // https://github.com/ziglang/zig/issues/4026
235271// {
236272// var a: f32 = 2.1;
237// expect(@nearbyInt(f32, a) == 2);
273// expect(@nearbyInt(a) == 2);
238274// }
239275// {
240276// var a: f64 = -3.75;
241// expect(@nearbyInt(f64, a) == -4);
277// expect(@nearbyInt(a) == -4);
242278// }
243279//}
test/stage1/behavior/math.zig+2-2
......@@ -587,12 +587,12 @@ test "@sqrt" {
587587
588588 const x = 14.0;
589589 const y = x * x;
590 const z = @sqrt(@TypeOf(y), y);
590 const z = @sqrt(y);
591591 comptime expect(z == x);
592592}
593593
594594fn testSqrt(comptime T: type, x: T) void {
595 expect(@sqrt(T, x * x) == x);
595 expect(@sqrt(x * x) == x);
596596}
597597
598598test "comptime_int param and return" {