polynomialRoot.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. Object.defineProperty(exports, "__esModule", {
  4. value: true
  5. });
  6. exports.createPolynomialRoot = void 0;
  7. var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
  8. var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
  9. var _factory = require("../../utils/factory.js");
  10. var name = 'polynomialRoot';
  11. var dependencies = ['typed', 'isZero', 'equalScalar', 'add', 'subtract', 'multiply', 'divide', 'sqrt', 'unaryMinus', 'cbrt', 'typeOf', 'im', 're'];
  12. var createPolynomialRoot = /* #__PURE__ */(0, _factory.factory)(name, dependencies, function (_ref) {
  13. var typed = _ref.typed,
  14. isZero = _ref.isZero,
  15. equalScalar = _ref.equalScalar,
  16. add = _ref.add,
  17. subtract = _ref.subtract,
  18. multiply = _ref.multiply,
  19. divide = _ref.divide,
  20. sqrt = _ref.sqrt,
  21. unaryMinus = _ref.unaryMinus,
  22. cbrt = _ref.cbrt,
  23. typeOf = _ref.typeOf,
  24. im = _ref.im,
  25. re = _ref.re;
  26. /**
  27. * Finds the numerical values of the distinct roots of a polynomial with real or complex coefficients.
  28. * Currently operates only on linear, quadratic, and cubic polynomials using the standard
  29. * formulas for the roots.
  30. *
  31. * Syntax:
  32. *
  33. * polynomialRoot(constant, linearCoeff, quadraticCoeff, cubicCoeff)
  34. *
  35. * Examples:
  36. * // linear
  37. * math.polynomialRoot(6, 3) // [-2]
  38. * math.polynomialRoot(math.complex(6,3), 3) // [-2 - i]
  39. * math.polynomialRoot(math.complex(6,3), math.complex(2,1)) // [-3 + 0i]
  40. * // quadratic
  41. * math.polynomialRoot(2, -3, 1) // [2, 1]
  42. * math.polynomialRoot(8, 8, 2) // [-2]
  43. * math.polynomialRoot(-2, 0, 1) // [1.4142135623730951, -1.4142135623730951]
  44. * math.polynomialRoot(2, -2, 1) // [1 + i, 1 - i]
  45. * math.polynomialRoot(math.complex(1,3), math.complex(-3, -2), 1) // [2 + i, 1 + i]
  46. * // cubic
  47. * math.polynomialRoot(-6, 11, -6, 1) // [1, 3, 2]
  48. * math.polynomialRoot(-8, 0, 0, 1) // [-1 - 1.7320508075688774i, 2, -1 + 1.7320508075688774i]
  49. * math.polynomialRoot(0, 8, 8, 2) // [0, -2]
  50. * math.polynomialRoot(1, 1, 1, 1) // [-1 + 0i, 0 - i, 0 + i]
  51. *
  52. * See also:
  53. * cbrt, sqrt
  54. *
  55. * @param {... number | Complex} coeffs
  56. * The coefficients of the polynomial, starting with with the constant coefficent, followed
  57. * by the linear coefficient and subsequent coefficients of increasing powers.
  58. * @return {Array} The distinct roots of the polynomial
  59. */
  60. return typed(name, {
  61. 'number|Complex, ...number|Complex': function numberComplexNumberComplex(constant, restCoeffs) {
  62. var coeffs = [constant].concat((0, _toConsumableArray2["default"])(restCoeffs));
  63. while (coeffs.length > 0 && isZero(coeffs[coeffs.length - 1])) {
  64. coeffs.pop();
  65. }
  66. if (coeffs.length < 2) {
  67. throw new RangeError("Polynomial [".concat(constant, ", ").concat(restCoeffs, "] must have a non-zero non-constant coefficient"));
  68. }
  69. switch (coeffs.length) {
  70. case 2:
  71. // linear
  72. return [unaryMinus(divide(coeffs[0], coeffs[1]))];
  73. case 3:
  74. {
  75. // quadratic
  76. var _coeffs = (0, _slicedToArray2["default"])(coeffs, 3),
  77. c = _coeffs[0],
  78. b = _coeffs[1],
  79. a = _coeffs[2];
  80. var denom = multiply(2, a);
  81. var d1 = multiply(b, b);
  82. var d2 = multiply(4, a, c);
  83. if (equalScalar(d1, d2)) return [divide(unaryMinus(b), denom)];
  84. var discriminant = sqrt(subtract(d1, d2));
  85. return [divide(subtract(discriminant, b), denom), divide(subtract(unaryMinus(discriminant), b), denom)];
  86. }
  87. case 4:
  88. {
  89. // cubic, cf. https://en.wikipedia.org/wiki/Cubic_equation
  90. var _coeffs2 = (0, _slicedToArray2["default"])(coeffs, 4),
  91. d = _coeffs2[0],
  92. _c = _coeffs2[1],
  93. _b = _coeffs2[2],
  94. _a = _coeffs2[3];
  95. var _denom = unaryMinus(multiply(3, _a));
  96. var D0_1 = multiply(_b, _b);
  97. var D0_2 = multiply(3, _a, _c);
  98. var D1_1 = add(multiply(2, _b, _b, _b), multiply(27, _a, _a, d));
  99. var D1_2 = multiply(9, _a, _b, _c);
  100. if (equalScalar(D0_1, D0_2) && equalScalar(D1_1, D1_2)) {
  101. return [divide(_b, _denom)];
  102. }
  103. var Delta0 = subtract(D0_1, D0_2);
  104. var Delta1 = subtract(D1_1, D1_2);
  105. var discriminant1 = add(multiply(18, _a, _b, _c, d), multiply(_b, _b, _c, _c));
  106. var discriminant2 = add(multiply(4, _b, _b, _b, d), multiply(4, _a, _c, _c, _c), multiply(27, _a, _a, d, d));
  107. if (equalScalar(discriminant1, discriminant2)) {
  108. return [divide(subtract(multiply(4, _a, _b, _c), add(multiply(9, _a, _a, d), multiply(_b, _b, _b))), multiply(_a, Delta0)),
  109. // simple root
  110. divide(subtract(multiply(9, _a, d), multiply(_b, _c)), multiply(2, Delta0)) // double root
  111. ];
  112. }
  113. // OK, we have three distinct roots
  114. var Ccubed;
  115. if (equalScalar(D0_1, D0_2)) {
  116. Ccubed = Delta1;
  117. } else {
  118. Ccubed = divide(add(Delta1, sqrt(subtract(multiply(Delta1, Delta1), multiply(4, Delta0, Delta0, Delta0)))), 2);
  119. }
  120. var allRoots = true;
  121. var rawRoots = cbrt(Ccubed, allRoots).toArray().map(function (C) {
  122. return divide(add(_b, C, divide(Delta0, C)), _denom);
  123. });
  124. return rawRoots.map(function (r) {
  125. if (typeOf(r) === 'Complex' && equalScalar(re(r), re(r) + im(r))) {
  126. return re(r);
  127. }
  128. return r;
  129. });
  130. }
  131. default:
  132. throw new RangeError("only implemented for cubic or lower-order polynomials, not ".concat(coeffs));
  133. }
  134. }
  135. });
  136. });
  137. exports.createPolynomialRoot = createPolynomialRoot;