UNPKG

5.79 kBJavaScriptView Raw
1import { factory } from '../../utils/factory';
2var name = 'norm';
3var dependencies = ['typed', 'abs', 'add', 'pow', 'conj', 'sqrt', 'multiply', 'equalScalar', 'larger', 'smaller', 'matrix'];
4export var createNorm =
5/* #__PURE__ */
6factory(name, dependencies, function (_ref) {
7 var typed = _ref.typed,
8 abs = _ref.abs,
9 add = _ref.add,
10 pow = _ref.pow,
11 conj = _ref.conj,
12 sqrt = _ref.sqrt,
13 multiply = _ref.multiply,
14 equalScalar = _ref.equalScalar,
15 larger = _ref.larger,
16 smaller = _ref.smaller,
17 matrix = _ref.matrix;
18
19 /**
20 * Calculate the norm of a number, vector or matrix.
21 *
22 * The second parameter p is optional. If not provided, it defaults to 2.
23 *
24 * Syntax:
25 *
26 * math.norm(x)
27 * math.norm(x, p)
28 *
29 * Examples:
30 *
31 * math.abs(-3.5) // returns 3.5
32 * math.norm(-3.5) // returns 3.5
33 *
34 * math.norm(math.complex(3, -4)) // returns 5
35 *
36 * math.norm([1, 2, -3], Infinity) // returns 3
37 * math.norm([1, 2, -3], -Infinity) // returns 1
38 *
39 * math.norm([3, 4], 2) // returns 5
40 *
41 * math.norm([[1, 2], [3, 4]], 1) // returns 6
42 * math.norm([[1, 2], [3, 4]], 'inf') // returns 7
43 * math.norm([[1, 2], [3, 4]], 'fro') // returns 5.477225575051661
44 *
45 * See also:
46 *
47 * abs, hypot
48 *
49 * @param {number | BigNumber | Complex | Array | Matrix} x
50 * Value for which to calculate the norm
51 * @param {number | BigNumber | string} [p=2]
52 * Vector space.
53 * Supported numbers include Infinity and -Infinity.
54 * Supported strings are: 'inf', '-inf', and 'fro' (The Frobenius norm)
55 * @return {number | BigNumber} the p-norm
56 */
57 var norm = typed(name, {
58 number: Math.abs,
59 Complex: function Complex(x) {
60 return x.abs();
61 },
62 BigNumber: function BigNumber(x) {
63 // norm(x) = abs(x)
64 return x.abs();
65 },
66 "boolean": function boolean(x) {
67 // norm(x) = abs(x)
68 return Math.abs(x);
69 },
70 Array: function Array(x) {
71 return _norm(matrix(x), 2);
72 },
73 Matrix: function Matrix(x) {
74 return _norm(x, 2);
75 },
76 'number | Complex | BigNumber | boolean, number | BigNumber | string': function numberComplexBigNumberBooleanNumberBigNumberString(x) {
77 // ignore second parameter, TODO: remove the option of second parameter for these types
78 return norm(x);
79 },
80 'Array, number | BigNumber | string': function ArrayNumberBigNumberString(x, p) {
81 return _norm(matrix(x), p);
82 },
83 'Matrix, number | BigNumber | string': function MatrixNumberBigNumberString(x, p) {
84 return _norm(x, p);
85 }
86 });
87 /**
88 * Calculate the norm for an array
89 * @param {Matrix} x
90 * @param {number | string} p
91 * @returns {number} Returns the norm
92 * @private
93 */
94
95 function _norm(x, p) {
96 // size
97 var sizeX = x.size(); // check if it is a vector
98
99 if (sizeX.length === 1) {
100 // check p
101 if (p === Number.POSITIVE_INFINITY || p === 'inf') {
102 // norm(x, Infinity) = max(abs(x))
103 var pinf = 0; // skip zeros since abs(0) === 0
104
105 x.forEach(function (value) {
106 var v = abs(value);
107
108 if (larger(v, pinf)) {
109 pinf = v;
110 }
111 }, true);
112 return pinf;
113 }
114
115 if (p === Number.NEGATIVE_INFINITY || p === '-inf') {
116 // norm(x, -Infinity) = min(abs(x))
117 var ninf; // skip zeros since abs(0) === 0
118
119 x.forEach(function (value) {
120 var v = abs(value);
121
122 if (!ninf || smaller(v, ninf)) {
123 ninf = v;
124 }
125 }, true);
126 return ninf || 0;
127 }
128
129 if (p === 'fro') {
130 return _norm(x, 2);
131 }
132
133 if (typeof p === 'number' && !isNaN(p)) {
134 // check p != 0
135 if (!equalScalar(p, 0)) {
136 // norm(x, p) = sum(abs(xi) ^ p) ^ 1/p
137 var n = 0; // skip zeros since abs(0) === 0
138
139 x.forEach(function (value) {
140 n = add(pow(abs(value), p), n);
141 }, true);
142 return pow(n, 1 / p);
143 }
144
145 return Number.POSITIVE_INFINITY;
146 } // invalid parameter value
147
148
149 throw new Error('Unsupported parameter value');
150 } // MxN matrix
151
152
153 if (sizeX.length === 2) {
154 // check p
155 if (p === 1) {
156 // norm(x) = the largest column sum
157 var c = []; // result
158
159 var maxc = 0; // skip zeros since abs(0) == 0
160
161 x.forEach(function (value, index) {
162 var j = index[1];
163 var cj = add(c[j] || 0, abs(value));
164
165 if (larger(cj, maxc)) {
166 maxc = cj;
167 }
168
169 c[j] = cj;
170 }, true);
171 return maxc;
172 }
173
174 if (p === Number.POSITIVE_INFINITY || p === 'inf') {
175 // norm(x) = the largest row sum
176 var r = []; // result
177
178 var maxr = 0; // skip zeros since abs(0) == 0
179
180 x.forEach(function (value, index) {
181 var i = index[0];
182 var ri = add(r[i] || 0, abs(value));
183
184 if (larger(ri, maxr)) {
185 maxr = ri;
186 }
187
188 r[i] = ri;
189 }, true);
190 return maxr;
191 }
192
193 if (p === 'fro') {
194 // norm(x) = sqrt(sum(diag(x'x)))
195 var fro = 0;
196 x.forEach(function (value, index) {
197 fro = add(fro, multiply(value, conj(value)));
198 });
199 return abs(sqrt(fro));
200 }
201
202 if (p === 2) {
203 // not implemented
204 throw new Error('Unsupported parameter value, missing implementation of matrix singular value decomposition');
205 } // invalid parameter value
206
207
208 throw new Error('Unsupported parameter value');
209 }
210 }
211
212 return norm;
213});
\No newline at end of file