Search Unity

Mathematical Matrix & Vectors in n dimension

Discussion in 'Scripting' started by AcexSpade, Nov 13, 2014.

  1. AcexSpade

    AcexSpade

    Joined:
    Jul 8, 2014
    Posts:
    6
    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

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class VectorN : Object {
    5.  
    6.     public int Length; //Size
    7.     public float[] values;
    8.  
    9.     /*-$-$-$-$-$-$-$-$-CONSTRUCTORS & INDEXERS-$-$-$-$-$-$-$-$-*/
    10.  
    11.     public VectorN(int size){
    12.         this.Length = size;
    13.         this.values = new float[Length];
    14.     }
    15.  
    16.     public float this[int i] //Be careful this does not look for errors
    17.     {
    18.         get
    19.         {
    20.             return values[i];
    21.         }
    22.         set
    23.         {
    24.             values[i] = value;
    25.         }
    26.     }
    27.  
    28.     /*-$-$-$-$-$-$-$-$-METHODS-$-$-$-$-$-$-$-$-*/
    29.  
    30.     public void print(){
    31.         for ( int i = 0; i < Length; i++){
    32.             Debug.Log(i+" -> "+values[i]);
    33.         }
    34.     }
    35.  
    36.     public float norme(){
    37.         return ScalarProduct(this,this);
    38.     }
    39.    
    40.     public static float ScalarProduct(VectorN v1, VectorN v2){
    41.         if ( v1.Length == v2.Length ){
    42.             float sum = 0;
    43.             for ( int i = 0; i < v1.Length; i++){
    44.                 sum += v1[i]*v2[i];
    45.             }
    46.             Debug.Log(sum);
    47.             return sum;
    48.         }
    49.         else{
    50.             throw new System.Exception("VECTORS DIMENSIONS MUST AGREE");
    51.         }
    52.     }
    53.  
    54.     public static Vector3 CrossProduct(Vector3 u, Vector3 v){ //Dimension 3
    55.         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);
    56.     }
    57.  
    58.     public static bool Orthogonal(VectorN v1, VectorN v2){
    59.         return VectorN.ScalarProduct(v1,v2) == 0;
    60.     }
    61.  
    62.     /*-$-$-$-$-$-$-$-$-OPERATORS-$-$-$-$-$-$-$-$-*/
    63.  
    64.     public static VectorN operator +(VectorN v1, VectorN v2){
    65.         if ( v1.Length == v2.Length ) {
    66.             VectorN v = new VectorN(v1.Length);
    67.             for ( int i = 0; i < v1.Length; i++){
    68.                 v[i] = v1[i] + v2[i];
    69.             }
    70.             return v;
    71.         }
    72.         else{
    73.             throw new System.Exception("VECTORS DIMENSIONS MUST AGREE");
    74.         }
    75.     }
    76.  
    77.     public static VectorN operator -(VectorN v1, VectorN v2){
    78.         if ( v1.Length == v2.Length ) {
    79.             VectorN v = new VectorN(v1.Length);
    80.             for ( int i = 0; i < v1.Length; i++){
    81.                 v[i] = v1[i] - v2[i];
    82.             }
    83.             return v;
    84.         }
    85.         else{
    86.             throw new System.Exception("VECTORS DIMENSIONS MUST AGREE");
    87.         }
    88.     }
    89.  
    90.     public static VectorN operator *(VectorN v1, float f){
    91.         VectorN v = new VectorN(v1.Length);
    92.         for ( int i = 0; i < v1.Length; i++){
    93.             v[i] = v1[i]*f;
    94.         }
    95.         return v;
    96.     }
    97.     public static VectorN operator *(float f, VectorN v1){
    98.         VectorN v = new VectorN(v1.Length);
    99.         for ( int i = 0; i < v1.Length; i++){
    100.             v[i] = v1[i]*f;
    101.         }
    102.         return v;
    103.     }
    104.    
    105.     public static VectorN operator /(VectorN v1, float f){
    106.         if ( f != 0 ){
    107.             VectorN v = new VectorN(v1.Length);
    108.             for ( int i = 0; i < v1.Length; i++){
    109.                 v[i] = v1[i]/f;
    110.             }
    111.             return v;
    112.         }
    113.         else{
    114.             throw new System.Exception("ARRGH, DIVISION BY ZERO");
    115.         }
    116.     }
    117.  
    118.     public static bool operator == (VectorN v1, VectorN v2){
    119.         if ( v1.Length == v2.Length){
    120.             for ( int i = 0; i < v1.Length; i++){
    121.                 if ( v1[i] != v2[i] ){
    122.                     return false;
    123.                 }
    124.             }
    125.             return true;
    126.         }
    127.         else{
    128.             return false;
    129.         }
    130.     }
    131.  
    132.     public static bool operator != (VectorN v1, VectorN v2){
    133.         if ( v1.Length == v2.Length){
    134.             for ( int i = 0; i < v1.Length; i++){
    135.                 if ( v1[i] != v2[i] ){
    136.                     return true;
    137.                 }
    138.             }
    139.             return false;
    140.         }
    141.         else{
    142.             return true;
    143.         }
    144.     }
    145.  
    146. }
    147.  
    Here the Matrix.CS

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Matrix : Object {
    5.  
    6.     public int columnNb;
    7.     public int rowNb;
    8.     public VectorN[] rows;
    9.  
    10.     /*-$-$-$-$-$-$-$-$-CONSTRUCTORS & INDEXERS-$-$-$-$-$-$-$-$-*/
    11.    
    12.     public Matrix(int rowNb, int columnNb){
    13.         this.rowNb = rowNb;
    14.         this.columnNb = columnNb;
    15.         rows = new VectorN[rowNb];
    16.         for (int i = 0; i < rowNb; i++){
    17.             rows[i] = new VectorN(columnNb);
    18.         }
    19.     }
    20.  
    21.     public Matrix(int size)  : this( size, size ){}
    22.  
    23.     public VectorN this[int i] //Be careful this does not look for errors
    24.     {
    25.         get
    26.         {
    27.             return rows[i];
    28.         }
    29.         set
    30.         {
    31.             rows[i] = value;
    32.         }
    33.     }
    34.  
    35.     /*-$-$-$-$-$-$-$-$-METHODS-$-$-$-$-$-$-$-$-*/
    36.  
    37.     public void printSize(){
    38.         Debug.Log("Matrix "+rows.Length+" x "+rows[0].Length);
    39.     }
    40.  
    41.     public void print(){
    42.         for (int i = 0; i < rows.Length; i++){
    43.             string Line = "Line n°"+i+" :";
    44.             for (int j = 0; j < columnNb; j++){
    45.                 Line += " "+this[i][j];
    46.             }
    47.             Debug.Log(Line);
    48.         }
    49.     }
    50.    
    51.     public bool isSquare(){
    52.         return columnNb == rowNb;
    53.     }
    54.    
    55.     public Matrix transpose(){ //Returns new matrice in case the input is not square
    56.         Matrix m = new Matrix(this.columnNb,this.rowNb);
    57.         for ( int i = 0; i < this.rowNb; i++){
    58.             for ( int j = 0; j < this.columnNb; j++){
    59.                 m[j][i] = this[i][j];
    60.             }
    61.         }
    62.         return m;
    63.     }
    64.  
    65.     /*-$-$-$-$-$-$-$-$-OPERATORS-$-$-$-$-$-$-$-$-*/
    66.    
    67.     public static Matrix operator + (Matrix m1, Matrix m2){
    68.         if ( m1.rowNb == m2.rowNb &&  m1.columnNb == m2.columnNb) {
    69.             Matrix m = new Matrix(m1.rowNb,m1.columnNb); //Destination matrix
    70.             for ( int i = 0; i < m1.rowNb; i++){
    71.                 m[i] = m1[i] + m2[i]; //CF Operations on VectorN
    72.             }
    73.             return m;
    74.         }
    75.         else{
    76.             throw new System.Exception("MATRIX DIMENSIONS MUST AGREE");
    77.         }
    78.     }
    79.    
    80.     public static Matrix Identity(int n){
    81.         Matrix m = new Matrix(n);
    82.         for (int i = 0; i < n; i++){
    83.             m[i][i] = 1;
    84.         }
    85.         return m;
    86.     }
    87.    
    88.     public static Matrix operator - (Matrix m1, Matrix m2){
    89.         if ( m1.rowNb == m2.rowNb &&  m1.columnNb == m2.columnNb) {
    90.             Matrix m = new Matrix(m1.rowNb,m1.columnNb); //Destination matrix
    91.             for ( int i = 0; i < m1.rowNb; i++){
    92.                 m[i] = m1[i] - m2[i]; //CF Operations on VectorN
    93.             }
    94.             return m;
    95.         }
    96.         else{
    97.             throw new System.Exception("MATRIX DIMENSIONS MUST AGREE");
    98.         }
    99.     }
    100.    
    101.     public static Matrix operator * (Matrix m1, float f){
    102.         Matrix m = new Matrix(m1.rowNb,m1.columnNb); //Destination matrix
    103.         for ( int i = 0; i < m1.rowNb; i++){
    104.             m[i] = m1[i]*f; //CF Operations on VectorN
    105.         }
    106.         return m;
    107.     }
    108.     public static Matrix operator * (float f,Matrix m1){
    109.         Matrix m = new Matrix(m1.rowNb,m1.columnNb); //Destination matrix
    110.         for ( int i = 0; i < m1.rowNb; i++){
    111.             m[i] = m1[i]*f; //CF Operations on VectorN
    112.         }
    113.         return m;
    114.     }
    115.  
    116.     public static Matrix operator * (Matrix m1, Matrix m2){
    117.         if ( m1.columnNb == m2.rowNb) { //Ex 2X8 * 8x1 => 2x1
    118.             Matrix m = new Matrix(m1.rowNb,m2.columnNb); //Destination matrix
    119.             for ( int i = 0; i < m.rowNb; i++){
    120.                 for ( int j = 0; j < m.columnNb; j++){
    121.                     float sum = 0;
    122.                     for (int k = 0; k < m.rowNb; k++){
    123.                         sum += m1[i][k]*m2[k][j]; // c(i,j) = a(i,k)b(k,j); and M = matrix of c(i,j)
    124.                     }
    125.                     m[i][j] = sum; //CF Operations on VectorN
    126.                 }
    127.             }
    128.             return m;
    129.         }
    130.         else{
    131.             throw new System.Exception("MATRIX DIMENSIONS MUST AGREE");
    132.         }
    133.     }
    134.    
    135.  
    136.     public static Matrix operator /(Matrix m1, float f){
    137.         if ( f != 0 ){
    138.             Matrix m = new Matrix(m1.rowNb,m1.columnNb); //Destination matrix
    139.             for ( int i = 0; i < m1.rowNb; i++){
    140.                 m[i] = m1[i]/f; //CF Operations on VectorN
    141.             }
    142.             return m;
    143.         }
    144.         else{
    145.             throw new System.Exception("ARRGH, DIVISION BY ZERO");
    146.         }
    147.     }
    148.    
    149.     public static bool operator == (Matrix m1, Matrix m2){
    150.         if ( m1.rowNb == m2.rowNb &&  m1.columnNb == m2.columnNb ){
    151.             for ( int i = 0; i < m1.rowNb; i++){
    152.                 if ( m1[i] == m2[i] ){ //CF Operations on VectorN
    153.                     return false;
    154.                 }
    155.             }
    156.             return true;
    157.         }
    158.         else{
    159.             return false;
    160.         }
    161.     }
    162.  
    163.     public static bool operator != (Matrix m1, Matrix m2){
    164.         if ( m1.rowNb == m2.rowNb &&  m1.columnNb == m2.columnNb ){
    165.             for ( int i = 0; i < m1.rowNb; i++){
    166.                 if ( m1[i] == m2[i] ){ //CF Operations on VectorN
    167.                     return true;
    168.                 }
    169.             }
    170.             return false;
    171.         }
    172.         else{
    173.             return true;
    174.         }
    175.     }
    176. }
    177.  
    Finally, here is a little example to show you how to use it :

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Test : MonoBehaviour {
    5.  
    6.     void Start () {
    7.         testMethodsVector();
    8.         testOperatorsVector();
    9.         testMatrix();
    10.     }
    11.  
    12.     /********** VECTORS **********/
    13.  
    14.     void testMethodsVector(){
    15.         VectorN v = new VectorN(5);
    16.         for ( int i = 0; i < 5; i++){
    17.             v[i] = 2+(float)i/10;
    18.         }
    19.         v.print();
    20.         //v.setValue(100,2); //To have an error
    21.         VectorN.ScalarProduct(v,v);
    22.         v.norme();
    23.         Debug.Log(VectorN.Orthogonal(v,v)); //Should be false
    24.     }
    25.  
    26.     void testOperatorsVector(){
    27.         VectorN v = new VectorN(5);
    28.         for ( int i = 0; i < 5; i++){
    29.             v[i] = 2+(float)i/10;
    30.         }
    31.         v = v + v;
    32.         v.print();
    33.         v = v*10;
    34.         v.print();
    35.         v = v/100;
    36.         v.print();
    37.         v += 10*v;
    38.         v.print();
    39.         v = v - v/2;
    40.         v.print();
    41.     }
    42.  
    43.     void testMatrix(){
    44.         Matrix m = new Matrix(2); //2 height, 3 width
    45.         m.printSize();
    46.  
    47.         /*
    48.          * This part is equivalent to
    49.          * m[0][0] : 1
    50.          * m[0][1] : 2
    51.          * m[1][0] : 0
    52.          * m[1][1] : 2
    53.          */
    54.        
    55.         VectorN v0 = new VectorN(2);
    56.         v0[0] = 0;
    57.         v0[1] = 2;
    58.        
    59.         VectorN v1 = new VectorN(2);
    60.         v1[0] = 0;
    61.         v1[1] = 0;
    62.        
    63.         m[0] = v0;
    64.         m[1] = v1;
    65.        
    66.         m.print();
    67.        
    68.         Matrix m0 = Matrix.Identity(2);
    69.         m = m + m0;
    70.         m.print();
    71.  
    72.         m = m * m;
    73.         m.print();
    74.         m = m.transpose();
    75.         m.print();
    76.     }
    77. }
    78.  
    Ask questions if you have or if there are issues :)
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    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.