QuadraticRealPolynomial.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import DeveloperError from './DeveloperError.js';
  2. import CesiumMath from './Math.js';
  3. /**
  4. * Defines functions for 2nd order polynomial functions of one variable with only real coefficients.
  5. *
  6. * @exports QuadraticRealPolynomial
  7. */
  8. var QuadraticRealPolynomial = {};
  9. /**
  10. * Provides the discriminant of the quadratic equation from the supplied coefficients.
  11. *
  12. * @param {Number} a The coefficient of the 2nd order monomial.
  13. * @param {Number} b The coefficient of the 1st order monomial.
  14. * @param {Number} c The coefficient of the 0th order monomial.
  15. * @returns {Number} The value of the discriminant.
  16. */
  17. QuadraticRealPolynomial.computeDiscriminant = function(a, b, c) {
  18. //>>includeStart('debug', pragmas.debug);
  19. if (typeof a !== 'number') {
  20. throw new DeveloperError('a is a required number.');
  21. }
  22. if (typeof b !== 'number') {
  23. throw new DeveloperError('b is a required number.');
  24. }
  25. if (typeof c !== 'number') {
  26. throw new DeveloperError('c is a required number.');
  27. }
  28. //>>includeEnd('debug');
  29. var discriminant = b * b - 4.0 * a * c;
  30. return discriminant;
  31. };
  32. function addWithCancellationCheck(left, right, tolerance) {
  33. var difference = left + right;
  34. if ((CesiumMath.sign(left) !== CesiumMath.sign(right)) &&
  35. Math.abs(difference / Math.max(Math.abs(left), Math.abs(right))) < tolerance) {
  36. return 0.0;
  37. }
  38. return difference;
  39. }
  40. /**
  41. * Provides the real valued roots of the quadratic polynomial with the provided coefficients.
  42. *
  43. * @param {Number} a The coefficient of the 2nd order monomial.
  44. * @param {Number} b The coefficient of the 1st order monomial.
  45. * @param {Number} c The coefficient of the 0th order monomial.
  46. * @returns {Number[]} The real valued roots.
  47. */
  48. QuadraticRealPolynomial.computeRealRoots = function(a, b, c) {
  49. //>>includeStart('debug', pragmas.debug);
  50. if (typeof a !== 'number') {
  51. throw new DeveloperError('a is a required number.');
  52. }
  53. if (typeof b !== 'number') {
  54. throw new DeveloperError('b is a required number.');
  55. }
  56. if (typeof c !== 'number') {
  57. throw new DeveloperError('c is a required number.');
  58. }
  59. //>>includeEnd('debug');
  60. var ratio;
  61. if (a === 0.0) {
  62. if (b === 0.0) {
  63. // Constant function: c = 0.
  64. return [];
  65. }
  66. // Linear function: b * x + c = 0.
  67. return [-c / b];
  68. } else if (b === 0.0) {
  69. if (c === 0.0) {
  70. // 2nd order monomial: a * x^2 = 0.
  71. return [0.0, 0.0];
  72. }
  73. var cMagnitude = Math.abs(c);
  74. var aMagnitude = Math.abs(a);
  75. if ((cMagnitude < aMagnitude) && (cMagnitude / aMagnitude < CesiumMath.EPSILON14)) { // c ~= 0.0.
  76. // 2nd order monomial: a * x^2 = 0.
  77. return [0.0, 0.0];
  78. } else if ((cMagnitude > aMagnitude) && (aMagnitude / cMagnitude < CesiumMath.EPSILON14)) { // a ~= 0.0.
  79. // Constant function: c = 0.
  80. return [];
  81. }
  82. // a * x^2 + c = 0
  83. ratio = -c / a;
  84. if (ratio < 0.0) {
  85. // Both roots are complex.
  86. return [];
  87. }
  88. // Both roots are real.
  89. var root = Math.sqrt(ratio);
  90. return [-root, root];
  91. } else if (c === 0.0) {
  92. // a * x^2 + b * x = 0
  93. ratio = -b / a;
  94. if (ratio < 0.0) {
  95. return [ratio, 0.0];
  96. }
  97. return [0.0, ratio];
  98. }
  99. // a * x^2 + b * x + c = 0
  100. var b2 = b * b;
  101. var four_ac = 4.0 * a * c;
  102. var radicand = addWithCancellationCheck(b2, -four_ac, CesiumMath.EPSILON14);
  103. if (radicand < 0.0) {
  104. // Both roots are complex.
  105. return [];
  106. }
  107. var q = -0.5 * addWithCancellationCheck(b, CesiumMath.sign(b) * Math.sqrt(radicand), CesiumMath.EPSILON14);
  108. if (b > 0.0) {
  109. return [q / a, c / q];
  110. }
  111. return [c / q, q / a];
  112. };
  113. export default QuadraticRealPolynomial;