math.norm()

This commit is contained in:
rjbaucells 2015-03-23 00:09:06 -04:00
parent b1c0428e8c
commit fc8dde607d
5 changed files with 103 additions and 64 deletions

View File

@ -3,12 +3,9 @@
module.exports = function (math) {
var util = require('../../util/index'),
array = require('../../../lib/util/array'),
BigNumber = math.type.BigNumber,
Complex = require('../../type/Complex'),
Matrix = math.type.Matrix,
collection = math.collection,
isNumber = util.number.isNumber,
isBoolean = util['boolean'].isBoolean,
@ -68,11 +65,11 @@ module.exports = function (math) {
var re = Math.abs(x.re);
var im = Math.abs(x.im);
if (re >= im) {
var x = im / re;
return re * Math.sqrt(1 + x * x);
var i = im / re;
return re * Math.sqrt(1 + i * i);
}
var y = re / im;
return im * Math.sqrt(1 + y * y);
var j = re / im;
return im * Math.sqrt(1 + j * j);
}
if (x instanceof BigNumber) {
@ -86,8 +83,13 @@ module.exports = function (math) {
}
if (isArray(x)) {
// use matrix optimized operations
return norm(math.matrix(x), p);
}
if (x instanceof Matrix) {
// size
var sizeX = array.size(x);
var sizeX = x.size();
// missing p
if (p == null)
p = 2;
@ -97,21 +99,25 @@ module.exports = function (math) {
if (p === Number.POSITIVE_INFINITY || p === 'inf') {
// norm(x, Infinity) = max(abs(x))
var n;
math.forEach(x, function (value) {
var v = math.abs(value);
if (!n || math.larger(v, n))
n = v;
});
x.forEach(
function (value) {
var v = math.abs(value);
if (!n || math.larger(v, n))
n = v;
},
true);
return n;
}
if (p === Number.NEGATIVE_INFINITY || p === '-inf') {
// norm(x, -Infinity) = min(abs(x))
var n;
math.forEach(x, function (value) {
var v = math.abs(value);
if (!n || math.smaller(v, n))
n = v;
});
x.forEach(
function (value) {
var v = math.abs(value);
if (!n || math.smaller(v, n))
n = v;
},
true);
return n;
}
if (p === 'fro')
@ -121,9 +127,11 @@ module.exports = function (math) {
if (!math.equal(p, 0)) {
// norm(x, p) = sum(abs(xi) ^ p) ^ 1/p
var n = 0;
math.forEach(x, function (value) {
n = math.add(math.pow(math.abs(value), p), n);
});
x.forEach(
function (value) {
n = math.add(math.pow(math.abs(value), p), n);
},
true);
return math.pow(n, 1 / p);
}
return Number.POSITIVE_INFINITY;
@ -136,39 +144,34 @@ module.exports = function (math) {
if (p == 1) {
// norm(x) = the largest column sum
var c = [];
// loop rows
for (var i = 0; i < x.length; i++) {
var r = x[i];
// loop columns
for (var j = 0; j < r.length; j++) {
c[j] = math.add(c[j] || 0, math.abs(r[j]));
}
}
x.forEach(
function (value, index) {
var j = index[1];
c[j] = math.add(c[j] || 0, math.abs(value));
},
true);
return math.max(c);
}
if (p == Number.POSITIVE_INFINITY || p === 'inf') {
// norm(x) = the largest row sum
var n = 0;
// loop rows
for (var i = 0; i < x.length; i++) {
var rs = 0;
var r = x[i];
// loop columns
for (var j = 0; j < r.length; j++) {
rs = math.add(rs, math.abs(r[j]));
}
if (math.larger(rs, n))
n = rs;
}
return n;
var r = [];
x.forEach(
function (value, index) {
var i = index[0];
r[i] = math.add(r[i] || 0, math.abs(value));
},
true);
return math.max(r);
}
if (p === 'fro') {
// norm(x) = sqrt(sum(diag(x'x)))
var d = math.diag(math.multiply(math.transpose(x), x));
var d = x.transpose().multiply(x).diagonal();
var s = 0;
math.forEach(d, function (value) {
s = math.add(value, s);
});
d.forEach(
function (value) {
s = math.add(s, value);
},
true);
return math.sqrt(s);
}
if (p == 2) {
@ -180,10 +183,6 @@ module.exports = function (math) {
}
}
if (x instanceof Matrix) {
return norm(x.valueOf(), p);
}
throw new math.error.UnsupportedTypeError('norm', x);
};
};

View File

@ -664,8 +664,9 @@ module.exports = function (math) {
* @param {function} callback The callback function is invoked with three
* parameters: the value of the element, the index
* of the element, and the Matrix being traversed.
* @param {boolean} [skipZeros] Invoke callback function for non-zero values only.
*/
CcsMatrix.prototype.forEach = function (callback) {
CcsMatrix.prototype.forEach = function (callback, skipZeros) {
// matrix instance
var me = this;
// rows and columns
@ -682,17 +683,23 @@ module.exports = function (math) {
for (var k = k0; k < k1; k++) {
// row index
var i = this._index[k];
// zero values
for (var x = p; x < i; x++)
callback(0, [x, j], me);
// check we need to process zeros
if (!skipZeros) {
// zero values
for (var x = p; x < i; x++)
callback(0, [x, j], me);
}
// value @ k
callback(this._values[k], [i, j], me);
// update pointer
p = i + 1;
}
// zero values
for (var y = p; y < rows; y++)
callback(0, [y, j], me);
// check we need to process zeros
if (!skipZeros) {
// zero values
for (var y = p; y < rows; y++)
callback(0, [y, j], me);
}
}
};

View File

@ -656,8 +656,9 @@ module.exports = function (math) {
* @param {function} callback The callback function is invoked with three
* parameters: the value of the element, the index
* of the element, and the Matrix being traversed.
* @param {boolean} [skipZeros] Invoke callback function for non-zero values only.
*/
CrsMatrix.prototype.forEach = function (callback) {
CrsMatrix.prototype.forEach = function (callback, skipZeros) {
// matrix instance
var me = this;
// rows and columns
@ -674,17 +675,23 @@ module.exports = function (math) {
for (var k = k0; k < k1; k++) {
// column index
var j = this._index[k];
// zero values
for (var x = p; x < j; x++)
callback(0, [i, x], me);
// check we need to process zeros
if (!skipZeros) {
// zero values
for (var x = p; x < j; x++)
callback(0, [i, x], me);
}
// value @ k
callback(this._values[k], [i, j], me);
// update pointer
p = j + 1;
}
// zero values
for (var y = p; y < columns; y++)
callback(0, [i, y], me);
// check we need to process zeros
if (!skipZeros) {
// zero values
for (var y = p; y < columns; y++)
callback(0, [i, y], me);
}
}
};

View File

@ -1114,6 +1114,19 @@ describe('CcsMatrix', function() {
m.forEach(function (value) { output.push(value); });
assert.deepEqual(output, []);
});
it('should process non-zero values', function() {
var m = new CcsMatrix(
[
[1, 0],
[0, 0]
]
);
var counter = 0;
m.forEach(function () { counter++; }, true);
assert(counter === 1);
});
it('should invoke callback with parameters value, index, obj', function() {
var m = new CcsMatrix([[1,2,3], [4,5,6]]);

View File

@ -1095,6 +1095,19 @@ describe('CrsMatrix', function() {
assert.deepEqual(output, []);
});
it('should process non-zero values', function() {
var m = new CrsMatrix(
[
[1, 0],
[0, 0]
]
);
var counter = 0;
m.forEach(function () { counter++; }, true);
assert(counter === 1);
});
it('should invoke callback with parameters value, index, obj', function() {
var m = new CrsMatrix([[1,2,3], [4,5,6]]);
var output = [];