Skip to content

Commit 9fc9837

Browse files
committed
Implemented basic linear solvers.
1 parent 7da0a76 commit 9fc9837

File tree

4 files changed

+99
-0
lines changed

4 files changed

+99
-0
lines changed

GameMakerScripts.yyp

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ Algorithms from computational mathematics (such as regression and interpolation)
2525

2626
Common linear algebra algorithms for dealing with matrices and vectors. In all functions, _vectors_ are considered to be 1D arrays while _matrices_ are 2D arrays.
2727

28+
* [`_linear_solve`](https://github.com/adam-rumpf/game-maker-scripts/blob/master/scripts/_linear_solve/_linear_solve.gml): Solves a linear system given a coefficient matrix and righthand vector.
2829
* [`_matrix_multiply`](https://github.com/adam-rumpf/game-maker-scripts/blob/master/scripts/_matrix_multiply/_matrix_multiply.gml): Performs matrix-matrix, matrix-vector, and vector-vector multiplication.
2930
* [`_matrix_transpose`](https://github.com/adam-rumpf/game-maker-scripts/blob/master/scripts/_matrix_transpose/_matrix_transpose.gml): Transposes a 2D matrix.
31+
* [`_triangular_solve`](https://github.com/adam-rumpf/game-maker-scripts/blob/master/scripts/_triangular_solve/_triangular_solve.gml): Solves an upper or lower triangular system.
3032
* [`_unit_vector`](https://github.com/adam-rumpf/game-maker-scripts/blob/master/scripts/_unit_vector/_unit_vector.gml): Defines a unit direction vector between two coordinates.
3133
* [`_vector_angle`](https://github.com/adam-rumpf/game-maker-scripts/blob/master/scripts/_vector_angle/_vector_angle.gml): Calculates the acute angle between two vectors.
3234
* [`_vector_distance`](https://github.com/adam-rumpf/game-maker-scripts/blob/master/scripts/_vector_distance/_vector_distance.gml): Calculates the Lp-distance between two vectors.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/// @func _linear_solve(a, b)
2+
/// @desc Solves a linear system of the form Ax = b (via Gaussian elimination) for a given coefficient matrix and constant vector.
3+
/// @requires _triangular_solve
4+
/// @param {real[]} a Square coefficient matrix (as a 2D array).
5+
/// @param {real[]} b Constraint vector (as a 1D array whose length matches a).
6+
/// @return {real[]} Solution vector x of the linear system Ax = b (undefined in case of inconsistent dimensions or singular matrix).
7+
8+
function _linear_solve(a, b)
9+
{
10+
// Verify that the inputs have compatible dimensions
11+
if ((array_length(a) != array_length(a[0])) || (array_length(a) != array_length(b)))
12+
return undefined;
13+
14+
// Initialize system
15+
var n, l, u;
16+
n = array_length(b); // size of system
17+
l = array_create(n, array_create(n, 0)); // lower triangular matrix
18+
for (var i = 0; i < n; i++)
19+
l[i][i] = 1; // initialize as identity matrix
20+
u = a; // upper triangular matrix
21+
22+
// Perform Gaussian elimination to obtain LU decomposition
23+
for (var i = 0; i < n-1; i++)
24+
{
25+
for (var j = i+1; j < n; j++)
26+
{
27+
// Verify that we are not dividing by zero
28+
if (u[i][i] == 0)
29+
return undefined;
30+
31+
l[j][i] = u[j][i]/u[i][i];
32+
for (var k = i; k < n; k++)
33+
u[j][k] = u[j][k] - l[j][i]*u[i][k];
34+
}
35+
}
36+
37+
// Solve Ly = b
38+
var yy = _triangular_solve(l, b, false);
39+
40+
// Solve Ux = y
41+
return _triangular_solve(u, yy, true);
42+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/// @func _triangular_solve(a, b[, upper])
2+
/// @desc Solves a triangular system of the form Ax = b for a given triangular coefficient matrix and constant vector.
3+
/// @param {real[]} a Triangular, square coefficient matrix (as a 2D array).
4+
/// @param {real[]} b Constraint vector (as a 1D array whose length matches a).
5+
/// @param {bool} [upper=true] True if a is upper triangular, false if a is lower triangular.
6+
/// @return {real[]} Solution vector x of the triangular system Ax = b (undefined in case of inconsistent dimensions or singular matrix).
7+
8+
function _triangular_solve(a, b)
9+
{
10+
// Check for optional upper argument
11+
var upper = (argument_count > 2 ? argument[2] : true);
12+
13+
// Verify that the inputs have compatible dimensions
14+
if ((array_length(a) != array_length(a[0])) || (array_length(a) != array_length(b)))
15+
return undefined;
16+
17+
// Initialize system
18+
var n, xx;
19+
n = array_length(b); // size of system
20+
xx = array_create(n); // solution vector
21+
22+
// Verify that no diagonal element is zero
23+
for (var i = 0; i < n; i++)
24+
{
25+
if (a[i][i] == 0)
26+
return undefined;
27+
}
28+
29+
// Separate procedure for upper or lower triangular systems
30+
if (upper == true)
31+
{
32+
// Use back substitution for upper triangular
33+
for (var i = n-1; i >= 0; i--)
34+
{
35+
xx[i] = b[i];
36+
for (var j = i+1; j < n; j++)
37+
xx[i] -= a[i][j]*xx[j];
38+
xx[i] /= a[i][i];
39+
}
40+
}
41+
else
42+
{
43+
// Use forward substitution for lower triangular
44+
for (var i = 0; i < n; i++)
45+
{
46+
xx[i] = b[i];
47+
for (var j = 0; j < i; j++)
48+
xx[i] -= a[i][j]*xx[j];
49+
}
50+
}
51+
52+
return xx;
53+
}

0 commit comments

Comments
 (0)