mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-24 00:00:44 +01:00
[poincare/power] Rename and comment computeRealRootOfRationalPow
This commit is contained in:
@@ -34,7 +34,7 @@ public:
|
||||
int polynomialDegree(Context * context, const char * symbolName) const override;
|
||||
int getPolynomialCoefficients(Context * context, const char * symbolName, Expression coefficients[], ExpressionNode::SymbolicComputation symbolicComputation) const override;
|
||||
|
||||
template<typename T> static Complex<T> computeRealRootOfRationalPow(const std::complex<T> c, T p, T q);
|
||||
template<typename T> static Complex<T> tryComputeRealRootOfRationalPow(const std::complex<T> c, T p, T q);
|
||||
template<typename T> static Complex<T> compute(const std::complex<T> c, const std::complex<T> d, Preferences::ComplexFormat complexFormat);
|
||||
|
||||
private:
|
||||
|
||||
@@ -48,7 +48,7 @@ Evaluation<T> NthRootNode::templatedApproximate(Context * context, Preferences::
|
||||
* correspond to the principale angle. */
|
||||
if (complexFormat == Preferences::ComplexFormat::Real && indexc.imag() == 0.0 && std::round(indexc.real()) == indexc.real()) {
|
||||
// root(x, q) with q integer and x real
|
||||
Complex<T> result = PowerNode::computeRealRootOfRationalPow(basec, (T)1.0, indexc.real());
|
||||
Complex<T> result = PowerNode::tryComputeRealRootOfRationalPow(basec, (T)1.0, indexc.real());
|
||||
if (!result.isUndefined()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -128,16 +128,24 @@ bool PowerNode::childAtIndexNeedsUserParentheses(const Expression & child, int c
|
||||
// Private
|
||||
|
||||
template<typename T>
|
||||
Complex<T> PowerNode::computeRealRootOfRationalPow(const std::complex<T> c, T p, T q) {
|
||||
// Compute real root of c^(p/q) with p, q integers if it has a real root
|
||||
Complex<T> PowerNode::tryComputeRealRootOfRationalPow(const std::complex<T> c, T p, T q) {
|
||||
// Assert p and q are in fact integers
|
||||
assert(std::round(p) == p);
|
||||
assert(std::round(q) == q);
|
||||
/* Try to find a real root of c^(p/q) with p, q integers. If none is found
|
||||
* easily, return undefined -> this does not mean there is no real root. */
|
||||
if (c.imag() == 0 && std::pow((T)-1.0, q) < 0.0) {
|
||||
/* If c real and q odd integer (q odd if (-1)^q = -1), a real root does
|
||||
* exist (which is not necessarily the principal root)! */
|
||||
* exist (which is not necessarily the principal root)!
|
||||
* For q even integer, a real root does not necessarily exist (example:
|
||||
* -2 ^(1/2)). */
|
||||
std::complex<T> absc = c;
|
||||
absc.real(std::fabs(absc.real()));
|
||||
// compute |c|^(p/q) which is a real
|
||||
Complex<T> absCPowD = PowerNode::compute(absc, std::complex<T>(p/q), Preferences::ComplexFormat::Real);
|
||||
// c^(p/q) = (sign(c)^p)*|c|^(p/q) = -|c|^(p/q) iff c < 0 and p odd
|
||||
/* As q is odd, c^(p/q) = (sign(c)^(1/q))^p * |c|^(p/q)
|
||||
* = sign(c)^p * |c|^(p/q)
|
||||
* = -|c|^(p/q) iff c < 0 and p odd */
|
||||
return c.real() < 0 && std::pow((T)-1.0, p) < 0.0 ? Complex<T>::Builder(-absCPowD.stdComplex()) : absCPowD;
|
||||
}
|
||||
return Complex<T>::Undefined();
|
||||
@@ -313,7 +321,7 @@ template<typename T> Evaluation<T> PowerNode::templatedApproximate(Context * con
|
||||
if (std::isnan(p) || std::isnan(q)) {
|
||||
goto defaultApproximation;
|
||||
}
|
||||
Complex<T> result = computeRealRootOfRationalPow(c, p, q);
|
||||
Complex<T> result = tryComputeRealRootOfRationalPow(c, p, q);
|
||||
if (!result.isUndefined()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user