@dxzmpk/js-algorithms-data-structures
Version:
Algorithms and data-structures implemented on JavaScript
456 lines (401 loc) • 8.78 kB
JavaScript
import * as mtrx from '../Matrix';
describe('Matrix', () => {
it('should throw when trying to add matrices of invalid shapes', () => {
expect(
() => mtrx.dot([0], [1]),
).toThrowError('Invalid matrix format');
expect(
() => mtrx.dot([[0]], [1]),
).toThrowError('Invalid matrix format');
expect(
() => mtrx.dot([[[0]]], [[1]]),
).toThrowError('Matrix is not of 2D shape');
expect(
() => mtrx.dot([[0]], [[1], [2]]),
).toThrowError('Matrices have incompatible shape for multiplication');
});
it('should calculate matrices dimensions', () => {
expect(mtrx.shape([])).toEqual([0]);
expect(mtrx.shape([
[],
])).toEqual([1, 0]);
expect(mtrx.shape([
[0],
])).toEqual([1, 1]);
expect(mtrx.shape([
[0, 0],
])).toEqual([1, 2]);
expect(mtrx.shape([
[0, 0],
[0, 0],
])).toEqual([2, 2]);
expect(mtrx.shape([
[0, 0, 0],
[0, 0, 0],
])).toEqual([2, 3]);
expect(mtrx.shape([
[0, 0],
[0, 0],
[0, 0],
])).toEqual([3, 2]);
expect(mtrx.shape([
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
])).toEqual([3, 3]);
expect(mtrx.shape([
[0],
[0],
[0],
])).toEqual([3, 1]);
expect(mtrx.shape([
[[0], [0], [0]],
[[0], [0], [0]],
[[0], [0], [0]],
])).toEqual([3, 3, 1]);
expect(mtrx.shape([
[[0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0]],
])).toEqual([3, 3, 3]);
});
it('should generate the matrix of zeros', () => {
expect(mtrx.zeros([1, 0])).toEqual([
[],
]);
expect(mtrx.zeros([1, 1])).toEqual([
[0],
]);
expect(mtrx.zeros([1, 3])).toEqual([
[0, 0, 0],
]);
expect(mtrx.zeros([3, 3])).toEqual([
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
]);
expect(mtrx.zeros([3, 3, 1])).toEqual([
[[0], [0], [0]],
[[0], [0], [0]],
[[0], [0], [0]],
]);
});
it('should generate the matrix with custom values', () => {
expect(mtrx.generate([1, 0], () => 1)).toEqual([
[],
]);
expect(mtrx.generate([1, 1], () => 1)).toEqual([
[1],
]);
expect(mtrx.generate([1, 3], () => 1)).toEqual([
[1, 1, 1],
]);
expect(mtrx.generate([3, 3], () => 1)).toEqual([
[1, 1, 1],
[1, 1, 1],
[1, 1, 1],
]);
expect(mtrx.generate([3, 3, 1], () => 1)).toEqual([
[[1], [1], [1]],
[[1], [1], [1]],
[[1], [1], [1]],
]);
});
it('should generate a custom matrix based on specific cell indices', () => {
const indicesCallback = jest.fn((indices) => {
return indices[0] * 10 + indices[1];
});
const m = mtrx.generate([3, 3], indicesCallback);
expect(indicesCallback).toHaveBeenCalledTimes(3 * 3);
expect(indicesCallback.mock.calls[0][0]).toEqual([0, 0]);
expect(indicesCallback.mock.calls[1][0]).toEqual([0, 1]);
expect(indicesCallback.mock.calls[2][0]).toEqual([0, 2]);
expect(indicesCallback.mock.calls[3][0]).toEqual([1, 0]);
expect(indicesCallback.mock.calls[4][0]).toEqual([1, 1]);
expect(indicesCallback.mock.calls[5][0]).toEqual([1, 2]);
expect(indicesCallback.mock.calls[6][0]).toEqual([2, 0]);
expect(indicesCallback.mock.calls[7][0]).toEqual([2, 1]);
expect(indicesCallback.mock.calls[8][0]).toEqual([2, 2]);
expect(m).toEqual([
[0, 1, 2],
[10, 11, 12],
[20, 21, 22],
]);
});
it('should multiply two matrices', () => {
let c;
c = mtrx.dot(
[
[1, 2],
[3, 4],
],
[
[5, 6],
[7, 8],
],
);
expect(mtrx.shape(c)).toEqual([2, 2]);
expect(c).toEqual([
[19, 22],
[43, 50],
]);
c = mtrx.dot(
[
[1, 2],
[3, 4],
],
[
[5],
[6],
],
);
expect(mtrx.shape(c)).toEqual([2, 1]);
expect(c).toEqual([
[17],
[39],
]);
c = mtrx.dot(
[
[1, 2, 3],
[4, 5, 6],
],
[
[7, 8],
[9, 10],
[11, 12],
],
);
expect(mtrx.shape(c)).toEqual([2, 2]);
expect(c).toEqual([
[58, 64],
[139, 154],
]);
c = mtrx.dot(
[
[3, 4, 2],
],
[
[13, 9, 7, 5],
[8, 7, 4, 6],
[6, 4, 0, 3],
],
);
expect(mtrx.shape(c)).toEqual([1, 4]);
expect(c).toEqual([
[83, 63, 37, 45],
]);
});
it('should transpose matrices', () => {
expect(mtrx.t([[1, 2, 3]])).toEqual([
[1],
[2],
[3],
]);
expect(mtrx.t([
[1],
[2],
[3],
])).toEqual([
[1, 2, 3],
]);
expect(mtrx.t([
[1, 2, 3],
[4, 5, 6],
])).toEqual([
[1, 4],
[2, 5],
[3, 6],
]);
expect(mtrx.t([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
])).toEqual([
[1, 4, 7],
[2, 5, 8],
[3, 6, 9],
]);
});
it('should throw when trying to transpose non 2D matrix', () => {
expect(() => {
mtrx.t([[[1]]]);
}).toThrowError('Matrix is not of 2D shape');
});
it('should add two matrices', () => {
expect(mtrx.add([[1]], [[2]])).toEqual([[3]]);
expect(mtrx.add(
[[1, 2, 3]],
[[4, 5, 6]],
))
.toEqual(
[[5, 7, 9]],
);
expect(mtrx.add(
[[1], [2], [3]],
[[4], [5], [6]],
))
.toEqual(
[[5], [7], [9]],
);
expect(mtrx.add(
[
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
],
[
[10, 11, 12],
[13, 14, 15],
[16, 17, 18],
],
))
.toEqual(
[
[11, 13, 15],
[17, 19, 21],
[23, 25, 27],
],
);
expect(mtrx.add(
[
[[1], [2], [3]],
[[4], [5], [6]],
[[7], [8], [9]],
],
[
[[10], [11], [12]],
[[13], [14], [15]],
[[16], [17], [18]],
],
))
.toEqual(
[
[[11], [13], [15]],
[[17], [19], [21]],
[[23], [25], [27]],
],
);
});
it('should throw when trying to add matrices of different shape', () => {
expect(() => mtrx.add([[0]], [[[0]]])).toThrowError(
'Matrices have different dimensions',
);
expect(() => mtrx.add([[0]], [[0, 0]])).toThrowError(
'Matrices have different shapes',
);
});
it('should do element wise multiplication two matrices', () => {
expect(mtrx.mul([[2]], [[3]])).toEqual([[6]]);
expect(mtrx.mul(
[[1, 2, 3]],
[[4, 5, 6]],
))
.toEqual(
[[4, 10, 18]],
);
expect(mtrx.mul(
[[1], [2], [3]],
[[4], [5], [6]],
))
.toEqual(
[[4], [10], [18]],
);
expect(mtrx.mul(
[
[1, 2],
[3, 4],
],
[
[5, 6],
[7, 8],
],
))
.toEqual(
[
[5, 12],
[21, 32],
],
);
expect(mtrx.mul(
[
[[1], [2]],
[[3], [4]],
],
[
[[5], [6]],
[[7], [8]],
],
))
.toEqual(
[
[[5], [12]],
[[21], [32]],
],
);
});
it('should throw when trying to multiply matrices element-wise of different shape', () => {
expect(() => mtrx.mul([[0]], [[[0]]])).toThrowError(
'Matrices have different dimensions',
);
expect(() => mtrx.mul([[0]], [[0, 0]])).toThrowError(
'Matrices have different shapes',
);
});
it('should do element wise subtraction two matrices', () => {
expect(mtrx.sub([[3]], [[2]])).toEqual([[1]]);
expect(mtrx.sub(
[[10, 12, 14]],
[[4, 5, 6]],
))
.toEqual(
[[6, 7, 8]],
);
expect(mtrx.sub(
[[[10], [12], [14]]],
[[[4], [5], [6]]],
))
.toEqual(
[[[6], [7], [8]]],
);
expect(mtrx.sub(
[
[10, 20],
[30, 40],
],
[
[5, 6],
[7, 8],
],
))
.toEqual(
[
[5, 14],
[23, 32],
],
);
expect(mtrx.sub(
[
[[10], [20]],
[[30], [40]],
],
[
[[5], [6]],
[[7], [8]],
],
))
.toEqual(
[
[[5], [14]],
[[23], [32]],
],
);
});
it('should throw when trying to subtract matrices element-wise of different shape', () => {
expect(() => mtrx.sub([[0]], [[[0]]])).toThrowError(
'Matrices have different dimensions',
);
expect(() => mtrx.sub([[0]], [[0, 0]])).toThrowError(
'Matrices have different shapes',
);
});
});