UNPKG

3.01 kBJavaScriptView Raw
1'use strict'
2
3const array = require('../../utils/array')
4const latex = require('../../utils/latex')
5const string = require('../../utils/string')
6
7function 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 * Calculate the principal square root of a square matrix.
20 * The principal square root matrix `X` of another matrix `A` is such that `X * X = A`.
21 *
22 * https://en.wikipedia.org/wiki/Square_root_of_a_matrix
23 *
24 * Syntax:
25 *
26 * X = math.sqrtm(A)
27 *
28 * Examples:
29 *
30 * math.sqrtm([[1, 2], [3, 4]]) // returns [[-2, 1], [1.5, -0.5]]
31 *
32 * See also:
33 *
34 * sqrt, pow
35 *
36 * @param {Array | Matrix} A The square matrix `A`
37 * @return {Array | Matrix} The principal square root of matrix `A`
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 // Single element Array | Matrix
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 // Two-dimensional Array | Matrix
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 * Calculate the principal square root matrix using the Denman–Beavers iterative method
71 *
72 * https://en.wikipedia.org/wiki/Square_root_of_a_matrix#By_Denman–Beavers_iteration
73 *
74 * @param {Array | Matrix} A The square matrix `A`
75 * @return {Array | Matrix} The principal square root of matrix `A`
76 * @private
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
105exports.name = 'sqrtm'
106exports.factory = factory