1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
|
#include "Cleanup.hh"
#include "algorithms/split_gamma.hh"
#include "algorithms/join_gamma.hh"
using namespace cadabra;
split_gamma::split_gamma(const Kernel& k, Ex& e, bool ob)
: Algorithm(k, e), on_back(ob)
{
}
bool split_gamma::can_apply(iterator it)
{
if(kernel.properties.get<GammaMatrix>(it))
if(tr.number_of_children(it)>1) {
return true;
}
return false;
}
Algorithm::result_t split_gamma::apply(iterator& it)
{
// Make a new expression which is the 'join' of the result which we want.
Ex work;
work.set_head(str_node("\\expression"));
iterator prodnode=work.append_child(work.begin(), str_node("\\prod"));
iterator firstgam, secondgam;
if(on_back) {
firstgam =work.append_child(prodnode, it);
secondgam=work.append_child(prodnode, *it);
}
else {
secondgam=work.append_child(prodnode, *it);
firstgam =work.append_child(prodnode, it);
}
sibling_iterator specind;
if(on_back) {
specind=work.end(firstgam);
--specind;
}
else specind=work.begin(firstgam);
work.append_child(secondgam, (iterator)(specind));
work.erase(specind);
join_gamma jn(kernel, tr, true, true);
const GammaMatrix *gm1=kernel.properties.get<GammaMatrix>(it);
jn.gm1=gm1;
jn.apply(prodnode);
// Replace maximally-antisymmetric gamma with the product
// in which one gamma is back-split.
iterator maxgam=work.begin(prodnode);
if(on_back) {
specind=work.end(maxgam);
--specind;
}
else specind=work.begin(maxgam);
iterator newprod=work.insert(maxgam, str_node("\\prod"));
sibling_iterator fr=maxgam, to=fr;
++to;
maxgam=work.reparent(newprod, fr, to);
iterator splitgam;
if(on_back) splitgam=work.append_child(newprod, *maxgam);
else splitgam=work.insert(maxgam, *maxgam);
work.append_child(splitgam,(iterator)(specind));
work.erase(specind);
// Flip signs on all other terms.
sibling_iterator other=work.begin(prodnode);
++other;
while(other!=work.end(prodnode)) {
flip_sign(other->multiplier);
++other;
}
it=tr.replace(it, prodnode);
cleanup_dispatch(kernel, tr, it);
return result_t::l_applied;
}
|