From f6680b411a3bdad427b1b26af2e9cc7ff2b44127 Mon Sep 17 00:00:00 2001 From: rnd-debug Date: Sat, 10 Oct 2020 07:57:53 +0200 Subject: [PATCH 1/5] emplementing rotate(w, theta) --- src/expression/embeddedDocs/embeddedDocs.js | 2 + .../embeddedDocs/function/matrix/rotate.js | 19 ++ src/factoriesAny.js | 1 + src/function/matrix/rotate.js | 80 ++++++++ src/function/matrix/rotationMatrix.js | 4 +- .../unit-tests/function/matrix/rotate.test.js | 177 ++++++++++++++++++ .../function/matrix/rotationMatrix.test.js | 2 +- 7 files changed, 282 insertions(+), 3 deletions(-) create mode 100644 src/expression/embeddedDocs/function/matrix/rotate.js create mode 100644 src/function/matrix/rotate.js create mode 100644 test/unit-tests/function/matrix/rotate.test.js diff --git a/src/expression/embeddedDocs/embeddedDocs.js b/src/expression/embeddedDocs/embeddedDocs.js index b787b41ece..cde0369da2 100644 --- a/src/expression/embeddedDocs/embeddedDocs.js +++ b/src/expression/embeddedDocs/embeddedDocs.js @@ -215,6 +215,7 @@ import { numericDocs } from './function/utils/numeric' import { columnDocs } from './function/matrix/column' import { rowDocs } from './function/matrix/row' import { rotationMatrixDocs } from './function/matrix/rotationMatrix' +import { rotateDocs } from './function/matrix/rotate' export const embeddedDocs = { @@ -427,6 +428,7 @@ export const embeddedDocs = { range: rangeDocs, resize: resizeDocs, reshape: reshapeDocs, + rotate: rotateDocs, rotationMatrix: rotationMatrixDocs, row: rowDocs, size: sizeDocs, diff --git a/src/expression/embeddedDocs/function/matrix/rotate.js b/src/expression/embeddedDocs/function/matrix/rotate.js new file mode 100644 index 0000000000..049965ec13 --- /dev/null +++ b/src/expression/embeddedDocs/function/matrix/rotate.js @@ -0,0 +1,19 @@ +export const rotateDocs = { + name: 'rotate', + category: 'Matrix', + syntax: [ + 'rotate(w, theta)', + 'rotate(w, theta, v)' + ], + description: 'Returns a 2-D rotation matrix (2x2) for a given angle (in radians). ' + + 'Returns a 2-D rotation matrix (3x3) of a given angle (in radians) around given axis.', + examples: [ + 'rotate([1, 0], math.pi / 2)', + 'rotate(matrix([1, 0]), unit("35deg"))', + 'rotate([1, 0, 0], unit("90deg"), [0, 0, 1])', + 'rotate(matrix([1, 0, 0]), unit("90deg"), matrix([0, 0, 1]))' + ], + seealso: [ + 'matrix', 'rotationMatrix' + ] +} diff --git a/src/factoriesAny.js b/src/factoriesAny.js index 7464c47eda..4f4cef2f01 100644 --- a/src/factoriesAny.js +++ b/src/factoriesAny.js @@ -78,6 +78,7 @@ export { createOnes } from './function/matrix/ones' export { createRange } from './function/matrix/range' export { createReshape } from './function/matrix/reshape' export { createResize } from './function/matrix/resize' +export { createRotate } from './function/matrix/rotate' export { createRotationMatrix } from './function/matrix/rotationMatrix' export { createRow } from './function/matrix/row' export { createSize } from './function/matrix/size' diff --git a/src/function/matrix/rotate.js b/src/function/matrix/rotate.js new file mode 100644 index 0000000000..29b4d6838a --- /dev/null +++ b/src/function/matrix/rotate.js @@ -0,0 +1,80 @@ +// import { isBigNumber } from '../../utils/is' +import { factory } from '../../utils/factory' + +const name = 'rotate' +const dependencies = [ + 'typed', + 'config', + 'multiply', + 'rotationMatrix' +] + +export const createRotate = /* #__PURE__ */ factory(name, dependencies, ( + { + typed, config, multiply, rotationMatrix + }) => { + /** + * Rotate a vector of size 1x2 counter-clockwise by a given angle + * Rotate a vector of size 1x3 counter-clockwise by a given angle around the given axis + * + * Syntax: + * + * math.rotate(w, theta) + * math.rotate(w, theta, v) + * + * Examples: + * + * math.rotate([11, 12], math.pi / 2) // returns matrix([-12, 11]) + * math.rotate(matrix([11, 12]), math.pi / 2) // returns matrix([-12, 11]) + * + * math.rotate([1, 0, 0], unit('90deg'), [0, 0, 1]) // returns matrix([0, 1, 0]) + * math.rotate(matrix([1, 0, 0]), unit('90deg'), [0, 0, 1]) // returns matrix([0, 1, 0]) + * + * math.rotate([1, 0], math.complex(1 + i)) // returns matrix([cos(1 + i) - sin(1 + i), sin(1 + i) + cos(1 + i)]) + * + * See also: + * + * matrix, rotationMatrix + * + * @param {Array | Matrix} w Vector to rotate + * @param {number | BigNumber | Complex | Unit} theta Rotation angle + * @param {Array | Matrix} [v] Rotation axis + * @return {Array | Matrix} Multiplication of the rotation matrix and w + */ + return typed(name, { + 'Array , number | BigNumber | Complex | Unit': function (w, theta) { + _validateArraySize(w, 2) + const matrixRes = multiply(rotationMatrix(theta), w) + return config.predictable ? matrixRes.toArray() : matrixRes + }, + + 'Matrix , number | BigNumber | Complex | Unit': function (w, theta) { + _validateVectorSize(w, 2) + return multiply(rotationMatrix(theta), w) + }, + + 'Array , number | BigNumber | Complex | Unit, Array | Matrix': function (w, theta, v) { + _validateArraySize(w, 3) + const matrixRes = multiply(rotationMatrix(theta, v), w) + return config.predictable ? matrixRes.toArray() : matrixRes + }, + + 'Matrix, number | BigNumber | Complex | Unit, Array | Matrix': function (w, theta, v) { + _validateVectorSize(w, 3) + return multiply(rotationMatrix(theta, v), w) + } + }) + + function _validateVectorSize (v, vSize) { + const size = v.size() + if (size.length < 1 || size[0] !== vSize) { + throw new RangeError(`Vector must be of dimensions 1x${vSize}`) + } + } + + function _validateArraySize (v, vSize) { + if (v.length !== vSize) { + throw new RangeError(`Vector must be of dimensions 1x${vSize}`) + } + } +}) diff --git a/src/function/matrix/rotationMatrix.js b/src/function/matrix/rotationMatrix.js index 09508e4d7c..cc357e1696 100644 --- a/src/function/matrix/rotationMatrix.js +++ b/src/function/matrix/rotationMatrix.js @@ -37,7 +37,7 @@ export const createRotationMatrix = /* #__PURE__ */ factory(name, dependencies, * Examples: * * math.rotationMatrix(math.pi / 2) // returns [[0, -1], [1, 0]] - * math.rotationMatrix(math.bignumber(45)) // returns [[ bignumber(1 / sqrt(2)), - bignumber(1 / sqrt(2))], [ bignumber(1 / sqrt(2)), bignumber(1 / sqrt(2))]] + * math.rotationMatrix(math.bignumber(1)) // returns [[bignumber(cos(1)), bignumber(-sin(1))], [bignumber(sin(1)), bignumber(cos(1))]] * math.rotationMatrix(math.complex(1 + i)) // returns [[cos(1 + i), -sin(1 + i)], [sin(1 + i), cos(1 + i)]] * math.rotationMatrix(math.unit('1rad')) // returns [[cos(1), -sin(1)], [sin(1), cos(1)]] * @@ -152,7 +152,7 @@ export const createRotationMatrix = /* #__PURE__ */ factory(name, dependencies, function _rotationMatrix3x3 (theta, v, format) { const normV = norm(v) if (normV === 0) { - return _convertToFormat([], format) + throw new RangeError('Rotation around zero vector') } const Big = isBigNumber(theta) ? BigNumber : null diff --git a/test/unit-tests/function/matrix/rotate.test.js b/test/unit-tests/function/matrix/rotate.test.js new file mode 100644 index 0000000000..7884a85fe8 --- /dev/null +++ b/test/unit-tests/function/matrix/rotate.test.js @@ -0,0 +1,177 @@ +import assert from 'assert' +import approx from '../../../../tools/approx' + +import math from '../../../../src/bundleAny' + +const unit = math.unit +const complex = math.complex +const cos = math.cos +const sin = math.sin +const add = math.add +const multiply = math.multiply +const matrix = math.matrix +const rotate = math.rotate + +describe('rotationMatrix', function () { + it('should return a rotated 1x2 vector when it is provided as array', function () { + assert.deepStrictEqual(rotate([1, 0], 0), matrix([1, 0])) + + assert.deepStrictEqual(rotate([100, 0], 1), matrix([100 * cos(1), 100 * sin(1)])) + assert.deepStrictEqual(rotate([2, 3], 2), matrix([2 * cos(2) - 3 * sin(2), 2 * sin(2) + 3 * cos(2)])) + + const cos45 = cos(unit('45deg')) + const sin45 = sin(unit('45deg')) + assert.deepStrictEqual(rotate([4, 5], unit('45deg')), matrix([4 * cos45 - 5 * sin45, + 4 * cos45 + 5 * sin45])) + + const reCos = 4.18962569096881 + const imCos = 9.10922789375534 + const reSin = 9.15449914691142 + const imSin = 4.16890695996656 + const cosComplex = complex(-reCos, -imCos) + const sinComplex = complex(reSin, -imSin) + approx.deepEqual(rotate([1, 1], complex('2+3i')), + matrix([add(cosComplex, multiply(-1.0, sinComplex)), add(cosComplex, sinComplex)])) + }) + + it('should return a rotated 1x2 vector when it is provided as matrix', function () { + assert.deepStrictEqual(rotate(matrix([100, 200]), 0), matrix([100, 200])) + + assert.deepStrictEqual(rotate(matrix([100, 0]), 1), matrix([100 * cos(1), 100 * sin(1)])) + assert.deepStrictEqual(rotate(matrix([2, 3]), 2), matrix([2 * cos(2) - 3 * sin(2), 2 * sin(2) + 3 * cos(2)])) + + const cos45 = cos(unit('45deg')) + const sin45 = sin(unit('45deg')) + assert.deepStrictEqual(rotate(matrix([4, 5]), unit('45deg')), matrix([4 * cos45 - 5 * sin45, + 4 * cos45 + 5 * sin45])) + + const reCos = 4.18962569096881 + const imCos = 9.10922789375534 + const reSin = 9.15449914691142 + const imSin = 4.16890695996656 + const cosComplex = complex(-reCos, -imCos) + const sinComplex = complex(reSin, -imSin) + approx.deepEqual(rotate(matrix([1, 1]), complex('2+3i')), + matrix([add(cosComplex, multiply(-1.0, sinComplex)), add(cosComplex, sinComplex)])) + }) + + it('should return a rotated 1x2 bignumber vector', function () { + const bigmath = math.create({ number: 'BigNumber' }) + const minusOne = bigmath.bignumber(-1) + const cos1 = bigmath.cos(bigmath.bignumber(1)) + const sin1 = bigmath.sin(bigmath.bignumber(1)) + const minusSin1 = bigmath.multiply(sin1, minusOne) + const big2 = bigmath.bignumber(2) + const big3 = bigmath.bignumber(3) + assert.deepStrictEqual(bigmath.rotate([big2, big3], bigmath.bignumber(1)), + bigmath.matrix([add(cos1.times(big2), minusSin1.times(big3)), add(sin1.times(big2), cos1.times(big3))])) + }) + + it('should return a rotated 1x3 vector when it is provided as an array', function () { + assert.deepStrictEqual(rotate([11, 12, 13], 0.7, [0, 0, 1]), + matrix([11 * cos(0.7) - 12 * sin(0.7), 11 * sin(0.7) + 12 * cos(0.7), 13])) + assert.deepStrictEqual(rotate([11, 12, 13], 0.7, [0, 1, 0]), + matrix([11 * cos(0.7) + 13 * sin(0.7), 12, -11 * sin(0.7) + 13 * cos(0.7)])) + assert.deepStrictEqual(rotate([11, 12, 13], 0.7, [1, 0, 0]), + matrix([11, 12 * cos(0.7) - 13 * sin(0.7), 12 * sin(0.7) + 13 * cos(0.7)])) + + const cos30 = cos(unit('30deg')) + const sin30 = sin(unit('30deg')) + assert.deepStrictEqual(rotate([11, 12, 13], unit('30deg'), [1, 0, 0]), + matrix([11, 12 * cos30 - 13 * sin30, 12 * sin30 + 13 * cos30])) + + const reCos = 4.18962569096881 + const imCos = 9.10922789375534 + const reSin = 9.15449914691142 + const imSin = 4.16890695996656 + const cosComplex = complex(-reCos, -imCos) + const sinComplex = complex(reSin, -imSin) + approx.deepEqual(rotate([11, 12, 13], complex('2+3i'), [0, 0, 1]), + matrix([add(multiply(11, cosComplex), multiply(-12.0, sinComplex)), + add(multiply(11, sinComplex), multiply(12, cosComplex)), + 13])) + }) + + it('should return a rotated 1x3 vector when it is provided as matrix', function () { + assert.deepStrictEqual(rotate(matrix([11, 12, 13]), 0.7, [0, 0, 1]), + matrix([11 * cos(0.7) - 12 * sin(0.7), 11 * sin(0.7) + 12 * cos(0.7), 13])) + assert.deepStrictEqual(rotate(matrix([11, 12, 13]), 0.7, [0, 1, 0]), + matrix([11 * cos(0.7) + 13 * sin(0.7), 12, -11 * sin(0.7) + 13 * cos(0.7)])) + assert.deepStrictEqual(rotate(matrix([11, 12, 13]), 0.7, [1, 0, 0]), + matrix([11, 12 * cos(0.7) - 13 * sin(0.7), 12 * sin(0.7) + 13 * cos(0.7)])) + + const cos30 = cos(unit('30deg')) + const sin30 = sin(unit('30deg')) + assert.deepStrictEqual(rotate(matrix([11, 12, 13]), unit('30deg'), [1, 0, 0]), + matrix([11, 12 * cos30 - 13 * sin30, 12 * sin30 + 13 * cos30])) + + const reCos = 4.18962569096881 + const imCos = 9.10922789375534 + const reSin = 9.15449914691142 + const imSin = 4.16890695996656 + const cosComplex = complex(-reCos, -imCos) + const sinComplex = complex(reSin, -imSin) + approx.deepEqual(rotate(matrix([11, 12, 13]), complex('2+3i'), [0, 0, 1]), + matrix([add(multiply(11, cosComplex), multiply(-12.0, sinComplex)), + add(multiply(11, sinComplex), multiply(12, cosComplex)), + 13])) + }) + + it('should return a rotated 1x3 bignumber vector', function () { + const bigmath = math.create({ number: 'BigNumber' }) + const minusOne = bigmath.bignumber(-1) + const cos1 = bigmath.cos(bigmath.bignumber(1)) + const sin1 = bigmath.sin(bigmath.bignumber(1)) + const minusSin1 = bigmath.multiply(sin1, minusOne) + const big2 = bigmath.bignumber(2) + const big3 = bigmath.bignumber(3) + const big4 = bigmath.bignumber(4) + assert.deepStrictEqual(bigmath.rotate([big2, big3, big4], bigmath.bignumber(1), [0, 0, 1]), + bigmath.matrix([add(cos1.times(big2), minusSin1.times(big3)), add(sin1.times(big2), cos1.times(big3)), big4])) + }) + + it('should return an object of predictable type', function () { + const predictableMath = math.create({ predictable: true }) + assert.deepStrictEqual(predictableMath.rotate([1, 0], 1), [cos(1), sin(1)]) + assert.deepStrictEqual(predictableMath.rotate([1, 0, 0], -1, [0, 0, 1]), [cos(-1), sin(-1), 0]) + + assert.deepStrictEqual(predictableMath.rotate(matrix([1, 0]), 1), + predictableMath.matrix([cos(1), sin(1)])) + assert.deepStrictEqual(predictableMath.rotate(matrix([1, 0, 0]), -1, [0, 0, 1]), + predictableMath.matrix([cos(-1), sin(-1), 0])) + }) + + it('should return a rotated 1x3 vector as sparse matrix', function () { + const expectedX = 4 * cos(unit('-90deg')) - 5 * sin(unit('-90deg')) + const expectedY = 4 * sin(unit('-90deg')) + 5 * cos(unit('-90deg')) + assert.deepStrictEqual(rotate(matrix([4, 5], 'sparse'), unit('-90deg')), matrix([expectedX, expectedY], 'sparse')) + }) + + it('should throw an error with invalid number of arguments', function () { + assert.throws(function () { rotate() }, /TypeError: Too few arguments/) + assert.throws(function () { rotate(1) }, /TypeError: Unexpected type of argument/) + assert.throws(function () { rotate([], null) }, /TypeError: Unexpected type of argument/) + assert.throws(function () { rotate([], 1, [], 2) }, /TypeError: Too many arguments/) + }) + + it('should throw an error with invalid type of arguments', function () { + assert.throws(function () { rotate(1) }, /TypeError: Unexpected type of argument/) + assert.throws(function () { rotate([], 1, [], 2) }, /TypeError: Too many arguments/) + + assert.throws(function () { rotate([1, 0], math.pi / 2, [0, 0, 1]) }, /RangeError: Vector must be of dimensions 1x3/) + assert.throws(function () { rotate(matrix([1, 0]), math.pi / 2, [0, 0, 1]) }, /RangeError: Vector must be of dimensions 1x3/) + assert.throws(function () { rotate([1, 0, 0, 0], math.pi / 2, [0, 0, 1]) }, /RangeError: Vector must be of dimensions 1x3/) + assert.throws(function () { rotate(matrix([1, 0, 0, 0]), math.pi / 2, [0, 0, 1]) }, /RangeError: Vector must be of dimensions 1x3/) + + assert.throws(function () { rotate([1, 0, 0], 1, [0.0, 0.0, 0.0]) }, /Rotation around zero vector/) + }) + + it('should LaTeX rotationMatrix', function () { + const expression1 = math.parse('rotate([1, 2, 3], 1)') + assert.strictEqual(expression1.toTex(), '\\mathrm{rotate}\\left(\\begin{bmatrix}1\\\\2\\\\3\\\\\\end{bmatrix},1\\right)') + + const expression2 = math.parse('rotate([1, 2, 3], 1, [4, 5, 6])') + assert.strictEqual(expression2.toTex(), '\\mathrm{rotate}\\left(\\begin{bmatrix}1\\\\2\\\\3\\\\\\end{bmatrix},1,' + + '\\begin{bmatrix}4\\\\5\\\\6\\\\\\end{bmatrix}\\right)') + }) +}) diff --git a/test/unit-tests/function/matrix/rotationMatrix.test.js b/test/unit-tests/function/matrix/rotationMatrix.test.js index 5fd9ab8577..5b31c6908f 100644 --- a/test/unit-tests/function/matrix/rotationMatrix.test.js +++ b/test/unit-tests/function/matrix/rotationMatrix.test.js @@ -17,7 +17,6 @@ describe('rotationMatrix', function () { it('should create an empty matrix', function () { assert.deepStrictEqual(rotationMatrix(), matrix()) - assert.deepStrictEqual(rotationMatrix(1, [0.0, 0.0, 0.0]), matrix()) assert.deepStrictEqual(rotationMatrix('sparse'), matrix('sparse')) assert.deepStrictEqual(rotationMatrix('dense'), matrix('dense')) @@ -243,6 +242,7 @@ describe('rotationMatrix', function () { assert.throws(function () { rotationMatrix(0, [0, 1]) }, /RangeError: Vector must be of dimensions 1x3/) assert.throws(function () { rotationMatrix(0, [0, 1, 0], 'something') }, /TypeError: Unknown matrix type/) assert.throws(function () { rotationMatrix(0, [0, 1, 0], 'sparse', 4) }, /TypeError: Too many arguments/) + assert.throws(function () { rotationMatrix(1, [0.0, 0.0, 0.0]) }, /Rotation around zero vector/) }) it('should LaTeX rotationMatrix', function () { From 4e7d25d3228f5a23d210d330260a89fc113a318c Mon Sep 17 00:00:00 2001 From: rnd-debug Date: Sun, 18 Oct 2020 18:40:31 +0200 Subject: [PATCH 2/5] will return same type as input --- src/function/matrix/rotate.js | 33 +++++++---------- .../unit-tests/function/matrix/rotate.test.js | 36 +++++++++++-------- 2 files changed, 35 insertions(+), 34 deletions(-) diff --git a/src/function/matrix/rotate.js b/src/function/matrix/rotate.js index 29b4d6838a..b8ccd0c11f 100644 --- a/src/function/matrix/rotate.js +++ b/src/function/matrix/rotate.js @@ -1,17 +1,16 @@ -// import { isBigNumber } from '../../utils/is' import { factory } from '../../utils/factory' +import { arraySize } from '../../utils/array' const name = 'rotate' const dependencies = [ 'typed', - 'config', 'multiply', 'rotationMatrix' ] export const createRotate = /* #__PURE__ */ factory(name, dependencies, ( { - typed, config, multiply, rotationMatrix + typed, multiply, rotationMatrix }) => { /** * Rotate a vector of size 1x2 counter-clockwise by a given angle @@ -43,38 +42,32 @@ export const createRotate = /* #__PURE__ */ factory(name, dependencies, ( */ return typed(name, { 'Array , number | BigNumber | Complex | Unit': function (w, theta) { - _validateArraySize(w, 2) + _validateSize(w, 2) const matrixRes = multiply(rotationMatrix(theta), w) - return config.predictable ? matrixRes.toArray() : matrixRes + return matrixRes.toArray() }, 'Matrix , number | BigNumber | Complex | Unit': function (w, theta) { - _validateVectorSize(w, 2) + _validateSize(w, 2) return multiply(rotationMatrix(theta), w) }, - 'Array , number | BigNumber | Complex | Unit, Array | Matrix': function (w, theta, v) { - _validateArraySize(w, 3) + 'Array, number | BigNumber | Complex | Unit, Array | Matrix': function (w, theta, v) { + _validateSize(w, 3) const matrixRes = multiply(rotationMatrix(theta, v), w) - return config.predictable ? matrixRes.toArray() : matrixRes + return matrixRes.toArray() }, 'Matrix, number | BigNumber | Complex | Unit, Array | Matrix': function (w, theta, v) { - _validateVectorSize(w, 3) + _validateSize(w, 3) return multiply(rotationMatrix(theta, v), w) } }) - function _validateVectorSize (v, vSize) { - const size = v.size() - if (size.length < 1 || size[0] !== vSize) { - throw new RangeError(`Vector must be of dimensions 1x${vSize}`) - } - } - - function _validateArraySize (v, vSize) { - if (v.length !== vSize) { - throw new RangeError(`Vector must be of dimensions 1x${vSize}`) + function _validateSize (v, expectedSize) { + const actualSize = Array.isArray(v) ? arraySize(v) : v.size() + if (actualSize[0] !== expectedSize) { + throw new RangeError(`Vector must be of dimensions 1x${expectedSize}`) } } }) diff --git a/test/unit-tests/function/matrix/rotate.test.js b/test/unit-tests/function/matrix/rotate.test.js index 7884a85fe8..9655a062ec 100644 --- a/test/unit-tests/function/matrix/rotate.test.js +++ b/test/unit-tests/function/matrix/rotate.test.js @@ -14,15 +14,15 @@ const rotate = math.rotate describe('rotationMatrix', function () { it('should return a rotated 1x2 vector when it is provided as array', function () { - assert.deepStrictEqual(rotate([1, 0], 0), matrix([1, 0])) + assert.deepStrictEqual(rotate([1, 0], 0), [1, 0]) - assert.deepStrictEqual(rotate([100, 0], 1), matrix([100 * cos(1), 100 * sin(1)])) - assert.deepStrictEqual(rotate([2, 3], 2), matrix([2 * cos(2) - 3 * sin(2), 2 * sin(2) + 3 * cos(2)])) + assert.deepStrictEqual(rotate([100, 0], 1), [100 * cos(1), 100 * sin(1)]) + assert.deepStrictEqual(rotate([2, 3], 2), [2 * cos(2) - 3 * sin(2), 2 * sin(2) + 3 * cos(2)]) const cos45 = cos(unit('45deg')) const sin45 = sin(unit('45deg')) - assert.deepStrictEqual(rotate([4, 5], unit('45deg')), matrix([4 * cos45 - 5 * sin45, - 4 * cos45 + 5 * sin45])) + assert.deepStrictEqual(rotate([4, 5], unit('45deg')), [4 * cos45 - 5 * sin45, + 4 * cos45 + 5 * sin45]) const reCos = 4.18962569096881 const imCos = 9.10922789375534 @@ -31,7 +31,7 @@ describe('rotationMatrix', function () { const cosComplex = complex(-reCos, -imCos) const sinComplex = complex(reSin, -imSin) approx.deepEqual(rotate([1, 1], complex('2+3i')), - matrix([add(cosComplex, multiply(-1.0, sinComplex)), add(cosComplex, sinComplex)])) + [add(cosComplex, multiply(-1.0, sinComplex)), add(cosComplex, sinComplex)]) }) it('should return a rotated 1x2 vector when it is provided as matrix', function () { @@ -64,21 +64,25 @@ describe('rotationMatrix', function () { const big2 = bigmath.bignumber(2) const big3 = bigmath.bignumber(3) assert.deepStrictEqual(bigmath.rotate([big2, big3], bigmath.bignumber(1)), - bigmath.matrix([add(cos1.times(big2), minusSin1.times(big3)), add(sin1.times(big2), cos1.times(big3))])) + [add(cos1.times(big2), minusSin1.times(big3)), add(sin1.times(big2), cos1.times(big3))]) + + assert.deepStrictEqual(bigmath.rotate(bigmath.matrix([big2, big3]), bigmath.bignumber(1)), + bigmath.matrix([add(cos1.times(big2), minusSin1.times(big3)), + add(sin1.times(big2), cos1.times(big3))])) }) it('should return a rotated 1x3 vector when it is provided as an array', function () { assert.deepStrictEqual(rotate([11, 12, 13], 0.7, [0, 0, 1]), - matrix([11 * cos(0.7) - 12 * sin(0.7), 11 * sin(0.7) + 12 * cos(0.7), 13])) + [11 * cos(0.7) - 12 * sin(0.7), 11 * sin(0.7) + 12 * cos(0.7), 13]) assert.deepStrictEqual(rotate([11, 12, 13], 0.7, [0, 1, 0]), - matrix([11 * cos(0.7) + 13 * sin(0.7), 12, -11 * sin(0.7) + 13 * cos(0.7)])) + [11 * cos(0.7) + 13 * sin(0.7), 12, -11 * sin(0.7) + 13 * cos(0.7)]) assert.deepStrictEqual(rotate([11, 12, 13], 0.7, [1, 0, 0]), - matrix([11, 12 * cos(0.7) - 13 * sin(0.7), 12 * sin(0.7) + 13 * cos(0.7)])) + [11, 12 * cos(0.7) - 13 * sin(0.7), 12 * sin(0.7) + 13 * cos(0.7)]) const cos30 = cos(unit('30deg')) const sin30 = sin(unit('30deg')) assert.deepStrictEqual(rotate([11, 12, 13], unit('30deg'), [1, 0, 0]), - matrix([11, 12 * cos30 - 13 * sin30, 12 * sin30 + 13 * cos30])) + [11, 12 * cos30 - 13 * sin30, 12 * sin30 + 13 * cos30]) const reCos = 4.18962569096881 const imCos = 9.10922789375534 @@ -87,9 +91,9 @@ describe('rotationMatrix', function () { const cosComplex = complex(-reCos, -imCos) const sinComplex = complex(reSin, -imSin) approx.deepEqual(rotate([11, 12, 13], complex('2+3i'), [0, 0, 1]), - matrix([add(multiply(11, cosComplex), multiply(-12.0, sinComplex)), + [add(multiply(11, cosComplex), multiply(-12.0, sinComplex)), add(multiply(11, sinComplex), multiply(12, cosComplex)), - 13])) + 13]) }) it('should return a rotated 1x3 vector when it is provided as matrix', function () { @@ -127,7 +131,11 @@ describe('rotationMatrix', function () { const big3 = bigmath.bignumber(3) const big4 = bigmath.bignumber(4) assert.deepStrictEqual(bigmath.rotate([big2, big3, big4], bigmath.bignumber(1), [0, 0, 1]), - bigmath.matrix([add(cos1.times(big2), minusSin1.times(big3)), add(sin1.times(big2), cos1.times(big3)), big4])) + [add(cos1.times(big2), minusSin1.times(big3)), add(sin1.times(big2), cos1.times(big3)), big4]) + + assert.deepStrictEqual(bigmath.rotate(bigmath.matrix([big2, big3, big4]), bigmath.bignumber(1), [0, 0, 1]), + bigmath.matrix([add(cos1.times(big2), minusSin1.times(big3)), + add(sin1.times(big2), cos1.times(big3)), big4])) }) it('should return an object of predictable type', function () { From 9f2991470c4150129c07d482d84ab3421481d72d Mon Sep 17 00:00:00 2001 From: rnd-debug Date: Sun, 18 Oct 2020 18:53:54 +0200 Subject: [PATCH 3/5] edge cases arraySize --- src/function/matrix/rotate.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/function/matrix/rotate.js b/src/function/matrix/rotate.js index b8ccd0c11f..4751af0ea8 100644 --- a/src/function/matrix/rotate.js +++ b/src/function/matrix/rotate.js @@ -66,6 +66,12 @@ export const createRotate = /* #__PURE__ */ factory(name, dependencies, ( function _validateSize (v, expectedSize) { const actualSize = Array.isArray(v) ? arraySize(v) : v.size() + if (actualSize.length > 2) { + throw new RangeError(`Vector must be of dimensions 1x${expectedSize}`) + } + if (actualSize.length === 2 && actualSize[1] !== 1) { + throw new RangeError(`Vector must be of dimensions 1x${expectedSize}`) + } if (actualSize[0] !== expectedSize) { throw new RangeError(`Vector must be of dimensions 1x${expectedSize}`) } From b5a15276d44c1c7293c5f9975c939bf27f9e9621 Mon Sep 17 00:00:00 2001 From: rnd-debug Date: Sun, 18 Oct 2020 20:28:21 +0200 Subject: [PATCH 4/5] rising coverage --- test/unit-tests/function/matrix/rotate.test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/unit-tests/function/matrix/rotate.test.js b/test/unit-tests/function/matrix/rotate.test.js index 9655a062ec..da47d55ef5 100644 --- a/test/unit-tests/function/matrix/rotate.test.js +++ b/test/unit-tests/function/matrix/rotate.test.js @@ -168,6 +168,8 @@ describe('rotationMatrix', function () { assert.throws(function () { rotate([1, 0], math.pi / 2, [0, 0, 1]) }, /RangeError: Vector must be of dimensions 1x3/) assert.throws(function () { rotate(matrix([1, 0]), math.pi / 2, [0, 0, 1]) }, /RangeError: Vector must be of dimensions 1x3/) + assert.throws(function () { rotate(matrix([[[1]], [[0]]]), math.pi / 2, [0, 0, 1]) }, /RangeError: Vector must be of dimensions 1x3/) + assert.throws(function () { rotate(matrix([[1, 0], [1, 0]]), math.pi / 2, [0, 0, 1]) }, /RangeError: Vector must be of dimensions 1x3/) assert.throws(function () { rotate([1, 0, 0, 0], math.pi / 2, [0, 0, 1]) }, /RangeError: Vector must be of dimensions 1x3/) assert.throws(function () { rotate(matrix([1, 0, 0, 0]), math.pi / 2, [0, 0, 1]) }, /RangeError: Vector must be of dimensions 1x3/) From 8dfcadb8c8805f53a79f3bc95c1593aac2bc2fd3 Mon Sep 17 00:00:00 2001 From: rnd-debug Date: Thu, 22 Oct 2020 19:32:29 +0200 Subject: [PATCH 5/5] making result type predictable --- src/function/matrix/rotate.js | 2 +- src/function/matrix/rotationMatrix.js | 5 +- .../unit-tests/function/matrix/rotate.test.js | 15 ++-- .../function/matrix/rotationMatrix.test.js | 76 ++++++++++--------- 4 files changed, 53 insertions(+), 45 deletions(-) diff --git a/src/function/matrix/rotate.js b/src/function/matrix/rotate.js index 4751af0ea8..9f5c4e7d3d 100644 --- a/src/function/matrix/rotate.js +++ b/src/function/matrix/rotate.js @@ -55,7 +55,7 @@ export const createRotate = /* #__PURE__ */ factory(name, dependencies, ( 'Array, number | BigNumber | Complex | Unit, Array | Matrix': function (w, theta, v) { _validateSize(w, 3) const matrixRes = multiply(rotationMatrix(theta, v), w) - return matrixRes.toArray() + return matrixRes }, 'Matrix, number | BigNumber | Complex | Unit, Array | Matrix': function (w, theta, v) { diff --git a/src/function/matrix/rotationMatrix.js b/src/function/matrix/rotationMatrix.js index cc357e1696..a32c9ab871 100644 --- a/src/function/matrix/rotationMatrix.js +++ b/src/function/matrix/rotationMatrix.js @@ -76,12 +76,13 @@ export const createRotationMatrix = /* #__PURE__ */ factory(name, dependencies, 'number | BigNumber | Complex | Unit, Array': function (theta, v) { const matrixV = matrix(v) _validateVector(matrixV) - return _rotationMatrix3x3(theta, matrixV, config.matrix === 'Matrix' ? 'dense' : undefined) + return _rotationMatrix3x3(theta, matrixV, undefined) }, 'number | BigNumber | Complex | Unit, Matrix': function (theta, v) { _validateVector(v) - return _rotationMatrix3x3(theta, v, config.matrix === 'Matrix' ? 'dense' : undefined) + const storageType = v.storage() || (config.matrix === 'Matrix' ? 'dense' : undefined) + return _rotationMatrix3x3(theta, v, storageType) }, 'number | BigNumber | Complex | Unit, Array, string': function (theta, v, format) { diff --git a/test/unit-tests/function/matrix/rotate.test.js b/test/unit-tests/function/matrix/rotate.test.js index da47d55ef5..6727907959 100644 --- a/test/unit-tests/function/matrix/rotate.test.js +++ b/test/unit-tests/function/matrix/rotate.test.js @@ -139,14 +139,13 @@ describe('rotationMatrix', function () { }) it('should return an object of predictable type', function () { - const predictableMath = math.create({ predictable: true }) - assert.deepStrictEqual(predictableMath.rotate([1, 0], 1), [cos(1), sin(1)]) - assert.deepStrictEqual(predictableMath.rotate([1, 0, 0], -1, [0, 0, 1]), [cos(-1), sin(-1), 0]) - - assert.deepStrictEqual(predictableMath.rotate(matrix([1, 0]), 1), - predictableMath.matrix([cos(1), sin(1)])) - assert.deepStrictEqual(predictableMath.rotate(matrix([1, 0, 0]), -1, [0, 0, 1]), - predictableMath.matrix([cos(-1), sin(-1), 0])) + assert.deepStrictEqual(rotate([1, 0], 1), [cos(1), sin(1)]) + assert.deepStrictEqual(rotate([1, 0, 0], -1, [0, 0, 1]), [cos(-1), sin(-1), 0]) + + assert.deepStrictEqual(rotate(matrix([1, 0]), 1), + matrix([cos(1), sin(1)])) + assert.deepStrictEqual(rotate(matrix([1, 0, 0]), -1, [0, 0, 1]), + matrix([cos(-1), sin(-1), 0])) }) it('should return a rotated 1x3 vector as sparse matrix', function () { diff --git a/test/unit-tests/function/matrix/rotationMatrix.test.js b/test/unit-tests/function/matrix/rotationMatrix.test.js index 5b31c6908f..51b2bc0885 100644 --- a/test/unit-tests/function/matrix/rotationMatrix.test.js +++ b/test/unit-tests/function/matrix/rotationMatrix.test.js @@ -31,6 +31,14 @@ describe('rotationMatrix', function () { approx.deepEqual(rotationMatrix(math.pi / 4), matrix([[sqrtTwoInv, -sqrtTwoInv], [sqrtTwoInv, sqrtTwoInv]])) }) + it('should return a 2D rotation array if requesting results as array', function () { + const mathArray = math.create({ matrix: 'Array' }) + approx.deepEqual(mathArray.rotationMatrix(0.0), [[1, 0.0], [0.0, 1]]) + approx.deepEqual(mathArray.rotationMatrix(mathArray.pi / 2), [[0.0, -1], [1, 0.0]]) + approx.deepEqual(mathArray.rotationMatrix(1), [[cos(1), -sin(1)], [sin(1), cos(1)]]) + approx.deepEqual(mathArray.rotationMatrix(mathArray.pi / 4), [[sqrtTwoInv, -sqrtTwoInv], [sqrtTwoInv, sqrtTwoInv]]) + }) + it('should create a 2D rotation matrix of given bignumber angle', function () { approx.deepEqual(rotationMatrix(bignumber(0.0)), matrix([[1, 0.0], [0.0, 1]])) @@ -79,23 +87,23 @@ describe('rotationMatrix', function () { approx.deepEqual(rotationMatrix(math.pi / 4, 'sparse'), matrix([[sqrtTwoInv, -sqrtTwoInv], [sqrtTwoInv, sqrtTwoInv]], 'sparse')) }) - it('should create a 3D rotation matrix by given angle around given axis', function () { - assert.deepStrictEqual(math.rotationMatrix(0.0, [1, 1, 1]), matrix([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]])) - approx.deepEqual(math.rotationMatrix(math.pi / 2, [1, 0, 0]), matrix([[1.0, 0.0, 0.0], [0.0, 0.0, -1.0], [0.0, 1.0, 0.0]])) - approx.deepEqual(math.rotationMatrix(math.pi / 2, [0, 1, 0]), matrix([[0.0, 0.0, 1.0], [0.0, 1.0, 0.0], [-1.0, 0.0, 0.0]])) - approx.deepEqual(math.rotationMatrix(math.pi / 2, [0, 0, 1]), matrix([[0.0, -1.0, 0.0], [1.0, 0.0, 0.0], [0.0, 0.0, 1.0]])) + it('should create a 3D rotation matrix by given angle around given axis provided as array', function () { + assert.deepStrictEqual(math.rotationMatrix(0.0, [1, 1, 1]), [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]) + approx.deepEqual(math.rotationMatrix(math.pi / 2, [1, 0, 0]), [[1.0, 0.0, 0.0], [0.0, 0.0, -1.0], [0.0, 1.0, 0.0]]) + approx.deepEqual(math.rotationMatrix(math.pi / 2, [0, 1, 0]), [[0.0, 0.0, 1.0], [0.0, 1.0, 0.0], [-1.0, 0.0, 0.0]]) + approx.deepEqual(math.rotationMatrix(math.pi / 2, [0, 0, 1]), [[0.0, -1.0, 0.0], [1.0, 0.0, 0.0], [0.0, 0.0, 1.0]]) approx.deepEqual(math.rotationMatrix(-math.pi / 4, [1, 0, 0]), - matrix([[1.0, 0.0, 0.0], [0.0, sqrtTwoInv, sqrtTwoInv], [0.0, minusSqrtTwoInv, sqrtTwoInv]])) + [[1.0, 0.0, 0.0], [0.0, sqrtTwoInv, sqrtTwoInv], [0.0, minusSqrtTwoInv, sqrtTwoInv]]) approx.deepEqual(math.rotationMatrix(-math.pi / 4, [0, 1, 0]), - matrix([[sqrtTwoInv, 0.0, minusSqrtTwoInv], [0.0, 1.0, 0.0], [sqrtTwoInv, 0.0, sqrtTwoInv]])) + [[sqrtTwoInv, 0.0, minusSqrtTwoInv], [0.0, 1.0, 0.0], [sqrtTwoInv, 0.0, sqrtTwoInv]]) approx.deepEqual(math.rotationMatrix(-math.pi / 4, [0, 0, 1]), - matrix([[sqrtTwoInv, sqrtTwoInv, 0.0], [minusSqrtTwoInv, sqrtTwoInv, 0.0], [0.0, 0.0, 1.0]])) + [[sqrtTwoInv, sqrtTwoInv, 0.0], [minusSqrtTwoInv, sqrtTwoInv, 0.0], [0.0, 0.0, 1.0]]) assert.deepStrictEqual(math.rotationMatrix(1, [1, 0, 0]), - matrix([[1, 0, 0], + [[1, 0, 0], [0, cos(1), -sin(1)], - [0, sin(1), cos(1)]])) + [0, sin(1), cos(1)]]) }) it('should create a 3D rotation matrix by given angle around given vector provided as matrix', function () { @@ -122,17 +130,17 @@ describe('rotationMatrix', function () { }) it('should create a unitary 3D rotation matrix around non-unit vector', function () { - approx.deepEqual(math.rotationMatrix(math.pi / 2, [1000, 0, 0]), + approx.deepEqual(math.rotationMatrix(math.pi / 2, matrix([1000, 0, 0])), matrix([[1.0, 0.0, 0.0], [0.0, 0.0, -1.0], [0.0, 1.0, 0.0]])) - approx.deepEqual(math.rotationMatrix(math.pi / 2, [1000, 0, 1000]), + approx.deepEqual(math.rotationMatrix(math.pi / 2, matrix([1000, 0, 1000])), matrix([[0.5, minusSqrtTwoInv, 0.5], [sqrtTwoInv, 0.0, minusSqrtTwoInv], [0.5, sqrtTwoInv, 0.5]])) - approx.deepEqual(math.rotationMatrix(math.pi / 2, matrix([0, 0, 1000])), - matrix([[0.0, -1.0, 0.0], [1.0, 0.0, 0.0], [0.0, 0.0, 1.0]])) + approx.deepEqual(math.rotationMatrix(math.pi / 2, [0, 0, 1000]), + [[0.0, -1.0, 0.0], [1.0, 0.0, 0.0], [0.0, 0.0, 1.0]]) - approx.deepEqual(math.rotationMatrix(math.pi / 2, matrix([0, 200, 200])), - matrix([[0.0, minusSqrtTwoInv, sqrtTwoInv], [sqrtTwoInv, 0.5, 0.5], [minusSqrtTwoInv, 0.5, 0.5]])) + approx.deepEqual(math.rotationMatrix(math.pi / 2, [0, 200, 200]), + [[0.0, minusSqrtTwoInv, sqrtTwoInv], [sqrtTwoInv, 0.5, 0.5], [minusSqrtTwoInv, 0.5, 0.5]]) }) it('should create a 3D rotation matrix by given bignumber angle around given axis', function () { @@ -142,15 +150,15 @@ describe('rotationMatrix', function () { const sin2 = sin(bignumber(2)) const minusSin2 = multiply(bignumber(-1), sin2) - assert.deepStrictEqual(math.rotationMatrix(bignumber(2), [1, 0, 0]), + assert.deepStrictEqual(math.rotationMatrix(bignumber(2), matrix([1, 0, 0])), matrix([[one, zero, zero], [zero, cos2, minusSin2], [zero, sin2, cos2]])) - assert.deepStrictEqual(math.rotationMatrix(bignumber(2), [0, 1, 0]), + assert.deepStrictEqual(math.rotationMatrix(bignumber(2), matrix([0, 1, 0])), matrix([[cos2, zero, sin2], [zero, one, zero], [minusSin2, zero, cos2]])) - assert.deepStrictEqual(math.rotationMatrix(bignumber(2), [0, 0, 1]), + assert.deepStrictEqual(math.rotationMatrix(bignumber(2), matrix([0, 0, 1])), matrix([[cos2, minusSin2, zero], [sin2, cos2, zero], [zero, zero, one]])) @@ -167,41 +175,41 @@ describe('rotationMatrix', function () { const sinTheta = math.sin(complex('2+3i')) const minusSinTheta = math.multiplyScalar(-1, sinTheta) - assert.deepStrictEqual(math.rotationMatrix(complex('2+3i'), [1, 0, 0]), + assert.deepStrictEqual(math.rotationMatrix(complex('2+3i'), matrix([1, 0, 0])), math.complex(matrix([[1, 0, 0], [complexZero, cosTheta, minusSinTheta], [complexZero, sinTheta, cosTheta]]))) - assert.deepStrictEqual(math.rotationMatrix(complex('2+3i'), [0, 1, 0]), + assert.deepStrictEqual(math.rotationMatrix(complex('2+3i'), matrix([0, 1, 0])), math.complex(matrix([[cosTheta, 0.0, sinTheta], [0.0, 1.0, 0.0], [minusSinTheta, 0.0, cosTheta]]))) assert.deepStrictEqual(math.rotationMatrix(complex('2+3i'), [0, 0, 1]), - math.complex(matrix([[cosTheta, minusSinTheta, 0.0], + math.complex([[cosTheta, minusSinTheta, 0.0], [sinTheta, cosTheta, 0.0], - [0.0, 0.0, 1.0]]))) + [0.0, 0.0, 1.0]])) - assert.deepStrictEqual(math.rotationMatrix(complex('2+3i'), matrix([0, 1, 0])), - math.complex(matrix([[cosTheta, 0.0, sinTheta], + assert.deepStrictEqual(math.rotationMatrix(complex('2+3i'), [0, 1, 0]), + math.complex([[cosTheta, 0.0, sinTheta], [0.0, 1.0, 0.0], - [minusSinTheta, 0.0, cosTheta]]))) + [minusSinTheta, 0.0, cosTheta]])) }) it('should create a 3D rotation matrix by given unit angle around given axis', function () { approx.deepEqual(math.rotationMatrix(unit('45deg'), [1, 0, 0]), - matrix([[1.0, 0.0, 0.0], [0.0, sqrtTwoInv, minusSqrtTwoInv], [0.0, sqrtTwoInv, sqrtTwoInv]])) + [[1.0, 0.0, 0.0], [0.0, sqrtTwoInv, minusSqrtTwoInv], [0.0, sqrtTwoInv, sqrtTwoInv]]) approx.deepEqual(math.rotationMatrix(unit('45deg'), [0, 1, 0]), - matrix([[sqrtTwoInv, 0.0, sqrtTwoInv], [0.0, 1.0, 0.0], [minusSqrtTwoInv, 0.0, sqrtTwoInv]])) + [[sqrtTwoInv, 0.0, sqrtTwoInv], [0.0, 1.0, 0.0], [minusSqrtTwoInv, 0.0, sqrtTwoInv]]) approx.deepEqual(math.rotationMatrix(unit('45deg'), [0, 0, 1]), - matrix([[sqrtTwoInv, minusSqrtTwoInv, 0.0], [sqrtTwoInv, sqrtTwoInv, 0.0], [0.0, 0.0, 1.0]])) + [[sqrtTwoInv, minusSqrtTwoInv, 0.0], [sqrtTwoInv, sqrtTwoInv, 0.0], [0.0, 0.0, 1.0]]) approx.deepEqual(math.rotationMatrix(unit('-135deg'), [1, 0, 0]), - matrix([[1.0, 0.0, 0.0], [0.0, minusSqrtTwoInv, sqrtTwoInv], [0.0, minusSqrtTwoInv, minusSqrtTwoInv]])) + [[1.0, 0.0, 0.0], [0.0, minusSqrtTwoInv, sqrtTwoInv], [0.0, minusSqrtTwoInv, minusSqrtTwoInv]]) approx.deepEqual(math.rotationMatrix(unit('-135deg'), [0, 1, 0]), - matrix([[minusSqrtTwoInv, 0.0, minusSqrtTwoInv], [0.0, 1.0, 0.0], [sqrtTwoInv, 0.0, minusSqrtTwoInv]])) + [[minusSqrtTwoInv, 0.0, minusSqrtTwoInv], [0.0, 1.0, 0.0], [sqrtTwoInv, 0.0, minusSqrtTwoInv]]) approx.deepEqual(math.rotationMatrix(unit('-135deg'), [0, 0, 1]), - matrix([[minusSqrtTwoInv, sqrtTwoInv, 0.0], [minusSqrtTwoInv, minusSqrtTwoInv, 0.0], [0.0, 0.0, 1.0]])) + [[minusSqrtTwoInv, sqrtTwoInv, 0.0], [minusSqrtTwoInv, minusSqrtTwoInv, 0.0], [0.0, 0.0, 1.0]]) - approx.deepEqual(rotationMatrix(unit(complex(1, 1), 'rad'), [1, 0, 1]), + approx.deepEqual(rotationMatrix(unit(complex(1, 1), 'rad'), matrix([1, 0, 1])), math.evaluate('matrix([[0.5 * (1 + cos(1+i)), -sin(1+i) / sqrt(2), 0.5 * (1 - cos(1+i))],' + '[sin(1+i) / sqrt(2), cos(1+i), -sin(1+i) / sqrt(2)],' + '[0.5 * (1 - cos(1+i)), sin(1+i) / sqrt(2), 0.5 * (1 + cos(1+i))]])')) @@ -231,7 +239,7 @@ describe('rotationMatrix', function () { approx.deepEqual(mathArray.rotationMatrix(mathArray.pi / 2, [0, 0, 1]), [[0.0, -1.0, 0.0], [1.0, 0.0, 0.0], [0.0, 0.0, 1.0]]) approx.deepEqual(mathArray.rotationMatrix(mathArray.pi / 2, matrix([0, 0, 1])), - [[0.0, -1.0, 0.0], [1.0, 0.0, 0.0], [0.0, 0.0, 1.0]]) + matrix([[0.0, -1.0, 0.0], [1.0, 0.0, 0.0], [0.0, 0.0, 1.0]])) }) it('should throw an error with an invalid input', function () {