norm.js 7.4 KB

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