/
QuadraticRealPolynomial.js
139 lines (120 loc) · 4.34 KB
/
QuadraticRealPolynomial.js
1
2
3
4
5
6
7
8
9
10
11
12
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*global define*/
define([
'./DeveloperError',
'./Math'
], function(
DeveloperError,
CesiumMath) {
'use strict';
/**
* Defines functions for 2nd order polynomial functions of one variable with only real coefficients.
*
* @exports QuadraticRealPolynomial
*/
var QuadraticRealPolynomial = {};
/**
* Provides the discriminant of the quadratic equation from the supplied coefficients.
*
* @param {Number} a The coefficient of the 2nd order monomial.
* @param {Number} b The coefficient of the 1st order monomial.
* @param {Number} c The coefficient of the 0th order monomial.
* @returns {Number} The value of the discriminant.
*/
QuadraticRealPolynomial.computeDiscriminant = function(a, b, c) {
//>>includeStart('debug', pragmas.debug);
if (typeof a !== 'number') {
throw new DeveloperError('a is a required number.');
}
if (typeof b !== 'number') {
throw new DeveloperError('b is a required number.');
}
if (typeof c !== 'number') {
throw new DeveloperError('c is a required number.');
}
//>>includeEnd('debug');
var discriminant = b * b - 4.0 * a * c;
return discriminant;
};
function addWithCancellationCheck(left, right, tolerance) {
var difference = left + right;
if ((CesiumMath.sign(left) !== CesiumMath.sign(right)) &&
Math.abs(difference / Math.max(Math.abs(left), Math.abs(right))) < tolerance) {
return 0.0;
}
return difference;
}
/**
* Provides the real valued roots of the quadratic polynomial with the provided coefficients.
*
* @param {Number} a The coefficient of the 2nd order monomial.
* @param {Number} b The coefficient of the 1st order monomial.
* @param {Number} c The coefficient of the 0th order monomial.
* @returns {Number[]} The real valued roots.
*/
QuadraticRealPolynomial.computeRealRoots = function(a, b, c) {
//>>includeStart('debug', pragmas.debug);
if (typeof a !== 'number') {
throw new DeveloperError('a is a required number.');
}
if (typeof b !== 'number') {
throw new DeveloperError('b is a required number.');
}
if (typeof c !== 'number') {
throw new DeveloperError('c is a required number.');
}
//>>includeEnd('debug');
var ratio;
if (a === 0.0) {
if (b === 0.0) {
// Constant function: c = 0.
return [];
}
// Linear function: b * x + c = 0.
return [-c / b];
} else if (b === 0.0) {
if (c === 0.0) {
// 2nd order monomial: a * x^2 = 0.
return [0.0, 0.0];
}
var cMagnitude = Math.abs(c);
var aMagnitude = Math.abs(a);
if ((cMagnitude < aMagnitude) && (cMagnitude / aMagnitude < CesiumMath.EPSILON14)) { // c ~= 0.0.
// 2nd order monomial: a * x^2 = 0.
return [0.0, 0.0];
} else if ((cMagnitude > aMagnitude) && (aMagnitude / cMagnitude < CesiumMath.EPSILON14)) { // a ~= 0.0.
// Constant function: c = 0.
return [];
}
// a * x^2 + c = 0
ratio = -c / a;
if (ratio < 0.0) {
// Both roots are complex.
return [];
}
// Both roots are real.
var root = Math.sqrt(ratio);
return [-root, root];
} else if (c === 0.0) {
// a * x^2 + b * x = 0
ratio = -b / a;
if (ratio < 0.0) {
return [ratio, 0.0];
}
return [0.0, ratio];
}
// a * x^2 + b * x + c = 0
var b2 = b * b;
var four_ac = 4.0 * a * c;
var radicand = addWithCancellationCheck(b2, -four_ac, CesiumMath.EPSILON14);
if (radicand < 0.0) {
// Both roots are complex.
return [];
}
var q = -0.5 * addWithCancellationCheck(b, CesiumMath.sign(b) * Math.sqrt(radicand), CesiumMath.EPSILON14);
if (b > 0.0) {
return [q / a, c / q];
}
return [c / q, q / a];
};
return QuadraticRealPolynomial;
});