evaluate method
Evaluates this expression according to given type and context.
Implementation
@override
dynamic evaluate(EvaluationType type, ContextModel context) {
final num base = first.evaluate(type, context);
if (type == EvaluationType.REAL) {
// Consider the following equation: x^(2/y).
// This equation can be evaluated for any negative x, since the sub result
// is positive due to the even numerator. However, the IEEE Standard for
// for Floating-Point Arithmetic defines NaN in the case of a negative
// base and a finite non-integer as the exponent. That's why we rewrite
// the equation manually.
if (base.isNegative && second is Divide) {
final Expression numerator = (second as Divide).first;
final Expression denominator = (second as Divide).second;
final double newBase = Power(base, numerator).evaluate(type, context);
final double newExponent = 1 / denominator.evaluate(type, context);
return Power(newBase, newExponent).evaluate(type, context);
}
// In case the exponent is a unary minus e.g. x^(-(2/y)), we rewrite the
// equation to 1/x^(2/3), for the same reason as stated above.
if (base.isNegative && second is UnaryMinus) {
final Expression exponent = (second as UnaryMinus).exp;
return 1 / Power(base, exponent).evaluate(type, context);
}
return math.pow(base, second.evaluate(type, context));
}
if (type == EvaluationType.INTERVAL) {
// Expect base to be interval.
final Interval interval = first.evaluate(type, context);
// Expect exponent to be a natural number.
dynamic exponent = second.evaluate(EvaluationType.REAL, context);
if (exponent is double) {
//print('Warning, expected natural exponent but is real. Interpreting as int: ${this}');
exponent = exponent.toInt();
}
num evalMin, evalMax;
// Distinction of cases depending on oddity of exponent.
if (exponent.isOdd) {
// [x, y]^n = [x^n, y^n] for n = odd
evalMin = math.pow(interval.min, exponent);
evalMax = math.pow(interval.max, exponent);
} else {
// [x, y]^n = [x^n, y^n] for x >= 0
if (interval.min >= 0) {
// Positive interval.
evalMin = math.pow(interval.min, exponent);
evalMax = math.pow(interval.max, exponent);
}
// [x, y]^n = [y^n, x^n] for y < 0
if (interval.min >= 0) {
// Positive interval.
evalMin = math.pow(interval.max, exponent);
evalMax = math.pow(interval.min, exponent);
}
// [x, y]^n = [0, max(x^n, y^n)] otherwise
evalMin = 0;
evalMax = math.max(
math.pow(interval.min, exponent), math.pow(interval.min, exponent));
}
assert(evalMin <= evalMax);
return Interval(evalMin, evalMax);
}
throw UnimplementedError(
'Evaluate Power with type $type not supported yet.');
}