1 | 'use strict'
|
2 |
|
3 | const isInteger = require('../../utils/number').isInteger
|
4 | const size = require('../../utils/array').size
|
5 |
|
6 | function factory (type, config, load, typed) {
|
7 | const latex = require('../../utils/latex')
|
8 | const identity = load(require('../matrix/identity'))
|
9 | const multiply = load(require('./multiply'))
|
10 | const matrix = load(require('../../type/matrix/function/matrix'))
|
11 | const fraction = load(require('../../type/fraction/function/fraction'))
|
12 | const number = load(require('../../type/number'))
|
13 |
|
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 | const pow = typed('pow', {
|
47 | 'number, number': _pow,
|
48 |
|
49 | 'Complex, Complex': function (x, y) {
|
50 | return x.pow(y)
|
51 | },
|
52 |
|
53 | 'BigNumber, BigNumber': function (x, y) {
|
54 | if (y.isInteger() || x >= 0 || config.predictable) {
|
55 | return x.pow(y)
|
56 | } else {
|
57 | return new type.Complex(x.toNumber(), 0).pow(y.toNumber(), 0)
|
58 | }
|
59 | },
|
60 |
|
61 | 'Fraction, Fraction': function (x, y) {
|
62 | if (y.d !== 1) {
|
63 | if (config.predictable) {
|
64 | throw new Error('Function pow does not support non-integer exponents for fractions.')
|
65 | } else {
|
66 | return _pow(x.valueOf(), y.valueOf())
|
67 | }
|
68 | } else {
|
69 | return x.pow(y)
|
70 | }
|
71 | },
|
72 |
|
73 | 'Array, number': _powArray,
|
74 |
|
75 | 'Array, BigNumber': function (x, y) {
|
76 | return _powArray(x, y.toNumber())
|
77 | },
|
78 |
|
79 | 'Matrix, number': _powMatrix,
|
80 |
|
81 | 'Matrix, BigNumber': function (x, y) {
|
82 | return _powMatrix(x, y.toNumber())
|
83 | },
|
84 |
|
85 | 'Unit, number | BigNumber': function (x, y) {
|
86 | return x.pow(y)
|
87 | }
|
88 |
|
89 | })
|
90 |
|
91 | |
92 |
|
93 |
|
94 |
|
95 |
|
96 |
|
97 |
|
98 | function _pow (x, y) {
|
99 |
|
100 |
|
101 | if (config.predictable && !isInteger(y) && x < 0) {
|
102 |
|
103 | try {
|
104 | const yFrac = fraction(y)
|
105 | const yNum = number(yFrac)
|
106 | if (y === yNum || Math.abs((y - yNum) / y) < 1e-14) {
|
107 | if (yFrac.d % 2 === 1) {
|
108 | return (yFrac.n % 2 === 0 ? 1 : -1) * Math.pow(-x, y)
|
109 | }
|
110 | }
|
111 | } catch (ex) {
|
112 |
|
113 | }
|
114 |
|
115 |
|
116 | }
|
117 |
|
118 |
|
119 |
|
120 | if ((x * x < 1 && y === Infinity) ||
|
121 | (x * x > 1 && y === -Infinity)) {
|
122 | return 0
|
123 | }
|
124 |
|
125 |
|
126 |
|
127 |
|
128 | if (config.predictable &&
|
129 | ((x < -1 && y === Infinity) ||
|
130 | (x > -1 && x < 0 && y === -Infinity))) {
|
131 | return NaN
|
132 | }
|
133 |
|
134 | if (isInteger(y) || x >= 0 || config.predictable) {
|
135 | return Math.pow(x, y)
|
136 | } else {
|
137 | return new type.Complex(x, 0).pow(y, 0)
|
138 | }
|
139 | }
|
140 |
|
141 | |
142 |
|
143 |
|
144 |
|
145 |
|
146 |
|
147 |
|
148 | function _powArray (x, y) {
|
149 | if (!isInteger(y) || y < 0) {
|
150 | throw new TypeError('For A^b, b must be a positive integer (value is ' + y + ')')
|
151 | }
|
152 |
|
153 | const s = size(x)
|
154 | if (s.length !== 2) {
|
155 | throw new Error('For A^b, A must be 2 dimensional (A has ' + s.length + ' dimensions)')
|
156 | }
|
157 | if (s[0] !== s[1]) {
|
158 | throw new Error('For A^b, A must be square (size is ' + s[0] + 'x' + s[1] + ')')
|
159 | }
|
160 |
|
161 | let res = identity(s[0]).valueOf()
|
162 | let px = x
|
163 | while (y >= 1) {
|
164 | if ((y & 1) === 1) {
|
165 | res = multiply(px, res)
|
166 | }
|
167 | y >>= 1
|
168 | px = multiply(px, px)
|
169 | }
|
170 | return res
|
171 | }
|
172 |
|
173 | |
174 |
|
175 |
|
176 |
|
177 |
|
178 |
|
179 |
|
180 | function _powMatrix (x, y) {
|
181 | return matrix(_powArray(x.valueOf(), y))
|
182 | }
|
183 |
|
184 | pow.toTex = {
|
185 | 2: `\\left(\${args[0]}\\right)${latex.operators['pow']}{\${args[1]}}`
|
186 | }
|
187 |
|
188 | return pow
|
189 | }
|
190 |
|
191 | exports.name = 'pow'
|
192 | exports.factory = factory
|