pow.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.createPow = void 0;
  6. var _factory = require("../../utils/factory.js");
  7. var _number = require("../../utils/number.js");
  8. var _array = require("../../utils/array.js");
  9. var _index = require("../../plain/number/index.js");
  10. var name = 'pow';
  11. var dependencies = ['typed', 'config', 'identity', 'multiply', 'matrix', 'inv', 'fraction', 'number', 'Complex'];
  12. var createPow = /* #__PURE__ */(0, _factory.factory)(name, dependencies, function (_ref) {
  13. var typed = _ref.typed,
  14. config = _ref.config,
  15. identity = _ref.identity,
  16. multiply = _ref.multiply,
  17. matrix = _ref.matrix,
  18. inv = _ref.inv,
  19. number = _ref.number,
  20. fraction = _ref.fraction,
  21. Complex = _ref.Complex;
  22. /**
  23. * Calculates the power of x to y, `x ^ y`.
  24. *
  25. * Matrix exponentiation is supported for square matrices `x` and integers `y`:
  26. * when `y` is nonnegative, `x` may be any square matrix; and when `y` is
  27. * negative, `x` must be invertible, and then this function returns
  28. * inv(x)^(-y).
  29. *
  30. * For cubic roots of negative numbers, the function returns the principal
  31. * root by default. In order to let the function return the real root,
  32. * math.js can be configured with `math.config({predictable: true})`.
  33. * To retrieve all cubic roots of a value, use `math.cbrt(x, true)`.
  34. *
  35. * Syntax:
  36. *
  37. * math.pow(x, y)
  38. *
  39. * Examples:
  40. *
  41. * math.pow(2, 3) // returns number 8
  42. *
  43. * const a = math.complex(2, 3)
  44. * math.pow(a, 2) // returns Complex -5 + 12i
  45. *
  46. * const b = [[1, 2], [4, 3]]
  47. * math.pow(b, 2) // returns Array [[9, 8], [16, 17]]
  48. *
  49. * const c = [[1, 2], [4, 3]]
  50. * math.pow(c, -1) // returns Array [[-0.6, 0.4], [0.8, -0.2]]
  51. *
  52. * See also:
  53. *
  54. * multiply, sqrt, cbrt, nthRoot
  55. *
  56. * @param {number | BigNumber | Complex | Unit | Array | Matrix} x The base
  57. * @param {number | BigNumber | Complex} y The exponent
  58. * @return {number | BigNumber | Complex | Array | Matrix} The value of `x` to the power `y`
  59. */
  60. return typed(name, {
  61. 'number, number': _pow,
  62. 'Complex, Complex': function ComplexComplex(x, y) {
  63. return x.pow(y);
  64. },
  65. 'BigNumber, BigNumber': function BigNumberBigNumber(x, y) {
  66. if (y.isInteger() || x >= 0 || config.predictable) {
  67. return x.pow(y);
  68. } else {
  69. return new Complex(x.toNumber(), 0).pow(y.toNumber(), 0);
  70. }
  71. },
  72. 'Fraction, Fraction': function FractionFraction(x, y) {
  73. var result = x.pow(y);
  74. if (result != null) {
  75. return result;
  76. }
  77. if (config.predictable) {
  78. throw new Error('Result of pow is non-rational and cannot be expressed as a fraction');
  79. } else {
  80. return _pow(x.valueOf(), y.valueOf());
  81. }
  82. },
  83. 'Array, number': _powArray,
  84. 'Array, BigNumber': function ArrayBigNumber(x, y) {
  85. return _powArray(x, y.toNumber());
  86. },
  87. 'Matrix, number': _powMatrix,
  88. 'Matrix, BigNumber': function MatrixBigNumber(x, y) {
  89. return _powMatrix(x, y.toNumber());
  90. },
  91. 'Unit, number | BigNumber': function UnitNumberBigNumber(x, y) {
  92. return x.pow(y);
  93. }
  94. });
  95. /**
  96. * Calculates the power of x to y, x^y, for two numbers.
  97. * @param {number} x
  98. * @param {number} y
  99. * @return {number | Complex} res
  100. * @private
  101. */
  102. function _pow(x, y) {
  103. // Alternatively could define a 'realmode' config option or something, but
  104. // 'predictable' will work for now
  105. if (config.predictable && !(0, _number.isInteger)(y) && x < 0) {
  106. // Check to see if y can be represented as a fraction
  107. try {
  108. var yFrac = fraction(y);
  109. var yNum = number(yFrac);
  110. if (y === yNum || Math.abs((y - yNum) / y) < 1e-14) {
  111. if (yFrac.d % 2 === 1) {
  112. return (yFrac.n % 2 === 0 ? 1 : -1) * Math.pow(-x, y);
  113. }
  114. }
  115. } catch (ex) {
  116. // fraction() throws an error if y is Infinity, etc.
  117. }
  118. // Unable to express y as a fraction, so continue on
  119. }
  120. // **for predictable mode** x^Infinity === NaN if x < -1
  121. // N.B. this behavour is different from `Math.pow` which gives
  122. // (-2)^Infinity === Infinity
  123. if (config.predictable && (x < -1 && y === Infinity || x > -1 && x < 0 && y === -Infinity)) {
  124. return NaN;
  125. }
  126. if ((0, _number.isInteger)(y) || x >= 0 || config.predictable) {
  127. return (0, _index.powNumber)(x, y);
  128. } else {
  129. // TODO: the following infinity checks are duplicated from powNumber. Deduplicate this somehow
  130. // x^Infinity === 0 if -1 < x < 1
  131. // A real number 0 is returned instead of complex(0)
  132. if (x * x < 1 && y === Infinity || x * x > 1 && y === -Infinity) {
  133. return 0;
  134. }
  135. return new Complex(x, 0).pow(y, 0);
  136. }
  137. }
  138. /**
  139. * Calculate the power of a 2d array
  140. * @param {Array} x must be a 2 dimensional, square matrix
  141. * @param {number} y a integer value (positive if `x` is not invertible)
  142. * @returns {Array}
  143. * @private
  144. */
  145. function _powArray(x, y) {
  146. if (!(0, _number.isInteger)(y)) {
  147. throw new TypeError('For A^b, b must be an integer (value is ' + y + ')');
  148. }
  149. // verify that A is a 2 dimensional square matrix
  150. var s = (0, _array.arraySize)(x);
  151. if (s.length !== 2) {
  152. throw new Error('For A^b, A must be 2 dimensional (A has ' + s.length + ' dimensions)');
  153. }
  154. if (s[0] !== s[1]) {
  155. throw new Error('For A^b, A must be square (size is ' + s[0] + 'x' + s[1] + ')');
  156. }
  157. if (y < 0) {
  158. try {
  159. return _powArray(inv(x), -y);
  160. } catch (error) {
  161. if (error.message === 'Cannot calculate inverse, determinant is zero') {
  162. throw new TypeError('For A^b, when A is not invertible, b must be a positive integer (value is ' + y + ')');
  163. }
  164. throw error;
  165. }
  166. }
  167. var res = identity(s[0]).valueOf();
  168. var px = x;
  169. while (y >= 1) {
  170. if ((y & 1) === 1) {
  171. res = multiply(px, res);
  172. }
  173. y >>= 1;
  174. px = multiply(px, px);
  175. }
  176. return res;
  177. }
  178. /**
  179. * Calculate the power of a 2d matrix
  180. * @param {Matrix} x must be a 2 dimensional, square matrix
  181. * @param {number} y a positive, integer value
  182. * @returns {Matrix}
  183. * @private
  184. */
  185. function _powMatrix(x, y) {
  186. return matrix(_powArray(x.valueOf(), y));
  187. }
  188. });
  189. exports.createPow = createPow;