< Summary

Class:Towel.Mathematics.Vector<T>
Assembly:Towel
File(s):File 1: /home/runner/work/Towel/Towel/Sources/Towel/Mathematics/Vector.cs
Covered lines:283
Uncovered lines:300
Coverable lines:583
Total lines:1245
Line coverage:48.5% (283 of 583)
Covered branches:80
Total branches:194
Branch coverage:41.2% (80 of 194)

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
File 1: get_X()0%20%
File 1: set_X(...)0%20%
File 1: get_Y()0%20%
File 1: set_Y(...)0%20%
File 1: get_Z()0%20%
File 1: set_Z(...)0%20%
File 1: get_Dimensions()50%2100%
File 1: get_Item(...)50%4100%
File 1: set_Item(...)0%40%
File 1: get_DebuggerString()0%20%
File 1: .ctor(...)50%271.42%
File 1: .ctor(...)100%1100%
File 1: .ctor(...)0%20%
File 1: .ctor(...)100%10%
File 1: FactoryZero(...)100%10%
File 1: .cctor()0%120%
File 1: FactoryOne(...)100%10%
File 1: GetMagnitude(...)50%2100%
File 1: get_Magnitude()100%1100%
File 1: GetMagnitudeSquared(...)75%4100%
File 1: get_MagnitudeSquared()100%1100%
File 1: Negate(...)50%1063.63%
File 1: Negate(...)100%1100%
File 1: op_UnaryNegation(...)100%1100%
File 1: Negate(...)100%10%
File 1: Negate()100%10%
File 1: Add(...)50%1268%
File 1: Add(...)100%1100%
File 1: op_Addition(...)100%1100%
File 1: Add(...)100%10%
File 1: Add(...)100%10%
File 1: Subtract(...)50%1268%
File 1: Subtract(...)100%1100%
File 1: op_Subtraction(...)100%1100%
File 1: Subtract(...)100%10%
File 1: Subtract(...)100%10%
File 1: Multiply(...)75%881.81%
File 1: Multiply(...)100%1100%
File 1: op_Multiply(...)100%1100%
File 1: op_Multiply(...)100%10%
File 1: Multiply(...)100%1100%
File 1: Multiply(...)100%10%
File 1: Divide(...)50%863.63%
File 1: Divide(...)100%1100%
File 1: op_Division(...)100%1100%
File 1: Divide(...)100%10%
File 1: Divide(...)100%10%
File 1: DotProduct(...)75%8100%
File 1: DotProduct(...)100%1100%
File 1: CrossProduct(...)66.66%12100%
File 1: CrossProduct(...)100%1100%
File 1: CrossProduct(...)100%10%
File 1: CrossProduct(...)100%1100%
File 1: Normalize(...)66.66%1287.5%
File 1: Normalize(...)100%1100%
File 1: Normalize(...)100%10%
File 1: Normalize()100%1100%
File 1: Angle(...)50%4100%
File 1: Angle(...)100%1100%
File 1: Angle(...)100%1100%
File 1: Angle(...)100%10%
File 1: Projection(...)66.66%1288.23%
File 1: Projection(...)100%1100%
File 1: Projection(...)100%10%
File 1: Projection(...)100%1100%
File 1: RotateBy(...)100%10%
File 1: RotateBy(...)100%10%
File 1: RotateBy(...)100%10%
File 1: RotateBy(...)100%10%
File 1: RotateBy(...)100%10%
File 1: LinearInterpolation(...)0%120%
File 1: LinearInterpolation(...)100%10%
File 1: LinearInterpolation(...)100%10%
File 1: LinearInterpolation(...)100%10%
File 1: SphericalInterpolation(...)100%10%
File 1: SphericalInterpolation(...)100%10%
File 1: SphericalInterpolation(...)100%10%
File 1: BarycentricInterpolation(...)0%80%
File 1: BarycentricInterpolation(...)100%10%
File 1: BarycentricInterpolation(...)100%10%
File 1: Equal(...)50%1253.84%
File 1: NotEqual(...)100%10%
File 1: op_Equality(...)100%1100%
File 1: op_Inequality(...)100%10%
File 1: Equal(...)100%10%
File 1: NotEqual(...)100%10%
File 1: Equal(...)58.33%1260%
File 1: Equal(...)100%1100%
File 1: Clone(...)0%20%
File 1: Clone()100%10%
File 1: op_Implicit(...)100%10%
File 1: op_Implicit(...)100%10%
File 1: op_Explicit(...)100%10%
File 1: op_Explicit(...)100%10%
File 1: GetHashCode()0%20%
File 1: Equals(...)0%20%

File(s)

/home/runner/work/Towel/Towel/Sources/Towel/Mathematics/Vector.cs

#LineLine coverage
 1using System.Diagnostics;
 2using System.Text;
 3
 4namespace Towel.Mathematics;
 5
 6/// <summary>Represents a vector with an arbitrary number of components of a generic type.</summary>
 7/// <typeparam name="T">The numeric type of this Vector.</typeparam>
 8[DebuggerDisplay("{" + nameof(DebuggerString) + "}")]
 9public class Vector<T>
 10{
 11  internal readonly T[] _vector;
 12
 13  #region Basic Properties
 14
 15  /// <summary>Index 0</summary>
 16  public T X
 17  {
 18    get
 019    {
 020      if (sourceof(Dimensions < 1, out string c1)) throw new InvalidOperationException(c1);
 021      return _vector[0];
 022    }
 23    set
 024    {
 025      if (sourceof(Dimensions < 1, out string c1)) throw new InvalidOperationException(c1);
 026      _vector[0] = value;
 027    }
 28  }
 29
 30  /// <summary>Index 1</summary>
 31  public T Y
 32  {
 33    get
 034    {
 035      if (sourceof(Dimensions < 2, out string c1)) throw new InvalidOperationException(c1);
 036      return _vector[1];
 037    }
 38    set
 039    {
 040      if (sourceof(Dimensions < 2, out string c1)) throw new InvalidOperationException(c1);
 041      _vector[1] = value;
 042    }
 43  }
 44
 45  /// <summary>Index 2</summary>
 46  public T Z
 47  {
 48    get
 049    {
 050      if (sourceof(Dimensions < 3, out string c1)) throw new InvalidOperationException(c1);
 051      return _vector[2];
 052    }
 53    set
 054    {
 055      if (sourceof(Dimensions < 3, out string c1)) throw new InvalidOperationException(c1);
 056      _vector[2] = value;
 057    }
 58  }
 59
 60  /// <summary>The number of components in this vector.</summary>
 21361  public int Dimensions => _vector is null ? 0 : _vector.Length;
 62
 63  /// <summary>Allows indexed access to this vector.</summary>
 64  /// <param name="index">The index to access.</param>
 65  /// <returns>The value of the given index.</returns>
 66  public T this[int index]
 67  {
 68    get
 1269    {
 1270      if (sourceof(0 > index || index > Dimensions, out string c1)) throw new ArgumentOutOfRangeException(nameof(index),
 1271      return _vector[index];
 1272    }
 73    set
 074    {
 075      if (sourceof(0 > index || index > Dimensions, out string c1)) throw new ArgumentOutOfRangeException(nameof(index),
 076      _vector[index] = value;
 077    }
 78  }
 79
 80  #endregion
 81
 82  #region Debugger Properties
 83
 84  internal string DebuggerString
 85  {
 86    get
 087    {
 088      StringBuilder stringBuilder = new();
 089      stringBuilder.Append('[');
 090      stringBuilder.Append(_vector[0]);
 091      for (int i = 1; i < _vector.Length; i++)
 092      {
 093        stringBuilder.Append(',');
 094        stringBuilder.Append(_vector[i]);
 095      }
 096      stringBuilder.Append(']');
 097      return stringBuilder.ToString();
 098    }
 99  }
 100
 101  #endregion
 102
 103  #region Constructors
 104
 105  /// <summary>Creates a new vector with the given number of components.</summary>
 106  /// <param name="dimensions">The number of dimensions this vector will have.</param>
 57107  public Vector(int dimensions)
 57108  {
 57109    if (dimensions < 0)
 0110    {
 0111      throw new ArgumentOutOfRangeException(nameof(dimensions), dimensions, "!(" + nameof(dimensions) + " >= 0)");
 112    }
 57113    _vector = new T[dimensions];
 57114  }
 115
 116  /// <summary>Creates a vector out of the given values.</summary>
 117  /// <param name="vector">The values to initialize the vector to.</param>
 167118  public Vector(params T[] vector)
 167119  {
 167120    _vector = vector;
 167121  }
 122
 123  /// <summary>Creates a new vector and initializes it via function.</summary>
 124  /// <param name="dimensions">The number of dimensions of the vector to construct.</param>
 125  /// <param name="function">The function to initialize the values of the vector.</param>
 0126  public Vector(int dimensions, Func<int, T> function) : this(dimensions)
 0127  {
 0128    for (int i = 0; i < dimensions; i++)
 0129    {
 0130      _vector[i] = function(i);
 0131    }
 0132  }
 133
 0134  internal Vector(Vector<T> vector)
 0135  {
 0136    _vector = (T[])vector._vector.Clone();
 0137  }
 138
 139  #endregion
 140
 141  #region Factories
 142
 143  /// <summary>Creates a vector with the given number of components with the values initialized to zeroes.</summary>
 144  /// <param name="dimensions">The number of components in the vector.</param>
 145  /// <returns>The newly constructed vector.</returns>
 146  public static Vector<T> FactoryZero(int dimensions)
 0147  {
 0148    return FactoryZeroImplementation(dimensions);
 0149  }
 150
 0151  internal static Func<int, Vector<T>> FactoryZeroImplementation = dimensions =>
 0152  {
 0153    if (Equate(default, Constant<T>.Zero))
 0154    {
 0155      FactoryZeroImplementation = DIMENSIONS => new Vector<T>(DIMENSIONS);
 0156    }
 0157    else
 0158    {
 0159      FactoryZeroImplementation = DIMENSIONS =>
 0160      {
 0161        T[] vector = new T[DIMENSIONS];
 0162        vector.Format(Constant<T>.Zero);
 0163        return new Vector<T>(vector);
 0164      };
 0165    }
 0166    return FactoryZeroImplementation(dimensions);
 0167  };
 168
 169  /// <summary>Creates a vector with the given number of components with the values initialized to ones.</summary>
 170  /// <param name="dimensions">The number of components in the vector.</param>
 171  /// <returns>The newly constructed vector.</returns>
 172  public static Vector<T> FactoryOne(int dimensions)
 0173  {
 0174    return FactoryOneImplementation(dimensions);
 0175  }
 176
 0177  internal static Func<int, Vector<T>> FactoryOneImplementation = dimensions =>
 0178  {
 0179    if (Equate(default, Constant<T>.One))
 0180    {
 0181      FactoryZeroImplementation = DIMENSIONS => new Vector<T>(DIMENSIONS);
 0182    }
 0183    else
 0184    {
 0185      FactoryZeroImplementation = DIMENSIONS =>
 0186      {
 0187        T[] vector = new T[DIMENSIONS];
 0188        vector.Format(Constant<T>.One);
 0189        return new Vector<T>(vector);
 0190      };
 0191    }
 0192    return FactoryZeroImplementation(dimensions);
 0193  };
 194
 195  #endregion
 196
 197  #region Mathematics
 198
 199  #region Magnitude
 200
 201  /// <summary>Computes the length of this vector.</summary>
 202  /// <param name="a">The <see cref="Vector{T}"/> to get the magnitude of.</param>
 203  /// <returns>The length of this vector.</returns>
 204  public static T GetMagnitude(Vector<T> a)
 12205  {
 12206    if (a is null) throw new ArgumentNullException(nameof(a));
 12207    return SquareRoot(GetMagnitudeSquared(a));
 12208  }
 209
 210  /// <summary>Computes the length of this vector.</summary>
 12211  public T Magnitude => GetMagnitude(this);
 212
 213  #endregion
 214
 215  #region MagnitudeSquared
 216
 217  /// <summary>Computes the length of this vector, but doesn't square root it for
 218  /// possible optimization purposes.</summary>
 219  /// <param name="a">The <see cref="Vector{T}"/> to get the magnitude squared of.</param>
 220  /// <returns>The squared length of the vector.</returns>
 221  public static T GetMagnitudeSquared(Vector<T> a)
 18222  {
 18223    if (a is null) throw new ArgumentNullException(nameof(a));
 18224    int Length = a.Dimensions;
 18225    T result = Constant<T>.Zero;
 18226    T[] A = a._vector;
 162227    for (int i = 0; i < Length; i++)
 63228    {
 63229      result = MultiplyAddImplementation<T>.Function(A[i], A[i], result);
 63230    }
 18231    return result;
 18232  }
 233
 234  /// <summary>Computes the length of this vector, but doesn't square root it for
 235  /// possible optimization purposes.</summary>
 6236  public T MagnitudeSquared => GetMagnitudeSquared(this);
 237
 238  #endregion
 239
 240  #region Negate
 241
 242  /// <summary>Negates all the values in a vector.</summary>
 243  /// <param name="a">The vector to have its values negated.</param>
 244  /// <param name="b">The result of the negations.</param>
 245  public static void Negate(Vector<T> a, ref Vector<T>? b)
 4246  {
 4247    if (a is null) throw new ArgumentNullException(nameof(a));
 4248    T[] A = a._vector;
 4249    int Length = A.Length;
 250    T[] B;
 4251    if (b is null || b.Dimensions != Length)
 4252    {
 4253      b = new Vector<T>(Length);
 4254      B = b._vector;
 4255    }
 256    else
 0257    {
 0258      B = b._vector;
 0259      if (B.Length != Length)
 0260      {
 0261        b = new Vector<T>(Length);
 0262        B = b._vector;
 0263      }
 0264    }
 32265    for (int i = 0; i < Length; i++)
 12266    {
 12267      B[i] = Statics.Negation(A[i]);
 12268    }
 4269  }
 270
 271  /// <summary>Negates all the values in a vector.</summary>
 272  /// <param name="a">The vector to have its values negated.</param>
 273  /// <returns>The result of the negations.</returns>
 274  public static Vector<T> Negate(Vector<T> a)
 4275  {
 4276    Vector<T>? b = null;
 4277    Negate(a, ref b);
 4278    return b!;
 4279  }
 280
 281  /// <summary>Negates a vector.</summary>
 282  /// <param name="vector">The vector to negate.</param>
 283  /// <returns>The result of the negation.</returns>
 284  public static Vector<T> operator -(Vector<T> vector)
 4285  {
 4286    return Negate(vector);
 4287  }
 288
 289  /// <summary>Negates all the values in a vector.</summary>
 290  /// <param name="b">The result of the negations.</param>
 291  public void Negate(ref Vector<T>? b)
 0292  {
 0293    Negate(this, ref b);
 0294  }
 295
 296  /// <summary>Negates this vector.</summary>
 297  /// <returns>The result of the negation.</returns>
 298  public Vector<T> Negate()
 0299  {
 0300    return -this;
 0301  }
 302
 303  #endregion
 304
 305  #region Add
 306
 307  /// <summary>Adds two vectors together.</summary>
 308  /// <param name="a">The first vector of the addition.</param>
 309  /// <param name="b">The second vector of the addiiton.</param>
 310  /// <param name="c">The result of the addition.</param>
 311  public static void Add(Vector<T> a, Vector<T> b, ref Vector<T>? c)
 8312  {
 8313    if (a is null) throw new ArgumentNullException(nameof(a));
 8314    if (b is null) throw new ArgumentNullException(nameof(b));
 8315    T[] A = a._vector;
 8316    T[] B = b._vector;
 8317    int Length = A.Length;
 8318    if (sourceof(Length != B.Length, out string c1)) throw new ArgumentException(c1);
 319    T[] C;
 8320    if (c is null)
 8321    {
 8322      c = new Vector<T>(Length);
 8323      C = c._vector;
 8324    }
 325    else
 0326    {
 0327      C = c._vector;
 0328      if (C.Length != Length)
 0329      {
 0330        c = new Vector<T>(Length);
 0331        C = c._vector;
 0332      }
 0333    }
 64334    for (int i = 0; i < Length; i++)
 24335    {
 24336      C[i] = Statics.Addition(A[i], B[i]);
 24337    }
 8338  }
 339
 340  /// <summary>Adds two vectors together.</summary>
 341  /// <param name="a">The first vector of the addition.</param>
 342  /// <param name="b">The second vector of the addiiton.</param>
 343  /// <returns>The result of the addition.</returns>
 344  public static Vector<T> Add(Vector<T> a, Vector<T> b)
 8345  {
 8346    Vector<T>? c = null;
 8347    Add(a, b, ref c);
 8348    return c!;
 8349  }
 350
 351  /// <summary>Adds two vectors together.</summary>
 352  /// <param name="a">The first vector of the addition.</param>
 353  /// <param name="b">The second vector of the addition.</param>
 354  /// <returns>The result of the addition.</returns>
 355  public static Vector<T> operator +(Vector<T> a, Vector<T> b)
 8356  {
 8357    return Add(a, b);
 8358  }
 359
 360  /// <summary>Adds two vectors together.</summary>
 361  /// <param name="b">The second vector of the addition.</param>
 362  /// <param name="c">The result of the addition.</param>
 363  public void Add(Vector<T> b, ref Vector<T>? c)
 0364  {
 0365    Add(this, b, ref c);
 0366  }
 367
 368  /// <summary>Adds two vectors together.</summary>
 369  /// <param name="b">The vector to add to this one.</param>
 370  /// <returns>The result of the addition.</returns>
 371  public Vector<T> Add(Vector<T> b)
 0372  {
 0373    return this + b;
 0374  }
 375
 376  #endregion
 377
 378  #region Subtract
 379
 380  /// <summary>Subtracts two vectors.</summary>
 381  /// <param name="a">The left vector of the subtraction.</param>
 382  /// <param name="b">The right vector of the subtraction.</param>
 383  /// <param name="c">The result of the vector subtracton.</param>
 384  public static void Subtract(Vector<T> a, Vector<T> b, ref Vector<T>? c)
 8385  {
 8386    if (a is null) throw new ArgumentNullException(nameof(a));
 8387    if (b is null) throw new ArgumentNullException(nameof(b));
 8388    T[] A = a._vector;
 8389    T[] B = b._vector;
 8390    int Length = A.Length;
 8391    if (sourceof(Length != B.Length, out string c1)) throw new ArgumentException(c1);
 392    T[] C;
 8393    if (c is null)
 8394    {
 8395      c = new Vector<T>(Length);
 8396      C = c._vector;
 8397    }
 398    else
 0399    {
 0400      C = c._vector;
 0401      if (C.Length != Length)
 0402      {
 0403        c = new Vector<T>(Length);
 0404        C = c._vector;
 0405      }
 0406    }
 64407    for (int i = 0; i < Length; i++)
 24408    {
 24409      C[i] = Subtraction(A[i], B[i]);
 24410    }
 8411  }
 412
 413  /// <summary>Subtracts two vectors.</summary>
 414  /// <param name="a">The left vector of the subtraction.</param>
 415  /// <param name="b">The right vector of the subtraction.</param>
 416  /// <returns>The result of the vector subtracton.</returns>
 417  public static Vector<T> Subtract(Vector<T> a, Vector<T> b)
 8418  {
 8419    Vector<T>? c = null;
 8420    Subtract(a, b, ref c);
 8421    return c!;
 8422  }
 423
 424  /// <summary>Subtracts two vectors.</summary>
 425  /// <param name="a">The left operand of the subtraction.</param>
 426  /// <param name="b">The right operand of the subtraction.</param>
 427  /// <returns>The result of the subtraction.</returns>
 428  public static Vector<T> operator -(Vector<T> a, Vector<T> b)
 8429  {
 8430    return Subtract(a, b);
 8431  }
 432
 433  /// <summary>Subtracts two vectors.</summary>
 434  /// <param name="b">The right vector of the subtraction.</param>
 435  /// <param name="c">The result of the vector subtracton.</param>
 436  public void Subtract(Vector<T> b, ref Vector<T>? c)
 0437  {
 0438    Subtract(this, b, ref c);
 0439  }
 440
 441  /// <summary>Subtracts another vector from this one.</summary>
 442  /// <param name="b">The vector to subtract from this one.</param>
 443  /// <returns>The result of the subtraction.</returns>
 444  public Vector<T> Subtract(Vector<T> b)
 0445  {
 0446    return this - b;
 0447  }
 448
 449  #endregion
 450
 451  #region Multiply
 452
 453  /// <summary>Multiplies all the values in a vector by a scalar.</summary>
 454  /// <param name="a">The vector to have all its values multiplied.</param>
 455  /// <param name="b">The scalar to multiply all the vector values by.</param>
 456  /// <param name="c">The result of the multiplication.</param>
 457  public static void Multiply(Vector<T> a, T b, ref Vector<T>? c)
 11458  {
 11459    if (a is null) throw new ArgumentNullException(nameof(a));
 11460    T[] A = a._vector;
 11461    int Length = A.Length;
 462    T[] C;
 11463    if (c is null)
 8464    {
 8465      c = new Vector<T>(Length);
 8466      C = c._vector;
 8467    }
 468    else
 3469    {
 3470      C = c._vector;
 3471      if (C.Length != Length)
 0472      {
 0473        c = new Vector<T>(Length);
 0474        C = c._vector;
 0475      }
 3476    }
 88477    for (int i = 0; i < Length; i++)
 33478    {
 33479      C[i] = Multiplication(A[i], b);
 33480    }
 11481  }
 482
 483  /// <summary>Multiplies all the values in a vector by a scalar.</summary>
 484  /// <param name="a">The vector to have all its values multiplied.</param>
 485  /// <param name="b">The scalar to multiply all the vector values by.</param>
 486  /// <returns>The result of the multiplication.</returns>
 487  public static Vector<T> Multiply(Vector<T> a, T b)
 8488  {
 8489    Vector<T>? c = null;
 8490    Multiply(a, b, ref c);
 8491    return c!;
 8492  }
 493
 494  /// <summary>Multiplies all the values in a vector by a scalar.</summary>
 495  /// <param name="a">The vector to have all its values multiplied.</param>
 496  /// <param name="b">The scalar to multiply all the vector values by.</param>
 497  /// <returns>The result of the multiplication.</returns>
 498  public static Vector<T> operator *(Vector<T> a, T b)
 8499  {
 8500    return Multiply(a, b);
 8501  }
 502
 503  /// <summary>Multiplies all the values in a vector by a scalar.</summary>
 504  /// <param name="a">The scalar to multiply all the vector values by.</param>
 505  /// <param name="b">The vector to have all its values multiplied.</param>
 506  /// <returns>The result of the multiplication.</returns>
 507  public static Vector<T> operator *(T a, Vector<T> b)
 0508  {
 0509    return Multiply(b, a);
 0510  }
 511
 512  /// <summary>Multiplies all the values in a vector by a scalar.</summary>
 513  /// <param name="b">The scalar to multiply all the vector values by.</param>
 514  /// <param name="c">The result of the multiplication.</param>
 515  public void Multiply(T b, ref Vector<T>? c)
 3516  {
 3517    Multiply(this, b, ref c);
 3518  }
 519
 520  /// <summary>Multiplies the values in this vector by a scalar.</summary>
 521  /// <param name="b">The scalar to multiply these values by.</param>
 522  /// <returns>The result of the multiplications</returns>
 523  public Vector<T> Multiply(T b)
 0524  {
 0525    return this * b;
 0526  }
 527
 528  #endregion
 529
 530  #region Divide
 531
 532  /// <summary>Divides all the components of a vector by a scalar.</summary>
 533  /// <param name="a">The vector to have the components divided by.</param>
 534  /// <param name="b">The scalar to divide the vector components by.</param>
 535  /// <param name="c">The resulting vector after the divisions.</param>
 536  public static void Divide(Vector<T> a, T b, ref Vector<T>? c)
 8537  {
 8538    if (a is null) throw new ArgumentNullException(nameof(a));
 8539    T[] A = a._vector;
 8540    int Length = A.Length;
 541    T[] C;
 8542    if (c is null)
 8543    {
 8544      c = new Vector<T>(Length);
 8545      C = c._vector;
 8546    }
 547    else
 0548    {
 0549      C = c._vector;
 0550      if (C.Length != Length)
 0551      {
 0552        c = new Vector<T>(Length);
 0553        C = c._vector;
 0554      }
 0555    }
 64556    for (int i = 0; i < Length; i++)
 24557    {
 24558      C[i] = Division(A[i], b);
 24559    }
 8560  }
 561
 562  /// <summary>Divides all the components of a vector by a scalar.</summary>
 563  /// <param name="a">The vector to have the components divided by.</param>
 564  /// <param name="b">The scalar to divide the vector components by.</param>
 565  /// <returns>The resulting vector after the divisions.</returns>
 566  public static Vector<T> Divide(Vector<T> a, T b)
 8567  {
 8568    Vector<T>? c = null;
 8569    Divide(a, b, ref c);
 8570    return c!;
 8571  }
 572
 573  /// <summary>Divides all the values in the vector by a scalar.</summary>
 574  /// <param name="a">The vector to have its values divided.</param>
 575  /// <param name="b">The scalar to divide all the vectors values by.</param>
 576  /// <returns>The vector after the divisions.</returns>
 8577  public static Vector<T> operator /(Vector<T> a, T b) => Divide(a, b);
 578
 579  /// <summary>Divides all the components of a vector by a scalar.</summary>
 580  /// <param name="b">The scalar to divide the vector components by.</param>
 581  /// <param name="c">The resulting vector after the divisions.</param>
 0582  public void Divide(T b, ref Vector<T>? c) => Divide(this, b, ref c);
 583
 584  /// <summary>Divides all the values in this vector by a scalar.</summary>
 585  /// <param name="b">The scalar to divide the values of the vector by.</param>
 586  /// <returns>The resulting vector after the divisions.</returns>
 0587  public Vector<T> Divide(T b) => this / b;
 588
 589  #endregion
 590
 591  #region DotProduct
 592
 593  /// <summary>Computes the dot product between two vectors.</summary>
 594  /// <param name="a">The first vector of the dot product operation.</param>
 595  /// <param name="b">The second vector of the dot product operation.</param>
 596  /// <returns>The result of the dot product operation.</returns>
 597  public static T DotProduct(Vector<T> a, Vector<T> b)
 11598  {
 11599    if (a is null) throw new ArgumentNullException(nameof(a));
 11600    if (b is null) throw new ArgumentNullException(nameof(b));
 11601    int Length = a.Dimensions;
 12602    if (sourceof(Length != b.Dimensions, out string c1)) throw new ArgumentException(c1);
 10603    T result = Constant<T>.Zero;
 10604    T[] A = a._vector;
 10605    T[] B = b._vector;
 80606    for (int i = 0; i < Length; i++)
 30607    {
 30608      result = MultiplyAddImplementation<T>.Function(A[i], B[i], result);
 30609    }
 10610    return result;
 10611  }
 612
 613  /// <summary>Computes the dot product between this vector and another.</summary>
 614  /// <param name="right">The second vector of the dot product operation.</param>
 615  /// <returns>The result of the dot product.</returns>
 616  public T DotProduct(Vector<T> right)
 11617  {
 11618    return DotProduct(this, right);
 10619  }
 620
 621  #endregion
 622
 623  #region CrossProduct
 624
 625  /// <summary>Computes the cross product of two vectors.</summary>
 626  /// <param name="a">The first vector of the cross product operation.</param>
 627  /// <param name="b">The second vector of the cross product operation.</param>
 628  /// <param name="c">The result of the cross product operation.</param>
 629  public static void CrossProduct(Vector<T> a, Vector<T> b, ref Vector<T>? c)
 5630  {
 5631    if (a is null) throw new ArgumentNullException(nameof(a));
 5632    if (b is null) throw new ArgumentNullException(nameof(b));
 5633    T[] A = a._vector;
 5634    T[] B = b._vector;
 6635    if (sourceof(A.Length != 3, out string c1)) throw new ArgumentException(c1);
 4636    if (sourceof(B.Length != 3, out string c2)) throw new ArgumentException(c2);
 4637    if (c is null || c.Dimensions != 3)
 4638    {
 4639      c = new Vector<T>(3);
 4640    }
 4641    T[] C = c._vector;
 4642    C[0] = Subtraction(Multiplication(A[1], B[2]), Multiplication(A[2], B[1]));
 4643    C[1] = Subtraction(Multiplication(A[2], B[0]), Multiplication(A[0], B[2]));
 4644    C[2] = Subtraction(Multiplication(A[0], B[1]), Multiplication(A[1], B[0]));
 4645  }
 646
 647  /// <summary>Computes the cross product of two vectors.</summary>
 648  /// <param name="a">The first vector of the cross product operation.</param>
 649  /// <param name="b">The second vector of the cross product operation.</param>
 650  /// <returns>The result of the cross product operation.</returns>
 651  public static Vector<T> CrossProduct(Vector<T> a, Vector<T> b)
 5652  {
 5653    Vector<T>? c = null;
 5654    CrossProduct(a, b, ref c);
 4655    return c!;
 4656  }
 657
 658  /// <summary>Computes the cross product of two vectors.</summary>
 659  /// <param name="b">The second vector of the cross product operation.</param>
 660  /// <param name="c">The result of the cross product operation.</param>
 661  public void CrossProduct(Vector<T> b, ref Vector<T>? c)
 0662  {
 0663    CrossProduct(this, b, ref c);
 0664  }
 665
 666  /// <summary>Computes the cross product of two vectors.</summary>
 667  /// <param name="b">The second vector of the dot product operation.</param>
 668  /// <returns>The result of the dot product operation.</returns>
 669  public Vector<T> CrossProduct(Vector<T> b)
 5670  {
 5671    return CrossProduct(this, b);
 4672  }
 673
 674  #endregion
 675
 676  #region Normalize
 677
 678  /// <summary>Normalizes a vector.</summary>
 679  /// <param name="a">The vector to normalize.</param>
 680  /// <param name="b">The result of the normalization.</param>
 681  public static void Normalize(Vector<T> a, ref Vector<T>? b)
 3682  {
 3683    if (a is null) throw new ArgumentNullException(nameof(a));
 3684    if (sourceof(a.Dimensions < 1, out string c1)) throw new ArgumentOutOfRangeException(nameof(a), a, c1);
 3685    T magnitude = a.Magnitude;
 3686    if (Equate(magnitude, Constant<T>.Zero))
 0687    {
 0688      throw new ArgumentOutOfRangeException(nameof(a), a, "!(" + nameof(a) + "." + nameof(a.Magnitude) + " > 0)");
 689    }
 3690    if (b is null || b.Dimensions != a.Dimensions)
 3691    {
 3692      b = new Vector<T>(a.Dimensions);
 3693    }
 30694    for (int i = 0; i < a.Dimensions; i++)
 12695    {
 12696      b._vector[i] = Division(a[i], magnitude);
 12697    }
 3698  }
 699
 700  /// <summary>Normalizes a vector.</summary>
 701  /// <param name="a">The vector to normalize.</param>
 702  /// <returns>The result of the normalization.</returns>
 703  public static Vector<T> Normalize(Vector<T> a)
 3704  {
 3705    Vector<T>? b = null;
 3706    Normalize(a, ref b);
 3707    return b!;
 3708  }
 709
 710  /// <summary>Normalizes a vector.</summary>
 711  /// <param name="b">The result of the normalization.</param>
 712  public void Normalize(ref Vector<T>? b)
 0713  {
 0714    Normalize(this, ref b);
 0715  }
 716
 717  /// <summary>Normalizes this vector.</summary>
 718  /// <returns>The result of the normalization.</returns>
 719  public Vector<T> Normalize()
 3720  {
 3721    return Normalize(this);
 3722  }
 723
 724  #endregion
 725
 726  #region Angle
 727
 728  /// <summary>Computes the angle between two vectors.</summary>
 729  /// <typeparam name="TArcCos">A type of function for how to compute the inverse of a cosine ratio.</typeparam>
 730  /// <param name="a">The first vector to determine the angle between.</param>
 731  /// <param name="b">The second vector to determine the angle between.</param>
 732  /// <param name="arccos">A function for how to compute the inverse of a cosine ratio.</param>
 733  /// <returns>The angle between the two vectors in radians.</returns>
 734  public static Angle<T> Angle<TArcCos>(Vector<T> a, Vector<T> b, TArcCos arccos = default)
 735    where TArcCos : struct, IFunc<T, Angle<T>>
 3736  {
 737    // a â‹… b = |a| * |b| * cosθ
 738
 3739    if (a is null) throw new ArgumentNullException(nameof(a));
 3740    if (b is null) throw new ArgumentNullException(nameof(b));
 3741    T dotProduct = a.DotProduct(b);
 3742    T aMagTimesbMag = Multiplication(a.Magnitude, b.Magnitude);
 3743    T divided = Division(dotProduct, aMagTimesbMag);
 3744    return arccos.Invoke(divided);
 3745  }
 746
 747  /// <summary>Computes the angle between two vectors.</summary>
 748  /// <param name="a">The first vector to determine the angle between.</param>
 749  /// <param name="b">The second vector to determine the angle between.</param>
 750  /// <param name="arccos">A delegate for how to compute the inverse of a cosine ratio.</param>
 751  /// <returns>The angle between the two vectors in radians.</returns>
 752  public static Angle<T> Angle(Vector<T> a, Vector<T> b, Func<T, Angle<T>> arccos) =>
 3753    Angle<SFunc<T, Angle<T>>>(a, b, arccos);
 754
 755  /// <summary>Computes the angle between two vectors.</summary>
 756  /// <param name="b">The second vector to determine the angle between.</param>
 757  /// <param name="arccos">A function for how to compute the inverse of a cosine ratio.</param>
 758  /// <returns>The angle between the two vectors in radians.</returns>
 3759  public Angle<T> Angle(Vector<T> b, Func<T, Angle<T>> arccos) => Angle(this, b, arccos);
 760
 761  /// <summary>Computes the angle between two vectors.</summary>
 762  /// <typeparam name="TArcCos">A type of function for how to compute the inverse of a cosine ratio.</typeparam>
 763  /// <param name="b">The second vector to determine the angle between.</param>
 764  /// <param name="arccos">A function for how to compute the inverse of a cosine ratio.</param>
 765  /// <returns>The angle between the two vectors in radians.</returns>
 766  public Angle<T> Angle<TArcCos>(Vector<T> b, TArcCos arccos = default)
 767    where TArcCos : struct, IFunc<T, Angle<T>> =>
 0768    Angle(this, b, arccos);
 769
 770  #endregion
 771
 772  #region Projection
 773
 774  /// <summary>Computes the cross product of two vectors.</summary>
 775  /// <param name="a">The first vector of the cross product operation.</param>
 776  /// <param name="b">The second vector of the cross product operation.</param>
 777  /// <param name="c">The result of the cross product operation.</param>
 778  public static void Projection(Vector<T> a, Vector<T> b, ref Vector<T>? c)
 4779  {
 4780    if (a is null) throw new ArgumentNullException(nameof(a));
 4781    if (b is null) throw new ArgumentNullException(nameof(b));
 5782    if (sourceof(a.Dimensions != b.Dimensions, out string c1)) throw new ArgumentException(c1);
 3783    int Dimensions = a.Dimensions;
 3784    if (c is null || c.Dimensions != Dimensions)
 3785    {
 3786      c = new Vector<T>(Dimensions);
 3787    }
 3788    T magSquared = a.MagnitudeSquared;
 3789    if (Equate(magSquared, Constant<T>.Zero))
 0790    {
 0791      throw new ArgumentOutOfRangeException(nameof(a), a, "!(" + nameof(a) + "." + nameof(a.Magnitude) + " > 0)");
 792    }
 3793    T dot = a.DotProduct(b);
 3794    T divided = Division(dot, magSquared);
 3795    a.Multiply(divided, ref c);
 3796  }
 797
 798  /// <summary>Computes the cross product of two vectors.</summary>
 799  /// <param name="a">The first vector of the cross product operation.</param>
 800  /// <param name="b">The second vector of the cross product operation.</param>
 801  /// <returns>The result of the cross product operation.</returns>
 802  public static Vector<T> Projection(Vector<T> a, Vector<T> b)
 4803  {
 4804    Vector<T>? c = null;
 4805    Projection(a, b, ref c);
 3806    return c!;
 3807  }
 808
 809  /// <summary>Computes the cross product of two vectors.</summary>
 810  /// <param name="b">The second vector of the cross product operation.</param>
 811  /// <param name="c">The result of the cross product operation.</param>
 812  public void Projection(Vector<T> b, ref Vector<T>? c)
 0813  {
 0814    Projection(this, b, ref c);
 0815  }
 816
 817  /// <summary>Computes the cross product of two vectors.</summary>
 818  /// <param name="b">The second vector of the dot product operation.</param>
 819  /// <returns>The result of the dot product operation.</returns>
 820  public Vector<T> Projection(Vector<T> b)
 4821  {
 4822    return Projection(this, b);
 3823  }
 824
 825  #endregion
 826
 827  #region RotateBy
 828
 829  /// <summary>Rotates a vector by the specified axis and rotation values.</summary>
 830  /// <param name="vector">The vector to rotate.</param>
 831  /// <param name="angle">The angle of the rotation.</param>
 832  /// <param name="x">The x component of the axis vector to rotate about.</param>
 833  /// <param name="y">The y component of the axis vector to rotate about.</param>
 834  /// <param name="z">The z component of the axis vector to rotate about.</param>
 835  /// <returns>The result of the rotation.</returns>
 836  public static Vector<T> RotateBy(Vector<T> vector, Angle<T> angle, T x, T y, T z)
 0837  {
 0838    throw new NotImplementedException();
 839  }
 840
 841  /// <summary>Rotates this vector by quaternon values.</summary>
 842  /// <param name="angle">The amount of rotation about the axis.</param>
 843  /// <param name="x">The x component deterniming the axis of rotation.</param>
 844  /// <param name="y">The y component determining the axis of rotation.</param>
 845  /// <param name="z">The z component determining the axis of rotation.</param>
 846  /// <returns>The resulting vector after the rotation.</returns>
 847  public Vector<T> RotateBy(Angle<T> angle, T x, T y, T z)
 0848  {
 0849    return RotateBy(this, angle, x, y, z);
 0850  }
 851
 852  /// <summary>Rotates a vector by a quaternion.</summary>
 853  /// <param name="a">The vector to rotate.</param>
 854  /// <param name="b">The quaternion to rotate the 3-component vector by.</param>
 855  /// <param name="c">The result of the rotation.</param>
 856  public static void RotateBy(Vector<T> a, Quaternion<T> b, ref Vector<T>? c)
 0857  {
 0858    Quaternion<T>.Rotate(b, a, ref c);
 0859  }
 860
 861  /// <summary>Rotates a vector by a quaternion.</summary>
 862  /// <param name="a">The vector to rotate.</param>
 863  /// <param name="b">The quaternion to rotate the 3-component vector by.</param>
 864  /// <returns>The result of the rotation.</returns>
 865  public static Vector<T> RotateBy(Vector<T> a, Quaternion<T> b)
 0866  {
 0867    Vector<T>? c = null;
 0868    Quaternion<T>.Rotate(b, a, ref c);
 0869    return c!;
 0870  }
 871
 872  /// <summary>Rotates a vector by a quaternion.</summary>
 873  /// <param name="b">The quaternion to rotate the 3-component vector by.</param>
 874  /// <returns>The result of the rotation.</returns>
 875  public Vector<T> RotateBy(Quaternion<T> b)
 0876  {
 0877    return RotateBy(this, b);
 0878  }
 879
 880  #endregion
 881
 882  #region LinearInterpolation
 883
 884  /// <summary>Computes the linear interpolation between two vectors.</summary>
 885  /// <param name="a">The starting vector of the interpolation.</param>
 886  /// <param name="b">The ending vector of the interpolation.</param>
 887  /// <param name="blend">The ratio 0.0 to 1.0 of the interpolation between the start and end.</param>
 888  /// <param name="c">The result of the interpolation.</param>
 889  public static void LinearInterpolation(Vector<T> a, Vector<T> b, T blend, ref Vector<T>? c)
 0890  {
 0891    if (LessThan(blend, Constant<T>.Zero) || GreaterThan(blend, Constant<T>.One))
 0892    {
 0893      throw new ArgumentOutOfRangeException(nameof(blend), blend, "!(0 <= " + nameof(blend) + " <= 1)");
 894    }
 0895    if (sourceof(a.Dimensions != b.Dimensions, out string c2)) throw new ArgumentException(c2);
 0896    if (c is null || c.Dimensions != a.Dimensions)
 0897    {
 0898      c = new Vector<T>(a.Dimensions);
 0899    }
 0900    for (int i = 0; i < a.Dimensions; i++)
 0901    {
 0902      c._vector[i] = Addition(a._vector[i], Multiplication(blend, Subtraction(b._vector[i], a._vector[i])));
 0903    }
 0904  }
 905
 906  /// <summary>Computes the linear interpolation between two vectors.</summary>
 907  /// <param name="a">The starting vector of the interpolation.</param>
 908  /// <param name="b">The ending vector of the interpolation.</param>
 909  /// <param name="blend">The ratio 0.0 to 1.0 of the interpolation between the start and end.</param>
 910  /// <returns>The result of the interpolation.</returns>
 911  public static Vector<T> LinearInterpolation(Vector<T> a, Vector<T> b, T blend)
 0912  {
 0913    Vector<T>? c = null;
 0914    LinearInterpolation(a, b, blend, ref c);
 0915    return c!;
 0916  }
 917
 918  /// <summary>Computes the linear interpolation between two vectors.</summary>
 919  /// <param name="b">The ending vector of the interpolation.</param>
 920  /// <param name="blend">The ratio 0.0 to 1.0 of the interpolation between the start and end.</param>
 921  /// <param name="c">The result of the interpolation.</param>
 922  public void LinearInterpolation(Vector<T> b, T blend, ref Vector<T>? c)
 0923  {
 0924    LinearInterpolation(this, b, blend, ref c);
 0925  }
 926
 927  /// <summary>Computes the linear interpolation between two vectors.</summary>
 928  /// <param name="b">The ending vector of the interpolation.</param>
 929  /// <param name="blend">The ratio 0.0 to 1.0 of the interpolation between the start and end.</param>
 930  /// <returns>The result of the interpolation.</returns>
 931  public Vector<T> LinearInterpolation(Vector<T> b, T blend)
 0932  {
 0933    return LinearInterpolation(this, b, blend);
 0934  }
 935
 936  #endregion
 937
 938  #region SphericalInterpolation
 939
 940  /// <summary>Spherically interpolates between two vectors.</summary>
 941  /// <param name="a">The starting vector of the interpolation.</param>
 942  /// <param name="b">The ending vector of the interpolation.</param>
 943  /// <param name="blend">The ratio 0.0 to 1.0 defining the interpolation distance between the two vectors.</param>
 944  /// <param name="c">The result of the slerp operation.</param>
 945  public static void SphericalInterpolation(Vector<T> a, Vector<T> b, T blend, ref Vector<T>? c)
 0946  {
 0947    throw new NotImplementedException();
 948  }
 949
 950  /// <summary>Spherically interpolates between two vectors.</summary>
 951  /// <param name="a">The starting vector of the interpolation.</param>
 952  /// <param name="b">The ending vector of the interpolation.</param>
 953  /// <param name="blend">The ratio 0.0 to 1.0 defining the interpolation distance between the two vectors.</param>
 954  /// <returns>The result of the slerp operation.</returns>
 955  public static Vector<T> SphericalInterpolation(Vector<T> a, Vector<T> b, T blend)
 0956  {
 0957    Vector<T>? c = null;
 0958    SphericalInterpolation(a, b, blend, ref c);
 0959    return c!;
 0960  }
 961
 962  /// <summary>Sphereically interpolates between two vectors.</summary>
 963  /// <param name="b">The ending vector of the interpolation.</param>
 964  /// <param name="blend">The ratio 0.0 to 1.0 defining the interpolation distance between the two vectors.</param>
 965  /// <returns>The result of the slerp operation.</returns>
 0966  public Vector<T> SphericalInterpolation(Vector<T> b, T blend) => SphericalInterpolation(this, b, blend);
 967
 968  #endregion
 969
 970  #region BarycentricInterpolation
 971
 972  /// <summary>Interpolates between three vectors using barycentric coordinates.</summary>
 973  /// <param name="a">The first vector of the interpolation.</param>
 974  /// <param name="b">The second vector of the interpolation.</param>
 975  /// <param name="c">The thrid vector of the interpolation.</param>
 976  /// <param name="u">The "U" value of the barycentric interpolation equation.</param>
 977  /// <param name="v">The "V" value of the barycentric interpolation equation.</param>
 978  /// <param name="d">The result of the interpolation.</param>
 979  public static void BarycentricInterpolation(Vector<T> a, Vector<T> b, Vector<T> c, T u, T v, ref Vector<T>? d)
 0980  {
 0981    if (a is null) throw new ArgumentNullException(nameof(a));
 0982    if (b is null) throw new ArgumentNullException(nameof(b));
 0983    if (c is null) throw new ArgumentNullException(nameof(c));
 0984    if (Equate(a.Dimensions, b.Dimensions, c.Dimensions))
 0985    {
 0986      throw new ArgumentException("Arguments invalid !(" +
 0987        nameof(a) + "." + nameof(a.Dimensions) + " == " +
 0988        nameof(b) + "." + nameof(b.Dimensions) + " == " +
 0989        nameof(c) + "." + nameof(c.Dimensions) + ")");
 990    }
 991
 992    // Note: needs optimization (call the "ref" methods)
 0993    d = a + (u * (b - a)) + (v * (c - a));
 0994  }
 995
 996  /// <summary>Interpolates between three vectors using barycentric coordinates.</summary>
 997  /// <param name="a">The first vector of the interpolation.</param>
 998  /// <param name="b">The second vector of the interpolation.</param>
 999  /// <param name="c">The thrid vector of the interpolation.</param>
 1000  /// <param name="u">The "U" value of the barycentric interpolation equation.</param>
 1001  /// <param name="v">The "V" value of the barycentric interpolation equation.</param>
 1002  /// <returns>The resulting vector of the barycentric interpolation.</returns>
 1003  public static Vector<T> BarycentricInterpolation(Vector<T> a, Vector<T> b, Vector<T> c, T u, T v)
 01004  {
 01005    Vector<T>? d = null;
 01006    BarycentricInterpolation(a._vector, b._vector, c._vector, u, v, ref d);
 01007    return d!;
 01008  }
 1009
 1010  /// <summary>Interpolates between three vectors using barycentric coordinates.</summary>
 1011  /// <param name="b">The second vector of the interpolation.</param>
 1012  /// <param name="c">The thrid vector of the interpolation.</param>
 1013  /// <param name="u">The "U" value of the barycentric interpolation equation.</param>
 1014  /// <param name="v">The "V" value of the barycentric interpolation equation.</param>
 1015  /// <returns>The resulting vector of the barycentric interpolation.</returns>
 1016  public Vector<T> BarycentricInterpolation(Vector<T> b, Vector<T> c, T u, T v)
 01017  {
 01018    return BarycentricInterpolation(this, b._vector, c._vector, u, v);
 01019  }
 1020
 1021  #endregion
 1022
 1023  #region Equal
 1024
 1025  /// <summary>Does a value equality check.</summary>
 1026  /// <param name="a">The first vector to check for equality.</param>
 1027  /// <param name="b">The second vector  to check for equality.</param>
 1028  /// <returns>True if values are equal, false if not.</returns>
 1029  public static bool Equal(Vector<T> a, Vector<T> b)
 541030  {
 541031    if (a is null)
 01032    {
 01033      if (b is null)
 01034      {
 01035        return true;
 1036      }
 1037      else
 01038      {
 01039        return false;
 1040      }
 1041    }
 541042    if (b is null)
 01043    {
 01044      return false;
 1045    }
 1046    else
 541047    {
 541048      int Length = a.Dimensions;
 541049      if (Length != b.Dimensions)
 01050      {
 01051        return false;
 1052      }
 541053      T[] A = a._vector;
 541054      T[] B = b._vector;
 4381055      for (int i = 0; i < Length; i++)
 1651056      {
 1651057        if (Statics.Inequate(A[i], B[i]))
 01058        {
 01059          return false;
 1060        }
 1651061      }
 541062      return true;
 1063    }
 541064  }
 1065
 1066  /// <summary>Does a value non-equality check.</summary>
 1067  /// <param name="a">The first vector to check for non-equality.</param>
 1068  /// <param name="b">The second vector  to check for non-equality.</param>
 1069  /// <returns>True if values are not equal, false if not.</returns>
 1070  public static bool NotEqual(Vector<T> a, Vector<T> b)
 01071  {
 01072    return !Equal(a, b);
 01073  }
 1074
 1075  /// <summary>Does an equality check by value. (warning for float errors)</summary>
 1076  /// <param name="a">The first vector of the equality check.</param>
 1077  /// <param name="b">The second vector of the equality check.</param>
 1078  /// <returns>true if the values are equal, false if not.</returns>
 1079  public static bool operator ==(Vector<T> a, Vector<T> b)
 541080  {
 541081    return Equal(a, b);
 541082  }
 1083
 1084  /// <summary>Does an anti-equality check by value. (warning for float errors)</summary>
 1085  /// <param name="a">The first vector of the anit-equality check.</param>
 1086  /// <param name="b">The second vector of the anti-equality check.</param>
 1087  /// <returns>true if the values are not equal, false if they are.</returns>
 1088  public static bool operator !=(Vector<T> a, Vector<T> b)
 01089  {
 01090    return !Equal(a, b);
 01091  }
 1092
 1093  /// <summary>Check for equality by value.</summary>
 1094  /// <param name="b">The other vector of the equality check.</param>
 1095  /// <returns>true if the values were equal, false if not.</returns>
 1096  public bool Equal(Vector<T> b)
 01097  {
 01098    return this == b;
 01099  }
 1100
 1101  /// <summary>Check for non-equality by value.</summary>
 1102  /// <param name="b">The other vector of the non-equality check.</param>
 1103  /// <returns>true if the values were not equal, false if not.</returns>
 1104  public bool NotEqual(Vector<T> b)
 01105  {
 01106    return this != b;
 01107  }
 1108
 1109  #endregion
 1110
 1111  #region Equal (+leniency)
 1112
 1113  /// <summary>Does a value equality check with leniency.</summary>
 1114  /// <param name="a">The first vector to check for equality.</param>
 1115  /// <param name="b">The second vector to check for equality.</param>
 1116  /// <param name="leniency">How much the values can vary but still be considered equal.</param>
 1117  /// <returns>True if values are equal, false if not.</returns>
 1118  public static bool Equal(Vector<T> a, Vector<T> b, T leniency)
 81119  {
 81120    if (a is null)
 01121    {
 01122      if (b is null)
 01123      {
 01124        return true;
 1125      }
 1126      else
 01127      {
 01128        return false;
 1129      }
 1130    }
 81131    if (b is null)
 01132    {
 01133      return false;
 1134    }
 81135    int Length = a.Dimensions;
 81136    if (Length != b.Dimensions)
 01137    {
 01138      return false;
 1139    }
 81140    T[] A = a._vector;
 81141    T[] B = b._vector;
 401142    for (int i = 0; i < Length; i++)
 161143    {
 161144      if (!Statics.EqualToLeniency(A[i], B[i], leniency))
 41145      {
 41146        return false;
 1147      }
 121148    }
 41149    return true;
 81150  }
 1151
 1152  /// <summary>Checks for equality by value with some leniency.</summary>
 1153  /// <param name="right">The other vector of the equality check.</param>
 1154  /// <param name="leniency">The ammount the values can differ but still be considered equal.</param>
 1155  /// <returns>true if the values were cinsidered equal, false if not.</returns>
 1156  public bool Equal(Vector<T> right, T leniency)
 81157  {
 81158    return Equal(this, right, leniency);
 81159  }
 1160
 1161  #endregion
 1162
 1163  #endregion
 1164
 1165  #region Other Methods
 1166
 1167  #region Clone
 1168
 1169  /// <summary>Creates a copy of a vector.</summary>
 1170  /// <param name="a">The vector to copy.</param>
 1171  /// <returns>The copy of this vector.</returns>
 1172  public static Vector<T> Clone(Vector<T> a)
 01173  {
 01174    if (a is null) throw new ArgumentNullException(nameof(a));
 01175    return new Vector<T>(a);
 01176  }
 1177
 1178  /// <summary>Copies this vector.</summary>
 1179  /// <returns>The copy of this vector.</returns>
 1180  public Vector<T> Clone()
 01181  {
 01182    return Clone(this);
 01183  }
 1184
 1185  #endregion
 1186
 1187  #endregion
 1188
 1189  #region Casting Operators
 1190
 1191  /// <summary>Implicit conversions from Vector to T[].</summary>
 1192  /// <param name="vector">The Vector to be converted to a T[].</param>
 1193  /// <returns>The T[] of the vector.</returns>
 1194  public static implicit operator T[](Vector<T> vector)
 01195  {
 01196    return vector._vector;
 01197  }
 1198
 1199  /// <summary>Implicit conversions from Vector to T[].</summary>
 1200  /// <param name="array">The Vector to be converted to a T[].</param>
 1201  /// <returns>The T[] of the vector.</returns>
 1202  public static implicit operator Vector<T>(T[] array)
 01203  {
 01204    return new Vector<T>(array);
 01205  }
 1206
 1207  /// <summary>Converts a vector into a matrix.</summary>
 1208  /// <param name="vector">The vector to convert.</param>
 1209  /// <returns>The resulting matrix.</returns>
 1210  public static explicit operator Matrix<T>(Vector<T> vector)
 01211  {
 01212    return new Matrix<T>(vector);
 01213  }
 1214
 1215  /// <summary>Implicitly converts a scalar into a one dimensional vector.</summary>
 1216  /// <param name="scalar">The scalar value.</param>
 1217  /// <returns>The one dimensional vector </returns>
 1218  public static explicit operator Vector<T>(T scalar)
 01219  {
 01220    return new Vector<T>(scalar);
 01221  }
 1222
 1223  #endregion
 1224
 1225  #region Overrides
 1226
 1227  /// <summary>Computes a hash code from the values of this matrix.</summary>
 1228  /// <returns>A hash code for the matrix.</returns>
 1229  public override int GetHashCode()
 01230  {
 01231    int hashCode = default;
 01232    for (int i = 1; i < _vector.Length; i++)
 01233    {
 01234      hashCode = HashCode.Combine(hashCode, Hash(_vector[i]));
 01235    }
 01236    return hashCode;
 01237  }
 1238
 1239  /// <summary>Does an equality check by reference.</summary>
 1240  /// <param name="right">The object to compare to.</param>
 1241  /// <returns>True if the references are equal, false if not.</returns>
 01242  public override bool Equals(object? right) => right is Vector<T> vector && Equal(this, vector);
 1243
 1244  #endregion
 1245}