const std = @import("std"); const vm = @import("../root.zig"); pub const Complex_x8 = struct { re: vm.f32x8, im: vm.f32x8, pub const identity = initSingle(1, 0); // --- INIT ---------------------------------------------------------------- pub inline fn init(re: vm.f32x8, im: vm.f32x8) Complex_x8 { return .{ .re = re, .im = im }; } pub inline fn initSingle(re: f32, im: f32) Complex_x8 { return .{ .re = vm.ps(re), .im = vm.ps(im) }; } pub inline fn initRotation(angle_turns: vm.f32x8) Complex_x8 { return vm.cossin_x8(angle_turns); } pub inline fn initRotationSingle(angle_turns: f32) Complex_x8 { const complex = vm.cossin(angle_turns); return .{ .re = vm.ps(complex.re), .im = vm.ps(complex.im) }; } pub inline fn splat(complex: vm.Complex) Complex_x8 { return .{ .re = vm.ps(complex.re), .im = vm.ps(complex.im) }; } // --- CONVERSION ---------------------------------------------------------- pub inline fn unpack(self: Complex_x8) [2]vm.f32x8 { return .{ self.re, self.im }; } // --- COMPONENT-WISE ------------------------------------------------------ pub inline fn add(self: Complex_x8, other: Complex_x8) Complex_x8 { return .{ .re = self.re + other.re, .im = self.im + other.im, }; } pub inline fn sub(self: Complex_x8, other: Complex_x8) Complex_x8 { return .{ .re = self.re - other.re, .im = self.im - other.im, }; } pub inline fn mulScalar(self: Complex_x8, scalar: vm.f32x8) Complex_x8 { return .{ .re = self.re * scalar, .im = self.im * scalar, }; } pub inline fn mulScalarSingle(self: Complex_x8, scalar: f32) Complex_x8 { return .{ .re = self.re * vm.ps(scalar), .im = self.im * vm.ps(scalar), }; } pub inline fn divScalar(self: Complex_x8, scalar: vm.f32x8) Complex_x8 { return .{ .re = self.re / scalar, .im = self.im / scalar, }; } pub inline fn divScalarSingle(self: Complex_x8, scalar: f32) Complex_x8 { return .{ .re = self.re / vm.ps(scalar), .im = self.im / vm.ps(scalar), }; } pub inline fn negate(self: Complex_x8) Complex_x8 { return .{ .re = -self.re, .im = -self.im, }; } pub inline fn conjugate(self: Complex_x8) Complex_x8 { return .{ .re = self.re, .im = -self.im, }; } // --- COMPOSE ------------------------------------------------------------- pub inline fn mulComplex(self: Complex_x8, other: Complex_x8) Complex_x8 { return .{ .re = self.re * other.re - self.im * other.im, .im = self.re * other.im + self.im * other.re, }; } pub inline fn mulComplexSingle(self: Complex_x8, other: vm.Complex) Complex_x8 { return .{ .re = self.re * vm.ps(other.re) - self.im * vm.ps(other.im), .im = self.re * vm.ps(other.im) + self.im * vm.ps(other.re), }; } pub inline fn inverseUnit(self: Complex_x8) Complex_x8 { std.debug.assert(@reduce(.And, @abs(self.mag() - vm.ps(1.0)) <= vm.ps(0x1p-5))); return .{ .re = self.re, .im = -self.im, }; } pub inline fn inverseFull(self: Complex_x8) Complex_x8 { const inv_mag_squared = 1.0 / (self.re * self.re + self.im * self.im); return .{ .re = inv_mag_squared * self.re, .im = -inv_mag_squared * self.im, }; } // --- OTHER --------------------------------------------------------------- pub inline fn mag(self: Complex_x8) vm.f32x8 { return @sqrt(self.re * self.re + self.im * self.im); } pub inline fn magSquared(self: Complex_x8) vm.f32x8 { return self.re * self.re + self.im * self.im; } pub inline fn lerp(a: Complex_x8, b: Complex_x8, t: vm.f32x8) Complex_x8 { return .{ .re = @mulAdd(vm.f32x8, t, b.re, @mulAdd(vm.f32x8, -t, a.re, a.re)), .im = @mulAdd(vm.f32x8, t, b.im, @mulAdd(vm.f32x8, -t, a.im, a.im)), }; } pub inline fn lerpSingle(a: Complex_x8, b: Complex_x8, t: f32) Complex_x8 { return .{ .re = @mulAdd(vm.f32x8, vm.ps(t), b.re, @mulAdd(vm.f32x8, -vm.ps(t), a.re, a.re)), .im = @mulAdd(vm.f32x8, vm.ps(t), b.im, @mulAdd(vm.f32x8, -vm.ps(t), a.im, a.im)), }; } test "refAllDecls" { std.testing.refAllDecls(@This()); } };