clog << "returned: " << e6 << endl;
return 1;
}
+
return 0;
}
{
// numeric evaluation
- ex e1=power(numeric(4),numeric(1)/numeric(2));
+ ex e1 = power(numeric(4),numeric(1,2));
if (e1 != 2) {
clog << "4^(1/2) wrongly returned " << e1 << endl;
return 1;
}
- ex e2=power(numeric(27),numeric(2)/numeric(3));
+ ex e2 = power(numeric(27),numeric(2,3));
if (e2 != 9) {
clog << "27^(2/3) wrongly returned " << e2 << endl;
return 1;
}
-
- ex e3=power(numeric(5),numeric(1)/numeric(2));
+
+ ex e3 = power(numeric(5),numeric(1,2));
if (!(is_ex_exactly_of_type(e3,power) &&
e3.op(0).is_equal(numeric(5)) &&
- e3.op(1).is_equal(numeric(1)/numeric(2)) )) {
+ e3.op(1).is_equal(numeric(1,2)))) {
clog << "5^(1/2) wrongly returned " << e3 << endl;
return 1;
}
- ex e4=power(numeric(5),evalf(numeric(1)/numeric(2)));
+ ex e4 = power(numeric(5),evalf(numeric(1,2)));
if (!(is_ex_exactly_of_type(e4,numeric))) {
clog << "5^(0.5) wrongly returned " << e4 << endl;
return 1;
}
- ex e5=power(evalf(numeric(5)),numeric(1)/numeric(2));
+ ex e5 = power(evalf(numeric(5)),numeric(1,2));
if (!(is_ex_exactly_of_type(e5,numeric))) {
clog << "5.0^(1/2) wrongly returned " << e5 << endl;
return 1;
static unsigned exam_powerlaws4(void)
{
// test for mul::eval()
-
+
symbol a("a");
symbol b("b");
symbol c("c");
- ex f1=power(a*b,ex(1)/ex(2));
- ex f2=power(a*b,ex(3)/ex(2));
- ex f3=c;
-
+ ex f1 = power(a*b,ex(1)/ex(2));
+ ex f2 = power(a*b,ex(3)/ex(2));
+ ex f3 = c;
+
exvector v;
v.push_back(f1);
v.push_back(f2);
v.push_back(f3);
- ex e1=mul(v);
+ ex e1 = mul(v);
if (e1!=a*a*b*b*c) {
clog << "(a*b)^(1/2)*(a*b)^(3/2)*c wrongly returned " << e1 << endl;
return 1;
}
+
+ return 0;
+}
+
+static unsigned exam_powerlaws5(void)
+{
+ // cabinet of slightly pathological cases
+
+ symbol a("a");
+
+ ex e1 = pow(1,a);
+ if (e1 != 1) {
+ clog << "1^a wrongly returned " << e1 << endl;
+ return 1;
+ }
+
+ ex e2 = pow(0,a);
+ if (!(is_ex_exactly_of_type(e2,power))) {
+ clog << "0^a was evaluated to " << e2
+ << " though nothing is known about a." << endl;
+ return 1;
+ }
+
return 0;
}
result += exam_powerlaws2(); cout << '.' << flush;
result += exam_powerlaws3(); cout << '.' << flush;
result += exam_powerlaws4(); cout << '.' << flush;
+ result += exam_powerlaws5(); cout << '.' << flush;
if (!result) {
cout << " passed " << endl;
{
// simplifications: ^(x,0) -> 1 (0^0 handled here)
// ^(x,1) -> x
- // ^(0,x) -> 0 (except if the realpart of x is non-positive, in which case an exception is thrown)
+ // ^(0,c1) -> 0 or exception (depending on real value of c1)
// ^(1,x) -> 1
// ^(c1,c2) -> *(c1^n,c1^(c2-n)) (c1, c2 numeric(), 0<(c2-n)<1 except if c1,c2 are rational, but c1^c2 is not)
// ^(^(x,c1),c2) -> ^(x,c1*c2) (c1, c2 numeric(), c2 integer or -1 < c1 <= 1, case c1=1 should not happen, see below!)
// ^(*(x,c1),c2) -> ^(-x,c2)*c1^c2 (c1, c2 numeric(), c1<0)
debugmsg("power eval",LOGLEVEL_MEMBER_FUNCTION);
-
+
if ((level==1) && (flags & status_flags::evaluated))
return *this;
else if (level == -max_recursion_level)
const ex & ebasis = level==1 ? basis : basis.eval(level-1);
const ex & eexponent = level==1 ? exponent : exponent.eval(level-1);
-
+
bool basis_is_numerical = 0;
bool exponent_is_numerical = 0;
numeric * num_basis;
numeric * num_exponent;
-
+
if (is_exactly_of_type(*ebasis.bp,numeric)) {
basis_is_numerical = 1;
num_basis = static_cast<numeric *>(ebasis.bp);
exponent_is_numerical = 1;
num_exponent = static_cast<numeric *>(eexponent.bp);
}
-
+
// ^(x,0) -> 1 (0^0 also handled here)
if (eexponent.is_zero())
if (ebasis.is_zero())
throw (std::domain_error("power::eval(): pow(0,0) is undefined"));
else
return _ex1();
-
+
// ^(x,1) -> x
if (eexponent.is_equal(_ex1()))
return ebasis;
-
- // ^(0,x) -> 0 (except if the realpart of x is non-positive)
- if (ebasis.is_zero()) {
- if (exponent_is_numerical) {
- if ((num_exponent->real()).is_zero())
- throw (std::domain_error("power::eval(): pow(0,I) is undefined"));
- else if ((num_exponent->real()).is_negative())
- throw (std::overflow_error("power::eval(): division by zero"));
- else
- return _ex0();
- } else
+
+ // ^(0,c1) -> 0 or exception (depending on real value of c1)
+ if (ebasis.is_zero() && exponent_is_numerical) {
+ if ((num_exponent->real()).is_zero())
+ throw (std::domain_error("power::eval(): pow(0,I) is undefined"));
+ else if ((num_exponent->real()).is_negative())
+ throw (std::overflow_error("power::eval(): division by zero"));
+ else
return _ex0();
}
-
+
// ^(1,x) -> 1
if (ebasis.is_equal(_ex1()))
return _ex1();
-
+
if (basis_is_numerical && exponent_is_numerical) {
// ^(c1,c2) -> c1^c2 (c1, c2 numeric(),
// except if c1,c2 are rational, but c1^c2 is not)
}
}
}
-
+
// ^(^(x,c1),c2) -> ^(x,c1*c2)
// (c1, c2 numeric(), c2 integer or -1 < c1 <= 1,
// case c1==1 should not happen, see below!)
is_ex_exactly_of_type(ebasis,mul)) {
return expand_mul(ex_to_mul(ebasis), *num_exponent);
}
-
+
// ^(*(...,x;c1),c2) -> ^(*(...,x;1),c2)*c1^c2 (c1, c2 numeric(), c1>0)
// ^(*(...,x,c1),c2) -> ^(*(...,x;-1),c2)*(-c1)^c2 (c1, c2 numeric(), c1<0)
if (exponent_is_numerical && is_ex_exactly_of_type(ebasis,mul)) {