66 if (
typeid(*
this) !=
typeid(other)) {
70 fl &= ~(status_flags::evaluated | status_flags::expanded | status_flags::hash_calculated);
101 n.add_string(
"class", class_name());
117 print_dispatch(get_class_info(),
c, level);
132 const std::vector<print_functor> & pdt = reg_info->
options.get_print_dispatch_table();
135 unsigned id = pc_info->
options.get_id();
136 if (
id >= pdt.size() || !(pdt[
id].is_valid())) {
140 if (parent_pc_info) {
141 pc_info = parent_pc_info;
147 if (parent_reg_info) {
148 reg_info = parent_reg_info;
149 pc_info = &
c.get_class_info();
158 throw (std::runtime_error(std::string(
"basic::print(): method for ") + class_name() +
"/" +
c.class_name() +
" not found"));
163 pdt[id](*
this,
c, level);
170 c.s <<
"[" << class_name() <<
" object]";
174void basic::do_print_tree(
const print_tree &
c,
unsigned level)
const
176 c.s << std::string(level,
' ') << class_name() <<
" @" <<
this
177 << std::hex <<
", hash=0x" << hashvalue <<
", flags=0x" << flags << std::dec;
179 c.s <<
", nops=" <<
nops();
181 for (
size_t i=0; i<
nops(); ++i)
188 c.s << class_name() <<
"()";
198void basic::dbgprint()
const
201 std::cerr << std::endl;
207void basic::dbgprinttree()
const
213unsigned basic::precedence()
const
221bool basic::info(
unsigned inf)
const
228size_t basic::nops()
const
237ex basic::op(
size_t i)
const
239 throw(std::range_error(std::string(
"basic::op(): ") + class_name() + std::string(
" has no operands")));
243ex & basic::let_op(
size_t i)
245 ensure_if_modifiable();
246 throw(std::range_error(std::string(
"basic::let_op(): ") + class_name() + std::string(
" has no operands")));
249ex basic::operator[](
const ex & index)
const
251 if (is_exactly_a<numeric>(index))
252 return op(
static_cast<size_t>(ex_to<numeric>(index).
to_int()));
254 throw(std::invalid_argument(std::string(
"non-numeric indices not supported by ") + class_name()));
257ex basic::operator[](
size_t i)
const
262ex & basic::operator[](
const ex & index)
264 if (is_exactly_a<numeric>(index))
265 return let_op(ex_to<numeric>(index).
to_int());
267 throw(std::invalid_argument(std::string(
"non-numeric indices not supported by ") + class_name()));
270ex & basic::operator[](
size_t i)
279bool basic::has(
const ex & pattern,
unsigned options)
const
282 if (
match(pattern, repl_lst))
284 for (
size_t i=0; i<
nops(); i++)
299 basic *copy =
nullptr;
300 for (
size_t i=0; i<num; i++) {
301 const ex & o =
op(i);
311 copy->
clearflag(status_flags::hash_calculated | status_flags::expanded);
318bool basic::is_polynomial(
const ex & var)
const
320 return !
has(var) || is_equal(ex_to<basic>(var));
324int basic::degree(
const ex & s)
const
326 return is_equal(ex_to<basic>(s)) ? 1 : 0;
330int basic::ldegree(
const ex & s)
const
332 return is_equal(ex_to<basic>(s)) ? 1 : 0;
336ex basic::coeff(
const ex & s,
int n)
const
338 if (is_equal(ex_to<basic>(s)))
341 return n==0 ? *this :
_ex0;
347ex basic::collect(
const ex & s,
bool distributed)
const
358 else if (distributed) {
363 const lst& l(ex_to<lst>(s));
367 for (
const auto & xi :
x) {
370 for (
auto & li : l) {
371 int cexp = pre_coeff.
degree(li);
372 pre_coeff = pre_coeff.
coeff(li, cexp);
373 key *=
pow(li, cexp);
375 auto ci = cmap.find(key);
376 if (ci != cmap.end())
377 ci->second += pre_coeff;
379 cmap.insert(exmap::value_type(key, pre_coeff));
383 for (
auto & mi : cmap)
384 resv.push_back((mi.first)*(mi.second));
385 return dynallocate<add>(resv);
391 size_t n = s.
nops() - 1;
412ex basic::eval()
const
424ex basic::evalf()
const
430 return map(map_evalf);
440ex basic::evalm()
const
454ex basic::eval_integ()
const
480ex basic::add_indexed(
const ex & self,
const ex & other)
const
492ex basic::scalar_mul_indexed(
const ex & self,
const numeric & other)
const
509bool basic::contract_with(exvector::iterator self, exvector::iterator other,
exvector & v)
const
518bool basic::match(
const ex & pattern,
exmap& repl_lst)
const
536 if (is_exactly_a<wildcard>(pattern)) {
541 for (
auto & it : repl_lst) {
542 if (it.first.is_equal(pattern))
543 return is_equal(ex_to<basic>(it.second));
545 repl_lst[pattern] = *
this;
551 if (
typeid(*
this) !=
typeid(ex_to<basic>(pattern)))
561 return is_equal_same_type(ex_to<basic>(pattern));
564 if (!match_same_type(ex_to<basic>(pattern)))
571 exmap tmp_repl = repl_lst;
573 for (
size_t i=0; i<
nops(); i++)
574 if (!
op(i).
match(pattern.
op(i), tmp_repl))
586 if (
options & subs_options::no_pattern) {
588 auto it =
m.
find(thisex);
593 for (
auto & it :
m) {
595 if (
match(ex_to<basic>(it.first), repl_lst))
596 return it.second.
subs(repl_lst,
options | subs_options::no_pattern);
612 for (
size_t i=0; i<num; i++) {
613 const ex & orig_op =
op(i);
618 basic *copy = duplicate();
619 copy->
clearflag(status_flags::hash_calculated | status_flags::expanded);
622 copy->
let_op(i++) = subsed_op;
645ex basic::diff(
const symbol & s,
unsigned nth)
const
652 if (!(flags & status_flags::evaluated))
653 return ex(*this).
diff(s, nth);
655 ex ndiff = this->derivative(s);
658 ndiff = ndiff.
diff(s);
670ex basic::conjugate()
const
675ex basic::real_part()
const
677 return real_part_function(*this).hold();
680ex basic::imag_part()
const
682 return imag_part_function(*this).hold();
709 return map(map_derivative);
718int basic::compare_same_type(
const basic & other)
const
728bool basic::is_equal_same_type(
const basic & other)
const
730 return compare_same_type(other)==0;
743bool basic::match_same_type(
const basic & other)
const
750unsigned basic::return_type()
const
752 return return_types::commutative;
758 rt.
tinfo = &
typeid(*this);
769unsigned basic::calchash()
const
771 unsigned v = make_hash_seed(
typeid(*
this));
772 for (
size_t i=0; i<
nops(); i++) {
778 if (flags & status_flags::evaluated) {
779 setflag(status_flags::hash_calculated);
798 return (
options == 0) ? setflag(status_flags::expanded) : *
this;
801 return ex_to<basic>(map(map_expand)).setflag(
options == 0 ? status_flags::expanded : 0);
815int basic::compare(
const basic & other)
const
817#ifdef GINAC_COMPARE_STATISTICS
818 compare_statistics.total_basic_compares++;
820 const unsigned hash_this = gethash();
821 const unsigned hash_other = other.
gethash();
822 if (hash_this<hash_other)
return -1;
823 if (hash_this>hash_other)
return 1;
824#ifdef GINAC_COMPARE_STATISTICS
825 compare_statistics.compare_same_hashvalue++;
828 const std::type_info& typeid_this =
typeid(*this);
829 const std::type_info& typeid_other =
typeid(other);
830 if (typeid_this == typeid_other) {
841#ifdef GINAC_COMPARE_STATISTICS
842 compare_statistics.compare_same_type++;
844 return compare_same_type(other);
852 return (typeid_this.before(typeid_other) ? -1 : 1);
862bool basic::is_equal(
const basic & other)
const
864#ifdef GINAC_COMPARE_STATISTICS
865 compare_statistics.total_basic_is_equals++;
867 if (this->gethash()!=other.
gethash())
869#ifdef GINAC_COMPARE_STATISTICS
870 compare_statistics.is_equal_same_hashvalue++;
872 if (
typeid(*
this) !=
typeid(other))
875#ifdef GINAC_COMPARE_STATISTICS
876 compare_statistics.is_equal_same_type++;
878 return is_equal_same_type(other);
888 return setflag(status_flags::evaluated);
893void basic::ensure_if_modifiable()
const
895 if (get_refcount() > 1)
896 throw(std::runtime_error(
"cannot modify multiply referenced object"));
897 clearflag(status_flags::hash_calculated | status_flags::evaluated);
904#ifdef GINAC_COMPARE_STATISTICS
905compare_statistics_t::~compare_statistics_t()
907 std::clog <<
"ex::compare() called " << total_compares <<
" times" << std::endl;
908 std::clog <<
"nontrivial compares: " << nontrivial_compares <<
" times" << std::endl;
909 std::clog <<
"basic::compare() called " << total_basic_compares <<
" times" << std::endl;
910 std::clog <<
"same hashvalue in compare(): " << compare_same_hashvalue <<
" times" << std::endl;
911 std::clog <<
"compare_same_type() called " << compare_same_type <<
" times" << std::endl;
912 std::clog << std::endl;
913 std::clog <<
"ex::is_equal() called " << total_is_equals <<
" times" << std::endl;
914 std::clog <<
"nontrivial is_equals: " << nontrivial_is_equals <<
" times" << std::endl;
915 std::clog <<
"basic::is_equal() called " << total_basic_is_equals <<
" times" << std::endl;
916 std::clog <<
"same hashvalue in is_equal(): " << is_equal_same_hashvalue <<
" times" << std::endl;
917 std::clog <<
"is_equal_same_type() called " << is_equal_same_type <<
" times" << std::endl;
918 std::clog << std::endl;
919 std::clog <<
"basic::gethash() called " << total_gethash <<
" times" << std::endl;
920 std::clog <<
"used cached hashvalue " << gethash_cached <<
" times" << std::endl;
923compare_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.
bool find(const ex &pattern, exset &found) const
Find all occurrences of a 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)
const numeric pow(const numeric &x, const numeric &y)
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 diff(const ex &thisex, const symbol &s, unsigned nth=1)
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)
int ldegree(const ex &thisex, const ex &s)
ex evalf(const ex &thisex)
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)
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).
#define GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(classname, supername, options)
Macro for inclusion in the implementation of each registered class.
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.