xolatilization/xatrix.h

496 lines
16 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...
/// Description
///
/// Xatrix, my tiny braindead unoptimized matrix library. Unlike vectors that use x, y, z and w structure fields, matrices are double array of
/// 32-bit floating point numbers, and they're accessed with integers, which should've been the same case with vectors, but mathematicians are
/// dumb sometimes (blame it on the one being older than the other one?). Again, nothing much to talk about here, learn linear algebra, include
/// this header file in your project, use it however you want, compilers might optimize this better than my vector library. This library isn't
/// intended for neural networks, as it's not generic, it can be used in simple CPU-based ray tracers and physics simulations.
/// Nice 2D, 3D and 4D matrix structures.
typedef real matrix_2 [2] [2]; /// Tiny 2x2 matrix.
typedef real matrix_3 [3] [3]; /// Tiny 3x3 matrix.
typedef real matrix_4 [4] [4]; /// Tiny 4x4 matrix.
/// Assign values to 2D, 3D or 4D matrix and return address of that matrix.
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);
}
/// Nullify values of 2D, 3D or 4D matrix and return address of that matrix.
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);
}
/// Identify values of 2D, 3D or 4D matrix and return address of that matrix.
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);
}
/// Return determinant of 2D, 3D or 4D matrix.
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);
}
/// Copy 2D, 3D or 4D source matrix into destination matrix.
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);
}
/// Scale 2D, 3D or 4D matrix by scalar value and return address of that matrix.
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);
}
/// Scale 2D, 3D or 4D source matrix by scalar value into destination matrix and return its address.
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);
}
/// Add 2D, 3D or 4D source matrix onto destination matrix and return address of destination matrix.
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);
}
/// Add two 2D, 3D or 4D matrices into destination matrix and return address of destination matrix.
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);
}
/// Subtract 2D, 3D or 4D source matrix from destination matrix and return address of destination matrix.
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);
}
/// Subtract two 2D, 3D or 4D matrices, save values into destination matrix and return address of destination matrix.
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);
}
/// Multiply two 2D, 3D or 4D matrices, save values into destination matrix and return address of destination matrix.
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);
}
/// Return trace of 2D, 3D or 4D matrix.
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]);
}
/// Compare if two 2D, 3D or 4D matrices are identical and return boolean value of it.
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);
}