#include "algorithms/flatten_product.hh" #include "properties/PartialDerivative.hh" using namespace cadabra; flatten_product::flatten_product(const Kernel& k, Ex& tr) : Algorithm(k, tr), make_consistent_only(false), is_diff(false) { } bool flatten_product::can_apply(iterator it) { is_diff=false; if(*it->name!="\\prod") return false; // FIXME: acting on PartialDerivative has been disabled because // it really does not make sense anymore. // if(properties::get(it)==0) // return false; // else is_diff=true; if(!is_diff && tr.number_of_children(it)==1) return true; sibling_iterator facs=tr.begin(it); while(facs!=tr.end(it)) { const PartialDerivative *pd=kernel.properties.get(facs); if((is_diff && pd) || (!is_diff && *facs->name=="\\prod")) return true; if(is_diff) break; ++facs; } return false; } Algorithm::result_t flatten_product::apply(iterator& it) { // debugout << "acting with flatten_product at " << *it->name << std::endl; if(!is_diff && tr.number_of_children(it)==1) { tr.begin(it)->fl.bracket = it->fl.bracket; multiply(tr.begin(it)->multiplier, *it->multiplier); tr.flatten(it); it=tr.erase(it); pushup_multiplier(it); return result_t::l_applied; } result_t ret=result_t::l_no_action; sibling_iterator facs=tr.begin(it); str_node::bracket_t btype=facs->fl.bracket; while(facs!=tr.end(it)) { const PartialDerivative *pd=kernel.properties.get(facs); if((is_diff && pd) || (!is_diff && *facs->name=="\\prod")) { str_node::bracket_t cbtype=tr.begin(facs)->fl.bracket; if(!make_consistent_only || cbtype==str_node::b_none || cbtype==str_node::b_no) { sibling_iterator prodch=tr.begin(facs); while(prodch!=tr.end(facs)) { prodch->fl.bracket=btype; ++prodch; } sibling_iterator tmp=facs; ++tmp; tr.flatten(facs); multiply(it->multiplier,*facs->multiplier); tr.erase(facs); pushup_multiplier(it); facs=tmp; ret=result_t::l_applied; } else ++facs; } else ++facs; if(is_diff) break; } return ret; }