1 | 'use strict'
|
2 |
|
3 | const array = require('../../utils/array')
|
4 | const latex = require('../../utils/latex')
|
5 | const string = require('../../utils/string')
|
6 |
|
7 | function factory (type, config, load, typed) {
|
8 | const abs = load(require('../arithmetic/abs'))
|
9 | const add = load(require('../arithmetic/add'))
|
10 | const multiply = load(require('../arithmetic/multiply'))
|
11 | const sqrt = load(require('../arithmetic/sqrt'))
|
12 | const subtract = load(require('../arithmetic/subtract'))
|
13 | const inv = load(require('../matrix/inv'))
|
14 | const size = load(require('../matrix/size'))
|
15 | const max = load(require('../statistics/max'))
|
16 | const identity = load(require('./identity'))
|
17 |
|
18 | |
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 | const sqrtm = typed('sqrtm', {
|
40 | 'Array | Matrix': function (A) {
|
41 | const size = type.isMatrix(A) ? A.size() : array.size(A)
|
42 | switch (size.length) {
|
43 | case 1:
|
44 |
|
45 | if (size[0] === 1) {
|
46 | return sqrt(A)
|
47 | } else {
|
48 | throw new RangeError('Matrix must be square ' +
|
49 | '(size: ' + string.format(size) + ')')
|
50 | }
|
51 |
|
52 | case 2:
|
53 |
|
54 | const rows = size[0]
|
55 | const cols = size[1]
|
56 | if (rows === cols) {
|
57 | return _denmanBeavers(A)
|
58 | } else {
|
59 | throw new RangeError('Matrix must be square ' +
|
60 | '(size: ' + string.format(size) + ')')
|
61 | }
|
62 | }
|
63 | }
|
64 | })
|
65 |
|
66 | const _maxIterations = 1e3
|
67 | const _tolerance = 1e-6
|
68 |
|
69 | |
70 |
|
71 |
|
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 | function _denmanBeavers (A) {
|
79 | let error
|
80 | let iterations = 0
|
81 |
|
82 | let Y = A
|
83 | let Z = identity(size(A))
|
84 |
|
85 | do {
|
86 | const Yk = Y
|
87 | Y = multiply(0.5, add(Yk, inv(Z)))
|
88 | Z = multiply(0.5, add(Z, inv(Yk)))
|
89 |
|
90 | error = max(abs(subtract(Y, Yk)))
|
91 |
|
92 | if (error > _tolerance && ++iterations > _maxIterations) {
|
93 | throw new Error('computing square root of matrix: iterative method could not converge')
|
94 | }
|
95 | } while (error > _tolerance)
|
96 |
|
97 | return Y
|
98 | }
|
99 |
|
100 | sqrtm.toTex = { 1: `{\${args[0]}}${latex.operators['pow']}{\\frac{1}{2}}` }
|
101 |
|
102 | return sqrtm
|
103 | }
|
104 |
|
105 | exports.name = 'sqrtm'
|
106 | exports.factory = factory
|