| 2013 | return this |
| 2014 | } |
| 2015 | pow(complex) { |
| 2016 | /* I couldn't find a good formula, so here is a derivation and optimization |
| 2017 | * |
| 2018 | * z_1^z_2 = (a + bi)^(c + di) |
| 2019 | * = exp((c + di) * log(a + bi) |
| 2020 | * = pow(a^2 + b^2, (c + di) / 2) * exp(i(c + di)atan2(b, a)) |
| 2021 | * =>... |
| 2022 | * Re = (pow(a^2 + b^2, c / 2) * exp(-d * atan2(b, a))) * cos(d * log(a^2 + b^2) / 2 + c * atan2(b, a)) |
| 2023 | * Im = (pow(a^2 + b^2, c / 2) * exp(-d * atan2(b, a))) * sin(d * log(a^2 + b^2) / 2 + c * atan2(b, a)) |
| 2024 | * |
| 2025 | * =>... |
| 2026 | * Re = exp(c * log(sqrt(a^2 + b^2)) - d * atan2(b, a)) * cos(d * log(sqrt(a^2 + b^2)) + c * atan2(b, a)) |
| 2027 | * Im = exp(c * log(sqrt(a^2 + b^2)) - d * atan2(b, a)) * sin(d * log(sqrt(a^2 + b^2)) + c * atan2(b, a)) |
| 2028 | * |
| 2029 | * => |
| 2030 | * Re = exp(c * logsq2 - d * arg(z_1)) * cos(d * logsq2 + c * arg(z_1)) |
| 2031 | * Im = exp(c * logsq2 - d * arg(z_1)) * sin(d * logsq2 + c * arg(z_1)) |
| 2032 | * |
| 2033 | */ |
| 2034 | if (!complex.isComplex) { |
| 2035 | throw "[TheoremJS]: Complex operation require complex numbers" |
| 2036 | } |
| 2037 | |
| 2038 | function logHypot(a, b) { |
| 2039 | a = new BigNumber(a).toNumber() |
| 2040 | b = new BigNumber(b).toNumber() |
| 2041 | |
| 2042 | const _a = Math.abs(a); |
| 2043 | const _b = Math.abs(b); |
| 2044 | |
| 2045 | if (a === 0) { |
| 2046 | return new BigNumber(Math.log(_b)); |
| 2047 | } |
| 2048 | |
| 2049 | if (b === 0) { |
| 2050 | return new BigNumber(Math.log(_a)); |
| 2051 | } |
| 2052 | |
| 2053 | if (_a < 3000 && _b < 3000) { |
| 2054 | return new BigNumber(Math.log(a * a + b * b) * 0.5); |
| 2055 | } |
| 2056 | |
| 2057 | /* I got 4 ideas to compute this property without overflow: |
| 2058 | * |
| 2059 | * Testing 1000000 times with random samples for a,b ∈ [1, 1000000000] against a big decimal library to get an error estimate |
| 2060 | * |
| 2061 | * 1. Only eliminate the square root: (OVERALL ERROR: 3.9122483030951116e-11) |
| 2062 | Math.log(a * a + b * b) / 2 |
| 2063 | * |
| 2064 | * |
| 2065 | * 2. Try to use the non-overflowing pythagoras: (OVERALL ERROR: 8.889760039210159e-10) |
| 2066 | var fn = function(a, b) { |
| 2067 | a = Math.abs(a); |
| 2068 | b = Math.abs(b); |
| 2069 | var t = Math.min(a, b); |
| 2070 | a = Math.max(a, b); |
| 2071 | t = t / a; |
| 2072 | return Math.log(a) + Math.log(1 + t * t) / 2; |