67 if (
typeid(*
this) !=
typeid(other)) {
71 fl &= ~(status_flags::evaluated | status_flags::expanded | status_flags::hash_calculated);
102 n.add_string(
"class", class_name());
118 print_dispatch(get_class_info(),
c, level);
133 const std::vector<print_functor> & pdt = reg_info->
options.get_print_dispatch_table();
136 unsigned id = pc_info->
options.get_id();
137 if (
id >= pdt.size() || !(pdt[
id].is_valid())) {
141 if (parent_pc_info) {
142 pc_info = parent_pc_info;
148 if (parent_reg_info) {
149 reg_info = parent_reg_info;
150 pc_info = &
c.get_class_info();
159 throw (std::runtime_error(std::string(
"basic::print(): method for ") + class_name() +
"/" +
c.class_name() +
" not found"));
164 pdt[id](*
this,
c, level);
171 c.s <<
"[" << class_name() <<
" object]";
175void basic::do_print_tree(
const print_tree &
c,
unsigned level)
const
177 c.s << std::string(level,
' ') << class_name() <<
" @" <<
this
178 << std::hex <<
", hash=0x" << hashvalue <<
", flags=0x" << flags << std::dec;
180 c.s <<
", nops=" <<
nops();
182 for (
size_t i=0; i<
nops(); ++i)
189 c.s << class_name() <<
"()";
199void basic::dbgprint()
const
202 std::cerr << std::endl;
208void basic::dbgprinttree()
const
214unsigned basic::precedence()
const
222bool basic::info(
unsigned inf)
const
240 throw(std::range_error(std::string(
"basic::op(): ") + class_name() + std::string(
" has no operands")));
244ex & basic::let_op(
size_t i)
246 ensure_if_modifiable();
247 throw(std::range_error(std::string(
"basic::let_op(): ") + class_name() + std::string(
" has no operands")));
250ex basic::operator[](
const ex & index)
const
252 if (is_exactly_a<numeric>(index))
253 return op(
static_cast<size_t>(ex_to<numeric>(index).
to_int()));
255 throw(std::invalid_argument(std::string(
"non-numeric indices not supported by ") + class_name()));
258ex basic::operator[](
size_t i)
const
263ex & basic::operator[](
const ex & index)
265 if (is_exactly_a<numeric>(index))
266 return let_op(ex_to<numeric>(index).
to_int());
268 throw(std::invalid_argument(std::string(
"non-numeric indices not supported by ") + class_name()));
271ex & basic::operator[](
size_t i)
283 if (
match(pattern, repl_lst))
285 for (
size_t i=0; i<
nops(); i++)
300 basic *copy =
nullptr;
301 for (
size_t i=0; i<num; i++) {
302 const ex & o =
op(i);
312 copy->
clearflag(status_flags::hash_calculated | status_flags::expanded);
321 return !
has(var) || is_equal(ex_to<basic>(var));
327 return is_equal(ex_to<basic>(s)) ? 1 : 0;
333 return is_equal(ex_to<basic>(s)) ? 1 : 0;
339 if (is_equal(ex_to<basic>(s)))
342 return n==0 ? *this :
_ex0;
359 else if (distributed) {
364 const lst& l(ex_to<lst>(s));
368 for (
const auto & xi :
x) {
371 for (
auto & li : l) {
372 int cexp = pre_coeff.
degree(li);
373 pre_coeff = pre_coeff.
coeff(li, cexp);
374 key *=
pow(li, cexp);
376 auto ci = cmap.find(key);
377 if (ci != cmap.end())
378 ci->second += pre_coeff;
380 cmap.insert(exmap::value_type(key, pre_coeff));
384 for (
auto & mi : cmap)
385 resv.push_back((mi.first)*(mi.second));
386 return dynallocate<add>(resv);
392 size_t n = s.
nops() - 1;
431 return map(map_evalf);
481ex basic::add_indexed(
const ex & self,
const ex & other)
const
493ex basic::scalar_mul_indexed(
const ex & self,
const numeric & other)
const
510bool basic::contract_with(exvector::iterator self, exvector::iterator other,
exvector & v)
const
537 if (is_exactly_a<wildcard>(pattern)) {
542 for (
auto & it : repl_lst) {
543 if (it.first.is_equal(pattern))
544 return is_equal(ex_to<basic>(it.second));
546 repl_lst[pattern] = *
this;
552 if (
typeid(*
this) !=
typeid(ex_to<basic>(pattern)))
562 return is_equal_same_type(ex_to<basic>(pattern));
565 if (!match_same_type(ex_to<basic>(pattern)))
572 exmap tmp_repl = repl_lst;
574 for (
size_t i=0; i<
nops(); i++)
575 if (!
op(i).
match(pattern.
op(i), tmp_repl))
587 if (
options & subs_options::no_pattern) {
589 auto it =
m.find(thisex);
594 for (
auto & it :
m) {
596 if (
match(ex_to<basic>(it.first), repl_lst))
597 return it.second.
subs(repl_lst,
options | subs_options::no_pattern);
613 for (
size_t i=0; i<num; i++) {
614 const ex & orig_op =
op(i);
619 basic *copy = duplicate();
620 copy->
clearflag(status_flags::hash_calculated | status_flags::expanded);
623 copy->
let_op(i++) = subsed_op;
653 if (!(flags & status_flags::evaluated))
654 return ex(*this).
diff(s, nth);
656 ex ndiff = this->derivative(s);
659 ndiff = ndiff.
diff(s);
678 return real_part_function(*this).hold();
683 return imag_part_function(*this).hold();
710 return map(map_derivative);
719int basic::compare_same_type(
const basic & other)
const
729bool basic::is_equal_same_type(
const basic & other)
const
731 return compare_same_type(other)==0;
744bool basic::match_same_type(
const basic & other)
const
751unsigned basic::return_type()
const
753 return return_types::commutative;
759 rt.
tinfo = &
typeid(*this);
770unsigned basic::calchash()
const
773 for (
size_t i=0; i<
nops(); i++) {
779 if (flags & status_flags::evaluated) {
780 setflag(status_flags::hash_calculated);
799 return (
options == 0) ? setflag(status_flags::expanded) : *
this;
802 return ex_to<basic>(map(map_expand)).setflag(
options == 0 ? status_flags::expanded : 0);
816int basic::compare(
const basic & other)
const
818#ifdef GINAC_COMPARE_STATISTICS
819 compare_statistics.total_basic_compares++;
821 const unsigned hash_this = gethash();
822 const unsigned hash_other = other.
gethash();
823 if (hash_this<hash_other)
return -1;
824 if (hash_this>hash_other)
return 1;
825#ifdef GINAC_COMPARE_STATISTICS
826 compare_statistics.compare_same_hashvalue++;
829 const std::type_info& typeid_this =
typeid(*this);
830 const std::type_info& typeid_other =
typeid(other);
831 if (typeid_this == typeid_other) {
842#ifdef GINAC_COMPARE_STATISTICS
843 compare_statistics.compare_same_type++;
845 return compare_same_type(other);
853 return (typeid_this.before(typeid_other) ? -1 : 1);
863bool basic::is_equal(
const basic & other)
const
865#ifdef GINAC_COMPARE_STATISTICS
866 compare_statistics.total_basic_is_equals++;
868 if (this->gethash()!=other.
gethash())
870#ifdef GINAC_COMPARE_STATISTICS
871 compare_statistics.is_equal_same_hashvalue++;
873 if (
typeid(*
this) !=
typeid(other))
876#ifdef GINAC_COMPARE_STATISTICS
877 compare_statistics.is_equal_same_type++;
879 return is_equal_same_type(other);
889 return setflag(status_flags::evaluated);
894void basic::ensure_if_modifiable()
const
896 if (get_refcount() > 1)
897 throw(std::runtime_error(
"cannot modify multiply referenced object"));
898 clearflag(status_flags::hash_calculated | status_flags::evaluated);
905#ifdef GINAC_COMPARE_STATISTICS
906compare_statistics_t::~compare_statistics_t()
908 std::clog <<
"ex::compare() called " << total_compares <<
" times" << std::endl;
909 std::clog <<
"nontrivial compares: " << nontrivial_compares <<
" times" << std::endl;
910 std::clog <<
"basic::compare() called " << total_basic_compares <<
" times" << std::endl;
911 std::clog <<
"same hashvalue in compare(): " << compare_same_hashvalue <<
" times" << std::endl;
912 std::clog <<
"compare_same_type() called " << compare_same_type <<
" times" << std::endl;
913 std::clog << std::endl;
914 std::clog <<
"ex::is_equal() called " << total_is_equals <<
" times" << std::endl;
915 std::clog <<
"nontrivial is_equals: " << nontrivial_is_equals <<
" times" << std::endl;
916 std::clog <<
"basic::is_equal() called " << total_basic_is_equals <<
" times" << std::endl;
917 std::clog <<
"same hashvalue in is_equal(): " << is_equal_same_hashvalue <<
" times" << std::endl;
918 std::clog <<
"is_equal_same_type() called " << is_equal_same_type <<
" times" << std::endl;
919 std::clog << std::endl;
920 std::clog <<
"basic::gethash() called " << total_gethash <<
" times" << std::endl;
921 std::clog <<
"used cached hashvalue " << gethash_cached <<
" times" << std::endl;
924compare_statistics_t compare_statistics;
Interface to GiNaC's sums of expressions.
Archiving of GiNaC expressions.
Interface to GiNaC's ABC.
This class stores all properties needed to record/retrieve the state of one object of class basic (or...
This class is the ABC (abstract base class) of GiNaC's class hierarchy.
const basic & clearflag(unsigned f) const
Clear some status_flags.
unsigned hashvalue
hash value
unsigned flags
of type status_flags
void do_print(const print_context &c, unsigned level) const
Default output to stream.
ex subs_one_level(const exmap &m, unsigned options) const
Helper function for subs().
virtual ex & let_op(size_t i)
Return modifiable operand/member at position i.
void do_print_tree(const print_tree &c, unsigned level) const
Tree output to stream.
void do_print_python_repr(const print_python_repr &c, unsigned level) const
Python parsable output to stream.
class_info * get_parent() const
Get pointer to class_info of parent class (or nullptr).
Wrapper template for making GiNaC classes out of STL containers.
Lightweight wrapper for GiNaC's symbolic objects.
bool match(const ex &pattern) const
Check whether expression matches a specified pattern.
ex diff(const symbol &s, unsigned nth=1) const
Compute partial derivative of an expression.
ex expand(unsigned options=0) const
Expand an expression.
int degree(const ex &s) const
bool has(const ex &pattern, unsigned options=0) const
ex subs(const exmap &m, unsigned options=0) const
void print(const print_context &c, unsigned level=0) const
Print expression to stream.
ex coeff(const ex &s, int n=1) const
This class is a wrapper around CLN-numbers within the GiNaC class hierarchy.
This class holds a two-component object, a basis and and exponent representing exponentiation.
Base class for print_contexts.
Context for default (ginsh-parsable) output.
Context for python-parsable output.
Context for tree-like output for debugging.
Flags to store information about the state of an object.
Interface to GiNaC's light-weight expression handles.
Interface to GiNaC's initially known functions.
Definition of GiNaC's lst.
ex hold_ncmul(const exvector &v)
ex real_part(const ex &thisex)
const numeric pow(const numeric &x, const numeric &y)
bool is_polynomial(const ex &thisex, const ex &vars)
std::map< ex, ex, ex_is_less > exmap
bool are_ex_trivially_equal(const ex &e1, const ex &e2)
Compare two objects of class quickly without doing a deep tree traversal.
int compare_pointers(const T *a, const T *b)
Compare two pointers (just to establish some sort of canonical order).
ex conjugate(const ex &thisex)
ex diff(const ex &thisex, const symbol &s, unsigned nth=1)
ex subs(const ex &thisex, const exmap &m, unsigned options=0)
ex eval(const ex &thisex)
int degree(const ex &thisex, const ex &s)
print_func< print_context >(&varidx::do_print). print_func< print_latex >(&varidx
bool match(const ex &thisex, const ex &pattern, exmap &repl_lst)
GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(add, expairseq, print_func< print_context >(&add::do_print). print_func< print_latex >(&add::do_print_latex). print_func< print_csrc >(&add::do_print_csrc). print_func< print_tree >(&add::do_print_tree). print_func< print_python_repr >(&add::do_print_python_repr)) add
int ldegree(const ex &thisex, const ex &s)
ex evalf(const ex &thisex)
static unsigned make_hash_seed(const std::type_info &tinfo)
We need a hash function which gives different values for objects of different types.
unsigned rotate_left(unsigned n)
Rotate bits of unsigned value by one bit to the left.
GiNaC::evalm_map_function map_evalm
ex op(const ex &thisex, size_t i)
ex coeff(const ex &thisex, const ex &s, int n=1)
ex collect(const ex &thisex, const ex &s, bool distributed=false)
int to_int(const numeric &x)
ex eval_integ(const ex &thisex)
ex evalm(const ex &thisex)
bool has(const ex &thisex, const ex &pattern, unsigned options=0)
std::vector< ex > exvector
size_t nops(const ex &thisex)
ex imag_part(const ex &thisex)
GiNaC::eval_integ_map_function map_eval_integ
ex expand(const ex &thisex, unsigned options=0)
Interface to GiNaC's non-commutative products of expressions.
Makes the interface to the underlying bignum package available.
Interface to GiNaC's overloaded operators.
Interface to GiNaC's symbolic exponentiation (basis^exponent).
Interface to relations between expressions.
Function object to be applied by basic::derivative().
derivative_map_function(const symbol &sym)
ex operator()(const ex &e) override
Function object to be applied by basic::eval_integ().
ex operator()(const ex &e) override
Function object to be applied by basic::evalf().
ex operator()(const ex &e) override
Function object to be applied by basic::evalm().
ex operator()(const ex &e) override
Function object to be applied by basic::expand().
expand_map_function(unsigned o)
ex operator()(const ex &e) override
Function object for map().
To distinguish between different kinds of non-commutative objects.
std::type_info const * tinfo
to distinguish between non-commutative objects of different type.
unsigned rl
to distinguish between non-commutative objects of the same type.
Interface to GiNaC's symbolic objects.
Interface to several small and furry utilities needed within GiNaC but not of any interest to the use...
Interface to GiNaC's wildcard objects.