Skip to content

Commit

Permalink
test: ✅ add testing for Matrix
Browse files Browse the repository at this point in the history
  • Loading branch information
thkruz committed Jan 15, 2024
1 parent 39673ba commit 416d5fa
Show file tree
Hide file tree
Showing 3 changed files with 606 additions and 21 deletions.
189 changes: 168 additions & 21 deletions src/operations/Matrix.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,45 @@
import { Radians } from 'src/main';
import { Vector } from './Vector';
import { Vector3D } from './Vector3D';

/**
* A matrix is a rectangular array of numbers or other mathematical objects for
* which operations such as addition and multiplication are defined.
*/
export class Matrix {
public elements: number[][];
public readonly rows: number;
public readonly columns: number;
elements: number[][];
readonly rows: number;
readonly columns: number;

constructor(elements: number[][]) {
this.elements = elements;
this.rows = elements.length;
this.columns = elements[0].length;
}

/**
* Creates a matrix with all elements set to zero.
*
* @param rows - The number of rows in the matrix.
* @param columns - The number of columns in the matrix. @returns A matrix
* with all elements set to zero.
*/
static allZeros(rows: number, columns: number): Matrix {
return this.fill(rows, columns, 0.0);
}

/**
* Creates a new Matrix with the specified number of rows and columns, filled
* with the specified value.
*
* @param rows The number of rows in the matrix.
*
* @param columns The number of columns in the matrix.
*
* @param value The value to fill the matrix with. Default is 0.0.
*
* @returns A new Matrix filled with the specified value.
*/
static fill(rows: number, columns: number, value = 0.0): Matrix {
const elements: number[][] = [];

Expand All @@ -29,7 +53,13 @@ export class Matrix {
return new Matrix(elements);
}

public static rotX(theta: number): Matrix {
/**
* Creates a rotation matrix around the X-axis.
* @param theta - The angle of rotation in radians.
*
* @returns The rotation matrix.
*/
static rotX(theta: Radians): Matrix {
const cosT = Math.cos(theta);
const sinT = Math.sin(theta);
const result = Matrix.zero(3, 3);
Expand All @@ -43,7 +73,13 @@ export class Matrix {
return result;
}

public static rotY(theta: number): Matrix {
/**
* Creates a rotation matrix around the y-axis.
* @param theta - The angle of rotation in radians.
*
* @returns The rotation matrix.
*/
static rotY(theta: Radians): Matrix {
const cosT = Math.cos(theta);
const sinT = Math.sin(theta);
const result = Matrix.zero(3, 3);
Expand All @@ -57,7 +93,13 @@ export class Matrix {
return result;
}

public static rotZ(theta: number): Matrix {
/**
* Creates a rotation matrix around the Z-axis.
*
* @param theta The angle of rotation in radians.
* @returns The rotation matrix.
*/
static rotZ(theta: Radians): Matrix {
const cosT = Math.cos(theta);
const sinT = Math.sin(theta);
const result = Matrix.zero(3, 3);
Expand All @@ -71,7 +113,15 @@ export class Matrix {
return result;
}

public static zero(rows: number, columns: number): Matrix {
/**
* Creates a zero matrix with the specified number of rows and columns.
* @param rows The number of rows in the matrix.
*
* @param columns The number of columns in the matrix.
*
* @returns A new Matrix object representing the zero matrix.
*/
static zero(rows: number, columns: number): Matrix {
const elements: number[][] = [];

for (let i = 0; i < rows; i++) {
Expand All @@ -84,7 +134,13 @@ export class Matrix {
return new Matrix(elements);
}

public static identity(dimension: number): Matrix {
/**
* Creates an identity matrix of the specified dimension.
* @param dimension The dimension of the identity matrix.
*
* @returns The identity matrix.
*/
static identity(dimension: number): Matrix {
const elements: number[][] = [];

for (let i = 0; i < dimension; i++) {
Expand All @@ -97,7 +153,14 @@ export class Matrix {
return new Matrix(elements);
}

public static diagonal(d: number[]): Matrix {
/**
* Creates a diagonal matrix with the given diagonal elements.
*
* @param d - An array of diagonal elements.
*
* @returns A new Matrix object representing the diagonal matrix.
*/
static diagonal(d: number[]): Matrix {
const dimension = d.length;
const elements: number[][] = [];

Expand All @@ -111,7 +174,13 @@ export class Matrix {
return new Matrix(elements);
}

public add(m: Matrix): Matrix {
/**
* Adds the elements of another matrix to this matrix and returns the result.
* @param m - The matrix to be added.
*
* @returns The resulting matrix after addition.
*/
add(m: Matrix): Matrix {
const result = Matrix.zero(this.rows, this.columns);

for (let i = 0; i < this.rows; i++) {
Expand All @@ -123,7 +192,14 @@ export class Matrix {
return result;
}

public subtract(m: Matrix): Matrix {
/**
* Subtracts the elements of another matrix from this matrix.
*
* @param m - The matrix to subtract.
*
* @returns A new matrix containing the result of the subtraction.
*/
subtract(m: Matrix): Matrix {
const result = Matrix.zero(this.rows, this.columns);

for (let i = 0; i < this.rows; i++) {
Expand All @@ -135,7 +211,13 @@ export class Matrix {
return result;
}

public scale(n: number): Matrix {
/**
* Scales the matrix by multiplying each element by a scalar value.
* @param n - The scalar value to multiply each element by.
*
* @returns A new Matrix object representing the scaled matrix.
*/
scale(n: number): Matrix {
const result = Matrix.zero(this.rows, this.columns);

for (let i = 0; i < this.rows; i++) {
Expand All @@ -147,11 +229,21 @@ export class Matrix {
return result;
}

public negate(): Matrix {
/**
* Negates the matrix by scaling it by -1.
* @returns The negated matrix.
*/
negate(): Matrix {
return this.scale(-1);
}

public multiply(m: Matrix): Matrix {
/**
* Multiplies this matrix with another matrix.
* @param m The matrix to multiply with.
*
* @returns The resulting matrix.
*/
multiply(m: Matrix): Matrix {
const result = Matrix.zero(this.rows, m.columns);

for (let i = 0; i < this.rows; i++) {
Expand All @@ -165,7 +257,14 @@ export class Matrix {
return result;
}

public outerProduct(m: Matrix): Matrix {
/**
* Computes the outer product of this matrix with another matrix.
*
* @param m - The matrix to compute the outer product with.
*
* @returns The resulting matrix.
*/
outerProduct(m: Matrix): Matrix {
const result = Matrix.zero(this.rows, this.columns);

for (let i = 0; i < this.rows; i++) {
Expand All @@ -177,7 +276,13 @@ export class Matrix {
return result;
}

public multiplyVector(v: Vector): Vector {
/**
* Multiplies the matrix by a vector.
* @param v The vector to multiply by.
*
* @returns A new vector representing the result of the multiplication.
*/
multiplyVector(v: Vector): Vector {
const result: number[] = [];

for (let i = 0; i < this.rows; i++) {
Expand All @@ -192,7 +297,16 @@ export class Matrix {
return new Vector(result);
}

public multiplyVector3D<T extends number>(v: Vector3D<T>): Vector3D<T> {
/**
* Multiplies a 3D vector by the matrix.
*
* @template T - The type of the vector elements.
*
* @param v - The 3D vector to multiply.
*
* @returns The resulting 3D vector after multiplication.
*/
multiplyVector3D<T extends number>(v: Vector3D<T>): Vector3D<T> {
const result: T[] = [];

for (let i = 0; i < this.rows; i++) {
Expand All @@ -219,7 +333,15 @@ export class Matrix {
return new Vector3D<T>(result[0], result[1], result[2]);
}

public reciprocal(): Matrix {
/**
* Returns a new Matrix object where each element is the reciprocal of the
* corresponding element in the current matrix. If an element in the current
* matrix is zero, the corresponding element in the output matrix will also be
* zero.
* @returns A new Matrix object representing the reciprocal of the current
* matrix.
*/
reciprocal(): Matrix {
const output = Matrix.zero(this.rows, this.columns);

for (let i = 0; i < this.rows; i++) {
Expand All @@ -233,7 +355,11 @@ export class Matrix {
return output;
}

public transpose(): Matrix {
/**
* Transposes the matrix by swapping rows with columns.
* @returns A new Matrix object representing the transposed matrix.
*/
transpose(): Matrix {
const result = Matrix.zero(this.columns, this.rows);

for (let i = 0; i < this.rows; i++) {
Expand All @@ -245,7 +371,13 @@ export class Matrix {
return result;
}

public cholesky(): Matrix {
/**
* Performs the Cholesky decomposition on the matrix.
*
* @returns A new Matrix object representing the Cholesky decomposition of the
* original matrix.
*/
cholesky(): Matrix {
const result = Matrix.zero(this.rows, this.rows);

for (let i = 0; i < this.rows; i++) {
Expand All @@ -265,6 +397,12 @@ export class Matrix {
return result;
}

/**
* Swaps two rows in the matrix.
*
* @param i - The index of the first row.
* @param j - The index of the second row.
*/
private _swapRows(i: number, j: number): void {
if (i === j) {
return;
Expand All @@ -275,6 +413,10 @@ export class Matrix {
this.elements[j] = tmp;
}

/**
* Converts the matrix to reduced row echelon form using the Gaussian
* elimination method. This method modifies the matrix in-place.
*/
private _toReducedRowEchelonForm(): void {
for (let lead = 0, row = 0; row < this.rows && lead < this.columns; ++row, ++lead) {
let i = row;
Expand Down Expand Up @@ -308,7 +450,12 @@ export class Matrix {
}
}

public inverse(): Matrix {
/**
* Calculates the inverse of the matrix.
*
* @returns The inverse of the matrix.
*/
inverse(): Matrix {
const tmp = Matrix.zero(this.rows, this.columns * 2);

for (let row = 0; row < this.rows; ++row) {
Expand Down
Loading

0 comments on commit 416d5fa

Please sign in to comment.