1 module aurorafw.math.matrix;
2 
3 /****************************************************************************
4 ** ┌─┐┬ ┬┬─┐┌─┐┬─┐┌─┐  ┌─┐┬─┐┌─┐┌┬┐┌─┐┬ ┬┌─┐┬─┐┬┌─
5 ** ├─┤│ │├┬┘│ │├┬┘├─┤  ├┤ ├┬┘├─┤│││├┤ ││││ │├┬┘├┴┐
6 ** ┴ ┴└─┘┴└─└─┘┴└─┴ ┴  └  ┴└─┴ ┴┴ ┴└─┘└┴┘└─┘┴└─┴ ┴
7 ** A Powerful General Purpose Framework
8 ** More information in: https://aurora-fw.github.io/
9 **
10 ** Copyright (C) 2018 Aurora Framework, All rights reserved.
11 **
12 ** This file is part of the Aurora Framework. This framework is free
13 ** software; you can redistribute it and/or modify it under the terms of
14 ** the GNU Lesser General Public License version 3 as published by the
15 ** Free Software Foundation and appearing in the file LICENSE included in
16 ** the packaging of this file. Please review the following information to
17 ** ensure the GNU Lesser General Public License version 3 requirements
18 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
19 ****************************************************************************/
20 
21 /** @file aurorafw/math/matrix.d
22  * Variable Matrix file. This contains a variable matrix struct that
23  * represents a grid with size of M * N.
24  * @author Luís Ferreira <contact@lsferreira.net>
25  * @since snapshot20180509
26  */
27 
28 /** A struct that represents a variable matrix. A struct that store's
29  * N*M array, allows to manipulate it.
30  * @since snapshot20190930
31  */
32 @nogc pure @safe struct mat(T, size_t M, size_t N) {
33 	this(T num)
34 	in {
35 		static assert(M == N, "invalid diagonal matrix");
36 	}
37 	body {
38 		foreach(size_t i; 0..M)
39 			matrix[i * M + i] = num;
40 	}
41 
42 	this(immutable ref mat!(T, M, N) mat)
43 	{
44 		this = mat;
45 	}
46 
47 	this(T[M*N] arr)
48 	{
49 		matrix[] = arr;
50 	}
51 
52 	this(T[] arr)
53 	in {
54 		assert(arr.length == M * N, "array doesn't have the same size");
55 	}
56 	body {
57 		matrix = arr;
58 	}
59 
60 	pragma(inline) static mat!(T, M, N) zero()
61 	{
62 		mat!(T, M, N) ret;
63 		ret.matrix[0..N*M] = 0;
64 		return ret;
65 	}
66 
67 	pragma(inline) static mat!(T, M, N) identity()
68 	{
69 		mat!(T, M, N) ret;
70 		ret.setIdentity();
71 		return ret;
72 	}
73 
74 	void setIdentity() @property
75 	{
76 		foreach(size_t x; 0 .. M)
77 			foreach(size_t y; 0 .. N)
78 				if (y == x)
79 					matrix[x * M + y] = 1;
80 				else
81 					matrix[x * M + y] = 0;
82 	}
83 
84 	bool opEquals(mat!(T, M, N) mat) const
85 	{
86 		return matrix == mat.matrix;
87 	}
88 
89 	T opIndex(in size_t m, in size_t n) const
90 	in
91 	{
92 		assert (n < N && m < M, "index out of bounds");
93 	}
94 	body
95 	{
96 		return matrix[m * M + n];
97 	}
98 
99 	T opIndex(in size_t i) const
100 	in
101 	{
102 		assert (i < N * M, "index out of bounds");
103 	}
104 	body
105 	{
106 		return matrix[i];
107 	}
108 
109 	T opIndexAssign(in T val, in size_t m, in size_t n)
110 	in
111 	{
112 		assert (n < N && m < M, "index out of bounds");
113 	}
114 	body
115 	{
116 		return (matrix[m * M + n] = val);
117 	}
118 
119 	T[] opSliceAssign(in T val, in size_t i1, in size_t i2)
120 	in
121 	{
122 		assert (i1 < N * M && i2 < N * M, "index out of bounds");
123 	}
124 	body
125 	{
126 		return (matrix[i1..i2] = val);
127 	}
128 
129 	T[] opSliceAssign(in T val)
130 	{
131 		return (matrix[] = val);
132 	}
133 
134 	T[M*N] matrix;
135 }
136 
137 alias mat!(float, 2, 2) Matrix2x2f, Matrix2f;
138 alias mat!(float, 3, 3) Matrix3x3f, Matrix3f;
139 alias mat!(float, 4, 4) Matrix4x4f, Matrix4f;
140 alias mat!(double, 2, 2) Matrix2x2d, Matrix2d;
141 alias mat!(double, 3, 3) Matrix3x3d, Matrix3d;
142 alias mat!(double, 4, 4) Matrix4x4d, Matrix4d;
143 
144 alias Matrix2x2f mat2;
145 alias Matrix3x3f mat3;
146 alias Matrix4x4f mat4;