norm.js (7832B)
1 "use strict"; 2 3 Object.defineProperty(exports, "__esModule", { 4 value: true 5 }); 6 exports.createNorm = void 0; 7 8 var _factory = require("../../utils/factory.js"); 9 10 var name = 'norm'; 11 var dependencies = ['typed', 'abs', 'add', 'pow', 'conj', 'sqrt', 'multiply', 'equalScalar', 'larger', 'smaller', 'matrix', 'ctranspose', 'eigs']; 12 var createNorm = /* #__PURE__ */(0, _factory.factory)(name, dependencies, function (_ref) { 13 var typed = _ref.typed, 14 abs = _ref.abs, 15 add = _ref.add, 16 pow = _ref.pow, 17 conj = _ref.conj, 18 sqrt = _ref.sqrt, 19 multiply = _ref.multiply, 20 equalScalar = _ref.equalScalar, 21 larger = _ref.larger, 22 smaller = _ref.smaller, 23 matrix = _ref.matrix, 24 ctranspose = _ref.ctranspose, 25 eigs = _ref.eigs; 26 27 /** 28 * Calculate the norm of a number, vector or matrix. 29 * 30 * The second parameter p is optional. If not provided, it defaults to 2. 31 * 32 * Syntax: 33 * 34 * math.norm(x) 35 * math.norm(x, p) 36 * 37 * Examples: 38 * 39 * math.abs(-3.5) // returns 3.5 40 * math.norm(-3.5) // returns 3.5 41 * 42 * math.norm(math.complex(3, -4)) // returns 5 43 * 44 * math.norm([1, 2, -3], Infinity) // returns 3 45 * math.norm([1, 2, -3], -Infinity) // returns 1 46 * 47 * math.norm([3, 4], 2) // returns 5 48 * 49 * math.norm([[1, 2], [3, 4]], 1) // returns 6 50 * math.norm([[1, 2], [3, 4]], 'inf') // returns 7 51 * math.norm([[1, 2], [3, 4]], 'fro') // returns 5.477225575051661 52 * 53 * See also: 54 * 55 * abs, hypot 56 * 57 * @param {number | BigNumber | Complex | Array | Matrix} x 58 * Value for which to calculate the norm 59 * @param {number | BigNumber | string} [p=2] 60 * Vector space. 61 * Supported numbers include Infinity and -Infinity. 62 * Supported strings are: 'inf', '-inf', and 'fro' (The Frobenius norm) 63 * @return {number | BigNumber} the p-norm 64 */ 65 return typed(name, { 66 number: Math.abs, 67 Complex: function Complex(x) { 68 return x.abs(); 69 }, 70 BigNumber: function BigNumber(x) { 71 // norm(x) = abs(x) 72 return x.abs(); 73 }, 74 boolean: function boolean(x) { 75 // norm(x) = abs(x) 76 return Math.abs(x); 77 }, 78 Array: function Array(x) { 79 return _norm(matrix(x), 2); 80 }, 81 Matrix: function Matrix(x) { 82 return _norm(x, 2); 83 }, 84 'number | Complex | BigNumber | boolean, number | BigNumber | string': function numberComplexBigNumberBooleanNumberBigNumberString(x) { 85 // ignore second parameter, TODO: remove the option of second parameter for these types 86 return this(x); 87 }, 88 'Array, number | BigNumber | string': function ArrayNumberBigNumberString(x, p) { 89 return _norm(matrix(x), p); 90 }, 91 'Matrix, number | BigNumber | string': function MatrixNumberBigNumberString(x, p) { 92 return _norm(x, p); 93 } 94 }); 95 /** 96 * Calculate the plus infinity norm for a vector 97 * @param {Matrix} x 98 * @returns {number} Returns the norm 99 * @private 100 */ 101 102 function _vectorNormPlusInfinity(x) { 103 // norm(x, Infinity) = max(abs(x)) 104 var pinf = 0; // skip zeros since abs(0) === 0 105 106 x.forEach(function (value) { 107 var v = abs(value); 108 109 if (larger(v, pinf)) { 110 pinf = v; 111 } 112 }, true); 113 return pinf; 114 } 115 /** 116 * Calculate the minus infinity norm for a vector 117 * @param {Matrix} x 118 * @returns {number} Returns the norm 119 * @private 120 */ 121 122 123 function _vectorNormMinusInfinity(x) { 124 // norm(x, -Infinity) = min(abs(x)) 125 var ninf; // skip zeros since abs(0) === 0 126 127 x.forEach(function (value) { 128 var v = abs(value); 129 130 if (!ninf || smaller(v, ninf)) { 131 ninf = v; 132 } 133 }, true); 134 return ninf || 0; 135 } 136 /** 137 * Calculate the norm for a vector 138 * @param {Matrix} x 139 * @param {number | string} p 140 * @returns {number} Returns the norm 141 * @private 142 */ 143 144 145 function _vectorNorm(x, p) { 146 // check p 147 if (p === Number.POSITIVE_INFINITY || p === 'inf') { 148 return _vectorNormPlusInfinity(x); 149 } 150 151 if (p === Number.NEGATIVE_INFINITY || p === '-inf') { 152 return _vectorNormMinusInfinity(x); 153 } 154 155 if (p === 'fro') { 156 return _norm(x, 2); 157 } 158 159 if (typeof p === 'number' && !isNaN(p)) { 160 // check p != 0 161 if (!equalScalar(p, 0)) { 162 // norm(x, p) = sum(abs(xi) ^ p) ^ 1/p 163 var n = 0; // skip zeros since abs(0) === 0 164 165 x.forEach(function (value) { 166 n = add(pow(abs(value), p), n); 167 }, true); 168 return pow(n, 1 / p); 169 } 170 171 return Number.POSITIVE_INFINITY; 172 } // invalid parameter value 173 174 175 throw new Error('Unsupported parameter value'); 176 } 177 /** 178 * Calculate the Frobenius norm for a matrix 179 * @param {Matrix} x 180 * @returns {number} Returns the norm 181 * @private 182 */ 183 184 185 function _matrixNormFrobenius(x) { 186 // norm(x) = sqrt(sum(diag(x'x))) 187 var fro = 0; 188 x.forEach(function (value, index) { 189 fro = add(fro, multiply(value, conj(value))); 190 }); 191 return abs(sqrt(fro)); 192 } 193 /** 194 * Calculate the norm L1 for a matrix 195 * @param {Matrix} x 196 * @returns {number} Returns the norm 197 * @private 198 */ 199 200 201 function _matrixNormOne(x) { 202 // norm(x) = the largest column sum 203 var c = []; // result 204 205 var maxc = 0; // skip zeros since abs(0) == 0 206 207 x.forEach(function (value, index) { 208 var j = index[1]; 209 var cj = add(c[j] || 0, abs(value)); 210 211 if (larger(cj, maxc)) { 212 maxc = cj; 213 } 214 215 c[j] = cj; 216 }, true); 217 return maxc; 218 } 219 /** 220 * Calculate the norm L2 for a matrix 221 * @param {Matrix} x 222 * @returns {number} Returns the norm 223 * @private 224 */ 225 226 227 function _matrixNormTwo(x) { 228 // norm(x) = sqrt( max eigenvalue of A*.A) 229 var sizeX = x.size(); 230 231 if (sizeX[0] !== sizeX[1]) { 232 throw new RangeError('Invalid matrix dimensions'); 233 } 234 235 var tx = ctranspose(x); 236 var squaredX = multiply(tx, x); 237 var eigenVals = eigs(squaredX).values.toArray(); 238 var rho = eigenVals[eigenVals.length - 1]; 239 return abs(sqrt(rho)); 240 } 241 /** 242 * Calculate the infinity norm for a matrix 243 * @param {Matrix} x 244 * @returns {number} Returns the norm 245 * @private 246 */ 247 248 249 function _matrixNormInfinity(x) { 250 // norm(x) = the largest row sum 251 var r = []; // result 252 253 var maxr = 0; // skip zeros since abs(0) == 0 254 255 x.forEach(function (value, index) { 256 var i = index[0]; 257 var ri = add(r[i] || 0, abs(value)); 258 259 if (larger(ri, maxr)) { 260 maxr = ri; 261 } 262 263 r[i] = ri; 264 }, true); 265 return maxr; 266 } 267 /** 268 * Calculate the norm for a 2D Matrix (M*N) 269 * @param {Matrix} x 270 * @param {number | string} p 271 * @returns {number} Returns the norm 272 * @private 273 */ 274 275 276 function _matrixNorm(x, p) { 277 // check p 278 if (p === 1) { 279 return _matrixNormOne(x); 280 } 281 282 if (p === Number.POSITIVE_INFINITY || p === 'inf') { 283 return _matrixNormInfinity(x); 284 } 285 286 if (p === 'fro') { 287 return _matrixNormFrobenius(x); 288 } 289 290 if (p === 2) { 291 return _matrixNormTwo(x); 292 } // invalid parameter value 293 294 295 throw new Error('Unsupported parameter value ' + p); 296 } 297 /** 298 * Calculate the norm for an array 299 * @param {Matrix} x 300 * @param {number | string} p 301 * @returns {number} Returns the norm 302 * @private 303 */ 304 305 306 function _norm(x, p) { 307 // size 308 var sizeX = x.size(); // check if it is a vector 309 310 if (sizeX.length === 1) { 311 return _vectorNorm(x, p); 312 } // MxN matrix 313 314 315 if (sizeX.length === 2) { 316 if (sizeX[0] && sizeX[1]) { 317 return _matrixNorm(x, p); 318 } else { 319 throw new RangeError('Invalid matrix dimensions'); 320 } 321 } 322 } 323 }); 324 exports.createNorm = createNorm;