pseries::print(): print trivial case, too.
others: documentation updates.
expair add::split_ex_to_pair(const ex & e) const
{
if (is_ex_exactly_of_type(e,mul)) {
- const mul & mulref=ex_to_mul(e);
- ex numfactor=mulref.overall_coeff;
- // mul * mulcopyp=static_cast<mul *>(mulref.duplicate());
- mul * mulcopyp=new mul(mulref);
- mulcopyp->overall_coeff=_ex1();
+ const mul & mulref = ex_to_mul(e);
+ ex numfactor = mulref.overall_coeff;
+ // mul * mulcopyp = static_cast<mul *>(mulref.duplicate());
+ mul * mulcopyp = new mul(mulref);
+ mulcopyp->overall_coeff = _ex1();
mulcopyp->clearflag(status_flags::evaluated);
mulcopyp->clearflag(status_flags::hash_calculated);
return expair(mulcopyp->setflag(status_flags::dynallocated),numfactor);
const ex & c) const
{
GINAC_ASSERT(is_ex_exactly_of_type(c, numeric));
- ex one = _ex1();
if (is_ex_exactly_of_type(e, mul)) {
const mul &mulref = ex_to_mul(e);
ex numfactor = mulref.overall_coeff;
mul *mulcopyp = new mul(mulref);
- mulcopyp->overall_coeff = one;
+ mulcopyp->overall_coeff = _ex1();
mulcopyp->clearflag(status_flags::evaluated);
mulcopyp->clearflag(status_flags::hash_calculated);
mulcopyp->setflag(status_flags::dynallocated);
- if (are_ex_trivially_equal(c, one)) {
+ if (are_ex_trivially_equal(c, _ex1())) {
return expair(*mulcopyp, numfactor);
- } else if (are_ex_trivially_equal(numfactor, one)) {
+ } else if (are_ex_trivially_equal(numfactor, _ex1())) {
return expair(*mulcopyp, c);
}
return expair(*mulcopyp, ex_to_numeric(numfactor).mul_dyn(ex_to_numeric(c)));
} else if (is_ex_exactly_of_type(e, numeric)) {
- if (are_ex_trivially_equal(c, one)) {
- return expair(e, one);
- }
- return expair(ex_to_numeric(e).mul_dyn(ex_to_numeric(c)), one);
+ if (are_ex_trivially_equal(c, _ex1()))
+ return expair(e, _ex1());
+ return expair(ex_to_numeric(e).mul_dyn(ex_to_numeric(c)), _ex1());
}
return expair(e, c);
}
}
/** Output to stream in ugly raw format, so brave developers can have a look
- * at the underlying structure. */
+ * at the underlying structure. */
void basic::printraw(std::ostream & os) const
{
debugmsg("basic printraw",LOGLEVEL_PRINT);
debugmsg("basic print csrc", LOGLEVEL_PRINT);
}
-/** Little wrapper arount print to be called within a debugger. */
+/** Little wrapper arount print to be called within a debugger.
+ * This is needed because you cannot call foo.print(cout) from within the
+ * debugger because it might not know what cout is. This method can be invoked
+ * with no argument and it will simply print to stdout.
+ *
+ * @see basic::print*/
void basic::dbgprint(void) const
{
print(std::cerr);
std::cerr << std::endl;
}
-/** Little wrapper arount printtree to be called within a debugger. */
+/** Little wrapper arount printtree to be called within a debugger.
+ *
+ * @see basic::dbgprint
+ * @see basic::printtree */
void basic::dbgprinttree(void) const
{
printtree(std::cerr,0);
void basic::ensure_if_modifiable(void) const
{
- if (refcount>1) {
+ if (refcount>1)
throw(std::runtime_error("cannot modify multiply referenced object"));
- }
}
//////////
#else
;
#endif // def INLINE_BASIC_CONSTRUCTORS
-
+
const basic & operator=(const basic & other);
-
+
protected:
void copy(const basic & other)
{
} else {
number = 0;
}
- // fct_assigned=other.fct_assigned;
}
void constant::destroy(bool call_parent)
std::string name;
evalffunctype ef;
numeric * number;
- // bool fct_assigned;
- unsigned serial; //!< unique serial number for comparision
+ unsigned serial; //! unique serial number for comparision
static unsigned next_serial;
};
#endif // ndef NO_NAMESPACE_GINAC
class ex;
-class expand_options;
-class status_flags;
-
class symbol;
class lst;
while (i != iend) {
n.add_ex("rest", i->rest);
n.add_ex("coeff", i->coeff);
- i++;
+ ++i;
}
n.add_ex("overall_coeff", overall_coeff);
}
for (epplist::const_iterator it=hashtab[i].begin();
it!=hashtab[i].end(); ++it) {
os << *it-seq.begin() << " ";
- this_bin_fill++;
+ ++this_bin_fill;
}
os << std::endl;
cum_fill += this_bin_fill;
cit=v.begin();
while (cit!=citend) {
if (cit->bp->tinfo()==tinfo()) {
- nexpairseqs++;
+ ++nexpairseqs;
noperands+=ex_to_expairseq(*cit).seq.size();
}
++cit;
cit = v.begin();
while (cit!=citend) {
if (cit->rest.bp->tinfo()==tinfo()) {
- nexpairseqs++;
+ ++nexpairseqs;
noperands += ex_to_expairseq((*cit).rest).seq.size();
}
++cit;
do {
last_numeric--;
} while (is_ex_exactly_of_type((*last_numeric).rest,numeric));
- last_numeric++;
+ ++last_numeric;
sort(last_numeric,seq.end(),expair_is_less());
}
}
unsigned hash=e.gethash();
unsigned hashindex;
if (is_a_numeric_hash(hash)) {
- hashindex=hashmask;
+ hashindex = hashmask;
} else {
- hashindex=hash & hashmask;
+ hashindex = hash & hashmask;
// last hashtab entry is reserved for numerics
- if (hashindex==hashmask) hashindex=0;
+ if (hashindex==hashmask) hashindex = 0;
}
GINAC_ASSERT(hashindex>=0);
GINAC_ASSERT((hashindex<hashtabsize)||(hashtabsize==0));
GINAC_ASSERT(new_hashtabsize<hashtabsize);
if (new_hashtabsize==0) {
hashtab.clear();
- hashtabsize=0;
+ hashtabsize = 0;
canonicalize();
return;
}
// shrink by a factor of 2
unsigned half_hashtabsize=hashtabsize/2;
- for (unsigned i=0; i<half_hashtabsize-1; ++i) {
+ for (unsigned i=0; i<half_hashtabsize-1; ++i)
hashtab[i].merge(hashtab[i+half_hashtabsize],epp_is_less());
- }
// special treatment for numeric hashes
hashtab[0].merge(hashtab[half_hashtabsize-1],epp_is_less());
- hashtab[half_hashtabsize-1]=hashtab[hashtabsize-1];
+ hashtab[half_hashtabsize-1] = hashtab[hashtabsize-1];
hashtab.resize(half_hashtabsize);
- hashtabsize=half_hashtabsize;
- hashmask=hashtabsize-1;
+ hashtabsize = half_hashtabsize;
+ hashmask = hashtabsize-1;
}
}
if (hashtabsize==0) return; // nothing to do
// calculate hashindex of element to be deleted
- unsigned hashindex=calc_hashindex((*element).rest);
+ unsigned hashindex = calc_hashindex((*element).rest);
// find it in hashtab and remove it
- epplist & eppl=hashtab[hashindex];
- epplist::iterator epplit=eppl.begin();
- bool erased=false;
+ epplist & eppl = hashtab[hashindex];
+ epplist::iterator epplit = eppl.begin();
+ bool erased = false;
while (epplit!=eppl.end()) {
if (*epplit == element) {
eppl.erase(epplit);
- erased=true;
+ erased = true;
break;
}
++epplit;
cout << "tried to erase " << element-seq.begin() << std::endl;
cout << "size " << seq.end()-seq.begin() << std::endl;
- unsigned hashindex=calc_hashindex((*element).rest);
- epplist & eppl=hashtab[hashindex];
+ unsigned hashindex = calc_hashindex((*element).rest);
+ epplist & eppl = hashtab[hashindex];
epplist::iterator epplit=eppl.begin();
bool erased=false;
while (epplit!=eppl.end()) {
if (*epplit == element) {
eppl.erase(epplit);
- erased=true;
+ erased = true;
break;
}
++epplit;
unsigned hashindex=calc_hashindex((*newpos).rest);
// find it in hashtab and modify it
- epplist & eppl=hashtab[hashindex];
+ epplist & eppl = hashtab[hashindex];
epplist::iterator epplit=eppl.begin();
while (epplit!=eppl.end()) {
if (*epplit == oldpos) {
void expairseq::sorted_insert(epplist & eppl, epp elem)
{
- epplist::iterator current=eppl.begin();
+ epplist::iterator current = eppl.begin();
while ((current!=eppl.end())&&((*(*current)).is_less(*elem))) {
++current;
}
// combine same terms, drop term with coeff 0, move numerics to end
// calculate size of hashtab
- hashtabsize=calc_hashtabsize(seq.size());
+ hashtabsize = calc_hashtabsize(seq.size());
// hashtabsize is a power of 2
- hashmask=hashtabsize-1;
+ hashmask = hashtabsize-1;
// allocate hashtab
hashtab.clear();
touched.reserve(seq.size());
for (unsigned i=0; i<seq.size(); ++i) touched[i]=false;
- unsigned number_of_zeroes=0;
+ unsigned number_of_zeroes = 0;
GINAC_ASSERT(!has_coeff_0());
build_hashtab_and_combine(first_numeric,last_non_zero,touched,number_of_zeroes);
if (!are_ex_trivially_equal((*cit).rest,subsed_ex)) {
// something changed, copy seq, subs and return it
- epvector *s=new epvector;
+ epvector *s = new epvector;
s->reserve(seq.size());
// copy parts of seq which are known not to have changed
};
};
+/** Flags to control series expansion. */
class series_options {
public:
enum {
};
};
+/** Switch to control algorithm for determinant computation. */
class determinant_algo {
public:
enum {
- automatic,
- gauss,
- divfree,
- laplace,
- bareiss
+ automatic, //! Let the system choose
+ gauss, //! Gauss elimiation
+ divfree, //! Division-free elimination
+ laplace, //! Laplace (or minor) elimination
+ bareiss //! Bareiss fraction-free elimination
};
};
+/** Switch to control algorithm for linear system solving. */
class solve_algo {
public:
enum {
- automatic,
- gauss,
- divfree,
- bareiss
+ automatic, //! Let the system choose
+ gauss, //! Gauss elimiation
+ divfree, //! Division-free elimination
+ bareiss //! Bareiss fraction-free elimination
};
};
+/** Flags to store information about the stato of an object. */
class status_flags {
public:
enum {
- dynallocated = 0x0001,
- evaluated = 0x0002,
- expanded = 0x0004,
- hash_calculated = 0x0008
+ dynallocated = 0x0001, //! Heap-allocated (i.e. created by new)
+ evaluated = 0x0002, //! .eval() has already done its job
+ expanded = 0x0004, //! .expand() has already done its job
+ hash_calculated = 0x0008 //! .calchash() has already done its job
};
};
};
};
+/** Strategies how to clean up the function remember cache.
+ * @see remember_table */
class remember_strategies {
public:
enum {
- delete_never, // let table grow undefinitely, not recommmended, but currently default
- delete_lru, // least recently used
- delete_lfu, // least frequently used
- delete_cyclic // first (oldest) one in list
+ delete_never, //! Let table grow undefinitely, not recommmended, but currently default
+ delete_lru, //! Least recently used
+ delete_lfu, //! Least frequently used
+ delete_cyclic //! First (oldest) one in list
};
};
#include <stdexcept>
#include "inifcns.h"
-#include "ex.h"
#include "constant.h"
#include "pseries.h"
#include "numeric.h"
#include <stdexcept>
#include "inifcns.h"
-#include "ex.h"
#include "constant.h"
#include "numeric.h"
#include "power.h"
#include "add.h"
#include "mul.h"
#include "debugmsg.h"
-#include "flags.h"
#include "lst.h"
#include "lortensor.h"
#include "operators.h"
void printcsrc(std::ostream & os, unsigned type, unsigned precedence=0) const;
bool info(unsigned inf) const;
bool has(const ex & other) const;
- ex eval(int level=0) const;
- ex evalf(int level=0) const;
+ ex eval(int level = 0) const;
+ ex evalf(int level = 0) const;
ex normal(lst &sym_lst, lst &repl_lst, int level=0) const;
ex to_rational(lst &repl_lst) const;
numeric integer_content(void) const;
{
debugmsg("pseries print", LOGLEVEL_PRINT);
if (precedence<=upper_precedence) os << "(";
+ // objects of type pseries must not have any zero entries, so the
+ // trivial (zero) pseries needs a special treatment here:
+ if (seq.size()==0)
+ os << '0';
for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) {
- // omit zero terms
- if (i->rest.is_zero())
- continue;
// print a sign, if needed
if (i!=seq.begin())
os << '+';
{
debugmsg("pseries printraw", LOGLEVEL_PRINT);
os << "pseries(" << var << ";" << point << ";";
- for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) {
+ for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i)
os << "(" << (*i).rest << "," << (*i).coeff << "),";
- }
os << ")";
}
}
}
+/** Return coefficient of degree n in power series if s is the expansion
+ * variable. If the expansion point is nonzero, by definition the n=1
+ * coefficient in s of a+b*(s-z)+c*(s-z)^2+Order((s-z)^3) is b (assuming
+ * the expansion took place in the s in the first place).
+ * If s is not the expansion variable, an attempt is made to convert the
+ * series to a polynomial and return the corresponding coefficient from
+ * there. */
ex pseries::coeff(const symbol &s, int n) const
{
if (var.is_equal(s)) {
return convert_to_poly().coeff(s, n);
}
-
+/** Does nothing. */
ex pseries::collect(const symbol &s) const
{
return *this;
{
epvector newseq;
newseq.reserve(seq.size());
- for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i)
- newseq.push_back(expair(i->rest.expand(), i->coeff));
+ for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) {
+ ex restexp = i->rest.expand();
+ if (!restexp.is_zero())
+ newseq.push_back(expair(restexp, i->coeff));
+ }
return (new pseries(relational(var,point), newseq))
->setflag(status_flags::dynallocated | status_flags::expanded);
}
/** Symbols as keys to expressions. */
class assigned_ex_info {
public:
- assigned_ex_info(); //!< Default ctor
- bool is_assigned; //!< True if there is an expression assigned
- ex assigned_expression; //!< The actual expression
- unsigned refcount; //!< Yet another refcounter. PLEASE EXPLAIN!
+ assigned_ex_info(); //! Default ctor
+ bool is_assigned; //! True if there is an expression assigned
+ ex assigned_expression; //! The actual expression
+ unsigned refcount; //! Yet another refcounter. PLEASE EXPLAIN!
};
// member functions