mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-23 07:40:42 +01:00
[poincare] Returns a RealUndefined evaluation for Expression that are
always real. This avoids that floor(i) is simplified to (undef, 0) but approximates to (undef, undef)
This commit is contained in:
@@ -45,6 +45,9 @@ public:
|
||||
static Complex<T> Undefined() {
|
||||
return Complex<T>::Builder(NAN, NAN);
|
||||
}
|
||||
static Complex<T> RealUndefined() {
|
||||
return Complex<T>::Builder(NAN, 0.0);
|
||||
}
|
||||
std::complex<T> stdComplex() { return *node(); }
|
||||
T real() { return node()->real(); }
|
||||
T imag() { return node()->imag(); }
|
||||
|
||||
@@ -26,7 +26,7 @@ int CeilingNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloa
|
||||
template<typename T>
|
||||
Complex<T> CeilingNode::computeOnComplex(const std::complex<T> c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) {
|
||||
if (c.imag() != 0) {
|
||||
return Complex<T>::Undefined();
|
||||
return Complex<T>::RealUndefined();
|
||||
}
|
||||
return Complex<T>::Builder(std::ceil(c.real()));
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ Evaluation<T> ConfidenceIntervalNode::templatedApproximate(Context * context, Pr
|
||||
T f = static_cast<Complex<T> &>(fInput).toScalar();
|
||||
T n = static_cast<Complex<T> &>(nInput).toScalar();
|
||||
if (std::isnan(f) || std::isnan(n) || n != (int)n || n < 0 || f < 0 || f > 1) {
|
||||
return Complex<T>::Undefined();
|
||||
return Complex<T>::RealUndefined();
|
||||
}
|
||||
std::complex<T> operands[2];
|
||||
operands[0] = std::complex<T>(f - 1/std::sqrt(n));
|
||||
|
||||
@@ -46,7 +46,7 @@ Evaluation<T> DerivativeNode::templatedApproximate(Context * context, Preference
|
||||
T functionValue = approximateWithArgument(evaluationArgument, context, complexFormat, angleUnit);
|
||||
// No complex/matrix version of Derivative
|
||||
if (std::isnan(evaluationArgument) || std::isnan(functionValue)) {
|
||||
return Complex<T>::Undefined();
|
||||
return Complex<T>::RealUndefined();
|
||||
}
|
||||
|
||||
T error = sizeof(T) == sizeof(double) ? DBL_MAX : FLT_MAX;
|
||||
@@ -71,7 +71,7 @@ Evaluation<T> DerivativeNode::templatedApproximate(Context * context, Preference
|
||||
|| (std::fabs(result) < k_maxErrorRateOnApproximation && std::fabs(error) > std::fabs(result))
|
||||
|| (std::fabs(result) >= k_maxErrorRateOnApproximation && std::fabs(error/result) > k_maxErrorRateOnApproximation))
|
||||
{
|
||||
return Complex<T>::Undefined();
|
||||
return Complex<T>::RealUndefined();
|
||||
}
|
||||
static T min = sizeof(T) == sizeof(double) ? DBL_MIN : FLT_MIN;
|
||||
if (std::fabs(error) < min) {
|
||||
|
||||
@@ -30,7 +30,7 @@ Evaluation<T> DivisionQuotientNode::templatedApproximate(Context * context, Pref
|
||||
T f1 = f1Input.toScalar();
|
||||
T f2 = f2Input.toScalar();
|
||||
if (std::isnan(f1) || std::isnan(f2) || f1 != (int)f1 || f2 != (int)f2) {
|
||||
return Complex<T>::Undefined();
|
||||
return Complex<T>::RealUndefined();
|
||||
}
|
||||
return Complex<T>::Builder(std::floor(f1/f2));
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ Evaluation<T> DivisionRemainderNode::templatedApproximate(Context * context, Pre
|
||||
T f1 = f1Input.toScalar();
|
||||
T f2 = f2Input.toScalar();
|
||||
if (std::isnan(f1) || std::isnan(f2) || f1 != (int)f1 || f2 != (int)f2) {
|
||||
return Complex<T>::Undefined();
|
||||
return Complex<T>::RealUndefined();
|
||||
}
|
||||
return Complex<T>::Builder(std::round(f1-f2*std::floor(f1/f2)));
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ template<typename T>
|
||||
Complex<T> FactorialNode::computeOnComplex(const std::complex<T> c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) {
|
||||
T n = c.real();
|
||||
if (c.imag() != 0 || std::isnan(n) || n != (int)n || n < 0) {
|
||||
return Complex<T>::Undefined();
|
||||
return Complex<T>::RealUndefined();
|
||||
}
|
||||
T result = 1;
|
||||
for (int i = 1; i <= (int)n; i++) {
|
||||
|
||||
@@ -26,7 +26,7 @@ int FloorNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatM
|
||||
template<typename T>
|
||||
Complex<T> FloorNode::computeOnComplex(const std::complex<T> c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) {
|
||||
if (c.imag() != 0) {
|
||||
return Complex<T>::Undefined();
|
||||
return Complex<T>::RealUndefined();
|
||||
}
|
||||
return Complex<T>::Builder(std::floor(c.real()));
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ Expression FracPartNode::shallowReduce(ReductionContext reductionContext) {
|
||||
template<typename T>
|
||||
Complex<T> FracPartNode::computeOnComplex(const std::complex<T> c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) {
|
||||
if (c.imag() != 0) {
|
||||
return Complex<T>::Undefined();
|
||||
return Complex<T>::RealUndefined();
|
||||
}
|
||||
return Complex<T>::Builder(c.real()-std::floor(c.real()));
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ Evaluation<T> GreatCommonDivisorNode::templatedApproximate(Context * context, Pr
|
||||
int a = ApproximationHelper::PositiveIntegerApproximationIfPossible<T>(childAtIndex(0), &isUndefined, context, complexFormat, angleUnit);
|
||||
int b = ApproximationHelper::PositiveIntegerApproximationIfPossible<T>(childAtIndex(1), &isUndefined, context, complexFormat, angleUnit);
|
||||
if (isUndefined) {
|
||||
return Complex<T>::Undefined();
|
||||
return Complex<T>::RealUndefined();
|
||||
}
|
||||
if (b > a) {
|
||||
int temp = b;
|
||||
|
||||
@@ -50,7 +50,7 @@ Evaluation<T> IntegralNode::templatedApproximate(Context * context, Preferences:
|
||||
T a = aInput.toScalar();
|
||||
T b = bInput.toScalar();
|
||||
if (std::isnan(a) || std::isnan(b)) {
|
||||
return Complex<T>::Undefined();
|
||||
return Complex<T>::RealUndefined();
|
||||
}
|
||||
#ifdef LAGRANGE_METHOD
|
||||
T result = lagrangeGaussQuadrature<T>(a, b, context, complexFormat, angleUnit);
|
||||
|
||||
@@ -32,7 +32,7 @@ Evaluation<T> LeastCommonMultipleNode::templatedApproximate(Context * context, P
|
||||
int a = ApproximationHelper::PositiveIntegerApproximationIfPossible<T>(childAtIndex(0), &isUndefined, context, complexFormat, angleUnit);
|
||||
int b = ApproximationHelper::PositiveIntegerApproximationIfPossible<T>(childAtIndex(1), &isUndefined, context, complexFormat, angleUnit);
|
||||
if (isUndefined) {
|
||||
return Complex<T>::Undefined();
|
||||
return Complex<T>::RealUndefined();
|
||||
}
|
||||
if (a == 0 || b == 0) {
|
||||
return Complex<T>::Builder(0.0);
|
||||
|
||||
@@ -34,7 +34,7 @@ Evaluation<T> PermuteCoefficientNode::templatedApproximate(Context * context, Pr
|
||||
T n = nInput.toScalar();
|
||||
T k = kInput.toScalar();
|
||||
if (std::isnan(n) || std::isnan(k) || n != std::round(n) || k != std::round(k) || n < 0.0f || k < 0.0f) {
|
||||
return Complex<T>::Undefined();
|
||||
return Complex<T>::RealUndefined();
|
||||
}
|
||||
if (k > n) {
|
||||
return Complex<T>::Builder(0.0);
|
||||
|
||||
@@ -37,7 +37,7 @@ Evaluation<T> PredictionIntervalNode::templatedApproximate(Context * context, Pr
|
||||
T p = static_cast<Complex<T> &>(pInput).toScalar();
|
||||
T n = static_cast<Complex<T> &>(nInput).toScalar();
|
||||
if (std::isnan(p) || std::isnan(n) || n != (int)n || n < 0 || p < 0 || p > 1) {
|
||||
return Complex<T>::Undefined();
|
||||
return Complex<T>::RealUndefined();
|
||||
}
|
||||
std::complex<T> operands[2];
|
||||
operands[0] = std::complex<T>(p - 1.96*std::sqrt(p*(1.0-p))/std::sqrt(n));
|
||||
|
||||
@@ -50,7 +50,7 @@ template <typename T> Evaluation<T> RandintNode::templateApproximate(Context * c
|
||||
|| a > b
|
||||
|| a != (int)a || b != (int)b
|
||||
|| (Expression::Epsilon<T>()*(b+1.0-a) > 1.0)) {
|
||||
return Complex<T>::Undefined();
|
||||
return Complex<T>::RealUndefined();
|
||||
}
|
||||
T result = std::floor(Random::random<T>()*(b+1.0-a)+a);
|
||||
return Complex<T>::Builder(result);
|
||||
|
||||
@@ -33,7 +33,7 @@ Evaluation<T> RoundNode::templatedApproximate(Context * context, Preferences::Co
|
||||
T f1 = f1Input.toScalar();
|
||||
T f2 = f2Input.toScalar();
|
||||
if (std::isnan(f2) || f2 != std::round(f2)) {
|
||||
return Complex<T>::Undefined();
|
||||
return Complex<T>::RealUndefined();
|
||||
}
|
||||
T err = std::pow(10, std::floor(f2));
|
||||
return Complex<T>::Builder(std::round(f1*err)/err);
|
||||
|
||||
@@ -42,7 +42,7 @@ Expression SignFunctionNode::shallowReduce(ReductionContext reductionContext) {
|
||||
template<typename T>
|
||||
Complex<T> SignFunctionNode::computeOnComplex(const std::complex<T> c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) {
|
||||
if (c.imag() != 0 || std::isnan(c.real())) {
|
||||
return Complex<T>::Undefined();
|
||||
return Complex<T>::RealUndefined();
|
||||
}
|
||||
if (c.real() == 0) {
|
||||
return Complex<T>::Builder(0.0);
|
||||
|
||||
Reference in New Issue
Block a user