Skip to content

Instantly share code, notes, and snippets.

@marionette-of-u
Last active December 13, 2015 19:29
Show Gist options
  • Select an option

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

Select an option

Save marionette-of-u/4963476 to your computer and use it in GitHub Desktop.
#include <typeinfo>
#include <cxxabi.h>
#include <cstdlib>
class demangle{
private:
char *realname;
public:
demangle(const std::type_info &ti){
int status = 0;
realname = abi::__cxa_demangle(ti.name(), 0, 0, &status);
}
demangle(const demangle&) = delete;
demangle &operator =(const demangle&) = delete;
~demangle(){
std::free(realname);
}
operator const char *() const{
return realname;
}
};
#include <iostream>
#include <ginac/ginac.h>
namespace ExtGiNaC{
using namespace GiNaC;
namespace detail{
template<class Dummy = void>
struct logarithm2_template{
logarithm2_template() = delete;
logarithm2_template(const ex &x_, const ex &y_) : x(x_), y(y_){}
logarithm2_template(const logarithm2_template &other) : x(other.x), y(other.y){}
logarithm2_template(logarithm2_template &&other) : x(other.x), y(other.y){}
const char *get_class_name(){ return "log2"; }
std::size_t nops() const{
return 2;
}
ex op(std::size_t i) const{
switch(i){
case 0:
return x;
case 1:
return y;
default:
throw(std::range_error("logarithm2::op(): no such operand"));
}
}
ex &let_op(std::size_t i){
switch(i){
case 0:
return x;
case 1:
return y;
default:
throw(std::range_error("logarithm2::let_op(): no such operand"));
}
}
ex x, y;
};
}
}
namespace GiNaC{
using logarithm2 = structure<ExtGiNaC::detail::logarithm2_template<>>;
template<>
ex logarithm2::evalf(int level) const{
const ExtGiNaC::detail::logarithm2_template<> &obj = get_struct();
return (log(obj.y).evalf(level) / log(obj.x).evalf(level)).evalf(level);
}
template<>
ex logarithm2::series(const relational &r, int order, unsigned int options) const{
const ExtGiNaC::detail::logarithm2_template<> &obj = get_struct();
return (log(obj.y) / log(obj.x)).series(r, order, options);
}
template<>
ex logarithm2::derivative(const symbol &s) const{
const ExtGiNaC::detail::logarithm2_template<> &obj = get_struct();
return (log(obj.y) / log(obj.x)).diff(s);
}
template<>
std::size_t logarithm2::nops() const{
return get_struct().nops();
}
template<>
ex logarithm2::op(std::size_t i) const{
return get_struct().op(i);
}
template<>
ex &logarithm2::let_op(std::size_t i){
return get_struct().let_op(i);
}
template<>
ex logarithm2::subs(const exmap &m, unsigned int options) const{
const ExtGiNaC::detail::logarithm2_template<> &obj = get_struct();
return (log(obj.y).subs(m, options) / log(obj.x).subs(m, options)).subs(m, options);
}
template<>
ex logarithm2::map(map_function &f) const{
const ExtGiNaC::detail::logarithm2_template<> &obj = get_struct();
return (log(obj.y) / log(obj.x)).map(f);
}
template<>
void logarithm2::print(const print_context &c, unsigned int level) const{
if(is_a<print_tree>(c)){
inherited::print(c, level);
}
const ExtGiNaC::detail::logarithm2_template<> &obj = get_struct();
const unsigned int prec = precedence();
c.s << "log(" << obj.x << ", " << obj.y << ")";
}
}
namespace ExtGiNaC{
inline logarithm2 log2(const ex &x, const ex &y){
return logarithm2(detail::logarithm2_template<>(x, y));
}
namespace detail{
inline ex exp_log_alternate_form(const ex &expression){
static const exmap equations = {
{
pow(wild(0), wild(1)) * pow(wild(0), wild(2)),
pow(wild(0), wild(1) + wild(2))
},
{
pow(pow(wild(0), wild(1)), wild(2)),
pow(wild(0), wild(1) * wild(2))
},
{
pow(wild(0), wild(1)) / pow(wild(0), wild(2)),
pow(wild(0), wild(1) - wild(2))
}
};
ex current = expression;
for(; ; ){
const ex temp = current.subs(equations, subs_options::algebraic);
if(temp == current){ break; }
current = temp;
}
return current;
}
}
inline ex alternate_form(const ex &expression){
symbol e;
return detail::exp_log_alternate_form(expression.subs(exp(wild(0)) == pow(e, wild(0)))).subs(pow(e, wild(0)) == exp(wild(0)));
}
}
int main(){
using namespace ExtGiNaC;
// logarithm2 test
{
symbol x("x"), y("y");
symbol a("a"), b("b");
ex e = log2(x, y);
std::cout << latex;
std::cout << e << std::endl;
std::cout << e.subs(lst(x == 2, y == 1024)).eval() << std::endl;
std::cout << e.subs(lst(x == 2, y == 1024)).evalf() << std::endl;
std::cout << e.op(0) << std::endl;
std::cout << e.op(1) << std::endl;
std::cout << e.series(y == a, 4) << std::endl;
std::cout << e.series(x == b, 4) << std::endl;
std::cout << e.diff(y) << std::endl;
std::cout << e.diff(x) << std::endl;
}
// alternate_form test
/*
{
symbol x("x"), y("y"), z("z");
auto f = [&z](const ex &expression){
return pow(z, expression);
};
symbol a("a"), b("b"), c("c");
ex p = exp(pow(a, b)) / exp(pow(a, c));
ex q = pow(p * exp(pow(a, c)), p * exp(pow(b, c)));
std::cout << q << " = " << alternate_form(q) << std::endl;
std::cout << (pow(exp(Pi), I) + 1) << " = " << alternate_form(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