Skip to content

Instantly share code, notes, and snippets.

@marionette-of-u
Last active December 12, 2015 10:39
Show Gist options
  • Select an option

  • Save marionette-of-u/4760513 to your computer and use it in GitHub Desktop.

Select an option

Save marionette-of-u/4760513 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <functional>
#include <ginac/ginac.h>
namespace ExtGiNaC{
using namespace GiNaC;
namespace detail{
class exp_alternate_form{
public:
ex operator ()(const ex &expression){
symbol e;
return
proc(
expression.subs(
exp(wild(0)) == pow(e, wild(0)), subs_options::algebraic
), e
).subs(
pow(e, wild(0)) == exp(wild(0)), subs_options::algebraic
);
}
private:
static ex proc(const ex &expression, const ex &base){
if(is_a<add>(expression)){
ex sum;
for(std::size_t i = 0, i_ = expression.nops(); i < i_; ++i){
sum += proc(expression.op(i), base);
}
return sum;
}
const ex mul_pattern = pow(pow(base, wild(0)), wild(1)), rep_pattern = wild(0) * wild(1);
if(is_a<mul>(expression)){
ex r, s = 1;
const ex pow_pattern = pow(base, wild(0));
for(std::size_t i = 0, i_ = expression.nops(); i < i_; ++i){
const ex &t = expression.op(i);
exmap match_result;
if(t.match(pow_pattern, match_result) || t.match(pow(pow(base, wild(0)), wild(1)), match_result)){
ex prod = 1;
for(const auto &item : match_result){
prod *= proc(item.second, base);
}
r += prod;
}else{
s *= proc(t, base);
s = s.subs(pow(wild(0), wild(1)) * pow(wild(0), wild(2)) == pow(wild(0), wild(1) + wild(2)), subs_options::algebraic);
}
}
return pow(base, r) * s;
}else if(is_a<power>(expression)){
ex n_expression = expression.match(mul_pattern) ?
pow(base, proc(expression.subs(mul_pattern == rep_pattern), base)) :
pow(proc(expression.op(0), base), proc(expression.op(1), base));
if(n_expression.match(pow(pow(wild(0), wild(1)), wild(2)))){
const ex &a = n_expression;
return pow(a.op(0).op(0), proc(a.op(0).op(1) * a.op(1), a.op(0).op(0)));
}else{
return n_expression;
}
}else{
return expression;
}
}
};
}
ex reduce(const ex &expression){
detail::exp_alternate_form r;
return r(expression);
}
} // namespace ExtGiNaC
int main(){
using namespace ExtGiNaC;
symbol z("z");
auto f = [](const ex &x){
return exp(x);
};
auto g = [&z](const ex &x){
return pow(z, x);
};
symbol a("a"), b("b"), c("c");
ex p = f(a) * f(a) * f(a) * f(a) * f(f(b) * f(b)) * f(f(c) * f(c) * f(c));
ex q = g(a) * g(a) * g(a) * g(a) * g(g(b) * g(b)) * g(g(c) * g(c) * g(c));
ex r = q * q * q * p * p * p;
std::cout << r << " = " << reduce(r) << std::endl;
std::cout << (pow(exp(Pi), I) + 1) << " = " << reduce(pow(exp(Pi), I) + 1) << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment