diff --git a/doc/langref.html.in b/doc/langref.html.in index 3be3131843..d5e64fb6d9 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -8076,94 +8076,146 @@ test "vector @splat" { {#header_close#} {#header_open|@sqrt#} -
{#syntax#}@sqrt(comptime T: type, value: T) T{#endsyntax#}
+ {#syntax#}@sqrt(value: var) @TypeOf(value){#endsyntax#}
Performs the square root of a floating point number. Uses a dedicated hardware instruction - when available. Supports {#syntax#}f16{#endsyntax#}, {#syntax#}f32{#endsyntax#}, {#syntax#}f64{#endsyntax#}, and {#syntax#}f128{#endsyntax#}, as well as vectors. + when available. +
++ Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that + some float operations are not yet implemented for all float types.
{#header_close#} {#header_open|@sin#} -{#syntax#}@sin(comptime T: type, value: T) T{#endsyntax#}
+ {#syntax#}@sin(value: var) @TypeOf(value){#endsyntax#}
Sine trigometric function on a floating point number. Uses a dedicated hardware instruction - when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}. + when available. +
++ Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that + some float operations are not yet implemented for all float types.
{#header_close#} {#header_open|@cos#} -{#syntax#}@cos(comptime T: type, value: T) T{#endsyntax#}
+ {#syntax#}@cos(value: var) @TypeOf(value){#endsyntax#}
Cosine trigometric function on a floating point number. Uses a dedicated hardware instruction - when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}. + when available. +
++ Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that + some float operations are not yet implemented for all float types.
{#header_close#} {#header_open|@exp#} -{#syntax#}@exp(comptime T: type, value: T) T{#endsyntax#}
+ {#syntax#}@exp(value: var) @TypeOf(value){#endsyntax#}
Base-e exponential function on a floating point number. Uses a dedicated hardware instruction - when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}. + when available. +
++ Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that + some float operations are not yet implemented for all float types.
{#header_close#} {#header_open|@exp2#} -{#syntax#}@exp2(comptime T: type, value: T) T{#endsyntax#}
+ {#syntax#}@exp2(value: var) @TypeOf(value){#endsyntax#}
Base-2 exponential function on a floating point number. Uses a dedicated hardware instruction - when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}. + when available. +
++ Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that + some float operations are not yet implemented for all float types.
{#header_close#} {#header_open|@ln#} -{#syntax#}@ln(comptime T: type, value: T) T{#endsyntax#}
+ {#syntax#}@ln(value: var) @TypeOf(value){#endsyntax#}
Returns the natural logarithm of a floating point number. Uses a dedicated hardware instruction - when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}. + when available. +
++ Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that + some float operations are not yet implemented for all float types.
{#header_close#} {#header_open|@log2#} -{#syntax#}@log2(comptime T: type, value: T) T{#endsyntax#}
+ {#syntax#}@log2(value: var) @TypeOf(value){#endsyntax#}
Returns the logarithm to the base 2 of a floating point number. Uses a dedicated hardware instruction - when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}. + when available. +
++ Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that + some float operations are not yet implemented for all float types.
{#header_close#} {#header_open|@log10#} -{#syntax#}@log10(comptime T: type, value: T) T{#endsyntax#}
+ {#syntax#}@log10(value: var) @TypeOf(value){#endsyntax#}
Returns the logarithm to the base 10 of a floating point number. Uses a dedicated hardware instruction - when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}. + when available. +
++ Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that + some float operations are not yet implemented for all float types.
{#header_close#} {#header_open|@fabs#} -{#syntax#}@fabs(comptime T: type, value: T) T{#endsyntax#}
+ {#syntax#}@fabs(value: var) @TypeOf(value){#endsyntax#}
Returns the absolute value of a floating point number. Uses a dedicated hardware instruction - when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}. + when available. +
++ Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that + some float operations are not yet implemented for all float types.
{#header_close#} {#header_open|@floor#} -{#syntax#}@floor(comptime T: type, value: T) T{#endsyntax#}
+ {#syntax#}@floor(value: var) @TypeOf(value){#endsyntax#}
- Returns the largest integral value not greater than the given floating point number. Uses a dedicated hardware instruction - when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}. + Returns the largest integral value not greater than the given floating point number. + Uses a dedicated hardware instruction when available. +
++ Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that + some float operations are not yet implemented for all float types.
{#header_close#} {#header_open|@ceil#} -{#syntax#}@ceil(comptime T: type, value: T) T{#endsyntax#}
+ {#syntax#}@ceil(value: var) @TypeOf(value){#endsyntax#}
- Returns the largest integral value not less than the given floating point number. Uses a dedicated hardware instruction - when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}. + Returns the largest integral value not less than the given floating point number. + Uses a dedicated hardware instruction when available. +
++ Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that + some float operations are not yet implemented for all float types.
{#header_close#} {#header_open|@trunc#} -{#syntax#}@trunc(comptime T: type, value: T) T{#endsyntax#}
+ {#syntax#}@trunc(value: var) @TypeOf(value){#endsyntax#}
- Rounds the given floating point number to an integer, towards zero. Uses a dedicated hardware instruction - when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}. + Rounds the given floating point number to an integer, towards zero. + Uses a dedicated hardware instruction when available. +
++ Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that + some float operations are not yet implemented for all float types.
{#header_close#} {#header_open|@round#} -{#syntax#}@round(comptime T: type, value: T) T{#endsyntax#}
+ {#syntax#}@round(value: var) @TypeOf(value){#endsyntax#}
Rounds the given floating point number to an integer, away from zero. Uses a dedicated hardware instruction - when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}. + when available. +
++ Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that + some float operations are not yet implemented for all float types.
{#header_close#} diff --git a/lib/std/math/sqrt.zig b/lib/std/math/sqrt.zig index 17c7003af1..493e2cacf6 100644 --- a/lib/std/math/sqrt.zig +++ b/lib/std/math/sqrt.zig @@ -12,12 +12,12 @@ const maxInt = std.math.maxInt; /// - sqrt(+-0) = +-0 /// - sqrt(x) = nan if x < 0 /// - sqrt(nan) = nan -pub fn sqrt(x: var) (if (@typeId(@TypeOf(x)) == TypeId.Int) @IntType(false, @TypeOf(x).bit_count / 2) else @TypeOf(x)) { +/// TODO Decide if all this logic should be implemented directly in the @sqrt bultin function. +pub fn sqrt(x: var) Sqrt(@TypeOf(x)) { const T = @TypeOf(x); - switch (@typeId(T)) { - TypeId.ComptimeFloat => return @as(T, @sqrt(f64, x)), // TODO upgrade to f128 - TypeId.Float => return @sqrt(T, x), - TypeId.ComptimeInt => comptime { + switch (@typeInfo(T)) { + .Float, .ComptimeFloat => return @sqrt(x), + .ComptimeInt => comptime { if (x > maxInt(u128)) { @compileError("sqrt not implemented for comptime_int greater than 128 bits"); } @@ -26,83 +26,11 @@ pub fn sqrt(x: var) (if (@typeId(@TypeOf(x)) == TypeId.Int) @IntType(false, @Typ } return @as(T, sqrt_int(u128, x)); }, - TypeId.Int => return sqrt_int(T, x), + .Int => return sqrt_int(T, x), else => @compileError("sqrt not implemented for " ++ @typeName(T)), } } -test "math.sqrt" { - expect(sqrt(@as(f16, 0.0)) == @sqrt(f16, 0.0)); - expect(sqrt(@as(f32, 0.0)) == @sqrt(f32, 0.0)); - expect(sqrt(@as(f64, 0.0)) == @sqrt(f64, 0.0)); -} - -test "math.sqrt16" { - const epsilon = 0.000001; - - expect(@sqrt(f16, 0.0) == 0.0); - expect(math.approxEq(f16, @sqrt(f16, 2.0), 1.414214, epsilon)); - expect(math.approxEq(f16, @sqrt(f16, 3.6), 1.897367, epsilon)); - expect(@sqrt(f16, 4.0) == 2.0); - expect(math.approxEq(f16, @sqrt(f16, 7.539840), 2.745877, epsilon)); - expect(math.approxEq(f16, @sqrt(f16, 19.230934), 4.385309, epsilon)); - expect(@sqrt(f16, 64.0) == 8.0); - expect(math.approxEq(f16, @sqrt(f16, 64.1), 8.006248, epsilon)); - expect(math.approxEq(f16, @sqrt(f16, 8942.230469), 94.563370, epsilon)); -} - -test "math.sqrt32" { - const epsilon = 0.000001; - - expect(@sqrt(f32, 0.0) == 0.0); - expect(math.approxEq(f32, @sqrt(f32, 2.0), 1.414214, epsilon)); - expect(math.approxEq(f32, @sqrt(f32, 3.6), 1.897367, epsilon)); - expect(@sqrt(f32, 4.0) == 2.0); - expect(math.approxEq(f32, @sqrt(f32, 7.539840), 2.745877, epsilon)); - expect(math.approxEq(f32, @sqrt(f32, 19.230934), 4.385309, epsilon)); - expect(@sqrt(f32, 64.0) == 8.0); - expect(math.approxEq(f32, @sqrt(f32, 64.1), 8.006248, epsilon)); - expect(math.approxEq(f32, @sqrt(f32, 8942.230469), 94.563370, epsilon)); -} - -test "math.sqrt64" { - const epsilon = 0.000001; - - expect(@sqrt(f64, 0.0) == 0.0); - expect(math.approxEq(f64, @sqrt(f64, 2.0), 1.414214, epsilon)); - expect(math.approxEq(f64, @sqrt(f64, 3.6), 1.897367, epsilon)); - expect(@sqrt(f64, 4.0) == 2.0); - expect(math.approxEq(f64, @sqrt(f64, 7.539840), 2.745877, epsilon)); - expect(math.approxEq(f64, @sqrt(f64, 19.230934), 4.385309, epsilon)); - expect(@sqrt(f64, 64.0) == 8.0); - expect(math.approxEq(f64, @sqrt(f64, 64.1), 8.006248, epsilon)); - expect(math.approxEq(f64, @sqrt(f64, 8942.230469), 94.563367, epsilon)); -} - -test "math.sqrt16.special" { - expect(math.isPositiveInf(@sqrt(f16, math.inf(f16)))); - expect(@sqrt(f16, 0.0) == 0.0); - expect(@sqrt(f16, -0.0) == -0.0); - expect(math.isNan(@sqrt(f16, -1.0))); - expect(math.isNan(@sqrt(f16, math.nan(f16)))); -} - -test "math.sqrt32.special" { - expect(math.isPositiveInf(@sqrt(f32, math.inf(f32)))); - expect(@sqrt(f32, 0.0) == 0.0); - expect(@sqrt(f32, -0.0) == -0.0); - expect(math.isNan(@sqrt(f32, -1.0))); - expect(math.isNan(@sqrt(f32, math.nan(f32)))); -} - -test "math.sqrt64.special" { - expect(math.isPositiveInf(@sqrt(f64, math.inf(f64)))); - expect(@sqrt(f64, 0.0) == 0.0); - expect(@sqrt(f64, -0.0) == -0.0); - expect(math.isNan(@sqrt(f64, -1.0))); - expect(math.isNan(@sqrt(f64, math.nan(f64)))); -} - fn sqrt_int(comptime T: type, value: T) @IntType(false, T.bit_count / 2) { var op = value; var res: T = 0; @@ -134,3 +62,12 @@ test "math.sqrt_int" { expect(sqrt_int(u32, 9) == 3); expect(sqrt_int(u32, 10) == 3); } + +/// Returns the return type `sqrt` will return given an operand of type `T`. +pub fn Sqrt(comptime T: type) type { + return switch (@typeInfo(T)) { + .Int => |int| @IntType(false, int.bits / 2), + else => T, + }; +} + diff --git a/lib/std/special/c.zig b/lib/std/special/c.zig index 0895b1e6f9..08c59337c5 100644 --- a/lib/std/special/c.zig +++ b/lib/std/special/c.zig @@ -728,6 +728,29 @@ export fn sqrt(x: f64) f64 { return @bitCast(f64, uz); } +test "sqrt" { + const epsilon = 0.000001; + + std.testing.expect(sqrt(0.0) == 0.0); + std.testing.expect(std.math.approxEq(f64, sqrt(2.0), 1.414214, epsilon)); + std.testing.expect(std.math.approxEq(f64, sqrt(3.6), 1.897367, epsilon)); + std.testing.expect(sqrt(4.0) == 2.0); + std.testing.expect(std.math.approxEq(f64, sqrt(7.539840), 2.745877, epsilon)); + std.testing.expect(std.math.approxEq(f64, sqrt(19.230934), 4.385309, epsilon)); + std.testing.expect(sqrt(64.0) == 8.0); + std.testing.expect(std.math.approxEq(f64, sqrt(64.1), 8.006248, epsilon)); + std.testing.expect(std.math.approxEq(f64, sqrt(8942.230469), 94.563367, epsilon)); +} + +test "sqrt special" { + std.testing.expect(std.math.isPositiveInf(sqrt(std.math.inf(f64)))); + std.testing.expect(sqrt(0.0) == 0.0); + std.testing.expect(sqrt(-0.0) == -0.0); + std.testing.expect(std.math.isNan(sqrt(-1.0))); + std.testing.expect(std.math.isNan(sqrt(std.math.nan(f64)))); +} + + export fn sqrtf(x: f32) f32 { const tiny: f32 = 1.0e-30; const sign: i32 = @bitCast(i32, @as(u32, 0x80000000)); @@ -803,3 +826,26 @@ export fn sqrtf(x: f32) f32 { ix += m << 23; return @bitCast(f32, ix); } + +test "sqrtf" { + const epsilon = 0.000001; + + std.testing.expect(sqrtf(0.0) == 0.0); + std.testing.expect(std.math.approxEq(f32, sqrtf(2.0), 1.414214, epsilon)); + std.testing.expect(std.math.approxEq(f32, sqrtf(3.6), 1.897367, epsilon)); + std.testing.expect(sqrtf(4.0) == 2.0); + std.testing.expect(std.math.approxEq(f32, sqrtf(7.539840), 2.745877, epsilon)); + std.testing.expect(std.math.approxEq(f32, sqrtf(19.230934), 4.385309, epsilon)); + std.testing.expect(sqrtf(64.0) == 8.0); + std.testing.expect(std.math.approxEq(f32, sqrtf(64.1), 8.006248, epsilon)); + std.testing.expect(std.math.approxEq(f32, sqrtf(8942.230469), 94.563370, epsilon)); +} + +test "sqrtf special" { + std.testing.expect(std.math.isPositiveInf(sqrtf(std.math.inf(f32)))); + std.testing.expect(sqrtf(0.0) == 0.0); + std.testing.expect(sqrtf(-0.0) == -0.0); + std.testing.expect(std.math.isNan(sqrtf(-1.0))); + std.testing.expect(std.math.isNan(sqrtf(std.math.nan(f32)))); +} + diff --git a/src/all_types.hpp b/src/all_types.hpp index ea46ab81a6..53fe034246 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -3840,9 +3840,8 @@ struct IrInstructionAddImplicitReturnType { struct IrInstructionFloatOp { IrInstruction base; - BuiltinFnId op; - IrInstruction *type; - IrInstruction *op1; + BuiltinFnId fn_id; + IrInstruction *operand; }; struct IrInstructionCheckRuntimeScope { diff --git a/src/codegen.cpp b/src/codegen.cpp index 734fc3be2b..5500b4029c 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -5785,10 +5785,9 @@ static LLVMValueRef ir_render_atomic_store(CodeGen *g, IrExecutable *executable, } static LLVMValueRef ir_render_float_op(CodeGen *g, IrExecutable *executable, IrInstructionFloatOp *instruction) { - LLVMValueRef op = ir_llvm_value(g, instruction->op1); - assert(instruction->base.value->type->id == ZigTypeIdFloat); - LLVMValueRef fn_val = get_float_fn(g, instruction->base.value->type, ZigLLVMFnIdFloatOp, instruction->op); - return LLVMBuildCall(g->builder, fn_val, &op, 1, ""); + LLVMValueRef operand = ir_llvm_value(g, instruction->operand); + LLVMValueRef fn_val = get_float_fn(g, instruction->base.value->type, ZigLLVMFnIdFloatOp, instruction->fn_id); + return LLVMBuildCall(g->builder, fn_val, &operand, 1, ""); } static LLVMValueRef ir_render_mul_add(CodeGen *g, IrExecutable *executable, IrInstructionMulAdd *instruction) { @@ -8201,20 +8200,20 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdDivFloor, "divFloor", 2); create_builtin_fn(g, BuiltinFnIdRem, "rem", 2); create_builtin_fn(g, BuiltinFnIdMod, "mod", 2); - create_builtin_fn(g, BuiltinFnIdSqrt, "sqrt", 2); - create_builtin_fn(g, BuiltinFnIdSin, "sin", 2); - create_builtin_fn(g, BuiltinFnIdCos, "cos", 2); - create_builtin_fn(g, BuiltinFnIdExp, "exp", 2); - create_builtin_fn(g, BuiltinFnIdExp2, "exp2", 2); - create_builtin_fn(g, BuiltinFnIdLn, "ln", 2); - create_builtin_fn(g, BuiltinFnIdLog2, "log2", 2); - create_builtin_fn(g, BuiltinFnIdLog10, "log10", 2); - create_builtin_fn(g, BuiltinFnIdFabs, "fabs", 2); - create_builtin_fn(g, BuiltinFnIdFloor, "floor", 2); - create_builtin_fn(g, BuiltinFnIdCeil, "ceil", 2); - create_builtin_fn(g, BuiltinFnIdTrunc, "trunc", 2); - create_builtin_fn(g, BuiltinFnIdNearbyInt, "nearbyInt", 2); - create_builtin_fn(g, BuiltinFnIdRound, "round", 2); + create_builtin_fn(g, BuiltinFnIdSqrt, "sqrt", 1); + create_builtin_fn(g, BuiltinFnIdSin, "sin", 1); + create_builtin_fn(g, BuiltinFnIdCos, "cos", 1); + create_builtin_fn(g, BuiltinFnIdExp, "exp", 1); + create_builtin_fn(g, BuiltinFnIdExp2, "exp2", 1); + create_builtin_fn(g, BuiltinFnIdLn, "ln", 1); + create_builtin_fn(g, BuiltinFnIdLog2, "log2", 1); + create_builtin_fn(g, BuiltinFnIdLog10, "log10", 1); + create_builtin_fn(g, BuiltinFnIdFabs, "fabs", 1); + create_builtin_fn(g, BuiltinFnIdFloor, "floor", 1); + create_builtin_fn(g, BuiltinFnIdCeil, "ceil", 1); + create_builtin_fn(g, BuiltinFnIdTrunc, "trunc", 1); + create_builtin_fn(g, BuiltinFnIdNearbyInt, "nearbyInt", 1); + create_builtin_fn(g, BuiltinFnIdRound, "round", 1); create_builtin_fn(g, BuiltinFnIdMulAdd, "mulAdd", 4); create_builtin_fn(g, BuiltinFnIdNewStackCall, "newStackCall", SIZE_MAX); create_builtin_fn(g, BuiltinFnIdAsyncCall, "asyncCall", SIZE_MAX); diff --git a/src/ir.cpp b/src/ir.cpp index fbd9ba7ac0..b013553e28 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -3162,14 +3162,14 @@ const char *float_op_to_name(BuiltinFnId op, bool llvm_name) { } } -static IrInstruction *ir_build_float_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op1, BuiltinFnId op) { +static IrInstruction *ir_build_float_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *operand, + BuiltinFnId fn_id) +{ IrInstructionFloatOp *instruction = ir_build_instruction