]> www.ginac.de Git - ginac.git/blobdiff - ginac/tensor.cpp
- powers with negative exponents are printed as fractions in the LaTeX output
[ginac.git] / ginac / tensor.cpp
index 08c2ecc65ea253fe70284f110f403a526392c171..b49cbc05498be1b2e0558d0ca2073924ba5702ab 100644 (file)
@@ -213,6 +213,13 @@ ex tensmetric::eval_indexed(const basic & i) const
        const varidx & i1 = ex_to<varidx>(i.op(1));
        const varidx & i2 = ex_to<varidx>(i.op(2));
 
+       // The dimension of the indices must be equal, otherwise we use the minimal
+       // dimension
+       if (!i1.get_dim().is_equal(i2.get_dim())) {
+               ex min_dim = i1.minimal_dim(i2);
+               return i.subs(lst(i1 == i1.replace_dim(min_dim), i2 == i2.replace_dim(min_dim)));
+       }
+
        // A metric tensor with one covariant and one contravariant index gets
        // replaced by a delta tensor
        if (i1.is_covariant() != i2.is_covariant())
@@ -341,8 +348,8 @@ again:
                                try {
                                        // minimal_dim() throws an exception when index dimensions are not comparable
                                        ex min_dim = self_idx->minimal_dim(other_idx);
-                                       *self = _ex1;
                                        *other = other->subs(other_idx == free_idx->replace_dim(min_dim));
+                                       *self = _ex1; // *other is assigned first because assigning *self invalidates free_idx
                                        return true;
                                } catch (std::exception &e) {
                                        return false;
@@ -452,9 +459,10 @@ again:
                        if (is_dummy_pair(*self_idx, other_idx)) {
 
                                // Contraction found, remove metric tensor and substitute
-                               // index in second object
-                               *self = (static_cast<const spinidx *>(self_idx)->is_covariant() ? sign : -sign);
+                               // index in second object (assign *self last because this
+                               // invalidates free_idx)
                                *other = other->subs(other_idx == *free_idx);
+                               *self = (static_cast<const spinidx *>(self_idx)->is_covariant() ? sign : -sign);
                                return true;
                        }
                }
@@ -484,14 +492,16 @@ bool tensepsilon::contract_with(exvector::iterator self, exvector::iterator othe
        if (is_ex_exactly_of_type(other->op(0), tensepsilon) && num+1 == other->nops()) {
 
                // Contraction of two epsilon tensors is a determinant
-               ex dim = ex_to<idx>(self->op(1)).get_dim();
+               bool variance = is_a<varidx>(self->op(1));
                matrix M(num, num);
                for (int i=0; i<num; i++) {
                        for (int j=0; j<num; j++) {
                                if (minkowski)
                                        M(i, j) = lorentz_g(self->op(i+1), other->op(j+1), pos_sig);
-                               else
+                               else if (variance)
                                        M(i, j) = metric_tensor(self->op(i+1), other->op(j+1));
+                               else
+                                       M(i, j) = delta_tensor(self->op(i+1), other->op(j+1));
                        }
                }
                int sign = minkowski ? -1 : 1;
@@ -519,9 +529,6 @@ ex metric_tensor(const ex & i1, const ex & i2)
 {
        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"));
-       ex dim = ex_to<idx>(i1).get_dim();
-       if (!dim.is_equal(ex_to<idx>(i2).get_dim()))
-               throw(std::invalid_argument("all indices of metric tensor must have the same dimension"));
 
        return indexed(tensmetric(), sy_symm(), i1, i2);
 }
@@ -530,9 +537,6 @@ ex lorentz_g(const ex & i1, const ex & i2, bool pos_sig)
 {
        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"));
-       ex dim = ex_to<idx>(i1).get_dim();
-       if (!dim.is_equal(ex_to<idx>(i2).get_dim()))
-               throw(std::invalid_argument("all indices of metric tensor must have the same dimension"));
 
        return indexed(minkmetric(pos_sig), sy_symm(), i1, i2);
 }