511 lines
15 KiB
C
511 lines
15 KiB
C
/// _ _
|
|
/// __ ____ _| |_ _ __(_)_ __
|
|
/// \ \/ / _` | __| '__| \ \/ /
|
|
/// > < (_| | |_| | | |> <
|
|
/// /_/\_\__,_|\__|_| |_/_/\_\
|
|
///
|
|
/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
|
|
///
|
|
/// xolatile@chud.cyou - xatrix - Very dumb and slow matrix library, mathematical matrix, because I don't like other people ideas...
|
|
///
|
|
/// This program is free software, free as in freedom and as in free beer, you can redistribute it and/or modify it under the terms of the GNU
|
|
/// General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version if you wish...
|
|
///
|
|
/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
|
|
/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
|
|
/// for more details, if you dare, it is a lot of text that nobody wants to read...
|
|
|
|
typedef real matrix_2 [2] [2];
|
|
typedef real matrix_3 [3] [3];
|
|
typedef real matrix_4 [4] [4];
|
|
|
|
static matrix_2 * matrix_2_assign (matrix_2 * destination,
|
|
real m00, real m01,
|
|
real m10, real m11) {
|
|
destination [0] [0] = m00;
|
|
destination [0] [1] = m01;
|
|
destination [1] [0] = m10;
|
|
destination [1] [1] = m11;
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_3 * matrix_3_assign (matrix_3 * destination,
|
|
real m00, real m01, real m02,
|
|
real m10, real m11, real m12,
|
|
real m20, real m21, real m22) {
|
|
destination [0] [0] = m00;
|
|
destination [0] [1] = m01;
|
|
destination [0] [2] = m02;
|
|
destination [1] [0] = m10;
|
|
destination [1] [1] = m11;
|
|
destination [1] [2] = m12;
|
|
destination [2] [0] = m20;
|
|
destination [2] [1] = m21;
|
|
destination [2] [2] = m22;
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_4 * matrix_4_assign (matrix_4 * destination,
|
|
real m00, real m01, real m02, real m03,
|
|
real m10, real m11, real m12, real m13,
|
|
real m20, real m21, real m22, real m23,
|
|
real m30, real m31, real m32, real m33) {
|
|
destination [0] [0] = m00;
|
|
destination [0] [1] = m01;
|
|
destination [0] [2] = m02;
|
|
destination [0] [3] = m03;
|
|
destination [1] [0] = m10;
|
|
destination [1] [1] = m11;
|
|
destination [1] [2] = m12;
|
|
destination [1] [3] = m13;
|
|
destination [2] [0] = m20;
|
|
destination [2] [1] = m21;
|
|
destination [2] [2] = m22;
|
|
destination [2] [3] = m23;
|
|
destination [3] [0] = m30;
|
|
destination [3] [1] = m31;
|
|
destination [3] [2] = m32;
|
|
destination [3] [3] = m33;
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_2 * matrix_2_nullify (matrix_2 * destination) {
|
|
for (natural row = 0; row < 2; ++row) {
|
|
for (natural column = 0; column < 2; ++column) {
|
|
destination [row] [column] = 0.0f;
|
|
}
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_3 * matrix_3_nullify (matrix_3 * destination) {
|
|
for (natural row = 0; row < 3; ++row) {
|
|
for (natural column = 0; column < 3; ++column) {
|
|
destination [row] [column] = 0.0f;
|
|
}
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_4 * matrix_4_nullify (matrix_4 * destination) {
|
|
for (natural row = 0; row < 4; ++row) {
|
|
for (natural column = 0; column < 4; ++column) {
|
|
destination [row] [column] = 0.0f;
|
|
}
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_2 * matrix_2_identity (matrix_2 * destination) {
|
|
destination = matrix_2_nullify (destination);
|
|
|
|
for (natural index = 0; index < 2; ++index) {
|
|
destination [index] [index] = 1.0f;
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_3 * matrix_3_identity (matrix_3 * destination) {
|
|
destination = matrix_3_nullify (destination);
|
|
|
|
for (natural index = 0; index < 3; ++index) {
|
|
destination [index] [index] = 1.0f;
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_4 * matrix_4_identity (matrix_4 * destination) {
|
|
destination = matrix_4_nullify (destination);
|
|
|
|
for (natural index = 0; index < 4; ++index) {
|
|
destination [index] [index] = 1.0f;
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static real matrix_2_determinant (matrix_2 * matrix) {
|
|
real a = matrix [0] [0] * matrix [1] [1];
|
|
real b = matrix [0] [1] * matrix [1] [0];
|
|
|
|
return (a - b);
|
|
}
|
|
|
|
static real matrix_3_determinant (matrix_3 * matrix) {
|
|
matrix_2 matrix_a = { { matrix [1] [1], matrix [1] [2] },
|
|
{ matrix [2] [1], matrix [2] [2] } };
|
|
matrix_2 matrix_b = { { matrix [1] [0], matrix [1] [2] },
|
|
{ matrix [2] [0], matrix [2] [2] } };
|
|
matrix_2 matrix_c = { { matrix [1] [0], matrix [1] [1] },
|
|
{ matrix [2] [0], matrix [2] [1] } };
|
|
|
|
real a = matrix [0] [0] * matrix_2_determinant (& matrix_a);
|
|
real b = matrix [0] [1] * matrix_2_determinant (& matrix_b);
|
|
real c = matrix [0] [2] * matrix_2_determinant (& matrix_c);
|
|
|
|
return (a - b + c);
|
|
}
|
|
|
|
static real matrix_4_determinant (matrix_4 * matrix) {
|
|
matrix_3 matrix_a = { { matrix [1] [1], matrix [1] [2], matrix [1] [3] },
|
|
{ matrix [2] [1], matrix [2] [2], matrix [2] [3] },
|
|
{ matrix [3] [1], matrix [3] [2], matrix [3] [3] } };
|
|
matrix_3 matrix_b = { { matrix [1] [0], matrix [1] [2], matrix [1] [3] },
|
|
{ matrix [2] [0], matrix [2] [2], matrix [2] [3] },
|
|
{ matrix [3] [0], matrix [3] [2], matrix [3] [3] } };
|
|
matrix_3 matrix_c = { { matrix [1] [0], matrix [1] [1], matrix [1] [3] },
|
|
{ matrix [2] [0], matrix [2] [1], matrix [2] [3] },
|
|
{ matrix [3] [0], matrix [3] [1], matrix [3] [3] } };
|
|
matrix_3 matrix_d = { { matrix [1] [0], matrix [1] [1], matrix [1] [2] },
|
|
{ matrix [2] [0], matrix [2] [1], matrix [2] [2] },
|
|
{ matrix [3] [0], matrix [3] [1], matrix [3] [2] } };
|
|
|
|
real a = matrix [0] [0] * matrix_3_determinant (& matrix_a);
|
|
real b = matrix [0] [1] * matrix_3_determinant (& matrix_b);
|
|
real c = matrix [0] [2] * matrix_3_determinant (& matrix_c);
|
|
real d = matrix [0] [3] * matrix_3_determinant (& matrix_d);
|
|
|
|
return (a - b + c - d);
|
|
}
|
|
|
|
static matrix_2 * matrix_2_copy (matrix_2 * destination, matrix_2 * source) {
|
|
for (natural row = 0; row < 2; ++row) {
|
|
for (natural column = 0; column < 2; ++column) {
|
|
destination [row] [column] = source [row] [column];
|
|
}
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_3 * matrix_3_copy (matrix_3 * destination, matrix_3 * source) {
|
|
for (natural row = 0; row < 3; ++row) {
|
|
for (natural column = 0; column < 3; ++column) {
|
|
destination [row] [column] = source [row] [column];
|
|
}
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_4 * matrix_4_copy (matrix_4 * destination, matrix_4 * source) {
|
|
for (natural row = 0; row < 4; ++row) {
|
|
for (natural column = 0; column < 4; ++column) {
|
|
destination [row] [column] = source [row] [column];
|
|
}
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_2 * matrix_2_scale (matrix_2 * destination, real scale) {
|
|
for (natural row = 0; row < 2; ++row) {
|
|
for (natural column = 0; column < 2; ++column) {
|
|
destination [row] [column] *= scale;
|
|
}
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_3 * matrix_3_scale (matrix_3 * destination, real scale) {
|
|
for (natural row = 0; row < 3; ++row) {
|
|
for (natural column = 0; column < 3; ++column) {
|
|
destination [row] [column] *= scale;
|
|
}
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_4 * matrix_4_scale (matrix_4 * destination, real scale) {
|
|
for (natural row = 0; row < 4; ++row) {
|
|
for (natural column = 0; column < 4; ++column) {
|
|
destination [row] [column] *= scale;
|
|
}
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_2 * matrix_2_scale_to (matrix_2 * destination, matrix_2 * source, real scale) {
|
|
for (natural row = 0; row < 2; ++row) {
|
|
for (natural column = 0; column < 2; ++column) {
|
|
destination [row] [column] = source [row] [column] * scale;
|
|
}
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_3 * matrix_3_scale_to (matrix_3 * destination, matrix_3 * source, real scale) {
|
|
for (natural row = 0; row < 3; ++row) {
|
|
for (natural column = 0; column < 3; ++column) {
|
|
destination [row] [column] = source [row] [column] * scale;
|
|
}
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_4 * matrix_4_scale_to (matrix_4 * destination, matrix_4 * source, real scale) {
|
|
for (natural row = 0; row < 4; ++row) {
|
|
for (natural column = 0; column < 4; ++column) {
|
|
destination [row] [column] = source [row] [column] * scale;
|
|
}
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_2 * matrix_2_add (matrix_2 * destination, matrix_2 * source) {
|
|
for (natural row = 0; row < 2; ++row) {
|
|
for (natural column = 0; column < 2; ++column) {
|
|
destination [row] [column] += source [row] [column];
|
|
}
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_3 * matrix_3_add (matrix_3 * destination, matrix_3 * source) {
|
|
for (natural row = 0; row < 3; ++row) {
|
|
for (natural column = 0; column < 3; ++column) {
|
|
destination [row] [column] += source [row] [column];
|
|
}
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_4 * matrix_4_add (matrix_4 * destination, matrix_4 * source) {
|
|
for (natural row = 0; row < 4; ++row) {
|
|
for (natural column = 0; column < 4; ++column) {
|
|
destination [row] [column] += source [row] [column];
|
|
}
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_2 * matrix_2_add_to (matrix_2 * destination, matrix_2 * matrix_a, matrix_2 * matrix_b) {
|
|
for (natural row = 0; row < 2; ++row) {
|
|
for (natural column = 0; column < 2; ++column) {
|
|
destination [row] [column] = matrix_a [row] [column] + matrix_b [row] [column];
|
|
}
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_3 * matrix_3_add_to (matrix_3 * destination, matrix_3 * matrix_a, matrix_3 * matrix_b) {
|
|
for (natural row = 0; row < 3; ++row) {
|
|
for (natural column = 0; column < 3; ++column) {
|
|
destination [row] [column] = matrix_a [row] [column] + matrix_b [row] [column];
|
|
}
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_4 * matrix_4_add_to (matrix_4 * destination, matrix_4 * matrix_a, matrix_4 * matrix_b) {
|
|
for (natural row = 0; row < 4; ++row) {
|
|
for (natural column = 0; column < 4; ++column) {
|
|
destination [row] [column] = matrix_a [row] [column] + matrix_b [row] [column];
|
|
}
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_2 * matrix_2_subtract (matrix_2 * destination, matrix_2 * source) {
|
|
for (natural row = 0; row < 2; ++row) {
|
|
for (natural column = 0; column < 2; ++column) {
|
|
destination [row] [column] -= source [row] [column];
|
|
}
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_3 * matrix_3_subtract (matrix_3 * destination, matrix_3 * source) {
|
|
for (natural row = 0; row < 3; ++row) {
|
|
for (natural column = 0; column < 3; ++column) {
|
|
destination [row] [column] -= source [row] [column];
|
|
}
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_4 * matrix_4_subtract (matrix_4 * destination, matrix_4 * source) {
|
|
for (natural row = 0; row < 4; ++row) {
|
|
for (natural column = 0; column < 4; ++column) {
|
|
destination [row] [column] -= source [row] [column];
|
|
}
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_2 * matrix_2_subtract_to (matrix_2 * destination, matrix_2 * matrix_a, matrix_2 * matrix_b) {
|
|
for (natural row = 0; row < 2; ++row) {
|
|
for (natural column = 0; column < 2; ++column) {
|
|
destination [row] [column] = matrix_a [row] [column] - matrix_b [row] [column];
|
|
}
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_3 * matrix_3_subtract_to (matrix_3 * destination, matrix_3 * matrix_a, matrix_3 * matrix_b) {
|
|
for (natural row = 0; row < 3; ++row) {
|
|
for (natural column = 0; column < 3; ++column) {
|
|
destination [row] [column] = matrix_a [row] [column] - matrix_b [row] [column];
|
|
}
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_4 * matrix_4_subtract_to (matrix_4 * destination, matrix_4 * matrix_a, matrix_4 * matrix_b) {
|
|
for (natural row = 0; row < 4; ++row) {
|
|
for (natural column = 0; column < 4; ++column) {
|
|
destination [row] [column] = matrix_a [row] [column] - matrix_b [row] [column];
|
|
}
|
|
}
|
|
|
|
return (destination);
|
|
}
|
|
|
|
static matrix_2 * matrix_2_multiply (matrix_2 * result, matrix_2 * matrix_a, matrix_2 * matrix_b) {
|
|
for (natural row = 0; row < 2; ++row) {
|
|
for (natural column = 0; column < 2; ++column) {
|
|
result [row] [column] = 0.0f;
|
|
|
|
for (natural index = 0; index < 2; ++index) {
|
|
result [row] [column] += matrix_a [row] [index] * matrix_b [index] [column];
|
|
}
|
|
}
|
|
}
|
|
|
|
return (result);
|
|
}
|
|
|
|
static matrix_3 * matrix_3_multiply (matrix_3 * result, matrix_3 * matrix_a, matrix_3 * matrix_b) {
|
|
for (natural row = 0; row < 3; ++row) {
|
|
for (natural column = 0; column < 3; ++column) {
|
|
result [row] [column] = 0.0f;
|
|
|
|
for (natural index = 0; index < 3; ++index) {
|
|
result [row] [column] += matrix_a [row] [index] * matrix_b [index] [column];
|
|
}
|
|
}
|
|
}
|
|
|
|
return (result);
|
|
}
|
|
|
|
static matrix_4 * matrix_4_multiply (matrix_4 * result, matrix_4 * matrix_a, matrix_4 * matrix_b) {
|
|
for (natural row = 0; row < 4; ++row) {
|
|
for (natural column = 0; column < 4; ++column) {
|
|
result [row] [column] = 0.0f;
|
|
|
|
for (natural index = 0; index < 4; ++index) {
|
|
result [row] [column] += matrix_a [row] [index] * matrix_b [index] [column];
|
|
}
|
|
}
|
|
}
|
|
|
|
return (result);
|
|
}
|
|
|
|
static real matrix_2_trace (matrix_2 * matrix) {
|
|
return (matrix [0] [0] + matrix [1] [1]);
|
|
}
|
|
|
|
static real matrix_3_trace (matrix_3 * matrix) {
|
|
return (matrix [0] [0] + matrix [1] [1] + matrix [2] [2]);
|
|
}
|
|
|
|
static real matrix_4_trace (matrix_4 * matrix) {
|
|
return (matrix [0] [0] + matrix [1] [1] + matrix [2] [2] + matrix [3] [3]);
|
|
}
|
|
|
|
static boolean matrix_2_compare (matrix_2 * matrix_a, matrix_2 * matrix_b) {
|
|
for (natural row = 0; row < 2; ++row) {
|
|
for (natural column = 0; column < 2; ++column) {
|
|
if (matrix_a [row] [column] != matrix_b [row] [column]) {
|
|
return (false);
|
|
}
|
|
}
|
|
}
|
|
|
|
return (true);
|
|
}
|
|
|
|
static boolean matrix_3_compare (matrix_3 * matrix_a, matrix_3 * matrix_b) {
|
|
for (natural row = 0; row < 3; ++row) {
|
|
for (natural column = 0; column < 3; ++column) {
|
|
if (matrix_a [row] [column] != matrix_b [row] [column]) {
|
|
return (false);
|
|
}
|
|
}
|
|
}
|
|
|
|
return (true);
|
|
}
|
|
|
|
static boolean matrix_4_compare (matrix_4 * matrix_a, matrix_4 * matrix_b) {
|
|
for (natural row = 0; row < 4; ++row) {
|
|
for (natural column = 0; column < 4; ++column) {
|
|
if (matrix_a [row] [column] != matrix_b [row] [column]) {
|
|
return (false);
|
|
}
|
|
}
|
|
}
|
|
|
|
return (true);
|
|
}
|
|
|
|
static procedure matrix_2_transpose (matrix_2 * matrix_a, matrix_2 * matrix_b) {
|
|
for (natural row = 0; row < 2; ++row) {
|
|
for (natural column = row + 1; column < 2; ++column) {
|
|
real temporary = matrix_a [row] [column];
|
|
|
|
matrix_a [row] [column] = matrix_b [column] [row];
|
|
matrix_b [column] [row] = temporary;
|
|
}
|
|
}
|
|
}
|
|
|
|
static procedure matrix_3_transpose (matrix_3 * matrix_a, matrix_3 * matrix_b) {
|
|
for (natural row = 0; row < 3; ++row) {
|
|
for (natural column = 0; column < 3; ++column) {
|
|
real temporary = matrix_a [row] [column];
|
|
|
|
matrix_a [row] [column] = matrix_b [column] [row];
|
|
matrix_b [column] [row] = temporary;
|
|
}
|
|
}
|
|
}
|
|
|
|
static procedure matrix_4_transpose (matrix_4 * matrix_a, matrix_4 * matrix_b) {
|
|
for (natural row = 0; row < 4; ++row) {
|
|
for (natural column = 0; column < 4; ++column) {
|
|
real temporary = matrix_a [row] [column];
|
|
|
|
matrix_a [row] [column] = matrix_b [column] [row];
|
|
matrix_b [column] [row] = temporary;
|
|
}
|
|
}
|
|
}
|