0.9.2 (<insert date here>)
* Epsilon tensor is more functional.
+* Several little bugfixes and consistency enhancements.
0.9.1 (27 June 2001)
* Ctors of class numeric are not explicit any more. All built-in callers for
return (new add(coeffseq, n==0 ? overall_coeff : _ex0()))->setflag(status_flags::dynallocated);
}
+/** Perform automatic term rewriting rules in this class. In the following
+ * x stands for a symbolic variables of type ex and c stands for such
+ * an expression that contain a plain number.
+ * - +(;c) -> c
+ * - +(x;1) -> x
+ *
+ * @param level cut-off in recursive evaluation */
ex add::eval(int level) const
{
- // simplifications: +(;c) -> c
- // +(x;1) -> x
-
debugmsg("add eval",LOGLEVEL_MEMBER_FUNCTION);
epvector *evaled_seqp = evalchildren(level);
return x + (*this - x).expand();
}
-/** Perform automatic non-interruptive symbolic evaluation on expression. */
+/** Perform automatic non-interruptive term rewriting rules. */
ex basic::eval(int level) const
{
// There is nothing to do for basic objects:
return thisexpairseq(v, f(overall_coeff));
}
+/** Perform coefficient-wise automatic term rewriting rules in this class. */
ex expairseq::eval(int level) const
{
if ((level==1) && (flags &status_flags::evaluated))
return _ex0();
}
+/** Perform automatic term rewriting rules in this class. In the following
+ * x, x1, x2,... stand for a symbolic variables of type ex and c, c1, c2...
+ * stand for such expressions that contain a plain number.
+ * - *(...,x;0) -> 0
+ * - *(+(x1,x2,...);c) -> *(+(*(x1,c),*(x2,c),...))
+ * - *(x;1) -> x
+ * - *(;c) -> c
+ *
+ * @param level cut-off in recursive evaluation */
ex mul::eval(int level) const
{
- // simplifications *(...,x;0) -> 0
- // *(+(x,y,...);c) -> *(+(*(x,c),*(y,c),...)) (c numeric())
- // *(x;1) -> x
- // *(;c) -> c
-
debugmsg("mul eval",LOGLEVEL_MEMBER_FUNCTION);
epvector *evaled_seqp = evalchildren(level);
typedef std::vector<unsigned> unsignedvector;
typedef std::vector<exvector> exvectorvector;
+/** Perform automatic term rewriting rules in this class. In the following
+ * x, x1, x2,... stand for a symbolic variables of type ex and c, c1, c2...
+ * stand for such expressions that contain a plain number.
+ * - ncmul(...,*(x1,x2),...,ncmul(x3,x4),...) -> ncmul(...,x1,x2,...,x3,x4,...) (associativity)
+ * - ncmul(x) -> x
+ * - ncmul() -> 1
+ * - ncmul(...,c1,...,c2,...) -> *(c1,c2,ncmul(...)) (pull out commutative elements)
+ * - ncmul(x1,y1,x2,y2) -> *(ncmul(x1,x2),ncmul(y1,y2)) (collect elements of same type)
+ * - ncmul(x1,x2,x3,...) -> x::simplify_ncmul(x1,x2,x3,...)
+ *
+ * @param level cut-off in recursive evaluation */
ex ncmul::eval(int level) const
{
- // simplifications: ncmul(...,*(x1,x2),...,ncmul(x3,x4),...) ->
- // ncmul(...,x1,x2,...,x3,x4,...) (associativity)
- // ncmul(x) -> x
- // ncmul() -> 1
- // ncmul(...,c1,...,c2,...)
- // *(c1,c2,ncmul(...)) (pull out commutative elements)
- // ncmul(x1,y1,x2,y2) -> *(ncmul(x1,x2),ncmul(y1,y2))
- // (collect elements of same type)
- // ncmul(x1,x2,x3,...) -> x::simplify_ncmul(x1,x2,x3,...)
- // the following rule would be nice, but produces a recursion,
+ // The following additional rule would be nice, but produces a recursion,
// which must be trapped by introducing a flag that the sub-ncmuls()
// are already evaluated (maybe later...)
// ncmul(x1,x2,...,X,y1,y2,...) ->
exvector evaledseq=evalchildren(level);
// ncmul(...,*(x1,x2),...,ncmul(x3,x4),...) ->
- // ncmul(...,x1,x2,...,x3,x4,...) (associativity)
+ // ncmul(...,x1,x2,...,x3,x4,...) (associativity)
unsigned factors = 0;
exvector::const_iterator cit = evaledseq.begin(), citend = evaledseq.end();
while (cit != citend)
{
// Optimal output of integer powers of symbols to aid compiler CSE.
// C.f. ISO/IEC 14882:1998, section 1.9 [intro execution], paragraph 15
- // to learn why such a hack is really necessary.
+ // to learn why such a parenthisation is really necessary.
if (exp == 1) {
x.print(c);
} else if (exp == 2) {
}
}
+/** Perform automatic term rewriting rules in this class. In the following
+ * x, x1, x2,... stand for a symbolic variables of type ex and c, c1, c2...
+ * stand for such expressions that contain a plain number.
+ * - ^(x,0) -> 1 (also handles ^(0,0))
+ * - ^(x,1) -> x
+ * - ^(0,c) -> 0 or exception (depending on the real part of c)
+ * - ^(1,x) -> 1
+ * - ^(c1,c2) -> *(c1^n,c1^(c2-n)) (so that 0<(c2-n)<1, try to evaluate roots, possibly in numerator and denominator of c1)
+ * - ^(^(x,c1),c2) -> ^(x,c1*c2) (c2 integer or -1 < c1 <= 1, case c1=1 should not happen, see below!)
+ * - ^(*(x,y,z),c) -> *(x^c,y^c,z^c) (if c integer)
+ * - ^(*(x,c1),c2) -> ^(x,c2)*c1^c2 (c1>0)
+ * - ^(*(x,c1),c2) -> ^(-x,c2)*c1^c2 (c1<0)
+ *
+ * @param level cut-off in recursive evaluation */
ex power::eval(int level) const
{
- // simplifications: ^(x,0) -> 1 (0^0 handled here)
- // ^(x,1) -> x
- // ^(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,y,z),c1) -> *(x^c1,y^c1,z^c1) (c1 integer)
- // ^(*(x,c1),c2) -> ^(x,c2)*c1^c2 (c1, c2 numeric(), c1>0)
- // ^(*(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))
num_exponent = static_cast<const numeric *>(eexponent.bp);
}
- // ^(x,0) -> 1 (0^0 also handled here)
+ // ^(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"));
if (eexponent.is_equal(_ex1()))
return ebasis;
- // ^(0,c1) -> 0 or exception (depending on real value of c1)
+ // ^(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"));
if (exponent_is_numerical) {
- // ^(c1,c2) -> c1^c2 (c1, c2 numeric(),
+ // ^(c1,c2) -> c1^c2 (c1, c2 numeric(),
// except if c1,c2 are rational, but c1^c2 is not)
if (basis_is_numerical) {
const bool basis_is_crational = num_basis->is_crational();
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)
+ // ^(*(...,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 (is_ex_exactly_of_type(ebasis,mul)) {
GINAC_ASSERT(!num_exponent->is_integer()); // should have been handled above
const mul & mulref = ex_to<mul>(ebasis);
return *this;
}
-/** Evaluate coefficients. */
+/** Perform coefficient-wise automatic term rewriting rules in this class. */
ex pseries::eval(int level) const
{
if (level == 1)