From 090911f3e2452e47b0011368f787e1c439d77fb3 Mon Sep 17 00:00:00 2001 From: rjbaucells Date: Thu, 12 Mar 2015 22:01:30 -0400 Subject: [PATCH] CCS resize --- lib/type/matrix/CcsMatrix.js | 115 +++++++++++++++-------------- test/type/matrix/CcsMatrix.test.js | 36 +++++++++ 2 files changed, 95 insertions(+), 56 deletions(-) diff --git a/lib/type/matrix/CcsMatrix.js b/lib/type/matrix/CcsMatrix.js index e14058d89..195e9a529 100644 --- a/lib/type/matrix/CcsMatrix.js +++ b/lib/type/matrix/CcsMatrix.js @@ -322,7 +322,7 @@ module.exports = function (math) { // check we need to resize matrix if (i > rows - 1 || j > columns - 1) { // resize matrix - this.resize([Math.max(i + 1, rows), Math.max(j + 1, columns)], defaultValue); + _resize(this, Math.max(i + 1, rows), Math.max(j + 1, columns), defaultValue); // update rows & columns rows = this._size[0]; columns = this._size[1]; @@ -395,16 +395,18 @@ module.exports = function (math) { }; /** - * Resize the matrix + * Resize the matrix to the given size. Returns a copy of the matrix when the + * `copy=true`, otherwise return the matrix itself (resize in place). * * @param {Number[]} size The new size the matrix should have. * @param {*} [defaultValue=0] Default value, filled in on new entries. * If not provided, the matrix elements will * be filled with zeros. + * @param {boolean} [copy] Return a resized copy of the matrix * - * @return {CcsMatrix} self The matrix itself is returned + * @return {CcsMatrix} The resized matrix */ - CcsMatrix.prototype.resize = function (size, defaultValue) { + CcsMatrix.prototype.resize = function (size, defaultValue, copy) { // validate arguments if (!isArray(size)) throw new TypeError('Array expected'); @@ -418,19 +420,22 @@ module.exports = function (math) { '(size: ' + string.format(size) + ')'); } }); - + + // matrix to resize + var m = copy ? this.clone() : this; + // resize matrix + return _resize(m, size[0], size[1], defaultValue); + }; + + var _resize = function (matrix, rows, columns, defaultValue) { // value to insert at the time of growing matrix var value = (defaultValue !== undefined) ? defaultValue : 0; // should we insert the value? var ins = !math.equal(value, 0); // old columns and rows - var r = this._size[0]; - var c = this._size[1]; - - // rows & columns - var rows = size[0]; - var columns = size[1]; + var r = matrix._size[0]; + var c = matrix._size[1]; var i, j, k; @@ -438,58 +443,58 @@ module.exports = function (math) { if (columns > c) { // loop new columns for (j = c; j < columns; j++) { - // update ptr for current column - this._ptr[j] = this._values.length; - // check we need to insert values + // update matrix._ptr for current column + matrix._ptr[j] = matrix._values.length; + // check we need to insert matrix._values if (ins) { // loop rows for (i = 0; i < r; i++) { - // add new values - this._values.push(value); - // update index - this._index.push(i); + // add new matrix._values + matrix._values.push(value); + // update matrix._index + matrix._index.push(i); } } } - // store number of values in ptr - this._ptr[columns] = this._values.length; + // store number of matrix._values in matrix._ptr + matrix._ptr[columns] = matrix._values.length; } else if (columns < c) { - // truncate ptr - this._ptr.splice(columns + 1, c - columns); - // truncate values and index - this._values.splice(this._ptr[columns], this._values.length); - this._index.splice(this._ptr[columns], this._index.length); + // truncate matrix._ptr + matrix._ptr.splice(columns + 1, c - columns); + // truncate matrix._values and matrix._index + matrix._values.splice(matrix._ptr[columns], matrix._values.length); + matrix._index.splice(matrix._ptr[columns], matrix._index.length); } // update columns c = columns; // check we need to increase rows if (rows > r) { - // check we have to insert values + // check we have to insert matrix._values if (ins) { // inserts var n = 0; // loop columns for (j = 0; j < c; j++) { - // update ptr for current column - this._ptr[j] = this._ptr[j] + n; - // where to insert values - k = this._ptr[j + 1] + n; + // update matrix._ptr for current column + matrix._ptr[j] = matrix._ptr[j] + n; + // where to insert matrix._values + k = matrix._ptr[j + 1] + n; // pointer var p = 0; // loop new rows, initialize pointer for (i = r; i < rows; i++, p++) { // add value - this._values.splice(k + p, 0, value); - // update index - this._index.splice(k + p, 0, i); + matrix._values.splice(k + p, 0, value); + // update matrix._index + matrix._index.splice(k + p, 0, i); // increment inserts n++; } } - // store number of values in ptr - this._ptr[c] = this._values.length; + // store number of matrix._values in matrix._ptr + matrix._ptr[c] = matrix._values.length; } } else if (rows < r) { @@ -497,35 +502,34 @@ module.exports = function (math) { var d = 0; // loop columns for (j = 0; j < c; j++) { - // update ptr for current column - this._ptr[j] = this._ptr[j] - d; - // where values start for next column - var k0 = this._ptr[j]; - var k1 = this._ptr[j + 1] - d; - // loop index + // update matrix._ptr for current column + matrix._ptr[j] = matrix._ptr[j] - d; + // where matrix._values start for next column + var k0 = matrix._ptr[j]; + var k1 = matrix._ptr[j + 1] - d; + // loop matrix._index for (k = k0; k < k1; k++) { // row - i = this._index[k]; - // check we need to delete value and index + i = matrix._index[k]; + // check we need to delete value and matrix._index if (i > rows - 1) { // remove value - this._values.splice(k, 1); - // remove item from index - this._index.splice(k, 1); + matrix._values.splice(k, 1); + // remove item from matrix._index + matrix._index.splice(k, 1); // increase deletes d++; } } } - // update ptr for current column - this._ptr[j] = this._values.length; + // update matrix._ptr for current column + matrix._ptr[j] = matrix._values.length; } - - // update size - this._size = [rows, columns]; - - // return the matrix itself - return this; + // update matrix._size + matrix._size[0] = rows; + matrix._size[1] = columns; + // return matrix + return matrix; }; /** @@ -848,9 +852,8 @@ module.exports = function (math) { * @returns {Number} The matrix trace */ CcsMatrix.prototype.trace = function () { - // size & data + // size var size = this._size; - var data = this._data; // check dimensions var rows = size[0]; var columns = size[1]; diff --git a/test/type/matrix/CcsMatrix.test.js b/test/type/matrix/CcsMatrix.test.js index 9dcb3f9cc..931067ccd 100644 --- a/test/type/matrix/CcsMatrix.test.js +++ b/test/type/matrix/CcsMatrix.test.js @@ -392,6 +392,42 @@ describe('CcsMatrix', function() { [0, 0] ]); }); + + it('should return a different matrix when copy=true', function() { + var m1 = new CcsMatrix( + [ + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0] + ]); + var m2 = m1.resize([2, 2], 0, true); + assert(m1 !== m2); + // original matrix cannot be modified + assert.deepEqual(m1._size, [4, 4]); + assert.deepEqual(m1._values, []); + assert.deepEqual(m1._index, []); + assert.deepEqual(m1._ptr, [0, 0, 0, 0, 0]); + assert.deepEqual( + m1.toArray(), + [ + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0] + ]); + // new matrix should have correct size + assert.deepEqual(m2._size, [2, 2]); + assert.deepEqual(m2._values, []); + assert.deepEqual(m2._index, []); + assert.deepEqual(m2._ptr, [0, 0, 0]); + assert.deepEqual( + m2.toArray(), + [ + [0, 0], + [0, 0] + ]); + }); }); describe('get', function () {