global using Vec3i = AdventOfCode.Utils.Models.Vec3; global using Vec2i = AdventOfCode.Utils.Models.Vec2; global using Vec3l = AdventOfCode.Utils.Models.Vec3; global using Vec2l = AdventOfCode.Utils.Models.Vec2; global using Vec3f = AdventOfCode.Utils.Models.Vec3; global using Vec2f = AdventOfCode.Utils.Models.Vec2; using System.Numerics; namespace AdventOfCode.Utils.Models; public record struct Vec2(T X, T Y) where T : INumber { public static Vec2 Zero => new (T.Zero, T.Zero); public static Vec2 One => new (T.One, T.One); public readonly Vec2 YX => new(Y, X); public readonly Vec2 YY => new(Y, Y); public readonly Vec2 XX => new(X, X); public static Vec2 Splat(T v) => new(v, v); public static Vec2 operator +(Vec2 left, Vec2 right) => new Vec2(left.X + right.X, left.Y + right.Y); public static Vec2 operator -(Vec2 left, Vec2 right) => new Vec2(left.X - right.X, left.Y - right.Y); public static Vec2 operator -(Vec2 vec) => new Vec2(-vec.X, -vec.Y); public static Vec2 operator *(Vec2 left, T right) => new Vec2(left.X * right, left.Y * right); public static Vec2 operator *(T left, Vec2 right) => new Vec2(right.X * left, right.Y * left); public static Vec2 operator /(Vec2 left, T right) => new Vec2(left.X / right, left.Y / right); public static implicit operator Vec2(T value) { return new(value, value); } public readonly T DistanceSq(Vec2 other) { var a = other.X - this.X; var b = other.Y - this.Y; return (a * a) + (b * b); } public readonly Vec2 Min(Vec2 other) => new(T.Min(X, other.X), T.Min(Y, other.Y)); public readonly Vec2 Max(Vec2 other) => new(T.Max(X, other.X), T.Max(Y, other.Y)); public readonly Vec2 Abs() => new(T.Abs(X), T.Abs(Y)); public override readonly string ToString() { return $"({X}, {Y})"; } } public record struct Vec3(T X, T Y, T Z) where T : INumber { public static Vec3 Zero => new(T.Zero, T.Zero, T.Zero); public static Vec3 One => new(T.One, T.One, T.One); public static Vec3 Splat(T v) => new(v, v, v); public static Vec3 operator +(Vec3 left, Vec3 right) => new Vec3(left.X + right.X, left.Y + right.Y, left.Z + right.Z); public static Vec3 operator -(Vec3 left, Vec3 right) => new Vec3(left.X - right.X, left.Y - right.Y, left.Z - right.Z); public static Vec3 operator -(Vec3 vec) => new Vec3(-vec.X, -vec.Y, -vec.Z); public static Vec3 operator *(Vec3 left, T right) => new Vec3(left.X * right, left.Y * right, left.Z * right); public static Vec3 operator *(T left, Vec3 right) => new Vec3(right.X * left, right.Y * left, right.Z * left); public static Vec3 operator /(Vec3 left, T right) => new Vec3(left.X / right, left.Y / right, left.Z / right); public static implicit operator Vec3(T value) { return new(value, value, value); } public readonly T DistanceSq(Vec3 other) { var a = other.X - this.X; var b = other.Y - this.Y; var c = other.Z - this.Z; return T.Abs((a * a) + (b * b) + (c * c)); } public readonly Vec3 Min(Vec3 other) => new(T.Min(X, other.X), T.Min(Y, other.Y), T.Min(Z, other.Z)); public readonly Vec3 Max(Vec3 other) => new(T.Max(X, other.X), T.Max(Y, other.Y), T.Max(Z, other.Z)); public readonly Vec3 Abs() => new(T.Abs(X), T.Abs(Y), T.Abs(Z)); public override readonly string ToString() { return $"({X}, {Y}, {Z})"; } }