'Returns new TIDS and sign.
Sign is either 1 or -1, to correct the sign after metric contraction
(for spinor indices).'

def contract_metric(self, g):

    components = self.components
    antisym = g.index_types[0].metric_antisym
    gpos = [i for (i, x) in enumerate(components) if (x == g)]
    if (not gpos):
        return (self, 1)
    sign = 1
    dum = self.dum[:]
    free = self.free[:]
    elim = set()
    for gposx in gpos:
        if (gposx in elim):
            continue
        free1 = [x for x in free if (x[(-1)] == gposx)]
        dum1 = [x for x in dum if ((x[(-2)] == gposx) or (x[(-1)] == gposx))]
        if (not dum1):
            continue
        elim.add(gposx)
        if (len(dum1) == 2):
            if (not antisym):
                (dum10, dum11) = dum1
                if (dum10[3] == gposx):
                    c0 = dum10[2]
                    p0 = dum10[0]
                else:
                    c0 = dum10[3]
                    p0 = dum10[1]
                if (dum11[3] == gposx):
                    c1 = dum11[2]
                    p1 = dum11[0]
                else:
                    c1 = dum11[3]
                    p1 = dum11[1]
                dum.append((p0, p1, c0, c1))
            else:
                (dum10, dum11) = dum1
                if (dum10[3] == gposx):
                    c0 = dum10[2]
                    p0 = dum10[0]
                    if (dum10[1] == 1):
                        sign = (- sign)
                else:
                    c0 = dum10[3]
                    p0 = dum10[1]
                    if (dum10[0] == 0):
                        sign = (- sign)
                if (dum11[3] == gposx):
                    c1 = dum11[2]
                    p1 = dum11[0]
                    sign = (- sign)
                else:
                    c1 = dum11[3]
                    p1 = dum11[1]
                dum.append((p0, p1, c0, c1))
        elif (len(dum1) == 1):
            if (not antisym):
                (dp0, dp1, dc0, dc1) = dum1[0]
                if (dc0 == dc1):
                    typ = g.index_types[0]
                    if (typ._dim is None):
                        raise ValueError('dimension    not    assigned')
                    sign = (sign * typ._dim)
                else:
                    if (dc0 == gposx):
                        p1 = dp1
                        c1 = dc1
                    else:
                        p1 = dp0
                        c1 = dc0
                    (ind, p, c) = free1[0]
                    free.append((ind, p1, c1))
            else:
                (dp0, dp1, dc0, dc1) = dum1[0]
                if (dc0 == dc1):
                    typ = g.index_types[0]
                    if (typ._dim is None):
                        raise ValueError('dimension    not    assigned')
                    sign = (sign * typ._dim)
                    if (dp0 < dp1):
                        sign = (- sign)
                else:
                    if (dc0 == gposx):
                        p1 = dp1
                        c1 = dc1
                        if (dp0 == 0):
                            sign = (- sign)
                    else:
                        p1 = dp0
                        c1 = dc0
                    (ind, p, c) = free1[0]
                    free.append((ind, p1, c1))
        dum = [x for x in dum if (x not in dum1)]
        free = [x for x in free if (x not in free1)]
    shift = 0
    shifts = ([0] * len(components))
    for i in range(len(components)):
        if (i in elim):
            shift += 1
            continue
        shifts[i] = shift
    free = [(ind, p, (c - shifts[c])) for (ind, p, c) in free if (c not in elim)]
    dum = [(p0, p1, (c0 - shifts[c0]), (c1 - shifts[c1])) for (i, (p0, p1, c0, c1)) in enumerate(dum) if ((c0 not in elim) and (c1 not in elim))]
    components = [c for (i, c) in enumerate(components) if (i not in elim)]
    tids = TIDS(components, free, dum)
    return (tids, sign)
