Inverse, cofactor and adjugate matrices

This commit is contained in:
DBotThePony 2022-02-19 20:52:27 +07:00
parent cb1bec0328
commit d0b3c7347c
Signed by: DBot
GPG Key ID: DCC23B5715498507
9 changed files with 1200 additions and 108 deletions

View File

@ -66,6 +66,33 @@ interface IDoubleMatrix<T : IDoubleMatrix<T>> : IMatrixGetterDouble {
* This matrix determinant. If matrix is not square matrix, null is returned.
*/
val determinant: Double?
/**
* This matrix' inverse matrix (this * I = identity).
*
* This operation is computation intense, do cache its result.
*
* If this matrix is not square matrix, or determinant is zero, null is returned.
*/
val inverse: T?
/**
* This matrix' cofactor matrix.
*
* This operation is computation intense, do cache its result.
*
* If this matrix is not square matrix, null is returned.
*/
val cofactor: T?
/**
* This matrix' adjugate matrix.
*
* This operation is computation intense, do cache its result.
*
* If this matrix is not square matrix, null is returned.
*/
val adjugate: T?
}
interface IMutableDoubleMatrix<T : IMutableDoubleMatrix<T>> : IMatrixSetterDouble {

View File

@ -66,6 +66,33 @@ interface IFloatMatrix<T : IFloatMatrix<T>> : IMatrixGetterFloat {
* This matrix determinant. If matrix is not square matrix, null is returned.
*/
val determinant: Float?
/**
* This matrix' inverse matrix (this * I = identity).
*
* This operation is computation intense, do cache its result.
*
* If this matrix is not square matrix, or determinant is zero, null is returned.
*/
val inverse: T?
/**
* This matrix' cofactor matrix.
*
* This operation is computation intense, do cache its result.
*
* If this matrix is not square matrix, null is returned.
*/
val cofactor: T?
/**
* This matrix' adjugate matrix.
*
* This operation is computation intense, do cache its result.
*
* If this matrix is not square matrix, null is returned.
*/
val adjugate: T?
}
interface IMutableFloatMatrix<T : IMutableFloatMatrix<T>> : IMatrixSetterFloat {

View File

@ -5,6 +5,8 @@ import ru.dbotthepony.kvector.api.IMatrix
import ru.dbotthepony.kvector.api.ISquareMatrix
import ru.dbotthepony.kvector.api.ITransposable
import ru.dbotthepony.kvector.matrix.*
import ru.dbotthepony.kvector.matrix.ndouble.*
import ru.dbotthepony.kvector.matrix.nfloat.*
import ru.dbotthepony.kvector.vector.ndouble.Vector2d
import ru.dbotthepony.kvector.vector.ndouble.Vector3d
import ru.dbotthepony.kvector.vector.ndouble.Vector4d
@ -33,6 +35,153 @@ interface IMatrix2d<T : IMatrix2d<T>> : IMatrix<T>, IDoubleMatrix<T>, ITransposa
val c1: Vector2d
val r0: Vector2d
val r1: Vector2d
/**
* Creates a copy of this matrix as [Matrix4d],
* setting last two rows and columns to 0
*/
fun toMatrix4d(): Matrix4d {
return Matrix4d(
c00, c01, 0.0, 0.0,
c10, c11, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,
)
}
/**
* Creates a copy of this matrix as [Matrix3d],
* setting last row and column to 0
*/
fun toMatrix3d(): Matrix3d {
return Matrix3d(
c00, c01, 0.0,
c10, c11, 0.0,
0.0, 0.0, 0.0,
)
}
/**
* Creates a copy of this matrix as [Matrix2d]
*/
fun toMatrix2d(): Matrix2d {
return Matrix2d(
c00, c01,
c10, c11,
)
}
/**
* Creates a copy of this matrix as [MutableMatrix4d],
* setting last two columns and rows to 0
*/
fun toMutableMatrix4d(): MutableMatrix4d {
return MutableMatrix4d(
c00, c01, 0.0, 0.0,
c10, c11, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,
)
}
/**
* Creates a copy of this matrix as [MutableMatrix3d],
* setting last column and row to 0
*/
fun toMutableMatrix3d(): MutableMatrix3d {
return MutableMatrix3d(
c00, c01, 0.0,
c10, c11, 0.0,
0.0, 0.0, 0.0,
)
}
/**
* Creates a copy of this matrix as [MutableMatrix2d]
*/
fun toMutableMatrix2d(): MutableMatrix2d {
return MutableMatrix2d(
c00, c01,
c10, c11,
)
}
/**
* Creates a copy of this matrix as [Matrix4f],
* casing all [Double]s to [Float]s,
* setting last two columns and rows to 0
*/
fun toMatrix4f(): Matrix4f {
return Matrix4f(
c00.toFloat(), c01.toFloat(), 0f, 0f,
c10.toFloat(), c11.toFloat(), 0f, 0f,
0f, 0f, 0f, 0f,
0f, 0f, 0f, 0f,
)
}
/**
* Creates a copy of this matrix as [Matrix3f],
* casing all [Double]s to [Float]s,
* setting last column and row to 0
*/
fun toMatrix3f(): Matrix3f {
return Matrix3f(
c00.toFloat(), c01.toFloat(), 0f,
c10.toFloat(), c11.toFloat(), 0f,
0f, 0f, 0f,
)
}
/**
* Creates a copy of this matrix as [Matrix2f],
* truncating last row and column
*/
fun toMatrix2f(): Matrix2f {
return Matrix2f(
c00.toFloat(), c01.toFloat(),
c10.toFloat(), c11.toFloat(),
)
}
/**
* Creates a copy of this matrix as [MutableMatrix4f],
* setting last two columns and rows to 0,
* casing all [Double]s to [Float]s
*/
fun toMutableMatrix4f(): MutableMatrix4f {
return MutableMatrix4f(
c00.toFloat(), c01.toFloat(), 0f, 0f,
c10.toFloat(), c11.toFloat(), 0f, 0f,
0f, 0f, 0f, 0f,
0f, 0f, 0f, 0f,
)
}
/**
* Creates a copy of this matrix as [MutableMatrix3f],
* setting last column and row to 0,
* casing all [Double]s to [Float]s
*/
fun toMutableMatrix3f(): MutableMatrix3f {
return MutableMatrix3f(
c00.toFloat(), c01.toFloat(), 0f,
c10.toFloat(), c11.toFloat(), 0f,
0f, 0f, 0f,
)
}
/**
* Creates a copy of this matrix as [MutableMatrix2f],
* truncating last row and column,
* casing all [Double]s to [Float]s
*/
fun toMutableMatrix2f(): MutableMatrix2f {
return MutableMatrix2f(
c00.toFloat(), c01.toFloat(),
c10.toFloat(), c11.toFloat(),
)
}
}
/**
@ -83,6 +232,152 @@ interface IMatrix3d<T : IMatrix3d<T>> : IMatrix<T>, IDoubleMatrix<T>, ITransposa
val r2: Vector3d
override val translation: Vector2d get() = Vector2d(r02, r12)
/**
* Creates a copy of this matrix as [Matrix4d],
* setting last row and column to 0
*/
fun toMatrix4d(): Matrix4d {
return Matrix4d(
c00, c01, c02, 0.0,
c10, c11, c12, 0.0,
c20, c21, c22, 0.0,
0.0, 0.0, 0.0, 0.0,
)
}
/**
* Creates a copy of this matrix as [Matrix3d],
*/
fun toMatrix3d(): Matrix3d {
return Matrix3d(
c00, c01, c02,
c10, c11, c12,
c20, c21, c22,
)
}
/**
* Creates a copy of this matrix as [Matrix2d],
* truncating last row and column
*/
fun toMatrix2d(): Matrix2d {
return Matrix2d(
c00, c01,
c10, c11,
)
}
/**
* Creates a copy of this matrix as [MutableMatrix4d],
* setting last column and row to 0
*/
fun toMutableMatrix4d(): MutableMatrix4d {
return MutableMatrix4d(
c00, c01, c02, 0.0,
c10, c11, c12, 0.0,
c20, c21, c22, 0.0,
0.0, 0.0, 0.0, 0.0,
)
}
/**
* Creates a copy of this matrix as [MutableMatrix3d]
*/
fun toMutableMatrix3d(): MutableMatrix3d {
return MutableMatrix3d(
c00, c01, c02,
c10, c11, c12,
c20, c21, c22,
)
}
/**
* Creates a copy of this matrix as [MutableMatrix2d],
* truncating last row and column
*/
fun toMutableMatrix2d(): MutableMatrix2d {
return MutableMatrix2d(
c00, c01,
c10, c11,
)
}
/**
* Creates a copy of this matrix as [Matrix4f],
* casing all [Double]s to [Float]s,
* setting last column and row to 0
*/
fun toMatrix4f(): Matrix4f {
return Matrix4f(
c00.toFloat(), c01.toFloat(), c02.toFloat(), 0f,
c10.toFloat(), c11.toFloat(), c12.toFloat(), 0f,
c20.toFloat(), c21.toFloat(), c22.toFloat(), 0f,
0f, 0f, 0f, 0f,
)
}
/**
* Creates a copy of this matrix as [Matrix3f],
* casing all [Double]s to [Float]s
*/
fun toMatrix3f(): Matrix3f {
return Matrix3f(
c00.toFloat(), c01.toFloat(), c02.toFloat(),
c10.toFloat(), c11.toFloat(), c12.toFloat(),
c20.toFloat(), c21.toFloat(), c22.toFloat(),
)
}
/**
* Creates a copy of this matrix as [Matrix2f],
* truncating last row and column,
* casing all [Double]s to [Float]s
*/
fun toMatrix2f(): Matrix2f {
return Matrix2f(
c00.toFloat(), c01.toFloat(),
c10.toFloat(), c11.toFloat(),
)
}
/**
* Creates a copy of this matrix as [MutableMatrix4f],
* setting last column and row to 0,
* casing all [Double]s to [Float]s
*/
fun toMutableMatrix4f(): MutableMatrix4f {
return MutableMatrix4f(
c00.toFloat(), c01.toFloat(), c02.toFloat(), 0f,
c10.toFloat(), c11.toFloat(), c12.toFloat(), 0f,
c20.toFloat(), c21.toFloat(), c22.toFloat(), 0f,
0f, 0f, 0f, 0f,
)
}
/**
* Creates a copy of this matrix as [MutableMatrix3f],
* casing all [Double]s to [Float]s
*/
fun toMutableMatrix3f(): MutableMatrix3f {
return MutableMatrix3f(
c00.toFloat(), c01.toFloat(), c02.toFloat(),
c10.toFloat(), c11.toFloat(), c12.toFloat(),
c20.toFloat(), c21.toFloat(), c22.toFloat(),
)
}
/**
* Creates a copy of this matrix as [MutableMatrix2f],
* truncating last row and column,
* casing all [Double]s to [Float]s
*/
fun toMutableMatrix2f(): MutableMatrix2f {
return MutableMatrix2f(
c00.toFloat(), c01.toFloat(),
c10.toFloat(), c11.toFloat(),
)
}
}
/**
@ -163,4 +458,150 @@ interface IMatrix4d<T : IMatrix4d<T>> : IMatrix<T>, IDoubleMatrix<T>, ITransposa
val r3: Vector4d
override val translation: Vector3d get() = Vector3d(r03, r13, r23)
/**
* Creates a copy of this matrix as [Matrix4d]
*/
fun toMatrix4d(): Matrix4d {
return Matrix4d(
c00, c01, c02, c03,
c10, c11, c12, c13,
c20, c21, c22, c23,
c30, c31, c32, c33,
)
}
/**
* Creates a copy of this matrix as [Matrix3d],
* truncating last row and column
*/
fun toMatrix3d(): Matrix3d {
return Matrix3d(
c00, c01, c02,
c10, c11, c12,
c20, c21, c22,
)
}
/**
* Creates a copy of this matrix as [Matrix2d],
* truncating two last rows and columns
*/
fun toMatrix2d(): Matrix2d {
return Matrix2d(
c00, c01,
c10, c11,
)
}
/**
* Creates a copy of this matrix as [MutableMatrix4d]
*/
fun toMutableMatrix4d(): MutableMatrix4d {
return MutableMatrix4d(
c00, c01, c02, c03,
c10, c11, c12, c13,
c20, c21, c22, c23,
c30, c31, c32, c33,
)
}
/**
* Creates a copy of this matrix as [MutableMatrix3d],
* truncating last row and column
*/
fun toMutableMatrix3d(): MutableMatrix3d {
return MutableMatrix3d(
c00, c01, c02,
c10, c11, c12,
c20, c21, c22,
)
}
/**
* Creates a copy of this matrix as [MutableMatrix2d],
* truncating two last rows and columns
*/
fun toMutableMatrix2d(): MutableMatrix2d {
return MutableMatrix2d(
c00, c01,
c10, c11,
)
}
/**
* Creates a copy of this matrix as [Matrix4f],
* casing all [Double]s to [Float]s
*/
fun toMatrix4f(): Matrix4f {
return Matrix4f(
c00.toFloat(), c01.toFloat(), c02.toFloat(), c03.toFloat(),
c10.toFloat(), c11.toFloat(), c12.toFloat(), c13.toFloat(),
c20.toFloat(), c21.toFloat(), c22.toFloat(), c23.toFloat(),
c30.toFloat(), c31.toFloat(), c32.toFloat(), c33.toFloat(),
)
}
/**
* Creates a copy of this matrix as [Matrix3f],
* truncating last row and column,
* casing all [Double]s to [Float]s
*/
fun toMatrix3f(): Matrix3f {
return Matrix3f(
c00.toFloat(), c01.toFloat(), c02.toFloat(),
c10.toFloat(), c11.toFloat(), c12.toFloat(),
c20.toFloat(), c21.toFloat(), c22.toFloat(),
)
}
/**
* Creates a copy of this matrix as [Matrix2f],
* truncating two last rows and columns,
* casing all [Double]s to [Float]s
*/
fun toMatrix2f(): Matrix2f {
return Matrix2f(
c00.toFloat(), c01.toFloat(),
c10.toFloat(), c11.toFloat(),
)
}
/**
* Creates a copy of this matrix as [MutableMatrix4f],
* casing all [Double]s to [Float]s
*/
fun toMutableMatrix4f(): MutableMatrix4f {
return MutableMatrix4f(
c00.toFloat(), c01.toFloat(), c02.toFloat(), c03.toFloat(),
c10.toFloat(), c11.toFloat(), c12.toFloat(), c13.toFloat(),
c20.toFloat(), c21.toFloat(), c22.toFloat(), c23.toFloat(),
c30.toFloat(), c31.toFloat(), c32.toFloat(), c33.toFloat(),
)
}
/**
* Creates a copy of this matrix as [MutableMatrix3f],
* truncating last row and column,
* casing all [Double]s to [Float]s
*/
fun toMutableMatrix3f(): MutableMatrix3f {
return MutableMatrix3f(
c00.toFloat(), c01.toFloat(), c02.toFloat(),
c10.toFloat(), c11.toFloat(), c12.toFloat(),
c20.toFloat(), c21.toFloat(), c22.toFloat(),
)
}
/**
* Creates a copy of this matrix as [MutableMatrix2f],
* truncating two last rows and columns,
* casing all [Double]s to [Float]s
*/
fun toMutableMatrix2f(): MutableMatrix2f {
return MutableMatrix2f(
c00.toFloat(), c01.toFloat(),
c10.toFloat(), c11.toFloat(),
)
}
}

View File

@ -8,6 +8,8 @@ import ru.dbotthepony.kvector.api.IMatrix
import ru.dbotthepony.kvector.api.ISquareMatrix
import ru.dbotthepony.kvector.api.ITransposable
import ru.dbotthepony.kvector.matrix.*
import ru.dbotthepony.kvector.matrix.ndouble.*
import ru.dbotthepony.kvector.matrix.nfloat.*
import ru.dbotthepony.kvector.vector.nfloat.*
/**
@ -34,6 +36,156 @@ interface IMatrix2f<T : IMatrix2f<T>> : IMatrix<T>, IFloatMatrix<T>, ITransposab
val c1: Vector2f
val r0: Vector2f
val r1: Vector2f
/**
* Creates a copy of this matrix as [Matrix4d],
* setting last two rows and columns to 0,
* casting all [Float]s to [Double]s
*/
fun toMatrix4d(): Matrix4d {
return Matrix4d(
c00.toDouble(), c01.toDouble(), 0.0, 0.0,
c10.toDouble(), c11.toDouble(), 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,
)
}
/**
* Creates a copy of this matrix as [Matrix3d],
* setting last row and column to 0,
* casting all [Float]s to [Double]s
*/
fun toMatrix3d(): Matrix3d {
return Matrix3d(
c00.toDouble(), c01.toDouble(), 0.0,
c10.toDouble(), c11.toDouble(), 0.0,
0.0, 0.0, 0.0,
)
}
/**
* Creates a copy of this matrix as [Matrix2d],
* casting all [Float]s to [Double]s
*/
fun toMatrix2d(): Matrix2d {
return Matrix2d(
c00.toDouble(), c01.toDouble(),
c10.toDouble(), c11.toDouble(),
)
}
/**
* Creates a copy of this matrix as [MutableMatrix4d],
* setting last two columns and rows to 0,
* casting all [Float]s to [Double]s
*/
fun toMutableMatrix4d(): MutableMatrix4d {
return MutableMatrix4d(
c00.toDouble(), c01.toDouble(), 0.0, 0.0,
c10.toDouble(), c11.toDouble(), 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,
)
}
/**
* Creates a copy of this matrix as [MutableMatrix3d],
* setting last column and row to 0,
* casting all [Float]s to [Double]s
*/
fun toMutableMatrix3d(): MutableMatrix3d {
return MutableMatrix3d(
c00.toDouble(), c01.toDouble(), 0.0,
c10.toDouble(), c11.toDouble(), 0.0,
0.0, 0.0, 0.0,
)
}
/**
* Creates a copy of this matrix as [MutableMatrix2d],
* casting all [Float]s to [Double]s
*/
fun toMutableMatrix2d(): MutableMatrix2d {
return MutableMatrix2d(
c00.toDouble(), c01.toDouble(),
c10.toDouble(), c11.toDouble(),
)
}
/**
* Creates a copy of this matrix as [Matrix4f],
* setting last two columns and rows to 0
*/
fun toMatrix4f(): Matrix4f {
return Matrix4f(
c00, c01, 0f, 0f,
c10, c11, 0f, 0f,
0f, 0f, 0f, 0f,
0f, 0f, 0f, 0f,
)
}
/**
* Creates a copy of this matrix as [Matrix3f],
* setting last column and row to 0
*/
fun toMatrix3f(): Matrix3f {
return Matrix3f(
c00, c01, 0f,
c10, c11, 0f,
0f, 0f, 0f,
)
}
/**
* Creates a copy of this matrix as [Matrix2f],
* truncating last row and column
*/
fun toMatrix2f(): Matrix2f {
return Matrix2f(
c00, c01,
c10, c11,
)
}
/**
* Creates a copy of this matrix as [MutableMatrix4f],
* setting last two columns and rows to 0,
*/
fun toMutableMatrix4f(): MutableMatrix4f {
return MutableMatrix4f(
c00, c01, 0f, 0f,
c10, c11, 0f, 0f,
0f, 0f, 0f, 0f,
0f, 0f, 0f, 0f,
)
}
/**
* Creates a copy of this matrix as [MutableMatrix3f],
* setting last column and row to 0,
* casing all [Double]s to [Float]s
*/
fun toMutableMatrix3f(): MutableMatrix3f {
return MutableMatrix3f(
c00, c01, 0f,
c10, c11, 0f,
0f, 0f, 0f,
)
}
/**
* Creates a copy of this matrix as [MutableMatrix2f],
* truncating last row and column,
* casing all [Double]s to [Float]s
*/
fun toMutableMatrix2f(): MutableMatrix2f {
return MutableMatrix2f(
c00, c01,
c10, c11,
)
}
}
/**
@ -84,6 +236,152 @@ interface IMatrix3f<T : IMatrix3f<T>> : IMatrix<T>, IFloatMatrix<T>, ITransposab
val r2: Vector3f
override val translation: Vector2f get() = Vector2f(r02, r12)
/**
* Creates a copy of this matrix as [Matrix4d],
* setting last row and column to 0,
* casting all [Float]s to [Double]s
*/
fun toMatrix4d(): Matrix4d {
return Matrix4d(
c00.toDouble(), c01.toDouble(), c02.toDouble(), 0.0,
c10.toDouble(), c11.toDouble(), c12.toDouble(), 0.0,
c20.toDouble(), c21.toDouble(), c22.toDouble(), 0.0,
0.0, 0.0, 0.0, 0.0,
)
}
/**
* Creates a copy of this matrix as [Matrix3d],
* casting all [Float]s to [Double]s
*/
fun toMatrix3d(): Matrix3d {
return Matrix3d(
c00.toDouble(), c01.toDouble(), c02.toDouble(),
c10.toDouble(), c11.toDouble(), c12.toDouble(),
c20.toDouble(), c21.toDouble(), c22.toDouble(),
)
}
/**
* Creates a copy of this matrix as [Matrix2d],
* truncating last row and column,
* casting all [Float]s to [Double]s
*/
fun toMatrix2d(): Matrix2d {
return Matrix2d(
c00.toDouble(), c01.toDouble(),
c10.toDouble(), c11.toDouble(),
)
}
/**
* Creates a copy of this matrix as [MutableMatrix4d],
* setting last column and row to 0,
* casting all [Float]s to [Double]s
*/
fun toMutableMatrix4d(): MutableMatrix4d {
return MutableMatrix4d(
c00.toDouble(), c01.toDouble(), c02.toDouble(), 0.0,
c10.toDouble(), c11.toDouble(), c12.toDouble(), 0.0,
c20.toDouble(), c21.toDouble(), c22.toDouble(), 0.0,
0.0, 0.0, 0.0, 0.0,
)
}
/**
* Creates a copy of this matrix as [MutableMatrix3d],
* casting all [Float]s to [Double]s
*/
fun toMutableMatrix3d(): MutableMatrix3d {
return MutableMatrix3d(
c00.toDouble(), c01.toDouble(), c02.toDouble(),
c10.toDouble(), c11.toDouble(), c12.toDouble(),
c20.toDouble(), c21.toDouble(), c22.toDouble(),
)
}
/**
* Creates a copy of this matrix as [MutableMatrix2d],
* truncating last row and column,
* casting all [Float]s to [Double]s
*/
fun toMutableMatrix2d(): MutableMatrix2d {
return MutableMatrix2d(
c00.toDouble(), c01.toDouble(),
c10.toDouble(), c11.toDouble(),
)
}
/**
* Creates a copy of this matrix as [Matrix4f],
* setting last column and row to 0
*/
fun toMatrix4f(): Matrix4f {
return Matrix4f(
c00, c01, c02, 0f,
c10, c11, c12, 0f,
c20, c21, c22, 0f,
0f, 0f, 0f, 0f,
)
}
/**
* Creates a copy of this matrix as [Matrix3f]
*/
fun toMatrix3f(): Matrix3f {
return Matrix3f(
c00, c01, c02,
c10, c11, c12,
c20, c21, c22,
)
}
/**
* Creates a copy of this matrix as [Matrix2f],
* truncating last row and column
*/
fun toMatrix2f(): Matrix2f {
return Matrix2f(
c00, c01,
c10, c11,
)
}
/**
* Creates a copy of this matrix as [MutableMatrix4f],
* setting last column and row to 0
*/
fun toMutableMatrix4f(): MutableMatrix4f {
return MutableMatrix4f(
c00, c01, c02, 0f,
c10, c11, c12, 0f,
c20, c21, c22, 0f,
0f, 0f, 0f, 0f,
)
}
/**
* Creates a copy of this matrix as [MutableMatrix3f]
*/
fun toMutableMatrix3f(): MutableMatrix3f {
return MutableMatrix3f(
c00, c01, c02,
c10, c11, c12,
c20, c21, c22,
)
}
/**
* Creates a copy of this matrix as [MutableMatrix2f],
* truncating last row and column
*/
fun toMutableMatrix2f(): MutableMatrix2f {
return MutableMatrix2f(
c00, c01,
c10, c11,
)
}
}
/**
@ -164,4 +462,148 @@ interface IMatrix4f<T : IMatrix4f<T>> : IMatrix<T>, IFloatMatrix<T>, ITransposab
val r3: Vector4f
override val translation: Vector3f get() = Vector3f(r03, r13, r23)
/**
* Creates a copy of this matrix as [Matrix4d],
* casting all [Float]s to [Double]s
*/
fun toMatrix4d(): Matrix4d {
return Matrix4d(
c00.toDouble(), c01.toDouble(), c02.toDouble(), c03.toDouble(),
c10.toDouble(), c11.toDouble(), c12.toDouble(), c13.toDouble(),
c20.toDouble(), c21.toDouble(), c22.toDouble(), c23.toDouble(),
c30.toDouble(), c31.toDouble(), c32.toDouble(), c33.toDouble(),
)
}
/**
* Creates a copy of this matrix as [Matrix3d],
* truncating last row and column,
* casting all [Float]s to [Double]s
*/
fun toMatrix3d(): Matrix3d {
return Matrix3d(
c00.toDouble(), c01.toDouble(), c02.toDouble(),
c10.toDouble(), c11.toDouble(), c12.toDouble(),
c20.toDouble(), c21.toDouble(), c22.toDouble(),
)
}
/**
* Creates a copy of this matrix as [Matrix2d],
* truncating two last rows and columns,
* casting all [Float]s to [Double]s
*/
fun toMatrix2d(): Matrix2d {
return Matrix2d(
c00.toDouble(), c01.toDouble(),
c10.toDouble(), c11.toDouble(),
)
}
/**
* Creates a copy of this matrix as [MutableMatrix4d],
* casting all [Float]s to [Double]s
*/
fun toMutableMatrix4d(): MutableMatrix4d {
return MutableMatrix4d(
c00.toDouble(), c01.toDouble(), c02.toDouble(), c03.toDouble(),
c10.toDouble(), c11.toDouble(), c12.toDouble(), c13.toDouble(),
c20.toDouble(), c21.toDouble(), c22.toDouble(), c23.toDouble(),
c30.toDouble(), c31.toDouble(), c32.toDouble(), c33.toDouble(),
)
}
/**
* Creates a copy of this matrix as [MutableMatrix3d],
* truncating last row and column
*/
fun toMutableMatrix3d(): MutableMatrix3d {
return MutableMatrix3d(
c00.toDouble(), c01.toDouble(), c02.toDouble(),
c10.toDouble(), c11.toDouble(), c12.toDouble(),
c20.toDouble(), c21.toDouble(), c22.toDouble(),
)
}
/**
* Creates a copy of this matrix as [MutableMatrix2d],
* truncating two last rows and columns
*/
fun toMutableMatrix2d(): MutableMatrix2d {
return MutableMatrix2d(
c00.toDouble(), c01.toDouble(),
c10.toDouble(), c11.toDouble(),
)
}
/**
* Creates a copy of this matrix as [Matrix4f]
*/
fun toMatrix4f(): Matrix4f {
return Matrix4f(
c00, c01, c02, c03,
c10, c11, c12, c13,
c20, c21, c22, c23,
c30, c31, c32, c33,
)
}
/**
* Creates a copy of this matrix as [Matrix3f],
* truncating last row and column
*/
fun toMatrix3f(): Matrix3f {
return Matrix3f(
c00, c01, c02,
c10, c11, c12,
c20, c21, c22,
)
}
/**
* Creates a copy of this matrix as [Matrix2f],
* truncating two last rows and columns
*/
fun toMatrix2f(): Matrix2f {
return Matrix2f(
c00, c01,
c10, c11,
)
}
/**
* Creates a copy of this matrix as [MutableMatrix4f]
*/
fun toMutableMatrix4f(): MutableMatrix4f {
return MutableMatrix4f(
c00, c01, c02, c03,
c10, c11, c12, c13,
c20, c21, c22, c23,
c30, c31, c32, c33,
)
}
/**
* Creates a copy of this matrix as [MutableMatrix3f],
* truncating last row and column
*/
fun toMutableMatrix3f(): MutableMatrix3f {
return MutableMatrix3f(
c00, c01, c02,
c10, c11, c12,
c20, c21, c22,
)
}
/**
* Creates a copy of this matrix as [MutableMatrix2f],
* truncating two last rows and columns
*/
fun toMutableMatrix2f(): MutableMatrix2f {
return MutableMatrix2f(
c00, c01,
c10, c11,
)
}
}

View File

@ -316,14 +316,16 @@ private fun load(matrix: IMatrixGetterLong, buffers: Array<Long2Dimensional>): L
}
/**
* Constructs new complement matrix from [input] representing square matrix, by taking out [column] and [row], and load result into [buffer].
* Constructs new complement matrix from [input] representing square matrix,
* by taking out [column] and [row], and load result into [buffer].
*
* @throws IllegalArgumentException if [column] or [row] is out of bounds, or if [input] does not represent a square matrix
* @throws IllegalArgumentException if [column] or [row] is out of bounds,
* or if [input] does not represent a square matrix
*
* @return [buffer]
*/
fun complementMatrix(input: IMatrixGetterDouble, column: Int, row: Int, buffer: Double2Dimensional): Double2Dimensional {
require(input.rows == input.columns) { "Provided matrix is not square matrix (${input.rows} rows, ${input.columns} columns)" }
require(input.rows == input.columns) { "Provided matrix is not square matrix (${input.columns} columns, ${input.rows} rows)" }
require(column < input.columns) { "$column < ${input.columns}" }
require(row < input.rows) { "$row < ${input.rows}" }
@ -349,14 +351,16 @@ fun complementMatrix(input: IMatrixGetterDouble, column: Int, row: Int, buffer:
}
/**
* Constructs new complement matrix from [input] representing square matrix, by taking out [column] and [row], and load result into [buffer].
* Constructs new complement matrix from [input] representing square matrix,
* by taking out [column] and [row], and load result into [buffer].
*
* @throws IllegalArgumentException if [column] or [row] is out of bounds, or if [input] does not represent a square matrix
* @throws IllegalArgumentException if [column] or [row] is out of bounds,
* or if [input] does not represent a square matrix
*
* @return [buffer]
*/
fun complementMatrix(input: IMatrixGetterFloat, column: Int, row: Int, buffer: Float2Dimensional): Float2Dimensional {
require(input.rows == input.columns) { "Provided matrix is not square matrix (${input.rows} rows, ${input.columns} columns)" }
require(input.rows == input.columns) { "Provided matrix is not square matrix (${input.columns} columns, ${input.rows} rows)" }
require(column < input.columns) { "$column < ${input.columns}" }
require(row < input.rows) { "$row < ${input.rows}" }
@ -382,14 +386,16 @@ fun complementMatrix(input: IMatrixGetterFloat, column: Int, row: Int, buffer: F
}
/**
* Constructs new complement matrix from [input] representing square matrix, by taking out [column] and [row], and load result into [buffer].
* Constructs new complement matrix from [input] representing square matrix,
* by taking out [column] and [row], and load result into [buffer].
*
* @throws IllegalArgumentException if [column] or [row] is out of bounds, or if [input] does not represent a square matrix
* @throws IllegalArgumentException if [column] or [row] is out of bounds,
* or if [input] does not represent a square matrix
*
* @return [buffer]
*/
fun complementMatrix(input: IMatrixGetterInt, column: Int, row: Int, buffer: Int2Dimensional): Int2Dimensional {
require(input.rows == input.columns) { "Provided matrix is not square matrix (${input.rows} rows, ${input.columns} columns)" }
require(input.rows == input.columns) { "Provided matrix is not square matrix (${input.columns} columns, ${input.rows} rows)" }
require(column < input.columns) { "$column < ${input.columns}" }
require(row < input.rows) { "$row < ${input.rows}" }
@ -415,14 +421,16 @@ fun complementMatrix(input: IMatrixGetterInt, column: Int, row: Int, buffer: Int
}
/**
* Constructs new complement matrix from [input] representing square matrix, by taking out [column] and [row], and load result into [buffer].
* Constructs new complement matrix from [input] representing square matrix,
* by taking out [column] and [row], and load result into [buffer].
*
* @throws IllegalArgumentException if [column] or [row] is out of bounds, or if [input] does not represent a square matrix
* @throws IllegalArgumentException if [column] or [row] is out of bounds,
* or if [input] does not represent a square matrix
*
* @return [buffer]
*/
fun complementMatrix(input: IMatrixGetterLong, column: Int, row: Int, buffer: Long2Dimensional): Long2Dimensional {
require(input.rows == input.columns) { "Provided matrix is not square matrix (${input.rows} rows, ${input.columns} columns)" }
require(input.rows == input.columns) { "Provided matrix is not square matrix (${input.columns} columns, ${input.rows} rows)" }
require(column < input.columns) { "$column < ${input.columns}" }
require(row < input.rows) { "$row < ${input.rows}" }
@ -447,7 +455,184 @@ fun complementMatrix(input: IMatrixGetterLong, column: Int, row: Int, buffer: Lo
return buffer
}
/**
* Computes cofactor matrix of specified square matrix [input],
* returning result as [Double2Dimensional]
*
* This operation requires n * n determinant calculations of matrix,
* so do cache result of this function in performance critical context.
*
* @throws IllegalArgumentException if provided [input] is not a square matrix
* @return 2d array containing result matrix
*/
fun cofactorMatrix(input: IMatrixGetterDouble): Double2Dimensional {
require(input.rows == input.columns) { "Provided matrix is not square matrix (${input.columns} columns, ${input.rows} rows)" }
if (input.rows == 1) {
return Double2Dimensional(1, 1).also { it[0, 0] = input[0, 0] }
} else if (input.rows == 2) {
return Double2Dimensional(2, 2).also {
it[0, 0] = input[1, 1]
it[1, 0] = -input[1, 0]
it[0, 1] = -input[0, 1]
it[1, 1] = input[0, 0]
}
}
val result = Double2Dimensional(input.columns, input.rows)
val buffers = Array(input.rows) { Double2Dimensional(it + 1, it + 1) }
for (column in 0 until input.columns) {
for (row in 0 until input.rows) {
val minor = matrixDeterminant(complementMatrix(input, column, row, buffers[input.columns - 2]), input.columns - 1, buffers)
val cofactor = (-1.0).pow(row + column) * minor
result[column, row] = cofactor
}
}
return result
}
/**
* Computes cofactor matrix of specified square matrix [input],
* returning result as [Float2Dimensional]
*
* This operation requires n * n determinant calculations of matrix,
* so do cache result of this function in performance critical context.
*
* @throws IllegalArgumentException if provided [input] is not a square matrix
* @return 2d array containing result matrix
*/
fun cofactorMatrix(input: IMatrixGetterFloat): Float2Dimensional {
require(input.rows == input.columns) { "Provided matrix is not square matrix (${input.columns} columns, ${input.rows} rows)" }
if (input.rows == 1) {
return Float2Dimensional(1, 1).also { it[0, 0] = input[0, 0] }
} else if (input.rows == 2) {
return Float2Dimensional(2, 2).also {
it[0, 0] = input[1, 1]
it[1, 0] = -input[1, 0]
it[0, 1] = -input[0, 1]
it[1, 1] = input[0, 0]
}
}
val result = Float2Dimensional(input.columns, input.rows)
val buffers = Array(input.rows) { Float2Dimensional(it + 1, it + 1) }
for (column in 0 until input.columns) {
for (row in 0 until input.rows) {
val minor = matrixDeterminant(complementMatrix(input, column, row, buffers[input.columns - 2]), input.columns - 1, buffers)
val cofactor = (-1f).pow(row + column) * minor
result[column, row] = cofactor
}
}
return result
}
/**
* Computes adjugate matrix of specified square matrix [input],
* returning result as [Double2Dimensional],
*
* [https://en.wikipedia.org/wiki/Adjugate_matrix]
*
* This operation requires n * n determinant calculations of matrix,
* so do cache result of this function in performance critical context.
*
* @throws IllegalArgumentException if provided [input] is not a square matrix
* @return 2d array containing result matrix
*/
fun adjugateMatrix(input: IMatrixGetterDouble): Double2Dimensional {
require(input.rows == input.columns) { "Provided matrix is not square matrix (${input.columns} columns, ${input.rows} rows)" }
return transposeMatrix(cofactorMatrix(input))
}
/**
* Computes adjugate matrix of specified square matrix [input],
* returning result as [Float2Dimensional],
*
* [https://en.wikipedia.org/wiki/Adjugate_matrix]
*
* This operation requires n * n determinant calculations of matrix,
* so do cache result of this function in performance critical context.
*
* @throws IllegalArgumentException if provided [input] is not a square matrix
* @return 2d array containing result matrix
*/
fun adjugateMatrix(input: IMatrixGetterFloat): Float2Dimensional {
require(input.rows == input.columns) { "Provided matrix is not square matrix (${input.columns} columns, ${input.rows} rows)" }
return transposeMatrix(cofactorMatrix(input))
}
/**
* Computes inverse matrix of specified square matrix [input],
* returning result as [Double2Dimensional],
*
* This operation requires 1 + n * n determinant calculations of original matrix,
* so do cache result of this function in performance critical context.
*
* If determinant is zero, null is returned.
*
* @throws IllegalArgumentException if provided [input] is not a square matrix
* @return 2d array containing result matrix, or null if determinant is zero.
*/
fun inverseMatrix(input: IMatrixGetterDouble): Double2Dimensional? {
require(input.rows == input.columns) { "Provided matrix is not square matrix (${input.columns} columns, ${input.rows} rows)" }
var determinant = matrixDeterminant(input)
if (determinant == 0.0)
return null
determinant = 1.0 / determinant
val adjugate = adjugateMatrix(input)
for (column in 0 until input.columns) {
for (row in 0 until input.rows) {
adjugate[column, row] *= determinant
}
}
return adjugate
}
/**
* Computes inverse matrix of specified square matrix [input],
* returning result as [Float2Dimensional],
*
* This operation requires 1 + n * n determinant calculations of original matrix,
* so do cache result of this function in performance critical context.
*
* If determinant is zero, null is returned.
*
* @throws IllegalArgumentException if provided [input] is not a square matrix
* @return 2d array containing result matrix, or null if determinant is zero.
*/
fun inverseMatrix(input: IMatrixGetterFloat): Float2Dimensional? {
require(input.rows == input.columns) { "Provided matrix is not square matrix (${input.columns} columns, ${input.rows} rows)" }
var determinant = matrixDeterminant(input)
if (determinant == 0f)
return null
determinant = 1f / determinant
val adjugate = adjugateMatrix(input)
for (column in 0 until input.columns) {
for (row in 0 until input.rows) {
adjugate[column, row] *= determinant
}
}
return adjugate
}
private fun matrixDeterminant(input: Double2Dimensional, size: Int, buffers: Array<Double2Dimensional>): Double {
if (input.rows == 1)
return input[0, 0]
val concrete = matrixConcreteDeterminant(input)
if (concrete != null) {
@ -468,19 +653,19 @@ private fun matrixDeterminant(input: Double2Dimensional, size: Int, buffers: Arr
/**
* Recursive determinant finder of specified structure representing square matrix.
*
* @throws IllegalArgumentException if [matrix] structure is not square matrix
* @throws IllegalArgumentException if [input] structure is not square matrix
*/
fun matrixDeterminant(matrix: IMatrixGetterDouble): Double {
require(matrix.rows == matrix.columns) { "Provided matrix is not square matrix (${matrix.rows} rows, ${matrix.columns} columns)" }
fun matrixDeterminant(input: IMatrixGetterDouble): Double {
require(input.rows == input.columns) { "Provided matrix is not square matrix (${input.columns} columns, ${input.rows} rows)" }
val concrete = matrixConcreteDeterminant(matrix)
val concrete = matrixConcreteDeterminant(input)
if (concrete != null) {
return concrete
}
val buffers = Array(matrix.rows) { Double2Dimensional(it + 1, it + 1) }
return matrixDeterminant(load(matrix, buffers), matrix.columns, buffers)
val buffers = Array(input.rows) { Double2Dimensional(it + 1, it + 1) }
return matrixDeterminant(load(input, buffers), input.columns, buffers)
}
private fun matrixDeterminant(input: Float2Dimensional, size: Int, buffers: Array<Float2Dimensional>): Float {
@ -504,18 +689,18 @@ private fun matrixDeterminant(input: Float2Dimensional, size: Int, buffers: Arra
/**
* Recursive determinant finder of specified structure representing square matrix.
*
* @throws IllegalArgumentException if [matrix] structure is not square matrix
* @throws IllegalArgumentException if [input] structure is not square matrix
*/
fun matrixDeterminant(matrix: IMatrixGetterFloat): Float {
require(matrix.rows == matrix.columns) { "Provided matrix is not square matrix (${matrix.rows} rows, ${matrix.columns} columns)" }
fun matrixDeterminant(input: IMatrixGetterFloat): Float {
require(input.rows == input.columns) { "Provided matrix is not square matrix (${input.columns} columns, ${input.rows} rows)" }
val concrete = matrixConcreteDeterminant(matrix)
val concrete = matrixConcreteDeterminant(input)
if (concrete != null) {
return concrete
}
val buffers = Array(matrix.rows) { Float2Dimensional(it + 1, it + 1) }
return matrixDeterminant(load(matrix, buffers), matrix.columns, buffers).toFloat()
val buffers = Array(input.rows) { Float2Dimensional(it + 1, it + 1) }
return matrixDeterminant(load(input, buffers), input.columns, buffers).toFloat()
}

View File

@ -4,10 +4,8 @@
package ru.dbotthepony.kvector.matrix.ndouble
import ru.dbotthepony.kvector.api.*
import ru.dbotthepony.kvector.matrix.*
import ru.dbotthepony.kvector.matrix.generated.MultiplicationsDouble
import ru.dbotthepony.kvector.matrix.matrixDeterminant
import ru.dbotthepony.kvector.matrix.multiplyMatrix
import ru.dbotthepony.kvector.matrix.transposeMatrix
import ru.dbotthepony.kvector.narray.Double2Dimensional
private fun checkRows(value: Int): Int {
@ -153,6 +151,31 @@ abstract class AbstractMatrixVd<T : AbstractMatrixVd<T>> protected constructor(
return false
}
override val inverse: T?
get() {
if (!isSquareMatrix)
return null
val result = inverseMatrix(memory) ?: return null
return factorize(result)
}
override val cofactor: T?
get() {
if (!isSquareMatrix)
return null
return factorize(cofactorMatrix(memory))
}
override val adjugate: T?
get() {
if (!isSquareMatrix)
return null
return factorize(adjugateMatrix(memory))
}
}
/**

View File

@ -4,10 +4,8 @@
package ru.dbotthepony.kvector.matrix.nfloat
import ru.dbotthepony.kvector.api.*
import ru.dbotthepony.kvector.matrix.*
import ru.dbotthepony.kvector.matrix.generated.MultiplicationsFloat
import ru.dbotthepony.kvector.matrix.matrixDeterminant
import ru.dbotthepony.kvector.matrix.multiplyMatrix
import ru.dbotthepony.kvector.matrix.transposeMatrix
import ru.dbotthepony.kvector.narray.Float2Dimensional
private fun checkRows(value: Int): Int {
@ -153,6 +151,31 @@ abstract class AbstractMatrixVf<T : AbstractMatrixVf<T>> protected constructor(
return false
}
override val inverse: T?
get() {
if (!isSquareMatrix)
return null
val result = inverseMatrix(memory) ?: return null
return factorize(result)
}
override val cofactor: T?
get() {
if (!isSquareMatrix)
return null
return factorize(cofactorMatrix(memory))
}
override val adjugate: T?
get() {
if (!isSquareMatrix)
return null
return factorize(adjugateMatrix(memory))
}
}
/**

View File

@ -1,50 +0,0 @@
package ru.dbotthepony.kstarbound.math
import kotlin.math.cos
import kotlin.math.sin
interface IAngle {
val pitch: Double
val yaw: Double
val roll: Double
fun matrixX(): Matrix4f {
val s = sin(pitch).toFloat()
val c = cos(pitch).toFloat()
return Matrix4f(
m11 = c, m12 = -s,
m21 = s, m22 = c,
)
}
fun matrixY(): Matrix4f {
val s = sin(yaw).toFloat()
val c = cos(yaw).toFloat()
return Matrix4f(
m00 = c, m02 = s,
m20 = -s, m22 = c
)
}
fun matrixZ(): Matrix4f {
val s = sin(roll).toFloat()
val c = cos(roll).toFloat()
return Matrix4f(
m00 = c, m01 = -s,
m10 = s, m11 = c
)
}
fun matrixXYZ(): Matrix4f {
return matrixX() * matrixY() * matrixZ()
}
}
data class Angle(
override val pitch: Double = 0.0,
override val yaw: Double = 0.0,
override val roll: Double = 0.0,
) : IAngle

View File

@ -7,9 +7,9 @@ import ru.dbotthepony.kstarbound.world.CHUNK_SIZE
import ru.dbotthepony.kstarbound.world.CHUNK_SIZE_FF
import ru.dbotthepony.kstarbound.world.CHUNK_SIZEd
import ru.dbotthepony.kstarbound.world.ChunkPos
import ru.dbotthepony.kvector.matrix.matrixDeterminant
import ru.dbotthepony.kvector.matrix.adjugateMatrix
import ru.dbotthepony.kvector.matrix.multiplyMatrix
import ru.dbotthepony.kvector.matrix.generated.*
import ru.dbotthepony.kvector.matrix.inverseMatrix
import ru.dbotthepony.kvector.narray.Double2Dimensional
object MathTests {
@ -155,30 +155,4 @@ object MathTests {
check(product[1, 1] == 96.0)
check(product[2, 1] == 26.0)
}
@Test
fun testAlloc() {
System.gc()
var t = System.currentTimeMillis()
var escape2 = 0.0
for (i in 0 .. 8000000) {
val matrix = Matrix4d()
escape2 += matrix[2, 3]
}
println(System.currentTimeMillis() - t)
System.gc()
t = System.currentTimeMillis()
var escape = 0.0
for (i in 0 .. 8000000) {
val matrix = Double2Dimensional(4, 4)
escape += matrix[2, 3]
}
println(System.currentTimeMillis() - t)
println(escape)
}
}