
def test01():
    __cdbkernel__=create_scope()
    {a,b,c,d}::Indices(type1);
    {m,n,p,q}::Indices(type2);
    A::ImplicitIndex(A_{m n});
    C::ImplicitIndex(C_{m n});
    D::ImplicitIndex(D_{a b});
    ex:= D C A D;
    sort_product(_)
    tst:= C A D D - @(ex);
    assert(tst==0)
    print("Test 01 passed")

test01()

def test02():
    __cdbkernel__=create_scope()
    {a,b,c,d}::Indices(spinor);
    Tr{#}::Trace(indices=spinor);
    A::ImplicitIndex(A_{a b});
    B::ImplicitIndex(B_{a b});    
    ex:= Tr( A B A C B ) - Tr( C );
    untrace(_)
    tst:= C Tr( A B A B ) - C Tr(1) - @(ex);
    assert(tst==0)
    print("Test 02 passed")

test02()

def test03():
    __cdbkernel__=create_scope()
    {a,b,c,d}::Indices(spinor);
    \sigma^{\mu}::ImplicitIndex(\sigma^{\mu a}_{b});    
    Tr{#}::Trace(indices=spinor);
    ex:= Tr( \sigma^{\mu} q \sigma^{\nu} );
    untrace(_)
    tst:= q Tr( \sigma^{\mu} \sigma^{\nu} ) - @(ex);
    assert(tst==0)
    print("Test 03 passed")
    
test03()
        
def test04():
    __cdbkernel__=create_scope()
    {a,b}::Indices(spinor);
    {m,n}::Indices(vector);
    Tr{#}::Trace(indices=spinor);
    A::ImplicitIndex(A_{a b});
    B::ImplicitIndex(B_{m n});
    A::Traceless(indices=spinor);
    B::Traceless(indices=vector);
    ex:=Tr( A ) + Tr( B );
    canonicalise(_)
    tst:= Tr( B ) - @(ex);
    assert(tst==0)
    print("Test 04 passed")

test04()

def test05():
    __cdbkernel__=create_scope()
    {a,b,c,d}::Indices(vector);
    ex:=(A)_{a b} (B)_{b c} (C)_{c d};
    combine(_)
    tst:= (A B C)_{a d} - @(ex);
    assert(tst==0)
    print("Test 05 passed")

test05()

def test06():
    __cdbkernel__=create_scope()
    {a,b}::Indices(vector);
    ex:=(A)_{a b} (B)_{b a};
    combine(_)
    tst:= (B A)_{b b} - @(ex);
    assert(tst==0)
    print("Test 06 passed")

test06()

def test07():
    __cdbkernel__=create_scope()
    {a,b}::Indices(vector);
    Tr{#}::Trace(indices=vector);
    ex:=(A)_{a b} (B)_{b a};
    combine(_, trace_op=$Tr$)
    tst:= Tr( B A ) - @(ex);
    assert(tst==0)
    print("Test 07 passed")

test07()

def test08():
    __cdbkernel__=create_scope()
    {a,b}::Indices(vector);
    {A,B}::AntiCommuting;
    ex:=(A)_{a b} (B)_{b a};
    combine(_)
    tst:= \indexbracket{-B A}_{b b} - @(ex);
    assert(tst==0)
    print("Test 08 passed")

test08()

def test09():
    __cdbkernel__=create_scope()
    {m,n}::Indices(vector);
    {a,b,c}::Indices(spinor, position=fixed);
    \Gamma^{m}::ImplicitIndex(\Gamma^{m a}_{b});
    \Gamma^{m}::Matrix;
    ex:=(\Gamma^{m} \Gamma^{n})^{a}_{c};
    expand(_)
    tst:= (\Gamma^{m})^{a}_{b} (\Gamma^{n})^{b}_{c} - @(ex);
    assert(tst==0)
    print("Test 09 passed")

test09()

def test10():
    __cdbkernel__=create_scope()
    {a,b}::Indices(vector);
    ex:=(u)_{a} (M)^{a b} (v)_{b};
    combine(_)
    tst:= \indexbracket(u M v) - @(ex);
    assert(tst==0)
    print("Test 10 passed")

if sys.platform == "darwin":
    print("Skipping test 10, segfault on Darwin.")
else:
    test10()

def test11():
    __cdbkernel__=create_scope()
    {a,b,c}::Indices(vector);
    ex:=(B)_{b c} (A)_{a b};
    combine(_)
    tst:= (A B)_{a c} - @(ex);
    assert(tst==0)
    print("Test 11 passed")

test11()

def test12():
    __cdbkernel__=create_scope()
    {a,b}::Indices(vector);
    Tr{#}::Trace(indices=vector);
    A::ImplicitIndex(A_{a b});
    B::ImplicitIndex(B_{a b});
    {A_{a b}, B_{a b}, C, D}::AntiCommuting;
    ex:=Tr( A C B D );
    untrace(_)
    sort_product(_)
    tst:= -C D Tr( A B ) - @(ex);
    assert(tst==0)
    print("Test 12 passed")

test12()

def test13():
    __cdbkernel__=create_scope()
    {a,b}::Indices(vector);
    Tr{#}::Trace(indices=vector);
    A::ImplicitIndex(A_{a b});
    B::ImplicitIndex(B_{a b});
    {A_{a b}, B_{a b}}::AntiCommuting;
    ex:=Tr( B A );
    sort_product(_)
    tst:= Tr( -A B ) - @(ex);
    assert(tst==0)
    print("Test 13 passed")

test13()

def test14():
    __cdbkernel__=create_scope()
    {A,B,C}::ImplicitIndex;
    ex:=(B A C)_{a a};
    sort_product(_)
    tst:= (A C B)_{a a} - @(ex);
    assert(tst==0)
    print("Test 14 passed")

test14()

def test15():
    __cdbkernel__=create_scope()
    {\mu,\nu,\rho}::Indices(vector).
    {a^{\mu},b^{\mu},c^{\mu}}::NonCommuting.
    tr{#}::Trace.
    ex:=tr(a^{\mu} b^{\nu} c^{\rho}  a^{\mu} b^{\rho} c^{\nu}+b^{\mu} c^{\nu} a^{\rho} b^{\nu} c^{\mu} a^{\rho}+c^{\mu} a^{\nu} b^{\mu} c^{\rho} a^{\nu} b^{\rho});
    sort_product(_)
    rename_dummies(_)
    tst:= 3 tr( a^{\mu} b^{\nu} c^{\rho}  a^{\mu} b^{\rho} c^{\nu} ) - @(ex);
    assert(tst==0)
    print("Test 15 passed")
    
test15()
        
def test16():
    __cdbkernel__=create_scope()
    {\mu,\nu,\rho}::Indices(vector).
    {a^{\mu},b^{\mu},c^{\mu}}::NonCommuting.
    tr{#}::Trace.
    ex:=tr( b^{\mu} c^{\nu} a^{\rho} b^{\nu} c^{\mu} a^{\rho} );
    sort_product(_)
    rename_dummies(_)
    tst:= tr( a^{\mu} b^{\nu} c^{\rho}  a^{\mu} b^{\rho} c^{\nu} ) - @(ex);
    assert(tst==0)
    print("Test 16 passed")
    
test16()

def test17():
    __cdbkernel__=create_scope()
    {A,B}::ImplicitIndex.
    tr{#}::Trace.
    ex:=tr( A B B A );
    sort_product(_)
    tst:= tr( A A B B ) - @(ex);
    assert(tst==0)
    print("Test 17 passed")

test17()

def test18():
    __cdbkernel__=create_scope()
    {\mu,\nu}::Indices(vector).
    tr{#}::Trace.
    {a^{\mu},b^{\mu}}::NonCommuting.
    {a^{\mu},b^{\mu}}::SelfNonCommuting.
    ex:=tr{a^{\mu} b^{\mu} b^{\nu} a^{\nu}} - tr{a^{\mu} a^{\nu} b^{\nu} b^{\mu} };
    sort_product(_)
    rename_dummies(_)        
    assert(ex==0)
    print("Test 18 passed")

test18()

def test19():
    __cdbkernel__=create_scope()
    i::ImaginaryI;
    A::ImplicitIndex.
    tr{#}::Trace.
    ex:= i tr(i A);
    untrace(_, repeat=True)
    tst:= -tr(A) - @(ex);
    assert("Test 19 passed")

test19()

def test20():
    __cdbkernel__=create_scope()
    {\mu,\nu}::Indices(vector).
    tr{#}::Trace.
    ex:=A A tr{u^{\mu} u^{\nu}} tr{u^{\nu} u^{\mu}}- B B tr{u^{\mu} u^{\nu}} tr{u^{\mu} u^{\nu}};
    collect_factors(_)
    tst:= A**2 tr{u^{\mu} u^{\nu}} tr{u^{\nu} u^{\mu}}- B**2 tr{u^{\mu} u^{\nu}} tr{u^{\mu} u^{\nu}} - @(ex);
    assert(tst==0)
    print("Test 20 passed")

test20()

def test21():
    __cdbkernel__=create_scope()
    {\mu,\nu}::Indices(vector).
    A^{\mu\nu}::Symmetric.
    B^{\mu\nu}::AntiSymmetric.
    tr{#}::Trace.
    B^{\mu\nu}::ImplicitIndex.
    \epsilon^{\mu\nu\rho\sigma}::EpsilonTensor.
    ex:=A^{\mu\nu} tr{B^{\mu\nu}};
    canonicalise(_)
    assert ex==0
    print("Test 21a passed")
    ex:=\epsilon^{\mu\nu\rho\sigma} tr{A^{\mu\nu} B^{\rho\sigma}};
    canonicalise(_)
    assert ex==0
    print("Test 21b passed")    
    ex:=\epsilon^{\mu\nu\rho\sigma} A^{\nu\mu} B^{\rho\sigma};
    canonicalise(_)
    assert ex==0
    print("Test 21c passed")    
    ex:=\epsilon^{\mu\nu\rho\sigma} tr{ A^{\nu\mu} B^{\rho\sigma} };
    canonicalise(_)    
    assert ex==0
    print("Test 21d passed")    
    ex:=\epsilon^{\mu\nu\rho\sigma} tr{ A^{\nu\mu} B^{\rho\sigma} + A^{\mu\nu} B^{\rho\sigma} };
    # FIXME: this does not work with repeat=True?
    canonicalise(_)
    canonicalise(_)
    assert ex==0
    print("Test 21e passed")
    
test21()
