if (level > 1)
return indexed(symmetry, evalchildren(level));
+ const ex &base = seq[0];
+
// If the base object is 0, the whole object is 0
- if (seq[0].is_zero())
+ if (base.is_zero())
return _ex0();
+ // If the base object is a product, pull out the numeric factor
+ if (is_ex_exactly_of_type(base, mul) && is_ex_exactly_of_type(base.op(base.nops() - 1), numeric)) {
+ exvector v = seq;
+ ex f = ex_to_numeric(base.op(base.nops() - 1));
+ v[0] = seq[0] / f;
+ return f * thisexprseq(v);
+ }
+
// Canonicalize indices according to the symmetry properties
if (seq.size() > 2 && (symmetry != unknown && symmetry != mixed)) {
exvector v = seq;
}
// Let the class of the base object perform additional evaluations
- return seq[0].bp->eval_indexed(*this);
+ return base.bp->eval_indexed(*this);
}
ex indexed::thisexprseq(const exvector & v) const
if (!is_ex_of_type(i1, varidx) || !is_ex_of_type(i2, varidx))
throw(std::invalid_argument("indices of metric tensor must be of type varidx"));
- return indexed(tensmetric(), i1, i2);
+ return indexed(tensmetric(), indexed::symmetric, i1, i2);
}
ex lorentz_g(const ex & i1, const ex & i2, bool pos_sig)
* @return newly constructed delta tensor */
ex delta_tensor(const ex & i1, const ex & i2);
-/** Create a metric tensor with specified indices. The indices must be of
- * class varidx or a subclass. A metric tensor with one covariant and one
- * contravariant index is equivalent to the delta tensor.
+/** Create a symmetric metric tensor with specified indices. The indices
+ * must be of class varidx or a subclass. A metric tensor with one
+ * covariant and one contravariant index is equivalent to the delta tensor.
*
* @param i1 First index
* @param i2 Second index