* Implementation of GiNaC's products of expressions. */
/*
- * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany
+ * GiNaC Copyright (C) 1999-2001 Johannes Gutenberg University Mainz, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include "debugmsg.h"
#include "utils.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
GINAC_IMPLEMENT_REGISTERED_CLASS(mul, expairseq)
//////////
-// default constructor, destructor, copy constructor assignment operator and helpers
+// default ctor, dctor, copy ctor assignment operator and helpers
//////////
-// public
-
mul::mul()
{
- debugmsg("mul default constructor",LOGLEVEL_CONSTRUCT);
+ debugmsg("mul default ctor",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_mul;
}
-mul::~mul()
-{
- debugmsg("mul destructor",LOGLEVEL_DESTRUCT);
- destroy(false);
-}
-
-mul::mul(const mul & other)
-{
- debugmsg("mul copy constructor",LOGLEVEL_CONSTRUCT);
- copy(other);
-}
-
-const mul & mul::operator=(const mul & other)
-{
- debugmsg("mul operator=",LOGLEVEL_ASSIGNMENT);
- if (this != &other) {
- destroy(true);
- copy(other);
- }
- return *this;
-}
-
-// protected
-
-void mul::copy(const mul & other)
-{
- inherited::copy(other);
-}
-
-void mul::destroy(bool call_parent)
-{
- if (call_parent) inherited::destroy(call_parent);
-}
+DEFAULT_COPY(mul)
+DEFAULT_DESTROY(mul)
//////////
-// other constructors
+// other ctors
//////////
// public
mul::mul(const ex & lh, const ex & rh)
{
- debugmsg("mul constructor from ex,ex",LOGLEVEL_CONSTRUCT);
+ debugmsg("mul ctor from ex,ex",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_mul;
overall_coeff = _ex1();
construct_from_2_ex(lh,rh);
mul::mul(const exvector & v)
{
- debugmsg("mul constructor from exvector",LOGLEVEL_CONSTRUCT);
+ debugmsg("mul ctor from exvector",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_mul;
overall_coeff = _ex1();
construct_from_exvector(v);
mul::mul(const epvector & v)
{
- debugmsg("mul constructor from epvector",LOGLEVEL_CONSTRUCT);
+ debugmsg("mul ctor from epvector",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_mul;
overall_coeff = _ex1();
construct_from_epvector(v);
mul::mul(const epvector & v, const ex & oc)
{
- debugmsg("mul constructor from epvector,ex",LOGLEVEL_CONSTRUCT);
+ debugmsg("mul ctor from epvector,ex",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_mul;
overall_coeff = oc;
construct_from_epvector(v);
mul::mul(epvector * vp, const ex & oc)
{
- debugmsg("mul constructor from epvector *,ex",LOGLEVEL_CONSTRUCT);
+ debugmsg("mul ctor from epvector *,ex",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_mul;
GINAC_ASSERT(vp!=0);
overall_coeff = oc;
mul::mul(const ex & lh, const ex & mh, const ex & rh)
{
- debugmsg("mul constructor from ex,ex,ex",LOGLEVEL_CONSTRUCT);
+ debugmsg("mul ctor from ex,ex,ex",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_mul;
exvector factors;
factors.reserve(3);
// archiving
//////////
-/** Construct object from archive_node. */
-mul::mul(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
-{
- debugmsg("mul constructor from archive_node", LOGLEVEL_CONSTRUCT);
-}
-
-/** Unarchive the object. */
-ex mul::unarchive(const archive_node &n, const lst &sym_lst)
-{
- return (new mul(n, sym_lst))->setflag(status_flags::dynallocated);
-}
-
-/** Archive the object. */
-void mul::archive(archive_node &n) const
-{
- inherited::archive(n);
-}
+DEFAULT_ARCHIVING(mul)
//////////
// functions overriding virtual functions from bases classes
// public
-basic * mul::duplicate() const
+void mul::print(const print_context & c, unsigned level) const
{
- debugmsg("mul duplicate",LOGLEVEL_ASSIGNMENT);
- return new mul(*this);
-}
+ debugmsg("mul print", LOGLEVEL_PRINT);
-void mul::print(std::ostream & os, unsigned upper_precedence) const
-{
- debugmsg("mul print",LOGLEVEL_PRINT);
- if (precedence<=upper_precedence) os << "(";
- bool first=true;
- // first print the overall numeric coefficient:
- numeric coeff = ex_to_numeric(overall_coeff);
- if (coeff.csgn()==-1) os << '-';
- if (!coeff.is_equal(_num1()) &&
- !coeff.is_equal(_num_1())) {
- if (coeff.is_rational()) {
- if (coeff.is_negative())
- os << -coeff;
- else
- os << coeff;
- } else {
- if (coeff.csgn()==-1)
- (-coeff).print(os, precedence);
- else
- coeff.print(os, precedence);
+ if (is_of_type(c, print_tree)) {
+
+ inherited::print(c, level);
+
+ } else if (is_of_type(c, print_csrc)) {
+
+ if (precedence() <= level)
+ c.s << "(";
+
+ if (!overall_coeff.is_equal(_ex1())) {
+ overall_coeff.bp->print(c, precedence());
+ c.s << "*";
}
- os << '*';
- }
- // then proceed with the remaining factors:
- for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
- if (!first) {
- os << '*';
- } else {
- first=false;
+
+ // Print arguments, separated by "*" or "/"
+ epvector::const_iterator it = seq.begin(), itend = seq.end();
+ while (it != itend) {
+
+ // If the first argument is a negative integer power, it gets printed as "1.0/<expr>"
+ if (it == seq.begin() && ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(_num0()) < 0) {
+ if (is_of_type(c, print_csrc_cl_N))
+ c.s << "recip(";
+ else
+ c.s << "1.0/";
+ }
+
+ // If the exponent is 1 or -1, it is left out
+ if (it->coeff.compare(_ex1()) == 0 || it->coeff.compare(_num_1()) == 0)
+ it->rest.print(c, precedence());
+ else {
+ // Outer parens around ex needed for broken gcc-2.95 parser:
+ (ex(power(it->rest, abs(ex_to_numeric(it->coeff))))).print(c, level);
+ }
+
+ // Separator is "/" for negative integer powers, "*" otherwise
+ ++it;
+ if (it != itend) {
+ if (ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(_num0()) < 0)
+ c.s << "/";
+ else
+ c.s << "*";
+ }
}
- recombine_pair_to_ex(*cit).print(os,precedence);
- }
- if (precedence<=upper_precedence) os << ")";
-}
-void mul::printraw(std::ostream & os) const
-{
- debugmsg("mul printraw",LOGLEVEL_PRINT);
+ if (precedence() <= level)
+ c.s << ")";
- os << "*(";
- for (epvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
- os << "(";
- (*it).rest.bp->printraw(os);
- os << ",";
- (*it).coeff.bp->printraw(os);
- os << "),";
- }
- os << ",hash=" << hashvalue << ",flags=" << flags;
- os << ")";
-}
+ } else {
-void mul::printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const
-{
- debugmsg("mul print csrc", LOGLEVEL_PRINT);
- if (precedence <= upper_precedence)
- os << "(";
+ if (precedence() <= level) {
+ if (is_of_type(c, print_latex))
+ c.s << "{(";
+ else
+ c.s << "(";
+ }
- if (!overall_coeff.is_equal(_ex1())) {
- overall_coeff.bp->printcsrc(os,type,precedence);
- os << "*";
- }
-
- // Print arguments, separated by "*" or "/"
- epvector::const_iterator it = seq.begin();
- epvector::const_iterator itend = seq.end();
- while (it != itend) {
-
- // If the first argument is a negative integer power, it gets printed as "1.0/<expr>"
- if (it == seq.begin() && ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(_num0()) < 0) {
- if (type == csrc_types::ctype_cl_N)
- os << "recip(";
+ bool first = true;
+
+ // First print the overall numeric coefficient
+ numeric coeff = ex_to_numeric(overall_coeff);
+ if (coeff.csgn() == -1)
+ c.s << '-';
+ if (!coeff.is_equal(_num1()) &&
+ !coeff.is_equal(_num_1())) {
+ if (coeff.is_rational()) {
+ if (coeff.is_negative())
+ (-coeff).print(c);
+ else
+ coeff.print(c);
+ } else {
+ if (coeff.csgn() == -1)
+ (-coeff).print(c, precedence());
+ else
+ coeff.print(c, precedence());
+ }
+ if (is_of_type(c, print_latex))
+ c.s << ' ';
else
- os << "1.0/";
+ c.s << '*';
}
- // If the exponent is 1 or -1, it is left out
- if (it->coeff.compare(_ex1()) == 0 || it->coeff.compare(_num_1()) == 0)
- it->rest.bp->printcsrc(os, type, precedence);
- else
- // outer parens around ex needed for broken gcc-2.95 parser:
- (ex(power(it->rest, abs(ex_to_numeric(it->coeff))))).bp->printcsrc(os, type, upper_precedence);
+ // Then proceed with the remaining factors
+ epvector::const_iterator it = seq.begin(), itend = seq.end();
+ while (it != itend) {
+ if (!first) {
+ if (is_of_type(c, print_latex))
+ c.s << ' ';
+ else
+ c.s << '*';
+ } else {
+ first = false;
+ }
+ recombine_pair_to_ex(*it).print(c, precedence());
+ it++;
+ }
- // Separator is "/" for negative integer powers, "*" otherwise
- ++it;
- if (it != itend) {
- if (ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(_num0()) < 0)
- os << "/";
+ if (precedence() <= level) {
+ if (is_of_type(c, print_latex))
+ c.s << ")}";
else
- os << "*";
+ c.s << ")";
}
}
- if (precedence <= upper_precedence)
- os << ")";
}
bool mul::info(unsigned inf) const
return inherited::info(inf);
}
-typedef std::vector<int> intvector;
-
-int mul::degree(const symbol & s) const
+int mul::degree(const ex & s) const
{
int deg_sum = 0;
for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
- deg_sum+=(*cit).rest.degree(s) * ex_to_numeric((*cit).coeff).to_int();
+ if (ex_to_numeric(cit->coeff).is_integer())
+ deg_sum+=cit->rest.degree(s) * ex_to_numeric(cit->coeff).to_int();
}
return deg_sum;
}
-int mul::ldegree(const symbol & s) const
+int mul::ldegree(const ex & s) const
{
int deg_sum = 0;
for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
- deg_sum+=(*cit).rest.ldegree(s) * ex_to_numeric((*cit).coeff).to_int();
+ if (ex_to_numeric(cit->coeff).is_integer())
+ deg_sum+=cit->rest.ldegree(s) * ex_to_numeric(cit->coeff).to_int();
}
return deg_sum;
}
-ex mul::coeff(const symbol & s, int n) const
+ex mul::coeff(const ex & s, int n) const
{
exvector coeffseq;
coeffseq.reserve(seq.size()+1);
if (n==0) {
// product of individual coeffs
// if a non-zero power of s is found, the resulting product will be 0
- epvector::const_iterator it=seq.begin();
+ epvector::const_iterator it = seq.begin();
while (it!=seq.end()) {
coeffseq.push_back(recombine_pair_to_ex(*it).coeff(s,n));
++it;
coeffseq.push_back(overall_coeff);
return (new mul(coeffseq))->setflag(status_flags::dynallocated);
}
-
+
epvector::const_iterator it=seq.begin();
- bool coeff_found=0;
+ bool coeff_found = 0;
while (it!=seq.end()) {
- ex t=recombine_pair_to_ex(*it);
- ex c=t.coeff(s,n);
+ ex t = recombine_pair_to_ex(*it);
+ ex c = t.coeff(s,n);
if (!c.is_zero()) {
coeffseq.push_back(c);
- coeff_found=1;
+ coeff_found = 1;
} else {
coeffseq.push_back(t);
}
// *(+(x,y,...);c) -> *(+(*(x,c),*(y,c),...)) (c numeric())
// *(x;1) -> x
// *(;c) -> c
-
+
debugmsg("mul eval",LOGLEVEL_MEMBER_FUNCTION);
-
- epvector * evaled_seqp=evalchildren(level);
+
+ epvector * evaled_seqp = evalchildren(level);
if (evaled_seqp!=0) {
// do more evaluation later
return (new mul(evaled_seqp,overall_coeff))->
- setflag(status_flags::dynallocated);
+ setflag(status_flags::dynallocated);
}
-
+
#ifdef DO_GINAC_ASSERT
for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
- GINAC_ASSERT((!is_ex_exactly_of_type((*cit).rest,mul))||
- (!(ex_to_numeric((*cit).coeff).is_integer())));
- GINAC_ASSERT(!((*cit).is_numeric_with_coeff_1()));
- if (is_ex_exactly_of_type(recombine_pair_to_ex(*cit),numeric)) {
- printtree(cerr,0);
- }
+ GINAC_ASSERT((!is_ex_exactly_of_type((*cit).rest,mul)) ||
+ (!(ex_to_numeric((*cit).coeff).is_integer())));
+ GINAC_ASSERT(!(cit->is_canonical_numeric()));
+ if (is_ex_exactly_of_type(recombine_pair_to_ex(*cit),numeric))
+ print(print_tree(std::cerr));
GINAC_ASSERT(!is_ex_exactly_of_type(recombine_pair_to_ex(*cit),numeric));
/* for paranoia */
- expair p=split_ex_to_pair(recombine_pair_to_ex(*cit));
+ expair p = split_ex_to_pair(recombine_pair_to_ex(*cit));
GINAC_ASSERT(p.rest.is_equal((*cit).rest));
GINAC_ASSERT(p.coeff.is_equal((*cit).coeff));
/* end paranoia */
}
#endif // def DO_GINAC_ASSERT
-
+
if (flags & status_flags::evaluated) {
GINAC_ASSERT(seq.size()>0);
- GINAC_ASSERT((seq.size()>1)||!overall_coeff.is_equal(_ex1()));
+ GINAC_ASSERT(seq.size()>1 || !overall_coeff.is_equal(_ex1()));
return *this;
}
-
- int seq_size=seq.size();
+
+ int seq_size = seq.size();
if (overall_coeff.is_equal(_ex0())) {
// *(...,x;0) -> 0
return _ex0();
} else if (seq_size==0) {
// *(;c) -> c
return overall_coeff;
- } else if ((seq_size==1)&&overall_coeff.is_equal(_ex1())) {
+ } else if (seq_size==1 && overall_coeff.is_equal(_ex1())) {
// *(x;1) -> x
return recombine_pair_to_ex(*(seq.begin()));
} else if ((seq_size==1) &&
is_ex_exactly_of_type((*seq.begin()).rest,add) &&
ex_to_numeric((*seq.begin()).coeff).is_equal(_num1())) {
// *(+(x,y,...);c) -> +(*(x,c),*(y,c),...) (c numeric(), no powers of +())
- const add & addref=ex_to_add((*seq.begin()).rest);
+ const add & addref = ex_to_add((*seq.begin()).rest);
epvector distrseq;
distrseq.reserve(addref.seq.size());
for (epvector::const_iterator cit=addref.seq.begin(); cit!=addref.seq.end(); ++cit) {
return mul(s,overall_coeff.evalf(level));
}
-exvector mul::get_indices(void) const
+ex mul::simplify_ncmul(const exvector & v) const
{
- // return union of indices of factors
- exvector iv;
- for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
- exvector subiv=(*cit).rest.get_indices();
- iv.reserve(iv.size()+subiv.size());
- for (exvector::const_iterator cit2=subiv.begin(); cit2!=subiv.end(); ++cit2) {
- iv.push_back(*cit2);
- }
+ if (seq.size()==0) {
+ return inherited::simplify_ncmul(v);
}
- return iv;
-}
-ex mul::simplify_ncmul(const exvector & v) const
-{
- throw(std::logic_error("mul::simplify_ncmul() should never have been called!"));
+ // Find first noncommutative element and call its simplify_ncmul()
+ for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
+ if (cit->rest.return_type() == return_types::noncommutative)
+ return cit->rest.simplify_ncmul(v);
+ }
+ return inherited::simplify_ncmul(v);
}
// protected
// mul without factors: should not happen, but commutes
return return_types::commutative;
}
-
+
bool all_commutative = 1;
unsigned rt;
epvector::const_iterator cit_noncommutative_element; // point to first found nc element
-
+
for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
rt=(*cit).rest.return_type();
if (rt==return_types::noncommutative_composite) return rt; // one ncc -> mul also ncc
unsigned mul::return_type_tinfo(void) const
{
- if (seq.size()==0) {
- // mul without factors: should not happen
- return tinfo_key;
- }
+ if (seq.size()==0)
+ return tinfo_key; // mul without factors: should not happen
+
// return type_info of first noncommutative element
for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
- if ((*cit).rest.return_type()==return_types::noncommutative) {
+ if ((*cit).rest.return_type()==return_types::noncommutative)
return (*cit).rest.return_type_tinfo();
- }
}
// no noncommutative element found, should not happen
return tinfo_key;
expair mul::split_ex_to_pair(const ex & e) const
{
if (is_ex_exactly_of_type(e,power)) {
- const power & powerref=ex_to_power(e);
- if (is_ex_exactly_of_type(powerref.exponent,numeric)) {
+ const power & powerref = ex_to_power(e);
+ if (is_ex_exactly_of_type(powerref.exponent,numeric))
return expair(powerref.basis,powerref.exponent);
- }
}
return expair(e,_ex1());
}
if (is_ex_exactly_of_type((*it).rest,mul) &&
ex_to_numeric((*it).coeff).is_integer()) {
// combined pair is product with integer power -> expand it
- *it=split_ex_to_pair(recombine_pair_to_ex(*it));
+ *it = split_ex_to_pair(recombine_pair_to_ex(*it));
return true;
}
if (is_ex_exactly_of_type((*it).rest,numeric)) {
expair ep=split_ex_to_pair(recombine_pair_to_ex(*it));
if (!ep.is_equal(*it)) {
// combined pair is a numeric power which can be simplified
- *it=ep;
+ *it = ep;
return true;
}
if (ex_to_numeric((*it).coeff).is_equal(_num1())) {
return *this;
exvector sub_expanded_seq;
- intvector positions_of_adds;
- intvector number_of_add_operands;
epvector * expanded_seqp = expandchildren(options);
const epvector & expanded_seq = expanded_seqp==0 ? seq : *expanded_seqp;
- positions_of_adds.resize(expanded_seq.size());
- number_of_add_operands.resize(expanded_seq.size());
-
int number_of_adds = 0;
- int number_of_expanded_terms = 1;
-
- unsigned current_position = 0;
+ epvector non_adds;
+ non_adds.reserve(expanded_seq.size());
+ epvector::const_iterator cit = expanded_seq.begin();
epvector::const_iterator last = expanded_seq.end();
- for (epvector::const_iterator cit = expanded_seq.begin(); cit!=last; ++cit) {
+ ex last_expanded = _ex1();
+ while (cit!=last) {
if (is_ex_exactly_of_type((*cit).rest,add) &&
((*cit).coeff.is_equal(_ex1()))) {
- positions_of_adds[number_of_adds] = current_position;
- const add & expanded_addref = ex_to_add((*cit).rest);
- unsigned addref_nops = expanded_addref.nops();
- number_of_add_operands[number_of_adds] = addref_nops;
- number_of_expanded_terms *= addref_nops;
++number_of_adds;
+ if (is_ex_exactly_of_type(last_expanded,add)) {
+ // expand adds
+ const add & add1 = ex_to_add(last_expanded);
+ const add & add2 = ex_to_add((*cit).rest);
+ int n1 = add1.nops();
+ int n2 = add2.nops();
+ exvector distrseq;
+ distrseq.reserve(n1*n2);
+ for (int i1=0; i1<n1; ++i1) {
+ for (int i2=0; i2<n2; ++i2) {
+ distrseq.push_back(add1.op(i1)*add2.op(i2));
+ }
+ }
+ last_expanded = (new add(distrseq))->setflag(status_flags::dynallocated | status_flags::expanded);
+ } else {
+ non_adds.push_back(split_ex_to_pair(last_expanded));
+ last_expanded = (*cit).rest;
+ }
+ } else {
+ non_adds.push_back(*cit);
}
- ++current_position;
- }
-
- if (number_of_adds==0) {
- if (expanded_seqp==0)
- return this->setflag(status_flags::expanded);
- else
- return ((new mul(expanded_seqp,overall_coeff))->
- setflag(status_flags::dynallocated | status_flags::expanded));
+ ++cit;
}
-
- exvector distrseq;
- distrseq.reserve(number_of_expanded_terms);
-
- intvector k;
- k.resize(number_of_adds, 0);
-
- for (;;) {
- epvector term;
- term = expanded_seq;
- for (int l=0; l<number_of_adds; ++l) {
- const add & addref = ex_to_add(expanded_seq[positions_of_adds[l]].rest);
- GINAC_ASSERT(term[positions_of_adds[l]].coeff.compare(_ex1())==0);
- term[positions_of_adds[l]]=split_ex_to_pair(addref.op(k[l]));
- }
- distrseq.push_back((new mul(term,overall_coeff))->
- setflag(status_flags::dynallocated | status_flags::expanded));
-
- // increment k[]
- int l = number_of_adds-1;
- while ((l>=0) && ((++k[l])>=number_of_add_operands[l])) {
- k[l] = 0;
- --l;
+ if (expanded_seqp)
+ delete expanded_seqp;
+
+ if (is_ex_exactly_of_type(last_expanded,add)) {
+ add const & finaladd = ex_to_add(last_expanded);
+ exvector distrseq;
+ int n = finaladd.nops();
+ distrseq.reserve(n);
+ for (int i=0; i<n; ++i) {
+ epvector factors = non_adds;
+ factors.push_back(split_ex_to_pair(finaladd.op(i)));
+ distrseq.push_back((new mul(factors,overall_coeff))->setflag(status_flags::dynallocated | status_flags::expanded));
}
- if (l < 0) break;
+ return ((new add(distrseq))->
+ setflag(status_flags::dynallocated | status_flags::expanded));
}
-
- if (expanded_seqp!=0)
- delete expanded_seqp;
-
- return (new add(distrseq))->setflag(status_flags::dynallocated |
- status_flags::expanded);
+ non_adds.push_back(split_ex_to_pair(last_expanded));
+ return (new mul(non_adds,overall_coeff))->
+ setflag(status_flags::dynallocated | status_flags::expanded);
}
+
//////////
// new virtual functions which can be overridden by derived classes
//////////
// non-virtual functions in this class
//////////
+
+/** Member-wise expand the expairs representing this sequence. This must be
+ * overridden from expairseq::expandchildren() and done iteratively in order
+ * to allow for early cancallations and thus safe memory.
+ *
+ * @see mul::expand()
+ * @return pointer to epvector containing expanded representation or zero
+ * pointer, if sequence is unchanged. */
epvector * mul::expandchildren(unsigned options) const
{
epvector::const_iterator last = seq.end();
if (!are_ex_trivially_equal(factor,expanded_factor)) {
// something changed, copy seq, eval 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
return 0; // nothing has changed
}
-
-//////////
-// static member variables
-//////////
-
-// protected
-
-unsigned mul::precedence = 50;
-
-
-//////////
-// global constants
-//////////
-
-const mul some_mul;
-const type_info & typeid_mul = typeid(some_mul);
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC