# Mathematical Matrix & Vectors in n dimension

Hi guys,

This afternoon I have been working on two simple scripts to allow the manipulation of vectors of dimension n and square/rectangle matrix. I have implemented :

VECTORS :

• and - operators for two Vectors
• and / for a Vector and a float
• == and != for two Vectors
• Scalar Product and Orthogonality

MATRIX :

• and - operators for two Matrix
• and / for a Matrix and a float
• for two Matrix
• == and != for two Matrix

• Identity Matrix

• transpose of a Matrix

Here is the VectorN.CS

``````using UnityEngine;
using System.Collections;

public class VectorN : Object {

public int Length; //Size
public float[] values;

/*-\$-\$-\$-\$-\$-\$-\$-\$-CONSTRUCTORS & INDEXERS-\$-\$-\$-\$-\$-\$-\$-\$-*/

public VectorN(int size){
this.Length = size;
this.values = new float[Length];
}

public float this[int i] //Be careful this does not look for errors
{
get
{
return values[i];
}
set
{
values[i] = value;
}
}

/*-\$-\$-\$-\$-\$-\$-\$-\$-METHODS-\$-\$-\$-\$-\$-\$-\$-\$-*/

public void print(){
for ( int i = 0; i < Length; i++){
Debug.Log(i+" -> "+values[i]);
}
}

public float norme(){
return ScalarProduct(this,this);
}

public static float ScalarProduct(VectorN v1, VectorN v2){
if ( v1.Length == v2.Length ){
float sum = 0;
for ( int i = 0; i < v1.Length; i++){
sum += v1[i]*v2[i];
}
Debug.Log(sum);
return sum;
}
else{
throw new System.Exception("VECTORS DIMENSIONS MUST AGREE");
}
}

public static Vector3 CrossProduct(Vector3 u, Vector3 v){ //Dimension 3
return new Vector3(u.y*v.z-u.z*v.y,u.z*v.x-u.x*v.z,u.x*v.y-u.y*v.x);
}

public static bool Orthogonal(VectorN v1, VectorN v2){
return VectorN.ScalarProduct(v1,v2) == 0;
}

/*-\$-\$-\$-\$-\$-\$-\$-\$-OPERATORS-\$-\$-\$-\$-\$-\$-\$-\$-*/

public static VectorN operator +(VectorN v1, VectorN v2){
if ( v1.Length == v2.Length ) {
VectorN v = new VectorN(v1.Length);
for ( int i = 0; i < v1.Length; i++){
v[i] = v1[i] + v2[i];
}
return v;
}
else{
throw new System.Exception("VECTORS DIMENSIONS MUST AGREE");
}
}

public static VectorN operator -(VectorN v1, VectorN v2){
if ( v1.Length == v2.Length ) {
VectorN v = new VectorN(v1.Length);
for ( int i = 0; i < v1.Length; i++){
v[i] = v1[i] - v2[i];
}
return v;
}
else{
throw new System.Exception("VECTORS DIMENSIONS MUST AGREE");
}
}

public static VectorN operator *(VectorN v1, float f){
VectorN v = new VectorN(v1.Length);
for ( int i = 0; i < v1.Length; i++){
v[i] = v1[i]*f;
}
return v;
}
public static VectorN operator *(float f, VectorN v1){
VectorN v = new VectorN(v1.Length);
for ( int i = 0; i < v1.Length; i++){
v[i] = v1[i]*f;
}
return v;
}

public static VectorN operator /(VectorN v1, float f){
if ( f != 0 ){
VectorN v = new VectorN(v1.Length);
for ( int i = 0; i < v1.Length; i++){
v[i] = v1[i]/f;
}
return v;
}
else{
throw new System.Exception("ARRGH, DIVISION BY ZERO");
}
}

public static bool operator == (VectorN v1, VectorN v2){
if ( v1.Length == v2.Length){
for ( int i = 0; i < v1.Length; i++){
if ( v1[i] != v2[i] ){
return false;
}
}
return true;
}
else{
return false;
}
}

public static bool operator != (VectorN v1, VectorN v2){
if ( v1.Length == v2.Length){
for ( int i = 0; i < v1.Length; i++){
if ( v1[i] != v2[i] ){
return true;
}
}
return false;
}
else{
return true;
}
}

}
``````

Here the Matrix.CS

``````using UnityEngine;
using System.Collections;

public class Matrix : Object {

public int columnNb;
public int rowNb;
public VectorN[] rows;

/*-\$-\$-\$-\$-\$-\$-\$-\$-CONSTRUCTORS & INDEXERS-\$-\$-\$-\$-\$-\$-\$-\$-*/

public Matrix(int rowNb, int columnNb){
this.rowNb = rowNb;
this.columnNb = columnNb;
rows = new VectorN[rowNb];
for (int i = 0; i < rowNb; i++){
rows[i] = new VectorN(columnNb);
}
}

public Matrix(int size)  : this( size, size ){}

public VectorN this[int i] //Be careful this does not look for errors
{
get
{
return rows[i];
}
set
{
rows[i] = value;
}
}

/*-\$-\$-\$-\$-\$-\$-\$-\$-METHODS-\$-\$-\$-\$-\$-\$-\$-\$-*/

public void printSize(){
Debug.Log("Matrix "+rows.Length+" x "+rows[0].Length);
}

public void print(){
for (int i = 0; i < rows.Length; i++){
string Line = "Line n°"+i+" :";
for (int j = 0; j < columnNb; j++){
Line += " "+this[i][j];
}
Debug.Log(Line);
}
}

public bool isSquare(){
return columnNb == rowNb;
}

public Matrix transpose(){ //Returns new matrice in case the input is not square
Matrix m = new Matrix(this.columnNb,this.rowNb);
for ( int i = 0; i < this.rowNb; i++){
for ( int j = 0; j < this.columnNb; j++){
m[j][i] = this[i][j];
}
}
return m;
}

/*-\$-\$-\$-\$-\$-\$-\$-\$-OPERATORS-\$-\$-\$-\$-\$-\$-\$-\$-*/

public static Matrix operator + (Matrix m1, Matrix m2){
if ( m1.rowNb == m2.rowNb &&  m1.columnNb == m2.columnNb) {
Matrix m = new Matrix(m1.rowNb,m1.columnNb); //Destination matrix
for ( int i = 0; i < m1.rowNb; i++){
m[i] = m1[i] + m2[i]; //CF Operations on VectorN
}
return m;
}
else{
throw new System.Exception("MATRIX DIMENSIONS MUST AGREE");
}
}

public static Matrix Identity(int n){
Matrix m = new Matrix(n);
for (int i = 0; i < n; i++){
m[i][i] = 1;
}
return m;
}

public static Matrix operator - (Matrix m1, Matrix m2){
if ( m1.rowNb == m2.rowNb &&  m1.columnNb == m2.columnNb) {
Matrix m = new Matrix(m1.rowNb,m1.columnNb); //Destination matrix
for ( int i = 0; i < m1.rowNb; i++){
m[i] = m1[i] - m2[i]; //CF Operations on VectorN
}
return m;
}
else{
throw new System.Exception("MATRIX DIMENSIONS MUST AGREE");
}
}

public static Matrix operator * (Matrix m1, float f){
Matrix m = new Matrix(m1.rowNb,m1.columnNb); //Destination matrix
for ( int i = 0; i < m1.rowNb; i++){
m[i] = m1[i]*f; //CF Operations on VectorN
}
return m;
}
public static Matrix operator * (float f,Matrix m1){
Matrix m = new Matrix(m1.rowNb,m1.columnNb); //Destination matrix
for ( int i = 0; i < m1.rowNb; i++){
m[i] = m1[i]*f; //CF Operations on VectorN
}
return m;
}

public static Matrix operator * (Matrix m1, Matrix m2){
if ( m1.columnNb == m2.rowNb) { //Ex 2X8 * 8x1 => 2x1
Matrix m = new Matrix(m1.rowNb,m2.columnNb); //Destination matrix
for ( int i = 0; i < m.rowNb; i++){
for ( int j = 0; j < m.columnNb; j++){
float sum = 0;
for (int k = 0; k < m.rowNb; k++){
sum += m1[i][k]*m2[k][j]; // c(i,j) = a(i,k)b(k,j); and M = matrix of c(i,j)
}
m[i][j] = sum; //CF Operations on VectorN
}
}
return m;
}
else{
throw new System.Exception("MATRIX DIMENSIONS MUST AGREE");
}
}

public static Matrix operator /(Matrix m1, float f){
if ( f != 0 ){
Matrix m = new Matrix(m1.rowNb,m1.columnNb); //Destination matrix
for ( int i = 0; i < m1.rowNb; i++){
m[i] = m1[i]/f; //CF Operations on VectorN
}
return m;
}
else{
throw new System.Exception("ARRGH, DIVISION BY ZERO");
}
}

public static bool operator == (Matrix m1, Matrix m2){
if ( m1.rowNb == m2.rowNb &&  m1.columnNb == m2.columnNb ){
for ( int i = 0; i < m1.rowNb; i++){
if ( m1[i] == m2[i] ){ //CF Operations on VectorN
return false;
}
}
return true;
}
else{
return false;
}
}

public static bool operator != (Matrix m1, Matrix m2){
if ( m1.rowNb == m2.rowNb &&  m1.columnNb == m2.columnNb ){
for ( int i = 0; i < m1.rowNb; i++){
if ( m1[i] == m2[i] ){ //CF Operations on VectorN
return true;
}
}
return false;
}
else{
return true;
}
}
}
``````

Finally, here is a little example to show you how to use it :

``````using UnityEngine;
using System.Collections;

public class Test : MonoBehaviour {

void Start () {
testMethodsVector();
testOperatorsVector();
testMatrix();
}

/********** VECTORS **********/

void testMethodsVector(){
VectorN v = new VectorN(5);
for ( int i = 0; i < 5; i++){
v[i] = 2+(float)i/10;
}
v.print();
//v.setValue(100,2); //To have an error
VectorN.ScalarProduct(v,v);
v.norme();
Debug.Log(VectorN.Orthogonal(v,v)); //Should be false
}

void testOperatorsVector(){
VectorN v = new VectorN(5);
for ( int i = 0; i < 5; i++){
v[i] = 2+(float)i/10;
}
v = v + v;
v.print();
v = v*10;
v.print();
v = v/100;
v.print();
v += 10*v;
v.print();
v = v - v/2;
v.print();
}

void testMatrix(){
Matrix m = new Matrix(2); //2 height, 3 width
m.printSize();

/*
* This part is equivalent to
* m[0][0] : 1
* m[0][1] : 2
* m[1][0] : 0
* m[1][1] : 2
*/

VectorN v0 = new VectorN(2);
v0[0] = 0;
v0[1] = 2;

VectorN v1 = new VectorN(2);
v1[0] = 0;
v1[1] = 0;

m[0] = v0;
m[1] = v1;

m.print();

Matrix m0 = Matrix.Identity(2);
m = m + m0;
m.print();

m = m * m;
m.print();
m = m.transpose();
m.print();
}
}
``````

Ask questions if you have or if there are issues

You should protect your fields by making them private. Currently a user of your classes can modify the arrays and values like ‘Length’ manually, disrupting the state of your objects.

Furthermore, ‘Length’ on VectorN is redundant, the array already has that value in it. Why not just have a property that returns that?

You name your method ‘ScalarProduct’, I’d suggest calling it ‘Dot’ merely because in Unity the built in Vectors use the name ‘Dot’ (short for dot product) instead of ‘scalar product’.

I’d suggest a multi-dimensional array in your MatrixN, instead of an array of VectorN’s, which is an array of arrays. It’ll be more compact with the memory that way… especially for large values of N.