Commit 7f0cf395aa
Changed files (15)
src
arch
test
src/arch/aarch64/CodeGen.zig
@@ -528,7 +528,20 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.max => try self.airMax(inst),
.slice => try self.airSlice(inst),
- .sqrt => try self.airUnaryMath(inst),
+ .sqrt,
+ .sin,
+ .cos,
+ .exp,
+ .exp2,
+ .log,
+ .log2,
+ .log10,
+ .fabs,
+ .floor,
+ .ceil,
+ .round,
+ .trunc_float
+ => try self.airUnaryMath(inst),
.add_with_overflow => try self.airAddWithOverflow(inst),
.sub_with_overflow => try self.airSubWithOverflow(inst),
src/arch/arm/CodeGen.zig
@@ -520,7 +520,20 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.max => try self.airMax(inst),
.slice => try self.airSlice(inst),
- .sqrt => try self.airUnaryMath(inst),
+ .sqrt,
+ .sin,
+ .cos,
+ .exp,
+ .exp2,
+ .log,
+ .log2,
+ .log10,
+ .fabs,
+ .floor,
+ .ceil,
+ .round,
+ .trunc_float,
+ => try self.airUnaryMath(inst),
.add_with_overflow => try self.airAddWithOverflow(inst),
.sub_with_overflow => try self.airSubWithOverflow(inst),
src/arch/riscv64/CodeGen.zig
@@ -507,7 +507,20 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.max => try self.airMax(inst),
.slice => try self.airSlice(inst),
- .sqrt => try self.airUnaryMath(inst),
+ .sqrt,
+ .sin,
+ .cos,
+ .exp,
+ .exp2,
+ .log,
+ .log2,
+ .log10,
+ .fabs,
+ .floor,
+ .ceil,
+ .round,
+ .trunc_float,
+ => try self.airUnaryMath(inst),
.add_with_overflow => try self.airAddWithOverflow(inst),
.sub_with_overflow => try self.airSubWithOverflow(inst),
src/arch/wasm/CodeGen.zig
@@ -1679,6 +1679,18 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
.unwrap_errunion_err_ptr,
.sqrt,
+ .sin,
+ .cos,
+ .exp,
+ .exp2,
+ .log,
+ .log2,
+ .log10,
+ .fabs,
+ .floor,
+ .ceil,
+ .round,
+ .trunc_float,
.ptr_slice_len_ptr,
.ptr_slice_ptr_ptr,
src/arch/x86_64/CodeGen.zig
@@ -599,7 +599,20 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.max => try self.airMax(inst),
.slice => try self.airSlice(inst),
- .sqrt => try self.airUnaryMath(inst),
+ .sqrt,
+ .sin,
+ .cos,
+ .exp,
+ .exp2,
+ .log,
+ .log2,
+ .log10,
+ .fabs,
+ .floor,
+ .ceil,
+ .round,
+ .trunc_float,
+ => try self.airUnaryMath(inst),
.add_with_overflow => try self.airAddWithOverflow(inst),
.sub_with_overflow => try self.airSubWithOverflow(inst),
src/codegen/c.zig
@@ -1446,7 +1446,20 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
.mul_sat => try airSatOp(f, inst, "muls_"),
.shl_sat => try airSatOp(f, inst, "shls_"),
- .sqrt => try airSqrt(f, inst),
+ .sqrt,
+ .sin,
+ .cos,
+ .exp,
+ .exp2,
+ .log,
+ .log2,
+ .log10,
+ .fabs,
+ .floor,
+ .ceil,
+ .round,
+ .trunc_float,
+ => |tag| return f.fail("TODO: C backend: implement unary op for tag '{s}'", .{@tagName(tag)}),
.add_with_overflow => try airAddWithOverflow(f, inst),
.sub_with_overflow => try airSubWithOverflow(f, inst),
@@ -3395,12 +3408,6 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
return CValue.none;
}
-fn airSqrt(f: *Function, inst: Air.Inst.Index) !CValue {
- _ = f;
- _ = inst;
- return f.fail("TODO: C backend: implement sqrt", .{});
-}
-
fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 {
return switch (order) {
.Unordered => "memory_order_relaxed",
src/codegen/llvm.zig
@@ -2050,7 +2050,19 @@ pub const FuncGen = struct {
.shr => try self.airShr(inst, false),
.shr_exact => try self.airShr(inst, true),
- .sqrt => try self.airSqrt(inst),
+ .sqrt => try self.airUnaryOp(inst, "llvm.sqrt"),
+ .sin => try self.airUnaryOp(inst, "llvm.sin"),
+ .cos => try self.airUnaryOp(inst, "llvm.cos"),
+ .exp => try self.airUnaryOp(inst, "llvm.exp"),
+ .exp2 => try self.airUnaryOp(inst, "llvm.exp2"),
+ .log => try self.airUnaryOp(inst, "llvm.log"),
+ .log2 => try self.airUnaryOp(inst, "llvm.log2"),
+ .log10 => try self.airUnaryOp(inst, "llvm.log10"),
+ .fabs => try self.airUnaryOp(inst, "llvm.fabs"),
+ .floor => try self.airUnaryOp(inst, "llvm.floor"),
+ .ceil => try self.airUnaryOp(inst, "llvm.ceil"),
+ .round => try self.airUnaryOp(inst, "llvm.round"),
+ .trunc_float => try self.airUnaryOp(inst, "llvm.trunc"),
.cmp_eq => try self.airCmp(inst, .eq),
.cmp_gt => try self.airCmp(inst, .gt),
@@ -4213,7 +4225,7 @@ pub const FuncGen = struct {
}
}
- fn airSqrt(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ fn airUnaryOp(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*const llvm.Value {
if (self.liveness.isUnused(inst)) return null;
const un_op = self.air.instructions.items(.data)[inst].un_op;
@@ -4221,7 +4233,7 @@ pub const FuncGen = struct {
const operand_ty = self.air.typeOf(un_op);
const operand_llvm_ty = try self.dg.llvmType(operand_ty);
- const fn_val = self.getIntrinsic("llvm.sqrt", &.{operand_llvm_ty});
+ const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty});
const params = [_]*const llvm.Value{operand};
return self.builder.buildCall(fn_val, ¶ms, params.len, .C, .Auto, "");
src/Air.zig
@@ -237,9 +237,45 @@ pub const Inst = struct {
/// Uses the `ty_op` field.
popcount,
- /// Computes the square root of a floating point number.
+ /// Square root of a floating point number.
/// Uses the `un_op` field.
sqrt,
+ /// Sine a floating point number.
+ /// Uses the `un_op` field.
+ sin,
+ /// Cosine a floating point number.
+ /// Uses the `un_op` field.
+ cos,
+ /// Base e exponential of a floating point number.
+ /// Uses the `un_op` field.
+ exp,
+ /// Base 2 exponential of a floating point number.
+ /// Uses the `un_op` field.
+ exp2,
+ /// Natural (base e) logarithm of a floating point number.
+ /// Uses the `un_op` field.
+ log,
+ /// Base 2 logarithm of a floating point number.
+ /// Uses the `un_op` field.
+ log2,
+ /// Base 10 logarithm of a floating point number.
+ /// Uses the `un_op` field.
+ log10,
+ /// Aboslute value of a floating point number.
+ /// Uses the `un_op` field.
+ fabs,
+ /// Floor: rounds a floating pointer number down to the nearest integer.
+ /// Uses the `un_op` field.
+ floor,
+ /// Ceiling: rounds a floating pointer number up to the nearest integer.
+ /// Uses the `un_op` field.
+ ceil,
+ /// Rounds a floating pointer number to the nearest integer.
+ /// Uses the `un_op` field.
+ round,
+ /// Rounds a floating pointer number to the nearest integer towards zero.
+ /// Uses the `un_op` field.
+ trunc_float,
/// `<`. Result type is always bool.
/// Uses the `bin_op` field.
@@ -754,7 +790,20 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
.max,
=> return air.typeOf(datas[inst].bin_op.lhs),
- .sqrt => return air.typeOf(datas[inst].un_op),
+ .sqrt,
+ .sin,
+ .cos,
+ .exp,
+ .exp2,
+ .log,
+ .log2,
+ .log10,
+ .fabs,
+ .floor,
+ .ceil,
+ .round,
+ .trunc_float,
+ => return air.typeOf(datas[inst].un_op),
.cmp_lt,
.cmp_lte,
src/Liveness.zig
@@ -339,6 +339,18 @@ fn analyzeInst(
.tag_name,
.error_name,
.sqrt,
+ .sin,
+ .cos,
+ .exp,
+ .exp2,
+ .log,
+ .log2,
+ .log10,
+ .fabs,
+ .floor,
+ .ceil,
+ .round,
+ .trunc_float,
=> {
const operand = inst_datas[inst].un_op;
return trackOperands(a, new_set, inst, main_tomb, .{ operand, .none, .none });
src/print_air.zig
@@ -159,6 +159,18 @@ const Writer = struct {
.tag_name,
.error_name,
.sqrt,
+ .sin,
+ .cos,
+ .exp,
+ .exp2,
+ .log,
+ .log2,
+ .log10,
+ .fabs,
+ .floor,
+ .ceil,
+ .round,
+ .trunc_float,
=> try w.writeUnOp(s, inst),
.breakpoint,
src/Sema.zig
@@ -747,18 +747,18 @@ fn analyzeBodyInner(
.ctz => try sema.zirClzCtz(block, inst, .ctz, Value.ctz),
.sqrt => try sema.zirUnaryMath(block, inst, .sqrt, Value.sqrt),
- .sin => @panic("TODO"),
- .cos => @panic("TODO"),
- .exp => @panic("TODO"),
- .exp2 => @panic("TODO"),
- .log => @panic("TODO"),
- .log2 => @panic("TODO"),
- .log10 => @panic("TODO"),
- .fabs => @panic("TODO"),
- .floor => @panic("TODO"),
- .ceil => @panic("TODO"),
- .trunc => @panic("TODO"),
- .round => @panic("TODO"),
+ .sin => try sema.zirUnaryMath(block, inst, .sin, Value.sin),
+ .cos => try sema.zirUnaryMath(block, inst, .cos, Value.cos),
+ .exp => try sema.zirUnaryMath(block, inst, .exp, Value.exp),
+ .exp2 => try sema.zirUnaryMath(block, inst, .exp2, Value.exp2),
+ .log => try sema.zirUnaryMath(block, inst, .log, Value.log),
+ .log2 => try sema.zirUnaryMath(block, inst, .log2, Value.log2),
+ .log10 => try sema.zirUnaryMath(block, inst, .log10, Value.log10),
+ .fabs => try sema.zirUnaryMath(block, inst, .fabs, Value.fabs),
+ .floor => try sema.zirUnaryMath(block, inst, .floor, Value.floor),
+ .ceil => try sema.zirUnaryMath(block, inst, .ceil, Value.ceil),
+ .round => try sema.zirUnaryMath(block, inst, .round, Value.round),
+ .trunc => try sema.zirUnaryMath(block, inst, .trunc_float, Value.trunc),
.error_set_decl => try sema.zirErrorSetDecl(block, inst, .parent),
.error_set_decl_anon => try sema.zirErrorSetDecl(block, inst, .anon),
src/value.zig
@@ -3308,6 +3308,390 @@ pub const Value = extern union {
}
}
+ pub fn sin(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ switch (float_type.floatBits(target)) {
+ 16 => {
+ const f = val.toFloat(f16);
+ return Value.Tag.float_16.create(arena, @sin(f));
+ },
+ 32 => {
+ const f = val.toFloat(f32);
+ return Value.Tag.float_32.create(arena, @sin(f));
+ },
+ 64 => {
+ const f = val.toFloat(f64);
+ return Value.Tag.float_64.create(arena, @sin(f));
+ },
+ 80 => {
+ if (true) {
+ @panic("TODO implement compiler_rt sin for f80");
+ }
+ const f = val.toFloat(f80);
+ return Value.Tag.float_80.create(arena, @sin(f));
+ },
+ 128 => {
+ if (true) {
+ @panic("TODO implement compiler_rt sin for f128");
+ }
+ const f = val.toFloat(f128);
+ return Value.Tag.float_128.create(arena, @sin(f));
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn cos(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ switch (float_type.floatBits(target)) {
+ 16 => {
+ const f = val.toFloat(f16);
+ return Value.Tag.float_16.create(arena, @cos(f));
+ },
+ 32 => {
+ const f = val.toFloat(f32);
+ return Value.Tag.float_32.create(arena, @cos(f));
+ },
+ 64 => {
+ const f = val.toFloat(f64);
+ return Value.Tag.float_64.create(arena, @cos(f));
+ },
+ 80 => {
+ if (true) {
+ @panic("TODO implement compiler_rt cos for f80");
+ }
+ const f = val.toFloat(f80);
+ return Value.Tag.float_80.create(arena, @cos(f));
+ },
+ 128 => {
+ if (true) {
+ @panic("TODO implement compiler_rt cos for f128");
+ }
+ const f = val.toFloat(f128);
+ return Value.Tag.float_128.create(arena, @cos(f));
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn exp(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ switch (float_type.floatBits(target)) {
+ 16 => {
+ const f = val.toFloat(f16);
+ return Value.Tag.float_16.create(arena, @exp(f));
+ },
+ 32 => {
+ const f = val.toFloat(f32);
+ return Value.Tag.float_32.create(arena, @exp(f));
+ },
+ 64 => {
+ const f = val.toFloat(f64);
+ return Value.Tag.float_64.create(arena, @exp(f));
+ },
+ 80 => {
+ if (true) {
+ @panic("TODO implement compiler_rt exp for f80");
+ }
+ const f = val.toFloat(f80);
+ return Value.Tag.float_80.create(arena, @exp(f));
+ },
+ 128 => {
+ if (true) {
+ @panic("TODO implement compiler_rt exp for f128");
+ }
+ const f = val.toFloat(f128);
+ return Value.Tag.float_128.create(arena, @exp(f));
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn exp2(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ switch (float_type.floatBits(target)) {
+ 16 => {
+ const f = val.toFloat(f16);
+ return Value.Tag.float_16.create(arena, @exp2(f));
+ },
+ 32 => {
+ const f = val.toFloat(f32);
+ return Value.Tag.float_32.create(arena, @exp2(f));
+ },
+ 64 => {
+ const f = val.toFloat(f64);
+ return Value.Tag.float_64.create(arena, @exp2(f));
+ },
+ 80 => {
+ if (true) {
+ @panic("TODO implement compiler_rt exp2 for f80");
+ }
+ const f = val.toFloat(f80);
+ return Value.Tag.float_80.create(arena, @exp2(f));
+ },
+ 128 => {
+ if (true) {
+ @panic("TODO implement compiler_rt exp2 for f128");
+ }
+ const f = val.toFloat(f128);
+ return Value.Tag.float_128.create(arena, @exp2(f));
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn log(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ switch (float_type.floatBits(target)) {
+ 16 => {
+ const f = val.toFloat(f16);
+ return Value.Tag.float_16.create(arena, @log(f));
+ },
+ 32 => {
+ const f = val.toFloat(f32);
+ return Value.Tag.float_32.create(arena, @log(f));
+ },
+ 64 => {
+ const f = val.toFloat(f64);
+ return Value.Tag.float_64.create(arena, @log(f));
+ },
+ 80 => {
+ if (true) {
+ @panic("TODO implement compiler_rt log for f80");
+ }
+ const f = val.toFloat(f80);
+ return Value.Tag.float_80.create(arena, @log(f));
+ },
+ 128 => {
+ if (true) {
+ @panic("TODO implement compiler_rt log for f128");
+ }
+ const f = val.toFloat(f128);
+ return Value.Tag.float_128.create(arena, @log(f));
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn log2(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ switch (float_type.floatBits(target)) {
+ 16 => {
+ const f = val.toFloat(f16);
+ return Value.Tag.float_16.create(arena, @log2(f));
+ },
+ 32 => {
+ const f = val.toFloat(f32);
+ return Value.Tag.float_32.create(arena, @log2(f));
+ },
+ 64 => {
+ const f = val.toFloat(f64);
+ return Value.Tag.float_64.create(arena, @log2(f));
+ },
+ 80 => {
+ if (true) {
+ @panic("TODO implement compiler_rt log2 for f80");
+ }
+ const f = val.toFloat(f80);
+ return Value.Tag.float_80.create(arena, @log2(f));
+ },
+ 128 => {
+ if (true) {
+ @panic("TODO implement compiler_rt log2 for f128");
+ }
+ const f = val.toFloat(f128);
+ return Value.Tag.float_128.create(arena, @log2(f));
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn log10(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ switch (float_type.floatBits(target)) {
+ 16 => {
+ const f = val.toFloat(f16);
+ return Value.Tag.float_16.create(arena, @log10(f));
+ },
+ 32 => {
+ const f = val.toFloat(f32);
+ return Value.Tag.float_32.create(arena, @log10(f));
+ },
+ 64 => {
+ const f = val.toFloat(f64);
+ return Value.Tag.float_64.create(arena, @log10(f));
+ },
+ 80 => {
+ if (true) {
+ @panic("TODO implement compiler_rt log10 for f80");
+ }
+ const f = val.toFloat(f80);
+ return Value.Tag.float_80.create(arena, @log10(f));
+ },
+ 128 => {
+ if (true) {
+ @panic("TODO implement compiler_rt log10 for f128");
+ }
+ const f = val.toFloat(f128);
+ return Value.Tag.float_128.create(arena, @log10(f));
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn fabs(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ switch (float_type.floatBits(target)) {
+ 16 => {
+ const f = val.toFloat(f16);
+ return Value.Tag.float_16.create(arena, @fabs(f));
+ },
+ 32 => {
+ const f = val.toFloat(f32);
+ return Value.Tag.float_32.create(arena, @fabs(f));
+ },
+ 64 => {
+ const f = val.toFloat(f64);
+ return Value.Tag.float_64.create(arena, @fabs(f));
+ },
+ 80 => {
+ if (true) {
+ @panic("TODO implement compiler_rt fabs for f80");
+ }
+ const f = val.toFloat(f80);
+ return Value.Tag.float_80.create(arena, @fabs(f));
+ },
+ 128 => {
+ if (true) {
+ @panic("TODO implement compiler_rt fabs for f128");
+ }
+ const f = val.toFloat(f128);
+ return Value.Tag.float_128.create(arena, @fabs(f));
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn floor(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ switch (float_type.floatBits(target)) {
+ 16 => {
+ const f = val.toFloat(f16);
+ return Value.Tag.float_16.create(arena, @floor(f));
+ },
+ 32 => {
+ const f = val.toFloat(f32);
+ return Value.Tag.float_32.create(arena, @floor(f));
+ },
+ 64 => {
+ const f = val.toFloat(f64);
+ return Value.Tag.float_64.create(arena, @floor(f));
+ },
+ 80 => {
+ if (true) {
+ @panic("TODO implement compiler_rt floor for f80");
+ }
+ const f = val.toFloat(f80);
+ return Value.Tag.float_80.create(arena, @floor(f));
+ },
+ 128 => {
+ if (true) {
+ @panic("TODO implement compiler_rt floor for f128");
+ }
+ const f = val.toFloat(f128);
+ return Value.Tag.float_128.create(arena, @floor(f));
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn ceil(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ switch (float_type.floatBits(target)) {
+ 16 => {
+ const f = val.toFloat(f16);
+ return Value.Tag.float_16.create(arena, @ceil(f));
+ },
+ 32 => {
+ const f = val.toFloat(f32);
+ return Value.Tag.float_32.create(arena, @ceil(f));
+ },
+ 64 => {
+ const f = val.toFloat(f64);
+ return Value.Tag.float_64.create(arena, @ceil(f));
+ },
+ 80 => {
+ if (true) {
+ @panic("TODO implement compiler_rt ceil for f80");
+ }
+ const f = val.toFloat(f80);
+ return Value.Tag.float_80.create(arena, @ceil(f));
+ },
+ 128 => {
+ if (true) {
+ @panic("TODO implement compiler_rt ceil for f128");
+ }
+ const f = val.toFloat(f128);
+ return Value.Tag.float_128.create(arena, @ceil(f));
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn round(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ switch (float_type.floatBits(target)) {
+ 16 => {
+ const f = val.toFloat(f16);
+ return Value.Tag.float_16.create(arena, @round(f));
+ },
+ 32 => {
+ const f = val.toFloat(f32);
+ return Value.Tag.float_32.create(arena, @round(f));
+ },
+ 64 => {
+ const f = val.toFloat(f64);
+ return Value.Tag.float_64.create(arena, @round(f));
+ },
+ 80 => {
+ if (true) {
+ @panic("TODO implement compiler_rt round for f80");
+ }
+ const f = val.toFloat(f80);
+ return Value.Tag.float_80.create(arena, @round(f));
+ },
+ 128 => {
+ if (true) {
+ @panic("TODO implement compiler_rt round for f128");
+ }
+ const f = val.toFloat(f128);
+ return Value.Tag.float_128.create(arena, @round(f));
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn trunc(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ switch (float_type.floatBits(target)) {
+ 16 => {
+ const f = val.toFloat(f16);
+ return Value.Tag.float_16.create(arena, @trunc(f));
+ },
+ 32 => {
+ const f = val.toFloat(f32);
+ return Value.Tag.float_32.create(arena, @trunc(f));
+ },
+ 64 => {
+ const f = val.toFloat(f64);
+ return Value.Tag.float_64.create(arena, @trunc(f));
+ },
+ 80 => {
+ if (true) {
+ @panic("TODO implement compiler_rt trunc for f80");
+ }
+ const f = val.toFloat(f80);
+ return Value.Tag.float_80.create(arena, @trunc(f));
+ },
+ 128 => {
+ if (true) {
+ @panic("TODO implement compiler_rt trunc for f128");
+ }
+ const f = val.toFloat(f128);
+ return Value.Tag.float_128.create(arena, @trunc(f));
+ },
+ else => unreachable,
+ }
+ }
+
/// This type is not copyable since it may contain pointers to its inner data.
pub const Payload = struct {
tag: Tag,
test/behavior/floatop.zig
@@ -1,12 +1,22 @@
const std = @import("std");
+const builtin = @import("builtin");
const expect = std.testing.expect;
const math = std.math;
const pi = std.math.pi;
const e = std.math.e;
const Vector = std.meta.Vector;
+const has_f80_rt = @import("builtin").cpu.arch == .x86_64;
+const epsilon_16 = 0.001;
const epsilon = 0.000001;
+fn epsForType(comptime T: type) T {
+ return switch (T) {
+ f16 => @as(f16, epsilon_16),
+ else => @as(T, epsilon),
+ };
+}
+
test "floating point comparisons" {
try testFloatComparisons();
comptime try testFloatComparisons();
@@ -79,19 +89,37 @@ test "@sqrt" {
}
fn testSqrt() !void {
- {
- var a: f16 = 4;
- try expect(@sqrt(a) == 2);
- }
- {
- var a: f32 = 9;
- try expect(@sqrt(a) == 3);
- var b: f32 = 1.1;
- try expect(math.approxEqAbs(f32, @sqrt(b), 1.0488088481701516, epsilon));
- }
- {
- var a: f64 = 25;
- try expect(@sqrt(a) == 5);
+ try expect(@sqrt(@as(f16, 4)) == 2);
+ try expect(@sqrt(@as(f32, 9)) == 3);
+ try expect(@sqrt(@as(f64, 25)) == 5);
+ try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 1.1)), 1.0488088481701516, epsilon));
+ try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 2.0)), 1.4142135623730950, epsilon));
+
+ if (builtin.zig_backend == .stage1) {
+ if (has_f80_rt) {
+ var a: f80 = 25;
+ try expect(@sqrt(a) == 5);
+ }
+ {
+ const a: comptime_float = 25.0;
+ try expect(@sqrt(a) == 5.0);
+ }
+ // TODO test f128, and c_longdouble
+ // https://github.com/ziglang/zig/issues/4026
+ //{
+ // var a: f128 = 49;
+ //try expect(@sqrt(a) == 7);
+ //}
+
+ // TODO Implement Vector support for stage2
+ {
+ var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
+ var result = @sqrt(v);
+ try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 1.1)), result[0], epsilon));
+ try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 2.2)), result[1], epsilon));
+ try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 3.3)), result[2], epsilon));
+ try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 4.4)), result[3], epsilon));
+ }
}
}
@@ -114,3 +142,311 @@ test "more @sqrt f16 tests" {
try expect(math.isNan(@sqrt(@as(f16, -1.0))));
try expect(math.isNan(@sqrt(@as(f16, math.nan(f16)))));
}
+
+test "@sin" {
+ comptime try testSin();
+ try testSin();
+}
+
+fn testSin() !void {
+ // TODO: Implement Vector support for other backends
+ if (builtin.zig_backend == .stage1) {
+ var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
+ var result = @sin(v);
+ try expect(math.approxEqAbs(f32, @sin(@as(f32, 1.1)), result[0], epsilon));
+ try expect(math.approxEqAbs(f32, @sin(@as(f32, 2.2)), result[1], epsilon));
+ try expect(math.approxEqAbs(f32, @sin(@as(f32, 3.3)), result[2], epsilon));
+ try expect(math.approxEqAbs(f32, @sin(@as(f32, 4.4)), result[3], epsilon));
+
+ // stage1 emits an incorrect compile error for `@as(ty, std.math.pi / 2)`
+ // so skip the rest of the tests.
+ return;
+ }
+
+ inline for ([_]type{ f16, f32, f64 }) |ty| {
+ const eps = epsForType(ty);
+ try expect(@sin(@as(ty, 0)) == 0);
+ try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi)), 0, eps));
+ try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi / 2)), 1, eps));
+ try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi / 4)), 0.7071067811865475, eps));
+ }
+}
+
+test "@cos" {
+ comptime try testCos();
+ try testCos();
+}
+
+fn testCos() !void {
+ // TODO: Implement Vector support for other backends
+ if (builtin.zig_backend == .stage1) {
+ var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
+ var result = @cos(v);
+ try expect(math.approxEqAbs(f32, @cos(@as(f32, 1.1)), result[0], epsilon));
+ try expect(math.approxEqAbs(f32, @cos(@as(f32, 2.2)), result[1], epsilon));
+ try expect(math.approxEqAbs(f32, @cos(@as(f32, 3.3)), result[2], epsilon));
+ try expect(math.approxEqAbs(f32, @cos(@as(f32, 4.4)), result[3], epsilon));
+
+ // stage1 emits an incorrect compile error for `@as(ty, std.math.pi / 2)`
+ // so skip the rest of the tests.
+ return;
+ }
+
+ inline for ([_]type{ f16, f32, f64 }) |ty| {
+ const eps = epsForType(ty);
+ try expect(@cos(@as(ty, 0)) == 1);
+ try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi)), -1, eps));
+ try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi / 2)), 0, eps));
+ try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi / 4)), 0.7071067811865475, eps));
+ }
+}
+
+test "@exp" {
+ comptime try testExp();
+ try testExp();
+}
+
+fn testExp() !void {
+ inline for ([_]type{ f16, f32, f64 }) |ty| {
+ const eps = epsForType(ty);
+ try expect(@exp(@as(ty, 0)) == 1);
+ try expect(math.approxEqAbs(ty, @exp(@as(ty, 2)), 7.389056098930650, eps));
+ try expect(math.approxEqAbs(ty, @exp(@as(ty, 5)), 148.4131591025766, eps));
+ }
+
+ // TODO: Implement Vector support for other backends
+ if (builtin.zig_backend == .stage1) {
+ var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
+ var result = @exp(v);
+ try expect(math.approxEqAbs(f32, @exp(@as(f32, 1.1)), result[0], epsilon));
+ try expect(math.approxEqAbs(f32, @exp(@as(f32, 2.2)), result[1], epsilon));
+ try expect(math.approxEqAbs(f32, @exp(@as(f32, 0.3)), result[2], epsilon));
+ try expect(math.approxEqAbs(f32, @exp(@as(f32, 0.4)), result[3], epsilon));
+ }
+}
+
+test "@exp2" {
+ comptime try testExp2();
+ try testExp2();
+}
+
+fn testExp2() !void {
+ inline for ([_]type{ f16, f32, f64 }) |ty| {
+ const eps = epsForType(ty);
+ try expect(@exp2(@as(ty, 2)) == 4);
+ try expect(math.approxEqAbs(ty, @exp2(@as(ty, 1.5)), 2.8284271247462, eps));
+ try expect(math.approxEqAbs(ty, @exp2(@as(ty, 4.5)), 22.627416997969, eps));
+ }
+
+ // TODO: Implement Vector support for other backends
+ if (builtin.zig_backend == .stage1) {
+ var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
+ var result = @exp2(v);
+ try expect(math.approxEqAbs(f32, @exp2(@as(f32, 1.1)), result[0], epsilon));
+ try expect(math.approxEqAbs(f32, @exp2(@as(f32, 2.2)), result[1], epsilon));
+ try expect(math.approxEqAbs(f32, @exp2(@as(f32, 0.3)), result[2], epsilon));
+ try expect(math.approxEqAbs(f32, @exp2(@as(f32, 0.4)), result[3], epsilon));
+ }
+}
+
+test "@log" {
+ // Old musl (and glibc?), and our current math.ln implementation do not return 1
+ // so also accept those values.
+ comptime try testLog();
+ try testLog();
+}
+
+fn testLog() !void {
+ {
+ var a: f16 = e;
+ try expect(math.approxEqAbs(f16, @log(a), 1, epsilon));
+ }
+ {
+ var a: f32 = e;
+ try expect(@log(a) == 1 or @log(a) == @bitCast(f32, @as(u32, 0x3f7fffff)));
+ }
+ {
+ var a: f64 = e;
+ try expect(@log(a) == 1 or @log(a) == @bitCast(f64, @as(u64, 0x3ff0000000000000)));
+ }
+ inline for ([_]type{ f16, f32, f64 }) |ty| {
+ const eps = epsForType(ty);
+ try expect(math.approxEqAbs(ty, @log(@as(ty, 2)), 0.6931471805599, eps));
+ try expect(math.approxEqAbs(ty, @log(@as(ty, 5)), 1.6094379124341, eps));
+ }
+
+ // TODO: Implement Vector support for other backends
+ if (builtin.zig_backend == .stage1) {
+ var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
+ var result = @log(v);
+ try expect(math.approxEqAbs(f32, @log(@as(f32, 1.1)), result[0], epsilon));
+ try expect(math.approxEqAbs(f32, @log(@as(f32, 2.2)), result[1], epsilon));
+ try expect(math.approxEqAbs(f32, @log(@as(f32, 0.3)), result[2], epsilon));
+ try expect(math.approxEqAbs(f32, @log(@as(f32, 0.4)), result[3], epsilon));
+ }
+}
+
+test "@log2" {
+ comptime try testLog2();
+ try testLog2();
+}
+
+fn testLog2() !void {
+ inline for ([_]type{ f16, f32, f64 }) |ty| {
+ const eps = epsForType(ty);
+ try expect(@log2(@as(ty, 4)) == 2);
+ try expect(math.approxEqAbs(ty, @log2(@as(ty, 6)), 2.5849625007212, eps));
+ try expect(math.approxEqAbs(ty, @log2(@as(ty, 10)), 3.3219280948874, eps));
+ }
+
+ // TODO: Implement Vector support for other backends
+ if (builtin.zig_backend == .stage1) {
+ var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
+ var result = @log2(v);
+ try expect(math.approxEqAbs(f32, @log2(@as(f32, 1.1)), result[0], epsilon));
+ try expect(math.approxEqAbs(f32, @log2(@as(f32, 2.2)), result[1], epsilon));
+ try expect(math.approxEqAbs(f32, @log2(@as(f32, 0.3)), result[2], epsilon));
+ try expect(math.approxEqAbs(f32, @log2(@as(f32, 0.4)), result[3], epsilon));
+ }
+}
+
+test "@log10" {
+ comptime try testLog10();
+ try testLog10();
+}
+
+fn testLog10() !void {
+ inline for ([_]type{ f16, f32, f64 }) |ty| {
+ const eps = epsForType(ty);
+ try expect(@log10(@as(ty, 100)) == 2);
+ try expect(math.approxEqAbs(ty, @log10(@as(ty, 15)), 1.176091259056, eps));
+ try expect(math.approxEqAbs(ty, @log10(@as(ty, 50)), 1.698970004336, eps));
+ }
+
+ // TODO: Implement Vector support for other backends
+ if (builtin.zig_backend == .stage1) {
+ var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
+ var result = @log10(v);
+ try expect(math.approxEqAbs(f32, @log10(@as(f32, 1.1)), result[0], epsilon));
+ try expect(math.approxEqAbs(f32, @log10(@as(f32, 2.2)), result[1], epsilon));
+ try expect(math.approxEqAbs(f32, @log10(@as(f32, 0.3)), result[2], epsilon));
+ try expect(math.approxEqAbs(f32, @log10(@as(f32, 0.4)), result[3], epsilon));
+ }
+}
+
+test "@fabs" {
+ comptime try testFabs();
+ try testFabs();
+}
+
+fn testFabs() !void {
+ try expect(@fabs(@as(f16, -2.5)) == 2.5);
+ try expect(@fabs(@as(f16, 2.5)) == 2.5);
+ try expect(@fabs(@as(f32, -2.5)) == 2.5);
+ try expect(@fabs(@as(f32, 2.5)) == 2.5);
+ try expect(@fabs(@as(f64, -2.5)) == 2.5);
+ try expect(@fabs(@as(f64, 2.5)) == 2.5);
+
+ // TODO test f128, and c_longdouble
+ // https://github.com/ziglang/zig/issues/4026
+ // {
+ // var a: f80 = -2.5;
+ // var b: f80 = 2.5;
+ // try expect(@fabs(a) == 2.5);
+ // try expect(@fabs(b) == 2.5);
+ // }
+
+ // TODO: Implement Vector support for other backends
+ if (builtin.zig_backend == .stage1) {
+ var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
+ var result = @fabs(v);
+ try expect(math.approxEqAbs(f32, @fabs(@as(f32, 1.1)), result[0], epsilon));
+ try expect(math.approxEqAbs(f32, @fabs(@as(f32, -2.2)), result[1], epsilon));
+ try expect(math.approxEqAbs(f32, @fabs(@as(f32, 0.3)), result[2], epsilon));
+ try expect(math.approxEqAbs(f32, @fabs(@as(f32, -0.4)), result[3], epsilon));
+ }
+}
+
+test "@floor" {
+ comptime try testFloor();
+ try testFloor();
+}
+
+fn testFloor() !void {
+ try expect(@floor(@as(f16, 2.1)) == 2);
+ try expect(@floor(@as(f32, 2.1)) == 2);
+ try expect(@floor(@as(f64, 3.5)) == 3);
+
+ // TODO test f128, and c_longdouble
+ // https://github.com/ziglang/zig/issues/4026
+ // {
+ // var a: f80 = 3.5;
+ // try expect(@floor(a) == 3);
+ // }
+
+ // TODO: Implement Vector support for other backends
+ if (builtin.zig_backend == .stage1) {
+ var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
+ var result = @floor(v);
+ try expect(math.approxEqAbs(f32, @floor(@as(f32, 1.1)), result[0], epsilon));
+ try expect(math.approxEqAbs(f32, @floor(@as(f32, -2.2)), result[1], epsilon));
+ try expect(math.approxEqAbs(f32, @floor(@as(f32, 0.3)), result[2], epsilon));
+ try expect(math.approxEqAbs(f32, @floor(@as(f32, -0.4)), result[3], epsilon));
+ }
+}
+
+test "@ceil" {
+ comptime try testCeil();
+ try testCeil();
+}
+
+fn testCeil() !void {
+ try expect(@ceil(@as(f16, 2.1)) == 3);
+ try expect(@ceil(@as(f32, 2.1)) == 3);
+ try expect(@ceil(@as(f64, 3.5)) == 4);
+
+ // TODO test f128, and c_longdouble
+ // https://github.com/ziglang/zig/issues/4026
+ // {
+ // var a: f80 = 3.5;
+ // try expect(@ceil(a) == 4);
+ // }
+
+ // TODO: Implement Vector support for other backends
+ if (builtin.zig_backend == .stage1) {
+ var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
+ var result = @ceil(v);
+ try expect(math.approxEqAbs(f32, @ceil(@as(f32, 1.1)), result[0], epsilon));
+ try expect(math.approxEqAbs(f32, @ceil(@as(f32, -2.2)), result[1], epsilon));
+ try expect(math.approxEqAbs(f32, @ceil(@as(f32, 0.3)), result[2], epsilon));
+ try expect(math.approxEqAbs(f32, @ceil(@as(f32, -0.4)), result[3], epsilon));
+ }
+}
+
+test "@trunc" {
+ comptime try testTrunc();
+ try testTrunc();
+}
+
+fn testTrunc() !void {
+ try expect(@trunc(@as(f16, 2.1)) == 2);
+ try expect(@trunc(@as(f32, 2.1)) == 2);
+ try expect(@trunc(@as(f64, -3.5)) == -3);
+
+ // TODO test f128, and c_longdouble
+ // https://github.com/ziglang/zig/issues/4026
+ // {
+ // var a: f80 = -3.5;
+ // try expect(@trunc(a) == -3);
+ // }
+
+ // TODO: Implement Vector support for other backends
+ if (builtin.zig_backend == .stage1) {
+ var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
+ var result = @trunc(v);
+ try expect(math.approxEqAbs(f32, @trunc(@as(f32, 1.1)), result[0], epsilon));
+ try expect(math.approxEqAbs(f32, @trunc(@as(f32, -2.2)), result[1], epsilon));
+ try expect(math.approxEqAbs(f32, @trunc(@as(f32, 0.3)), result[2], epsilon));
+ try expect(math.approxEqAbs(f32, @trunc(@as(f32, -0.4)), result[3], epsilon));
+ }
+}
test/behavior/floatop_stage1.zig
@@ -1,452 +0,0 @@
-const std = @import("std");
-const expect = std.testing.expect;
-const math = std.math;
-const pi = std.math.pi;
-const e = std.math.e;
-const Vector = std.meta.Vector;
-const has_f80_rt = @import("builtin").cpu.arch == .x86_64;
-
-const epsilon = 0.000001;
-
-test "@sqrt" {
- comptime try testSqrt();
- try testSqrt();
-}
-
-fn testSqrt() !void {
- if (has_f80_rt) {
- var a: f80 = 25;
- try expect(@sqrt(a) == 5);
- }
- {
- const a: comptime_float = 25.0;
- try expect(@sqrt(a) == 5.0);
- }
- // TODO https://github.com/ziglang/zig/issues/4026
- //{
- // var a: f128 = 49;
- //try expect(@sqrt(a) == 7);
- //}
- {
- var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
- var result = @sqrt(v);
- try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 1.1)), result[0], epsilon));
- try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 2.2)), result[1], epsilon));
- try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 3.3)), result[2], epsilon));
- try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 4.4)), result[3], epsilon));
- }
-}
-
-test "@sin" {
- comptime try testSin();
- try testSin();
-}
-
-fn testSin() !void {
- // TODO test f128, and c_longdouble
- // https://github.com/ziglang/zig/issues/4026
- {
- var a: f16 = 0;
- try expect(@sin(a) == 0);
- }
- {
- var a: f32 = 0;
- try expect(@sin(a) == 0);
- }
- {
- var a: f64 = 0;
- try expect(@sin(a) == 0);
- }
- // {
- // var a: f80 = 0;
- // try expect(@sin(a) == 0);
- // }
- {
- var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
- var result = @sin(v);
- try expect(math.approxEqAbs(f32, @sin(@as(f32, 1.1)), result[0], epsilon));
- try expect(math.approxEqAbs(f32, @sin(@as(f32, 2.2)), result[1], epsilon));
- try expect(math.approxEqAbs(f32, @sin(@as(f32, 3.3)), result[2], epsilon));
- try expect(math.approxEqAbs(f32, @sin(@as(f32, 4.4)), result[3], epsilon));
- }
-}
-
-test "@cos" {
- comptime try testCos();
- try testCos();
-}
-
-fn testCos() !void {
- // TODO test f128, and c_longdouble
- // https://github.com/ziglang/zig/issues/4026
- {
- var a: f16 = 0;
- try expect(@cos(a) == 1);
- }
- {
- var a: f32 = 0;
- try expect(@cos(a) == 1);
- }
- {
- var a: f64 = 0;
- try expect(@cos(a) == 1);
- }
- // {
- // var a: f80 = 0;
- // try expect(@cos(a) == 1);
- // }
- {
- var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
- var result = @cos(v);
- try expect(math.approxEqAbs(f32, @cos(@as(f32, 1.1)), result[0], epsilon));
- try expect(math.approxEqAbs(f32, @cos(@as(f32, 2.2)), result[1], epsilon));
- try expect(math.approxEqAbs(f32, @cos(@as(f32, 3.3)), result[2], epsilon));
- try expect(math.approxEqAbs(f32, @cos(@as(f32, 4.4)), result[3], epsilon));
- }
-}
-
-test "@exp" {
- comptime try testExp();
- try testExp();
-}
-
-fn testExp() !void {
- // TODO test f128, and c_longdouble
- // https://github.com/ziglang/zig/issues/4026
- {
- var a: f16 = 0;
- try expect(@exp(a) == 1);
- }
- {
- var a: f32 = 0;
- try expect(@exp(a) == 1);
- }
- {
- var a: f64 = 0;
- try expect(@exp(a) == 1);
- }
- // {
- // var a: f80 = 0;
- // try expect(@exp(a) == 1);
- // }
- {
- var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
- var result = @exp(v);
- try expect(math.approxEqAbs(f32, @exp(@as(f32, 1.1)), result[0], epsilon));
- try expect(math.approxEqAbs(f32, @exp(@as(f32, 2.2)), result[1], epsilon));
- try expect(math.approxEqAbs(f32, @exp(@as(f32, 0.3)), result[2], epsilon));
- try expect(math.approxEqAbs(f32, @exp(@as(f32, 0.4)), result[3], epsilon));
- }
-}
-
-test "@exp2" {
- comptime try testExp2();
- try testExp2();
-}
-
-fn testExp2() !void {
- // TODO test f128, and c_longdouble
- // https://github.com/ziglang/zig/issues/4026
- {
- var a: f16 = 2;
- try expect(@exp2(a) == 4);
- }
- {
- var a: f32 = 2;
- try expect(@exp2(a) == 4);
- }
- {
- var a: f64 = 2;
- try expect(@exp2(a) == 4);
- }
- // {
- // var a: f80 = 2;
- // try expect(@exp2(a) == 4);
- // }
- {
- var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
- var result = @exp2(v);
- try expect(math.approxEqAbs(f32, @exp2(@as(f32, 1.1)), result[0], epsilon));
- try expect(math.approxEqAbs(f32, @exp2(@as(f32, 2.2)), result[1], epsilon));
- try expect(math.approxEqAbs(f32, @exp2(@as(f32, 0.3)), result[2], epsilon));
- try expect(math.approxEqAbs(f32, @exp2(@as(f32, 0.4)), result[3], epsilon));
- }
-}
-
-test "@log" {
- // Old musl (and glibc?), and our current math.ln implementation do not return 1
- // so also accept those values.
- comptime try testLog();
- try testLog();
-}
-
-fn testLog() !void {
- // TODO test f128, and c_longdouble
- // https://github.com/ziglang/zig/issues/4026
- {
- var a: f16 = e;
- try expect(math.approxEqAbs(f16, @log(a), 1, epsilon));
- }
- {
- var a: f32 = e;
- try expect(@log(a) == 1 or @log(a) == @bitCast(f32, @as(u32, 0x3f7fffff)));
- }
- {
- var a: f64 = e;
- try expect(@log(a) == 1 or @log(a) == @bitCast(f64, @as(u64, 0x3ff0000000000000)));
- }
- // {
- // var a: f80 = e;
- // try expect(@log(a) == 1);
- // }
- {
- var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
- var result = @log(v);
- try expect(math.approxEqAbs(f32, @log(@as(f32, 1.1)), result[0], epsilon));
- try expect(math.approxEqAbs(f32, @log(@as(f32, 2.2)), result[1], epsilon));
- try expect(math.approxEqAbs(f32, @log(@as(f32, 0.3)), result[2], epsilon));
- try expect(math.approxEqAbs(f32, @log(@as(f32, 0.4)), result[3], epsilon));
- }
-}
-
-test "@log2" {
- comptime try testLog2();
- try testLog2();
-}
-
-fn testLog2() !void {
- // TODO test f128, and c_longdouble
- // https://github.com/ziglang/zig/issues/4026
- {
- var a: f16 = 4;
- try expect(@log2(a) == 2);
- }
- {
- var a: f32 = 4;
- try expect(@log2(a) == 2);
- }
- {
- var a: f64 = 4;
- try expect(@log2(a) == 2);
- }
- // {
- // var a: f80 = 4;
- // try expect(@log2(a) == 2);
- // }
- {
- var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
- var result = @log2(v);
- try expect(math.approxEqAbs(f32, @log2(@as(f32, 1.1)), result[0], epsilon));
- try expect(math.approxEqAbs(f32, @log2(@as(f32, 2.2)), result[1], epsilon));
- try expect(math.approxEqAbs(f32, @log2(@as(f32, 0.3)), result[2], epsilon));
- try expect(math.approxEqAbs(f32, @log2(@as(f32, 0.4)), result[3], epsilon));
- }
-}
-
-test "@log10" {
- comptime try testLog10();
- try testLog10();
-}
-
-fn testLog10() !void {
- // TODO test f128, and c_longdouble
- // https://github.com/ziglang/zig/issues/4026
- {
- var a: f16 = 100;
- try expect(@log10(a) == 2);
- }
- {
- var a: f32 = 100;
- try expect(@log10(a) == 2);
- }
- {
- var a: f64 = 1000;
- try expect(@log10(a) == 3);
- }
- // {
- // var a: f80 = 1000;
- // try expect(@log10(a) == 3);
- // }
- {
- var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
- var result = @log10(v);
- try expect(math.approxEqAbs(f32, @log10(@as(f32, 1.1)), result[0], epsilon));
- try expect(math.approxEqAbs(f32, @log10(@as(f32, 2.2)), result[1], epsilon));
- try expect(math.approxEqAbs(f32, @log10(@as(f32, 0.3)), result[2], epsilon));
- try expect(math.approxEqAbs(f32, @log10(@as(f32, 0.4)), result[3], epsilon));
- }
-}
-
-test "@fabs" {
- comptime try testFabs();
- try testFabs();
-}
-
-fn testFabs() !void {
- // TODO test f128, and c_longdouble
- // https://github.com/ziglang/zig/issues/4026
- {
- var a: f16 = -2.5;
- var b: f16 = 2.5;
- try expect(@fabs(a) == 2.5);
- try expect(@fabs(b) == 2.5);
- }
- {
- var a: f32 = -2.5;
- var b: f32 = 2.5;
- try expect(@fabs(a) == 2.5);
- try expect(@fabs(b) == 2.5);
- }
- {
- var a: f64 = -2.5;
- var b: f64 = 2.5;
- try expect(@fabs(a) == 2.5);
- try expect(@fabs(b) == 2.5);
- }
- // {
- // var a: f80 = -2.5;
- // var b: f80 = 2.5;
- // try expect(@fabs(a) == 2.5);
- // try expect(@fabs(b) == 2.5);
- // }
- {
- var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
- var result = @fabs(v);
- try expect(math.approxEqAbs(f32, @fabs(@as(f32, 1.1)), result[0], epsilon));
- try expect(math.approxEqAbs(f32, @fabs(@as(f32, -2.2)), result[1], epsilon));
- try expect(math.approxEqAbs(f32, @fabs(@as(f32, 0.3)), result[2], epsilon));
- try expect(math.approxEqAbs(f32, @fabs(@as(f32, -0.4)), result[3], epsilon));
- }
-}
-
-test "@floor" {
- comptime try testFloor();
- try testFloor();
-}
-
-fn testFloor() !void {
- // TODO test f128, and c_longdouble
- // https://github.com/ziglang/zig/issues/4026
- {
- var a: f16 = 2.1;
- try expect(@floor(a) == 2);
- }
- {
- var a: f32 = 2.1;
- try expect(@floor(a) == 2);
- }
- {
- var a: f64 = 3.5;
- try expect(@floor(a) == 3);
- }
- // {
- // var a: f80 = 3.5;
- // try expect(@floor(a) == 3);
- // }
- {
- var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
- var result = @floor(v);
- try expect(math.approxEqAbs(f32, @floor(@as(f32, 1.1)), result[0], epsilon));
- try expect(math.approxEqAbs(f32, @floor(@as(f32, -2.2)), result[1], epsilon));
- try expect(math.approxEqAbs(f32, @floor(@as(f32, 0.3)), result[2], epsilon));
- try expect(math.approxEqAbs(f32, @floor(@as(f32, -0.4)), result[3], epsilon));
- }
-}
-
-test "@ceil" {
- comptime try testCeil();
- try testCeil();
-}
-
-fn testCeil() !void {
- // TODO test f128, and c_longdouble
- // https://github.com/ziglang/zig/issues/4026
- {
- var a: f16 = 2.1;
- try expect(@ceil(a) == 3);
- }
- {
- var a: f32 = 2.1;
- try expect(@ceil(a) == 3);
- }
- {
- var a: f64 = 3.5;
- try expect(@ceil(a) == 4);
- }
- // {
- // var a: f80 = 3.5;
- // try expect(@ceil(a) == 4);
- // }
- {
- var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
- var result = @ceil(v);
- try expect(math.approxEqAbs(f32, @ceil(@as(f32, 1.1)), result[0], epsilon));
- try expect(math.approxEqAbs(f32, @ceil(@as(f32, -2.2)), result[1], epsilon));
- try expect(math.approxEqAbs(f32, @ceil(@as(f32, 0.3)), result[2], epsilon));
- try expect(math.approxEqAbs(f32, @ceil(@as(f32, -0.4)), result[3], epsilon));
- }
-}
-
-test "@trunc" {
- comptime try testTrunc();
- try testTrunc();
-}
-
-fn testTrunc() !void {
- // TODO test f128, and c_longdouble
- // https://github.com/ziglang/zig/issues/4026
- {
- var a: f16 = 2.1;
- try expect(@trunc(a) == 2);
- }
- {
- var a: f32 = 2.1;
- try expect(@trunc(a) == 2);
- }
- {
- var a: f64 = -3.5;
- try expect(@trunc(a) == -3);
- }
- // {
- // var a: f80 = -3.5;
- // try expect(@trunc(a) == -3);
- // }
- {
- var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
- var result = @trunc(v);
- try expect(math.approxEqAbs(f32, @trunc(@as(f32, 1.1)), result[0], epsilon));
- try expect(math.approxEqAbs(f32, @trunc(@as(f32, -2.2)), result[1], epsilon));
- try expect(math.approxEqAbs(f32, @trunc(@as(f32, 0.3)), result[2], epsilon));
- try expect(math.approxEqAbs(f32, @trunc(@as(f32, -0.4)), result[3], epsilon));
- }
-}
-
-test "floating point comparisons" {
- if (has_f80_rt) try testFloatComparisons();
- comptime try testFloatComparisons();
-}
-
-fn testFloatComparisons() !void {
- inline for ([_]type{ f16, f32, f64, f80, f128 }) |ty| {
- // No decimal part
- {
- const x: ty = 1.0;
- try expect(x == 1);
- try expect(x != 0);
- try expect(x > 0);
- try expect(x < 2);
- try expect(x >= 1);
- try expect(x <= 1);
- }
- // Non-zero decimal part
- {
- const x: ty = 1.5;
- try expect(x != 1);
- try expect(x != 2);
- try expect(x > 1);
- try expect(x < 2);
- try expect(x >= 1);
- try expect(x <= 2);
- }
- }
-}
test/behavior.zig
@@ -150,7 +150,6 @@ test {
_ = @import("behavior/const_slice_child.zig");
_ = @import("behavior/export_self_referential_type_info.zig");
_ = @import("behavior/field_parent_ptr.zig");
- _ = @import("behavior/floatop_stage1.zig");
_ = @import("behavior/fn_delegation.zig");
_ = @import("behavior/ir_block_deps.zig");
_ = @import("behavior/misc.zig");