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
|
#include "Cleanup.hh"
#include "algorithms/replace_match.hh"
#include "algorithms/substitute.hh"
using namespace cadabra;
replace_match::replace_match(const Kernel& k, Ex& e)
: Algorithm(k, e)
{
}
bool replace_match::can_apply(iterator)
{
if(tr.history_size()>0) return true;
return false;
}
Algorithm::result_t replace_match::apply(iterator& it)
{
// Preserve the expression before popping. After this, the 'tr' is
// the original expression from before 'take_match'.
Ex current(tr);
auto to_keep=tr.pop_history();
if(to_keep.size()==0) {
return result_t::l_applied;
}
// Remove the terms which we will replace, by converting
// the 'to_keep' paths above to iterators, then removing.
iterator sum_node = tr.parent(tr.iterator_from_path(to_keep[0], tr.begin()));
std::vector<iterator> to_erase;
for(const auto& p: to_keep)
to_erase.push_back( tr.iterator_from_path(p, tr.begin()) );
for(auto& erase: to_erase)
tr.erase(erase);
// If the replacement is zero, there is nothing to substitute.
if(!current.begin()->is_zero()) {
// We already have an iterator to the sum node in the now-current
// expression (sum_node). We also need one to the sum node in the
// replacement sum.
iterator replacement_sum_node = current.iterator_from_path(tr.path_from_iterator(sum_node, tr.begin()), current.begin());
// If the original sum has disappeared (because subsequent manipulations
// made all but one terms vanish), wrap it again in a sum.
if(*replacement_sum_node->name!="\\sum")
replacement_sum_node = current.wrap(replacement_sum_node, str_node("\\sum"));
// If we are inside an integral, determine the \int multiplier in the original
// and in the replacement.
multiplier_t rescale=1;
if(!tr.is_head(it) && *tr.parent(it)->name=="\\int") {
multiplier_t orig_mult = *tr.parent(it)->multiplier;
multiplier_t repl_mult = *current.parent(replacement_sum_node)->multiplier;
rescale = repl_mult/orig_mult;
}
sibling_iterator repit=current.begin(replacement_sum_node);
while(repit!=current.end(replacement_sum_node)) {
multiply( tr.append_child(sum_node, iterator(repit))->multiplier, rescale);
++repit;
}
}
cleanup_dispatch(kernel, tr, it);
return result_t::l_applied;
}
|