/*
* Generic Matrix Class for Math.NET
* written by MovGP0 (mailto:movgp0@gmail.com)
* licensed under the terms of the CC GNU LGPL 2.1
* (http://creativecommons.org/licenses/LGPL/2.1/)
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MathNet.Numerics.LinearAlgebra
{
/// <summary>This is a generic Matrix Class.</summary>
/// <typeparam name="T">
/// Type of the Matrix Elwements.
/// Usually the type should be real, double, or rational.
/// Note: There should be an extended Matrix-Class for complex values.
/// </typeparam>
partial class NMatrix<T>
{
#region Array
private T[,] array;
private uint m
{
get{
return this.array.GetUpperBound(0);
}
}
private uint n
{
get
{
return this.array.GetUpperBound(1);
}
}
#endregion
#region Constructors
/// <summary>
/// Creates a new square Matrix.
/// </summary>
/// <param name="Dimension">The Dimension N of the NxN Matrix.</param>
public NMatrix(uint Dimension)
{
NMatrix(Dimension, Dimension);
}
/// <summary>Creates a new Matrix from a 2-dimensional Array</summary>
/// <param name="Array">
/// The Array where the Matrix is built from.
/// The array must be of rectangular shape and has
/// to be one or two dimensional.
/// </param>
public NMatrix(T [,] Array )
{//TODO: check C# Documentation if Array is forced to be 2D because of the "[,]"
// TODO: remove if Array is forced to be 2D
// Check if the Array is 1D or 2D
if (Array.Rank < 1 || Array.Rank > 2)
{
string message = String.Format(
"Array must be of dimension 1 or 2.{0}" +
"Dimension of the Array is {1}.",
Environment.NewLine, Array.Rank);
throw new ArgumentException(message);
}
#region copy the elements
uint x,y = 1;
// create a new array of fitting size
uint[] lowerBonds = { 1, 1 }; // index starting at 1,1 instead of 0,0
uint[] lengths = { // size of the array
// size of first dimension (lenght of the vector)
Array.GetLength(0),
// if Array is 1D then the new matrix is a vector (1 column)
//TODO: simplify to "Array.GetLength(1)" if Array is forced to be 2D
(Array.Rank == 2) ? Array.GetLength(1) : 1
};
array = Array.CreateInstance(typeof(T), lengths, lowerBonds);
for(int i = Array.GetLowerBound(0); i <= Array.GetUpperBound(0); i++)
{
if (Array.Rank == 2) // array is 2D
{
for (int j = Array.GetLowerBound(1); j <= Array.GetUpperBound(1); j++)
{
array[y, x] == Array[i,j];
x++; y++;
}
}
//TODO: remove if Array is forced to be 2D
else // array is 1D
{
array[y, 1] == Array

;
y++;
}
}
#endregion
}
/// <summary>
/// Creates a new Matrix of a given size.
/// After the size got set it can't get changed.
/// </summary>
/// <param name="m">Number of Columns.</param>
/// <param name="n">Number of Rows.</param>
public NMatrix(uint m, uint n)
{
// check size of the matrix
if(m=0 || n=0)
{
string message = String.Format(
"Size of a Matrix can't be zero.{0}"+
"Number of Columns was {1} and the Number of Rows was {2}.",
Environment.NewLine, m, n);
throw new ArgumentNullException(message);
}
// create a new array of the given Type
uint[] lowerBonds = { 1, 1 }; // index starting at 1,1 instead of 0,0
uint[] lengths = { n, m }; // size of the array
array = Array.CreateInstance(typeof(T), lengths, lowerBonds);
// initialize the array
for(uint i = 1; i <= m; i++)
{
for (uint j = 1; j <= n; j++)
{
array[i, j] = (T)0;
}
}
}
/// <summary>Creates a new Identity-Matrix.</summary>
/// <param name="Dimension">The Dimension N the matrix shall have.</param>
/// <returns>The NxN Identity-Matrix.</returns>
public static NMatrix<T> IdentityMatrix(uint Dimension)
{
// check arguments
if(Dimension == 0)
{
throw new ArgumentNullException("Dimension of a Identity-Matrix can't be zero.");
}
// generate a new empty matrix
NMatrix matrix = new NMatrix<T>(Dimension, Dimension);
// fill diagonal with ones
for (uint i = 1; i <= Dimension; i++)
{
matrix[i, i] = (T)1;
}
// return the identity-matrix
return matrix;
}
#endregion
#region Properties
/// <summary>
/// Gives access to a specific element in the matrix.
/// </summary>
/// <param name="i">The Number of the column. First column is 1.</param>
/// <param name="j">The Number of the row. First row is 1. </param>
/// <returns>The Element on Position [i,j].</returns>
public T this[uint i, uint j]
{
get
{
CheckPosition(i, j);
array[i, j] = value;
}
set
{
CheckPosition(i, j);
array[i, j] = value;
}
}
/// <summary>Helper function to determine if a given position is in the range of the Matrix.</summary>
/// <param name="i">The Row of the matrix to access.</param>
/// <param name="j">The Column of the matrix to access.</param>
private void CheckPosition(uint i, uint j)
{
if (i > m || j > n)
{
string message = String.Format(
"The given Position is out of the size of the matrix.{0}" +
"The matrix has size {1},{2} and the requested position was {3},{4}.",
Environment.NewLine, this.m, this.n, i, j);
throw new ArgumentOutOfRangeException(message);
}
if (i == 0 || j == 0)
{
string message = String.Format(
"Index of a Matrix starts by definition at 1,1.{0}" +
"The requested position was {1},{2}.",
Environment.NewLine, i, j);
throw new ArgumentNullException(message);
}
}
/// <summary>Returns the dimension (size) of the matrix. </summary>
/// <param name="m">The number of Columns the matrix has. </param>
/// <param name="n">The number of Rows the matrix has. </param>
public void Dimension(out uint m, out uint n)
{
m = this.m;
n = this.n;
}
public uint Dimension
{
get{
if(!IsSquare())
{
throw new ArithmeticException("Matrix is not square." +
"Please use \"Dimension(out i, out j)\" instead.");
}
return this.m;
}
}
/// <summary>Determines the Rank of the Matrix.</summary>
public uint Rank
{
get
{
throw new NotImplementedException();
}
}
#endregion
#region Operators
/// <summary>Adds two Matrices of same Dimensions. </summary>
/// <param name="A">The one matrix to add.</param>
/// <param name="B">The other matrix to add.</param>
/// <returns>A new matrix that is the sum of the other two.</returns>
/// <remarks>
/// This Function is inefficient because it creates a new Matrix.
/// Use <code>A.Add(B)</code> or <code>A + B</code> where possible.
/// </remarks>
public static NMatrix<T> Add(NMatrix<T> A, NMatrix<T> B)
{
throw NotImplementedException();
NMatrix<T> C = (NMatrix<T>) A.Clone();
return C.Add(B);
}
/// <summary>Calls the Add-Function to add another Matrix of same Dimensions to this one. </summary>
/// <param name="A">The matrix containing the values to add.</param>
public void operator +(NMatrix<T> A)
{
this.Add(A);
}
/// <summary>Adds another Matrix of same Dimensions to this one. </summary>
/// <param name="A">The matrix containing the values to add.</param>
public void Add(NMatrix<T> A)
{
throw new NotImplementedException();
uint tm, tn, am, an;
// check if the matrices have the same dimensions
this.Dimension(out tm, out tn);
A.Dimension(out am, an);
if (tm != am || tn != am)
{
string message = String.Format(
"The Matrices can't get added, because they don't have equal dimensions.{0}" +
"This Matrix has Dimension {1},{2}, while the other Matrix has Dimension {3},{4}.",
Environment.NewLine, tm, tn, am, an);
throw new ArithmeticException(message);
}
// sum up the elements.
for (uint i = 1; i <= tm; i++)
{
for (uint j = 1; j <= tn; j++)
{
array[i, j] += A[i, j];
}
}
}
#endregion
}
}