CCS resize

This commit is contained in:
rjbaucells 2015-03-12 22:01:30 -04:00
parent b1166871ac
commit 090911f3e2
2 changed files with 95 additions and 56 deletions

View File

@ -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];

View File

@ -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 () {