1: /*
2: Copyright (c) 2010 <a href="http://www.gutgames.com">James Craig</a>
3:
4: Permission is hereby granted, free of charge, to any person obtaining a copy
5: of this software and associated documentation files (the "Software"), to deal
6: in the Software without restriction, including without limitation the rights
7: to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8: copies of the Software, and to permit persons to whom the Software is
9: furnished to do so, subject to the following conditions:
10:
11: The above copyright notice and this permission notice shall be included in
12: all copies or substantial portions of the Software.
13:
14: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17: AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18: LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20: THE SOFTWARE.*/
21:
22: #region Usings
23: using System;
24: using System.Text;
25: using System.Xml.Serialization;
26: #endregion
27:
28: namespace Utilities.Math
29: {
30: /// <summary>
31: /// Matrix used in linear algebra
32: /// </summary>
33: [Serializable()]
34: public class Matrix
35: {
36: #region Constructor
37:
38: /// <summary>
39: /// Constructor
40: /// </summary>
41: /// <param name="Width">Width of the matrix</param>
42: /// <param name="Height">Height of the matrix</param>
43: public Matrix(int Width, int Height)
44: {
45: _Width = Width;
46: _Height = Height;
47: _Values = new double[Width, Height];
48: }
49:
50: #endregion
51:
52: #region Public Properties
53:
54: /// <summary>
55: /// Width of the matrix
56: /// </summary>
57: [XmlElement]
58: public int Width
59: {
60: get { return _Width; }
61: set { _Width = value; _Values = new double[Width, Height]; }
62: }
63:
64: /// <summary>
65: /// Height of the matrix
66: /// </summary>
67: [XmlElement]
68: public int Height
69: {
70: get { return _Height; }
71: set { _Height = value; _Values = new double[Width, Height]; }
72: }
73: /// <summary>
74: /// Sets the values of the matrix
75: /// </summary>
76: /// <param name="X">X position</param>
77: /// <param name="Y">Y position</param>
78: /// <returns>the value at a point in the matrix</returns>
79: public double this[int X, int Y]
80: {
81: get
82: {
83: if (X < _Width && X >= 0 && Y < _Height && Y >= 0)
84: {
85: return _Values[X, Y];
86: }
87: throw new Exception("Index out of bounds");
88: }
89:
90: set
91: {
92: if (X < _Width && X >= 0 && Y < _Height && Y >= 0)
93: {
94: _Values[X, Y] = value;
95: return;
96: }
97: throw new Exception("Index out of bounds");
98: }
99: }
100:
101: /// <summary>
102: /// Values for the matrix
103: /// </summary>
104: [XmlElement]
105: public double[,] Values
106: {
107: get { return _Values; }
108: set { _Values = value; }
109: }
110:
111: #endregion
112:
113: #region Private Variables
114: private int _Width = 1;
115: private int _Height = 1;
116: private double[,] _Values = null;
117: #endregion
118:
119: #region Operators
120:
121: public static bool operator ==(Matrix M1, Matrix M2)
122: {
123: if (M1.Width != M2.Width || M1.Height != M2.Height)
124: return false;
125: for (int x = 0; x <= M1.Width; ++x)
126: {
127: for (int y = 0; y <= M1.Height; ++y)
128: {
129: if (M1[x, y] != M2[x, y])
130: return false;
131: }
132: }
133: return true;
134: }
135:
136: public static bool operator !=(Matrix M1, Matrix M2)
137: {
138: return !(M1 == M2);
139: }
140:
141: public static Matrix operator +(Matrix M1, Matrix M2)
142: {
143: if (M1.Width != M2.Width || M1.Height != M2.Height)
144: throw new ArgumentException("Both matrices must be the same dimensions.");
145: Matrix TempMatrix = new Matrix(M1.Width, M1.Height);
146: for (int x = 0; x < M1.Width; ++x)
147: {
148: for (int y = 0; y < M1.Height; ++y)
149: {
150: TempMatrix[x, y] = M1[x, y] + M2[x, y];
151: }
152: }
153: return TempMatrix;
154: }
155:
156: public static Matrix operator -(Matrix M1, Matrix M2)
157: {
158: if (M1.Width != M2.Width || M1.Height != M2.Height)
159: throw new ArgumentException("Both matrices must be the same dimensions.");
160: Matrix TempMatrix = new Matrix(M1.Width, M1.Height);
161: for (int x = 0; x < M1.Width; ++x)
162: {
163: for (int y = 0; y < M1.Height; ++y)
164: {
165: TempMatrix[x, y] = M1[x, y] - M2[x, y];
166: }
167: }
168: return TempMatrix;
169: }
170:
171: public static Matrix operator -(Matrix M1)
172: {
173: Matrix TempMatrix = new Matrix(M1.Width, M1.Height);
174: for (int x = 0; x < M1.Width; ++x)
175: {
176: for (int y = 0; y < M1.Height; ++y)
177: {
178: TempMatrix[x, y] = -M1[x, y];
179: }
180: }
181: return TempMatrix;
182: }
183:
184: public static Matrix operator *(Matrix M1, Matrix M2)
185: {
186: if (M1.Width != M2.Width || M1.Height != M2.Height)
187: throw new ArgumentException("Dimensions for the matrices are incorrect.");
188: Matrix TempMatrix = new Matrix(M2.Width, M1.Height);
189:
190: for (int x = 0; x < M2.Width; ++x)
191: {
192: for (int y = 0; y < M1.Height; ++y)
193: {
194: TempMatrix[x, y] = 0.0;
195: for (int i = 0; i < M1.Width; ++i)
196: {
197: for (int j = 0; j < M2.Height; ++j)
198: {
199: TempMatrix[x, y] += (M1[i, y] * M2[x, j]);
200: }
201: }
202: }
203: }
204: return TempMatrix;
205: }
206:
207: public static Matrix operator *(Matrix M1, double D)
208: {
209: Matrix TempMatrix = new Matrix(M1.Width, M1.Height);
210: for (int x = 0; x < M1.Width; ++x)
211: {
212: for (int y = 0; y < M1.Height; ++y)
213: {
214: TempMatrix[x, y] = M1[x, y] * D;
215: }
216: }
217: return TempMatrix;
218: }
219:
220: public static Matrix operator *(double D, Matrix M1)
221: {
222: Matrix TempMatrix = new Matrix(M1.Width, M1.Height);
223: for (int x = 0; x < M1.Width; ++x)
224: {
225: for (int y = 0; y < M1.Height; ++y)
226: {
227: TempMatrix[x, y] = M1[x, y] * D;
228: }
229: }
230: return TempMatrix;
231: }
232:
233: public static Matrix operator /(Matrix M1, double D)
234: {
235: return M1 * (1 / D);
236: }
237:
238: public static Matrix operator /(double D, Matrix M1)
239: {
240: return M1 * (1 / D);
241: }
242:
243: #endregion
244:
245: #region Public Overridden Functions
246:
247: public override bool Equals(object obj)
248: {
249: if (obj is Matrix)
250: {
251: return this == (Matrix)obj;
252: }
253: return false;
254: }
255:
256: public override int GetHashCode()
257: {
258: double Hash = 0;
259: for (int x = 0; x < Width; ++x)
260: {
261: for (int y = 0; y < Height; ++y)
262: {
263: Hash += this[x, y];
264: }
265: }
266: return (int)Hash;
267: }
268:
269: public override string ToString()
270: {
271: StringBuilder Builder = new StringBuilder();
272: string Seperator = "";
273: Builder.Append("{").Append(System.Environment.NewLine);
274: for (int x = 0; x < Width; ++x)
275: {
276: Builder.Append("{");
277: for (int y = 0; y < Height; ++y)
278: {
279: Builder.Append(Seperator).Append(this[x, y]);
280: Seperator = ",";
281: }
282: Builder.Append("}").Append(System.Environment.NewLine);
283: Seperator = "";
284: }
285: Builder.Append("}");
286: return Builder.ToString();
287: }
288:
289: #endregion
290:
291: #region Public Functions
292:
293: /// <summary>
294: /// Transposes the matrix
295: /// </summary>
296: /// <returns>Returns a new transposed matrix</returns>
297: public Matrix Transpose()
298: {
299: Matrix TempValues = new Matrix(Height, Width);
300: for (int x = 0; x < Width; ++x)
301: {
302: for (int y = 0; y < Height; ++y)
303: {
304: TempValues[y, x] = _Values[x, y];
305: }
306: }
307: return TempValues;
308: }
309:
310: /// <summary>
311: /// Gets the determinant of a square matrix
312: /// </summary>
313: /// <returns>The determinant of a square matrix</returns>
314: public double Determinant()
315: {
316: if (Width != Height)
317: throw new Exception("The determinant can not be calculated for a non square matrix");
318: if (Width == 2)
319: {
320: return (this[0, 0] * this[1, 1]) - (this[0, 1] * this[1, 0]);
321: }
322: double Answer = 0.0;
323: for (int x = 0; x < Width; ++x)
324: {
325: Matrix TempMatrix = new Matrix(Width - 1, Height - 1);
326: int WidthCounter = 0;
327: for (int y = 0; y < Width; ++y)
328: {
329: if (y != x)
330: {
331: for (int z = 1; z < Height; ++z)
332: {
333: TempMatrix[WidthCounter, z - 1] = this[y, z];
334: }
335: ++WidthCounter;
336: }
337: }
338: if (x % 2 == 0)
339: {
340: Answer += TempMatrix.Determinant();
341: }
342: else
343: {
344: Answer -= TempMatrix.Determinant();
345: }
346: }
347: return Answer;
348: }
349:
350: #endregion
351: }
352: }