1 | 'use strict'
|
2 |
|
3 | function factory (type, config, load, typed) {
|
4 | const abs = load(require('../arithmetic/abs'))
|
5 | const add = load(require('../arithmetic/add'))
|
6 | const pow = load(require('../arithmetic/pow'))
|
7 | const conj = load(require('../complex/conj'))
|
8 | const sqrt = load(require('../arithmetic/sqrt'))
|
9 | const multiply = load(require('../arithmetic/multiply'))
|
10 | const equalScalar = load(require('../relational/equalScalar'))
|
11 | const larger = load(require('../relational/larger'))
|
12 | const smaller = load(require('../relational/smaller'))
|
13 | const matrix = load(require('../../type/matrix/function/matrix'))
|
14 |
|
15 | |
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 | const norm = typed('norm', {
|
54 | 'number': Math.abs,
|
55 |
|
56 | 'Complex': function (x) {
|
57 | return x.abs()
|
58 | },
|
59 |
|
60 | 'BigNumber': function (x) {
|
61 |
|
62 | return x.abs()
|
63 | },
|
64 |
|
65 | 'boolean': function (x) {
|
66 |
|
67 | return Math.abs(x)
|
68 | },
|
69 |
|
70 | 'Array': function (x) {
|
71 | return _norm(matrix(x), 2)
|
72 | },
|
73 |
|
74 | 'Matrix': function (x) {
|
75 | return _norm(x, 2)
|
76 | },
|
77 |
|
78 | 'number | Complex | BigNumber | boolean, number | BigNumber | string': function (x) {
|
79 |
|
80 | return norm(x)
|
81 | },
|
82 |
|
83 | 'Array, number | BigNumber | string': function (x, p) {
|
84 | return _norm(matrix(x), p)
|
85 | },
|
86 |
|
87 | 'Matrix, number | BigNumber | string': function (x, p) {
|
88 | return _norm(x, p)
|
89 | }
|
90 | })
|
91 |
|
92 | |
93 |
|
94 |
|
95 |
|
96 |
|
97 |
|
98 |
|
99 | function _norm (x, p) {
|
100 |
|
101 | const sizeX = x.size()
|
102 |
|
103 |
|
104 | if (sizeX.length === 1) {
|
105 |
|
106 | if (p === Number.POSITIVE_INFINITY || p === 'inf') {
|
107 |
|
108 | let pinf = 0
|
109 |
|
110 | x.forEach(
|
111 | function (value) {
|
112 | const v = abs(value)
|
113 | if (larger(v, pinf)) { pinf = v }
|
114 | },
|
115 | true)
|
116 | return pinf
|
117 | }
|
118 | if (p === Number.NEGATIVE_INFINITY || p === '-inf') {
|
119 |
|
120 | let ninf
|
121 |
|
122 | x.forEach(
|
123 | function (value) {
|
124 | const v = abs(value)
|
125 | if (!ninf || smaller(v, ninf)) { ninf = v }
|
126 | },
|
127 | true)
|
128 | return ninf || 0
|
129 | }
|
130 | if (p === 'fro') {
|
131 | return _norm(x, 2)
|
132 | }
|
133 | if (typeof p === 'number' && !isNaN(p)) {
|
134 |
|
135 | if (!equalScalar(p, 0)) {
|
136 |
|
137 | let n = 0
|
138 |
|
139 | x.forEach(
|
140 | function (value) {
|
141 | n = add(pow(abs(value), p), n)
|
142 | },
|
143 | true)
|
144 | return pow(n, 1 / p)
|
145 | }
|
146 | return Number.POSITIVE_INFINITY
|
147 | }
|
148 |
|
149 | throw new Error('Unsupported parameter value')
|
150 | }
|
151 |
|
152 | if (sizeX.length === 2) {
|
153 |
|
154 | if (p === 1) {
|
155 |
|
156 | const c = []
|
157 |
|
158 | let maxc = 0
|
159 |
|
160 | x.forEach(
|
161 | function (value, index) {
|
162 | const j = index[1]
|
163 | const cj = add(c[j] || 0, abs(value))
|
164 | if (larger(cj, maxc)) { maxc = cj }
|
165 | c[j] = cj
|
166 | },
|
167 | true)
|
168 | return maxc
|
169 | }
|
170 | if (p === Number.POSITIVE_INFINITY || p === 'inf') {
|
171 |
|
172 | const r = []
|
173 |
|
174 | let maxr = 0
|
175 |
|
176 | x.forEach(
|
177 | function (value, index) {
|
178 | const i = index[0]
|
179 | const ri = add(r[i] || 0, abs(value))
|
180 | if (larger(ri, maxr)) { maxr = ri }
|
181 | r[i] = ri
|
182 | },
|
183 | true)
|
184 | return maxr
|
185 | }
|
186 | if (p === 'fro') {
|
187 |
|
188 | let fro = 0
|
189 | x.forEach(
|
190 | function (value, index) {
|
191 | fro = add(fro, multiply(value, conj(value)))
|
192 | })
|
193 | return abs(sqrt(fro))
|
194 | }
|
195 | if (p === 2) {
|
196 |
|
197 | throw new Error('Unsupported parameter value, missing implementation of matrix singular value decomposition')
|
198 | }
|
199 |
|
200 | throw new Error('Unsupported parameter value')
|
201 | }
|
202 | }
|
203 |
|
204 | norm.toTex = {
|
205 | 1: `\\left\\|\${args[0]}\\right\\|`,
|
206 | 2: undefined
|
207 | }
|
208 |
|
209 | return norm
|
210 | }
|
211 |
|
212 | exports.name = 'norm'
|
213 | exports.factory = factory
|