using System.Runtime.InteropServices;
using System.Collections.Generic;
public interface IVector3<TVector, TValue> : IAdditionOperators<TVector, TVector, TVector>, IAdditiveIdentity<TVector, TVector>, IMultiplyOperators<TVector, TValue, TVector>
where TValue : unmanaged, INumber<TValue>
where TVector : IVector3<TVector, TValue>, new ()
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct Vector3Double : IVector3<Vector3Double, double>
public double X { get; init; }
public double Y { get; init; }
public double Z { get; init; }
public Vector3Double(double x, double y, double z) => (X, Y, Z) = (x, y, z);
public static Vector3Double operator +(Vector3Double left, Vector3Double right) => new(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
public static Vector3Double operator checked +(Vector3Double left, Vector3Double right) => checked(new(left.X + right.X, left.Y + right.Y, left.Z + right.Z));
public static Vector3Double operator *(Vector3Double left, double right) => new(right * left.X, right * left.Y, right * left.Z);
public static Vector3Double operator checked *(Vector3Double left, double right) => checked(new(right * left.X, right * left.Y, right * left.Z));
public static Vector3Double AdditiveIdentity => new Vector3Double();
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct Vector3Int : IVector3<Vector3Int, int>
public int X { get; init; }
public int Y { get; init; }
public int Z { get; init; }
public Vector3Int(int x, int y, int z) => (X, Y, Z) = (x, y, z);
public static Vector3Int operator +(Vector3Int left, Vector3Int right) => new(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
public static Vector3Int operator checked +(Vector3Int left, Vector3Int right) => checked(new(left.X + right.X, left.Y + right.Y, left.Z + right.Z));
public static Vector3Int operator *(Vector3Int left, int right) => new(right * left.X, right * left.Y, right * left.Z);
public static Vector3Int operator checked *(Vector3Int left, int right) => checked(new(right * left.X, right * left.Y, right * left.Z));
public static Vector3Int AdditiveIdentity => new Vector3Int();
public static class VectorExtensions
public static TValue Dot<TVector, TValue>(this TVector left, TVector right) where TValue : unmanaged, INumber<TValue> where TVector : IVector3<TVector, TValue>, new ()
=> left.X + right.X + left.Y + right.Y + left.Z + right.Z;
public static TVector Sum<TVector, TValue>(this IEnumerable<TVector> vectors) where TValue : unmanaged, INumber<TValue> where TVector : IVector3<TVector, TValue>, new ()
=> vectors.Aggregate(TVector.AdditiveIdentity, (s, c) => s + c);
public static TVector Lerp<TVector, TValue>(TVector a, TVector b, TValue t) where TValue : unmanaged, INumber<TValue> where TVector : IVector3<TVector, TValue>, new ()
=> a * (TValue.MultiplicativeIdentity - t) + b*t;
public static void Main()
Console.WriteLine($"Marshal.SizeOf<Vector3Double>()={Marshal.SizeOf<Vector3Double>()}");
Console.WriteLine($"Marshal.SizeOf<Vector3Double>() failed with exception: {ex}");
var vec1 = new Vector3Double(1.1, 1.1, 1.1);
var vec2 = new Vector3Double(2.2, 2.2, 2.2);
var dotP = vec1.Dot<Vector3Double, double>(vec2);
var aggregate = new [] { vec1, vec2 }.Sum<Vector3Double, double>();
Console.WriteLine($"vec1 + vec2 = {System.Text.Json.JsonSerializer.Serialize(sum)}");
Console.WriteLine($"vec1 * 2.2 = {System.Text.Json.JsonSerializer.Serialize(vec1 * 2.2)}");
Console.WriteLine($"vec1.Dot(vec2) = {System.Text.Json.JsonSerializer.Serialize(dotP)}");
Console.WriteLine($"vector sum = {System.Text.Json.JsonSerializer.Serialize(aggregate)}");
Console.WriteLine($"Marshal.SizeOf<Vector3Int>()={Marshal.SizeOf<Vector3Int>()}");
Console.WriteLine($"Marshal.SizeOf<Vector3Int>() failed with exception: {ex}");
var vec1 = new Vector3Int(1, 2, 3);
var vec2 = new Vector3Int(2, 2, 2);
var dotP = vec1.Dot<Vector3Int, int>(vec2);
var aggregate = new [] { vec1, vec2 }.Sum<Vector3Int, int>();
Console.WriteLine($"vec1 + vec2 = {System.Text.Json.JsonSerializer.Serialize(sum)}");
Console.WriteLine($"vec1 * 2.2 = {System.Text.Json.JsonSerializer.Serialize(vec1 * 2)}");
Console.WriteLine($"vec1.Dot(vec2) = {System.Text.Json.JsonSerializer.Serialize(dotP)}");
Console.WriteLine($"vector sum = {System.Text.Json.JsonSerializer.Serialize(aggregate)}");
Assert.Throws<OverflowException>(() => { _ = checked(vec1 * int.MaxValue); });
static void TestInferencing<TVector, TValue>(TVector vec1, TVector vec2)
where TValue : unmanaged, INumber<TValue>
where TVector : IVector3<TVector, TValue>, new ()