/// <summary>Attempts to invert the given matrix. If the operation succeeds, the inverted matrix is stored in the result parameter.</summary>
        /// <param name="matrix">The source matrix.</param>
        /// <param name="result">The output matrix.</param>
        /// <returns>True if the operation succeeded, False otherwise.</returns>
        public static bool Invert <T>(Matrix3X2 <T> matrix, out Matrix3X2 <T> result)
            where T : unmanaged, IFormattable, IEquatable <T>, IComparable <T>
        {
            T det = Scalar.Subtract(Scalar.Multiply(matrix.M11, matrix.M22), Scalar.Multiply(matrix.M21, matrix.M12));

            if (!Scalar.GreaterThanOrEqual(Scalar.Abs(det), Scalar <T> .Epsilon))
            {
                result = new(Scalar <T> .NaN, Scalar <T> .NaN, Scalar <T> .NaN, Scalar <T> .NaN, Scalar <T> .NaN, Scalar <T> .NaN);
                return(false);
            }

            T invDet = Scalar.Reciprocal(det);

            result = default;

            result.M11 = Scalar.Multiply(matrix.M22, invDet);
            result.M12 = Scalar.Negate(Scalar.Multiply(matrix.M12, invDet));

            result.M21 = Scalar.Negate(Scalar.Multiply(matrix.M21, invDet));
            result.M22 = Scalar.Multiply(matrix.M11, invDet);

            result.M31 = Scalar.Multiply(Scalar.Subtract(Scalar.Multiply(matrix.M21, matrix.M32), Scalar.Multiply(matrix.M31, matrix.M22)), invDet);
            result.M32 = Scalar.Multiply(Scalar.Subtract(Scalar.Multiply(matrix.M31, matrix.M12), Scalar.Multiply(matrix.M11, matrix.M32)), invDet);

            return(true);
        }
 /// <summary>Linearly interpolates from matrix1 to matrix2, based on the third parameter.</summary>
 /// <param name="matrix1">The first source matrix.</param>
 /// <param name="matrix2">The second source matrix.</param>
 /// <param name="amount">The relative weighting of matrix2.</param>
 /// <returns>The interpolated matrix.</returns>
 public static Matrix3X2 <T> Lerp <T>(Matrix3X2 <T> matrix1, Matrix3X2 <T> matrix2, T amount)
     where T : unmanaged, IFormattable, IEquatable <T>, IComparable <T>
 {
     return(new(Vector2D.Lerp(matrix1.Row1, matrix2.Row1, amount),
                Vector2D.Lerp(matrix1.Row2, matrix2.Row2, amount),
                Vector2D.Lerp(matrix1.Row3, matrix2.Row3, amount)));
 }
        /// <summary>Creates a translation matrix from the given vector.</summary>
        /// <param name="position">The translation position.</param>                        `
        /// <returns>A translation matrix.</returns>
        public static Matrix3X2 <T> CreateTranslation <T>(Vector2D <T> position)
            where T : unmanaged, IFormattable, IEquatable <T>, IComparable <T>
        {
            Matrix3X2 <T> result = Matrix3X2 <T> .Identity;

            result.M31 = position.X;
            result.M32 = position.Y;

            return(result);
        }
        /// <summary>Creates a translation matrix from the given X and Y components.</summary>
        /// <param name="xPosition">The X position.</param>
        /// <param name="yPosition">The Y position.</param>
        /// <returns>A translation matrix.</returns>
        public static Matrix3X2 <T> CreateTranslation <T>(T xPosition, T yPosition)
            where T : unmanaged, IFormattable, IEquatable <T>, IComparable <T>
        {
            Matrix3X2 <T> result = Matrix3X2 <T> .Identity;

            result.M31 = xPosition;
            result.M32 = yPosition;

            return(result);
        }
        /// <summary>Creates a scale matrix that scales uniformly with the given scale.</summary>
        /// <param name="scale">The uniform scale to use.</param>
        /// <returns>A scaling matrix.</returns>
        public static Matrix3X2 <T> CreateScale <T>(T scale)
            where T : unmanaged, IFormattable, IEquatable <T>, IComparable <T>
        {
            Matrix3X2 <T> result = Matrix3X2 <T> .Identity;

            result.M11 = scale;
            result.M22 = scale;

            return(result);
        }
        /// <summary>Creates a skew matrix from the given angles in radians.</summary>
        /// <param name="radiansX">The X angle, in radians.</param>
        /// <param name="radiansY">The Y angle, in radians.</param>
        /// <returns>A skew matrix.</returns>
        public static Matrix3X2 <T> CreateSkew <T>(T radiansX, T radiansY)
            where T : unmanaged, IFormattable, IEquatable <T>, IComparable <T>
        {
            Matrix3X2 <T> result = Matrix3X2 <T> .Identity;

            T xTan = Scalar.Tan(radiansX);
            T yTan = Scalar.Tan(radiansY);

            result.M12 = yTan;
            result.M21 = xTan;

            return(result);
        }
        /// <summary>Creates a scale matrix that scales uniformly with the given scale with an offset from the given center.</summary>
        /// <param name="scale">The uniform scale to use.</param>
        /// <param name="centerPoint">The center offset.</param>
        /// <returns>A scaling matrix.</returns>
        public static Matrix3X2 <T> CreateScale <T>(T scale, Vector2D <T> centerPoint)
            where T : unmanaged, IFormattable, IEquatable <T>, IComparable <T>
        {
            Matrix3X2 <T> result = Matrix3X2 <T> .Identity;

            T tx = Scalar.Multiply(centerPoint.X, Scalar.Subtract(Scalar <T> .One, scale));
            T ty = Scalar.Multiply(centerPoint.Y, Scalar.Subtract(Scalar <T> .One, scale));

            result.M11 = scale;
            result.M22 = scale;
            result.M31 = tx;
            result.M32 = ty;

            return(result);
        }
        /// <summary>Creates a skew matrix from the given angles in radians and a center point.</summary>
        /// <param name="radiansX">The X angle, in radians.</param>
        /// <param name="radiansY">The Y angle, in radians.</param>
        /// <param name="centerPoint">The center point.</param>
        /// <returns>A skew matrix.</returns>
        public static Matrix3X2 <T> CreateSkew <T>(T radiansX, T radiansY, Vector2D <T> centerPoint)
            where T : unmanaged, IFormattable, IEquatable <T>, IComparable <T>
        {
            Matrix3X2 <T> result = Matrix3X2 <T> .Identity;

            T xTan = Scalar.Tan(radiansX);
            T yTan = Scalar.Tan(radiansY);

            T tx = Scalar.Negate(Scalar.Multiply(centerPoint.Y, xTan));
            T ty = Scalar.Negate(Scalar.Multiply(centerPoint.X, yTan));

            result.M12 = yTan;
            result.M21 = xTan;

            result.M31 = tx;
            result.M32 = ty;

            return(result);
        }
 public static Matrix3X2 <T> Subtract <T>(Matrix3X2 <T> value1, Matrix3X2 <T> value2)
     where T : unmanaged, IFormattable, IEquatable <T>, IComparable <T>
 => value1 - value2;
 public static Matrix3X2 <T> Negate <T>(Matrix3X2 <T> value)
     where T : unmanaged, IFormattable, IEquatable <T>, IComparable <T>
 => - value;
 public static Matrix3X2 <T> Multiply <T>(Matrix3X2 <T> value1, T value2)
     where T : unmanaged, IFormattable, IEquatable <T>, IComparable <T>
 => value1 * value2;
        /// <summary>Creates a rotation matrix using the given rotation in radians.</summary>
        /// <param name="radians">The amount of rotation, in radians.</param>
        /// <returns>A rotation matrix.</returns>
        public static Matrix3X2 <T> CreateRotation <T>(T radians)
            where T : unmanaged, IFormattable, IEquatable <T>, IComparable <T>
        {
            radians = Scalar.IEEERemainder(radians, Scalar <T> .Tau);

            T c, s;

            if (Scalar.GreaterThan(radians, Scalar.As <float, T>(-RotationEpsilon)) && !Scalar.GreaterThanOrEqual(radians, Scalar.As <float, T>(RotationEpsilon)))
            {
                // Exact case for zero rotation.
                c = Scalar <T> .One;
                s = Scalar <T> .Zero;
            }
            else if (Scalar.GreaterThan(radians, Scalar.As <float, T>(
#if MATHF
                                            MathF.PI
#else
                                                ((float)Math.PI)
#endif
                                            / 2 - RotationEpsilon)) && !Scalar.GreaterThanOrEqual(radians, Scalar.As <float, T>(
#if MATHF
                                                                                                      MathF.PI
#else
                                                                                                          ((float)Math.PI)
#endif
                                                                                                      / 2 + RotationEpsilon)))
            {
                // Exact case for 90 degree rotation.
                c = Scalar <T> .Zero;
                s = Scalar <T> .One;
            }
            else if (!Scalar.GreaterThanOrEqual(radians, Scalar.As <float, T>(-
#if MATHF
                                                                              MathF.PI
#else
                                                                                  ((float)Math.PI)
#endif
                                                                              + RotationEpsilon)) || Scalar.GreaterThan(radians, Scalar.As <float, T>(
#if MATHF
                                                                                                                            MathF.PI
#else
                                                                                                                                ((float)Math.PI)
#endif
                                                                                                                            - RotationEpsilon)))
            {
                // Exact case for 180 degree rotation.
                c = Scalar <T> .MinusOne;
                s = Scalar <T> .Zero;
            }
            else if (Scalar.GreaterThan(radians, Scalar.As <float, T>(-
#if MATHF
                                                                      MathF.PI
#else
                                                                          ((float)Math.PI)
#endif
                                                                      / 2 - RotationEpsilon)) && !Scalar.GreaterThanOrEqual(radians, Scalar.As <float, T>(-
#if MATHF
                                                                                                                                                          MathF.PI
#else
                                                                                                                                                              ((float)Math.PI)
#endif
                                                                                                                                                          / 2 + RotationEpsilon)))
            {
                // Exact case for 270 degree rotation.
                c = Scalar <T> .Zero;
                s = Scalar <T> .MinusOne;
            }
            else
            {
                // Arbitrary rotation.
                c = Scalar.Cos(radians);
                s = Scalar.Sin(radians);
            }

            // [  c  s ]
            // [ -s  c ]
            // [  0  0 ]
            Matrix3X2 <T> result = Matrix3X2 <T> .Identity;

            result.M11 = c;
            result.M12 = s;
            result.M21 = Scalar.Negate(s);
            result.M22 = c;

            return(result);
        }