This file records noteworthy changes.
1.1.0 (<date>)
-* "(x+1).subs(x==x-1)" now returns the correct result "x" instead of "x-1".
-* Fixed LaTeX output of indexed objects.
+* Removed deprecated macros is_ex_a, is_ex_exactly_a and friends.
-1.0.5 (<date>)
+Backlog from 1.0.n:
+* Fixed LaTeX output of indexed and matrix objects.
+* Fixed matrix::pow(n) for n==0.
+* "(x+1).subs(x==x-1)" now returns the correct result "x" instead of "x-1".
* (l)degree(s), coeff(s, n) and collect(s) were extended to accept expressions
of any class (except add/mul/ncmul/numeric) for "s". They should even work
if "s" is a "power" object, as long as the exponent is non-integer, but with
some limitations. For example, you can "collect(a*2^x+b*2^x, 2^x)" to get
"(a+b)*2^x", but "degree(2^(3*x), 2^x)" yields 0 instead of 3).
-
-1.0.4 (24 January 2001)
* Speedup in expand().
* Faster Bernoulli numbers (Markus Nullmeier).
-* Some minor bugfixes and documentation updates.
-
-1.0.3 (21 December 2001)
* Fixed a bug where quo() would call vector::reserve() with a negative
argument.
-* Fix several bugs in code generation.
+* Several small bugfices in code generation, output and documentation.
1.0.2 (19 December 2001)
* Input parser recognizes "sqrt()", which is also used in the output.
epvector::const_iterator i = seq.begin(), end = seq.end();
while (i != end) {
GINAC_ASSERT(!is_exactly_a<add>(i->rest));
- if (is_ex_exactly_of_type(i->rest,numeric))
+ if (is_exactly_a<numeric>(i->rest))
dbgprint();
GINAC_ASSERT(!is_exactly_a<numeric>(i->rest));
++i;
while (it != itend) {
const ex &m = recombine_pair_to_ex(*it).evalm();
s->push_back(split_ex_to_pair(m));
- if (is_ex_of_type(m, matrix)) {
+ if (is_a<matrix>(m)) {
if (first_term) {
sum = ex_to<matrix>(m);
first_term = false;
expair add::split_ex_to_pair(const ex & e) const
{
- if (is_ex_exactly_of_type(e,mul)) {
+ if (is_exactly_a<mul>(e)) {
const mul &mulref(ex_to<mul>(e));
const ex &numfactor = mulref.overall_coeff;
mul *mulcopyp = new mul(mulref);
const ex & c) const
{
GINAC_ASSERT(is_exactly_a<numeric>(c));
- if (is_ex_exactly_of_type(e, mul)) {
+ if (is_exactly_a<mul>(e)) {
const mul &mulref(ex_to<mul>(e));
const ex &numfactor = mulref.overall_coeff;
mul *mulcopyp = new mul(mulref);
return expair(*mulcopyp, c);
else
return expair(*mulcopyp, ex_to<numeric>(numfactor).mul_dyn(ex_to<numeric>(c)));
- } else if (is_ex_exactly_of_type(e, numeric)) {
+ } else if (is_exactly_a<numeric>(e)) {
if (are_ex_trivially_equal(c, _ex1))
return expair(e, _ex1);
return expair(ex_to<numeric>(e).mul_dyn(ex_to<numeric>(c)), _ex1);
GINAC_ASSERT(is_exactly_a<numeric>(p.coeff));
GINAC_ASSERT(is_exactly_a<numeric>(c));
- if (is_ex_exactly_of_type(p.rest,numeric)) {
+ if (is_exactly_a<numeric>(p.rest)) {
GINAC_ASSERT(ex_to<numeric>(p.coeff).is_equal(_num1)); // should be normalized
return expair(ex_to<numeric>(p.rest).mul_dyn(ex_to<numeric>(c)),_ex1);
}
* level for placing parentheses and formatting */
void basic::print(const print_context & c, unsigned level) const
{
- if (is_of_type(c, print_tree)) {
+ if (is_a<print_tree>(c)) {
c.s << std::string(level, ' ') << class_name()
<< std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
ex basic::operator[](const ex & index) const
{
- if (is_ex_exactly_of_type(index,numeric))
+ if (is_exactly_a<numeric>(index))
return op(ex_to<numeric>(index).to_int());
throw(std::invalid_argument("non-numeric indices not supported by this type"));
ex basic::collect(const ex & s, bool distributed) const
{
ex x;
- if (is_ex_of_type(s, lst)) {
+ if (is_a<lst>(s)) {
// List of objects specified
if (s.nops() == 0)
Bog is the king of Pattern.
*/
- if (is_ex_exactly_of_type(pattern, wildcard)) {
+ if (is_exactly_a<wildcard>(pattern)) {
// Wildcard matches anything, but check whether we already have found
// a match for that wildcard first (if so, it the earlier match must
else
return _ex0;
- } else if (is_ex_exactly_of_type(e, mul)) {
+ } else if (is_exactly_a<mul>(e)) {
// Trace of product: pull out non-clifford factors
ex prod = _ex1;
}
return prod;
- } else if (is_ex_exactly_of_type(e, ncmul)) {
+ } else if (is_exactly_a<ncmul>(e)) {
if (!is_clifford_tinfo(e.return_type_tinfo(), rl))
return _ex0;
ex lhs = srl.op(i).lhs();
ex rhs = srl.op(i).rhs();
- if (is_ex_exactly_of_type(rhs, ncmul)
+ if (is_exactly_a<ncmul>(rhs)
&& rhs.return_type() == return_types::noncommutative
&& is_clifford_tinfo(rhs.return_type_tinfo())) {
// Remove superfluous ONEs
exvector::const_iterator it = v.begin(), itend = v.end();
while (it != itend) {
- if (!is_ex_of_type(it->op(0), su3one))
+ if (!is_a<su3one>(it->op(0)))
s.push_back(*it);
it++;
}
GINAC_ASSERT(is_a<su3t>(self->op(0)));
unsigned char rl = ex_to<color>(*self).get_representation_label();
- if (is_ex_exactly_of_type(other->op(0), su3t)) {
+ if (is_exactly_a<su3t>(other->op(0))) {
// T.a T.a = 4/3 ONE
if (other - self == 1) {
// T.a T.b T.a = -1/6 T.b
} else if (other - self == 2
- && is_ex_of_type(self[1], color)) {
+ && is_a<color>(self[1])) {
*self = numeric(-1, 6);
*other = _ex1;
return true;
} else {
exvector::iterator it = self + 1;
while (it != other) {
- if (!is_ex_of_type(*it, color)) {
+ if (!is_a<color>(*it)) {
return false;
}
it++;
GINAC_ASSERT(self->nops() == 4);
GINAC_ASSERT(is_a<su3d>(self->op(0)));
- if (is_ex_exactly_of_type(other->op(0), su3d)) {
+ if (is_exactly_a<su3d>(other->op(0))) {
// Find the dummy indices of the contraction
exvector self_indices = ex_to<indexed>(*self).get_indices();
return true;
}
- } else if (is_ex_exactly_of_type(other->op(0), su3t)) {
+ } else if (is_exactly_a<su3t>(other->op(0))) {
// d.abc T.b T.c = 5/6 T.a
if (other+1 != v.end()
- && is_ex_exactly_of_type(other[1].op(0), su3t)
+ && is_exactly_a<su3t>(other[1].op(0))
&& ex_to<indexed>(*self).has_dummy_index_for(other[1].op(1))) {
exvector self_indices = ex_to<indexed>(*self).get_indices();
GINAC_ASSERT(self->nops() == 4);
GINAC_ASSERT(is_a<su3f>(self->op(0)));
- if (is_ex_exactly_of_type(other->op(0), su3f)) { // f*d is handled by su3d class
+ if (is_exactly_a<su3f>(other->op(0))) { // f*d is handled by su3d class
// Find the dummy indices of the contraction
exvector dummy_indices;
return true;
}
- } else if (is_ex_exactly_of_type(other->op(0), su3t)) {
+ } else if (is_exactly_a<su3t>(other->op(0))) {
// f.abc T.b T.c = 3/2 I T.a
if (other+1 != v.end()
- && is_ex_exactly_of_type(other[1].op(0), su3t)
+ && is_exactly_a<su3t>(other[1].op(0))
&& ex_to<indexed>(*self).has_dummy_index_for(other[1].op(1))) {
exvector self_indices = ex_to<indexed>(*self).get_indices();
ex color_T(const ex & a, unsigned char rl)
{
- if (!is_ex_of_type(a, idx))
+ if (!is_a<idx>(a))
throw(std::invalid_argument("indices of color_T must be of type idx"));
if (!ex_to<idx>(a).get_dim().is_equal(8))
throw(std::invalid_argument("index dimension for color_T must be 8"));
ex color_f(const ex & a, const ex & b, const ex & c)
{
- if (!is_ex_of_type(a, idx) || !is_ex_of_type(b, idx) || !is_ex_of_type(c, idx))
+ if (!is_a<idx>(a) || !is_a<idx>(b) || !is_a<idx>(c))
throw(std::invalid_argument("indices of color_f must be of type idx"));
if (!ex_to<idx>(a).get_dim().is_equal(8) || !ex_to<idx>(b).get_dim().is_equal(8) || !ex_to<idx>(c).get_dim().is_equal(8))
throw(std::invalid_argument("index dimension for color_f must be 8"));
ex color_d(const ex & a, const ex & b, const ex & c)
{
- if (!is_ex_of_type(a, idx) || !is_ex_of_type(b, idx) || !is_ex_of_type(c, idx))
+ if (!is_a<idx>(a) || !is_a<idx>(b) || !is_a<idx>(c))
throw(std::invalid_argument("indices of color_d must be of type idx"));
if (!ex_to<idx>(a).get_dim().is_equal(8) || !ex_to<idx>(b).get_dim().is_equal(8) || !ex_to<idx>(c).get_dim().is_equal(8))
throw(std::invalid_argument("index dimension for color_d must be 8"));
ex color_trace(const ex & e, unsigned char rl)
{
- if (is_ex_of_type(e, color)) {
+ if (is_a<color>(e)) {
if (ex_to<color>(e).get_representation_label() == rl
- && is_ex_of_type(e.op(0), su3one))
+ && is_a<su3one>(e.op(0)))
return _ex3;
else
return _ex0;
- } else if (is_ex_exactly_of_type(e, mul)) {
+ } else if (is_exactly_a<mul>(e)) {
// Trace of product: pull out non-color factors
ex prod = _ex1;
}
return prod;
- } else if (is_ex_exactly_of_type(e, ncmul)) {
+ } else if (is_exactly_a<ncmul>(e)) {
if (!is_color_tinfo(e.return_type_tinfo(), rl))
return _ex0;
// Expand product, if necessary
ex e_expanded = e.expand();
- if (!is_ex_of_type(e_expanded, ncmul))
+ if (!is_a<ncmul>(e_expanded))
return color_trace(e_expanded, rl);
unsigned num = e.nops();
/** Left hand side of relational expression. */
ex ex::lhs(void) const
{
- if (!is_ex_of_type(*this,relational))
+ if (!is_a<relational>(*this))
throw std::runtime_error("ex::lhs(): not a relation");
return (*static_cast<relational *>(bp)).lhs();
}
/** Right hand side of relational expression. */
ex ex::rhs(void) const
{
- if (!is_ex_of_type(*this,relational))
+ if (!is_a<relational>(*this))
throw std::runtime_error("ex::rhs(): not a relation");
return (*static_cast<relational *>(bp)).rhs();
}
// member variables
-public:
- basic *bp; ///< pointer to basic object managed by this, direct manipulation deprecated
+private:
+ basic *bp; ///< pointer to basic object managed by this
#ifdef OBSCURE_CINT_HACK
+public:
static basic * last_created_or_assigned_bp;
static basic * dummy_bp;
static long last_created_or_assigned_exp;
void expairseq::print(const print_context &c, unsigned level) const
{
- if (is_of_type(c, print_tree)) {
+ if (is_a<print_tree>(c)) {
unsigned delta_indent = static_cast<const print_tree &>(c).delta_indent;
bool has_global_wildcard = false;
ex global_wildcard;
for (unsigned int i=0; i<pattern.nops(); i++) {
- if (is_ex_exactly_of_type(pattern.op(i), wildcard)) {
+ if (is_exactly_a<wildcard>(pattern.op(i))) {
has_global_wildcard = true;
global_wildcard = pattern.op(i);
break;
hashtabsize = 0;
#endif // EXPAIRSEQ_USE_HASHTAB
- if (is_ex_exactly_of_type(lh,numeric)) {
- if (is_ex_exactly_of_type(rh,numeric)) {
+ if (is_exactly_a<numeric>(lh)) {
+ if (is_exactly_a<numeric>(rh)) {
combine_overall_coeff(lh);
combine_overall_coeff(rh);
} else {
seq.push_back(split_ex_to_pair(rh));
}
} else {
- if (is_ex_exactly_of_type(rh,numeric)) {
+ if (is_exactly_a<numeric>(rh)) {
combine_overall_coeff(rh);
seq.push_back(split_ex_to_pair(lh));
} else {
const ex &e)
{
combine_overall_coeff(s.overall_coeff);
- if (is_ex_exactly_of_type(e,numeric)) {
+ if (is_exactly_a<numeric>(e)) {
combine_overall_coeff(e);
seq = s.seq;
return;
++cit_s;
}
} else {
- if (is_ex_exactly_of_type(*cit,numeric))
+ if (is_exactly_a<numeric>(*cit))
combine_overall_coeff(*cit);
else
seq.push_back(split_ex_to_pair(*cit));
epp current = seq.begin();
while (current!=first_numeric) {
- if (is_ex_exactly_of_type(current->rest,numeric)) {
+ if (is_exactly_a<numeric>(current->rest)) {
--first_numeric;
iter_swap(current,first_numeric);
} else {
epvector::const_iterator it_last = it;
for (++it; it!=itend; it_last=it, ++it) {
if (!(it_last->is_less(*it) || it_last->is_equal(*it))) {
- if (!is_ex_exactly_of_type(it_last->rest,numeric) ||
- !is_ex_exactly_of_type(it->rest,numeric)) {
+ if (!is_exactly_a<numeric>(it_last->rest) ||
+ !is_exactly_a<numeric>(it->rest)) {
// double test makes it easier to set a breakpoint...
- if (!is_ex_exactly_of_type(it_last->rest,numeric) ||
- !is_ex_exactly_of_type(it->rest,numeric)) {
+ if (!is_exactly_a<numeric>(it_last->rest) ||
+ !is_exactly_a<numeric>(it->rest)) {
printpair(std::clog, *it_last, 0);
std::clog << ">";
printpair(std::clog, *it, 0);
// because the numeric coefficients may be part of the search pattern.
bool complex_subs = false;
for (unsigned i=0; i<ls.nops(); ++i)
- if (is_ex_exactly_of_type(ls.op(i), mul) || is_ex_exactly_of_type(ls.op(i), power)) {
+ if (is_exactly_a<mul>(ls.op(i)) || is_exactly_a<power>(ls.op(i))) {
complex_subs = true;
break;
}
{
GINAC_ASSERT(serial<registered_functions().size());
- if (is_of_type(c, print_tree)) {
+ if (is_a<print_tree>(c)) {
c.s << std::string(level, ' ') << class_name() << " "
<< registered_functions()[serial].name
seq[i].print(c, level + delta_indent);
c.s << std::string(level + delta_indent, ' ') << "=====" << std::endl;
- } else if (is_of_type(c, print_csrc)) {
+ } else if (is_a<print_csrc>(c)) {
// Print function name in lowercase
std::string lname = registered_functions()[serial].name;
}
c.s << ")";
- } else if (is_of_type(c, print_latex)) {
+ } else if (is_a<print_latex>(c)) {
c.s << registered_functions()[serial].TeX_name;
printseq(c, '(', ',', ')', exprseq::precedence(), function::precedence());
} else {
int function::compare_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other, function));
+ GINAC_ASSERT(is_a<function>(other));
const function & o = static_cast<const function &>(other);
if (serial != o.serial)
bool function::is_equal_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other, function));
+ GINAC_ASSERT(is_a<function>(other));
const function & o = static_cast<const function &>(other);
if (serial != o.serial)
bool function::match_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other, function));
+ GINAC_ASSERT(is_a<function>(other));
const function & o = static_cast<const function &>(other);
return serial == o.serial;
void idx::print(const print_context & c, unsigned level) const
{
- if (is_of_type(c, print_tree)) {
+ if (is_a<print_tree>(c)) {
c.s << std::string(level, ' ') << class_name()
<< std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
c.s << "{";
else
c.s << ".";
- bool need_parens = !(is_ex_exactly_of_type(value, numeric) || is_ex_of_type(value, symbol));
+ bool need_parens = !(is_exactly_a<numeric>(value) || is_a<symbol>(value));
if (need_parens)
c.s << "(";
value.print(c);
void varidx::print(const print_context & c, unsigned level) const
{
- if (is_of_type(c, print_tree)) {
+ if (is_a<print_tree>(c)) {
c.s << std::string(level, ' ') << class_name()
<< std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
else
c.s << "~";
}
- bool need_parens = !(is_ex_exactly_of_type(value, numeric) || is_ex_of_type(value, symbol));
+ bool need_parens = !(is_exactly_a<numeric>(value) || is_a<symbol>(value));
if (need_parens)
c.s << "(";
value.print(c);
void spinidx::print(const print_context & c, unsigned level) const
{
- if (is_of_type(c, print_tree)) {
+ if (is_a<print_tree>(c)) {
c.s << std::string(level, ' ') << class_name()
<< std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
} else {
- bool is_tex = is_of_type(c, print_latex);
+ bool is_tex = is_a<print_latex>(c);
if (is_tex) {
if (covariant)
c.s << "_{";
else
c.s << "*";
}
- bool need_parens = !(is_ex_exactly_of_type(value, numeric) || is_ex_of_type(value, symbol));
+ bool need_parens = !(is_exactly_a<numeric>(value) || is_a<symbol>(value));
if (need_parens)
c.s << "(";
value.print(c);
if (is_equal(ex_to<basic>(ls.op(i)))) {
// Substitution index->index
- if (is_ex_of_type(lr.op(i), idx))
+ if (is_a<idx>(lr.op(i)))
return lr.op(i);
// Otherwise substitute value
const idx &o = static_cast<const idx &>(other);
// Only pure symbols form dummy pairs, "2n+1" doesn't
- if (!is_ex_of_type(value, symbol))
+ if (!is_a<symbol>(value))
return false;
// Value must be equal, of course
bool is_dummy_pair(const ex & e1, const ex & e2)
{
// The expressions must be indices
- if (!is_ex_of_type(e1, idx) || !is_ex_of_type(e2, idx))
+ if (!is_a<idx>(e1) || !is_a<idx>(e2))
return false;
return is_dummy_pair(ex_to<idx>(e1), ex_to<idx>(e2));
{
GINAC_ASSERT(seq.size() > 0);
- if (is_of_type(c, print_tree)) {
+ if (is_a<print_tree>(c)) {
c.s << std::string(level, ' ') << class_name()
<< std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
} else {
- bool is_tex = is_of_type(c, print_latex);
+ bool is_tex = is_a<print_latex>(c);
const ex & base = seq[0];
- bool need_parens = is_ex_exactly_of_type(base, add) || is_ex_exactly_of_type(base, mul)
- || is_ex_exactly_of_type(base, ncmul) || is_ex_exactly_of_type(base, power)
- || is_ex_of_type(base, indexed);
+ bool need_parens = is_exactly_a<add>(base) || is_exactly_a<mul>(base)
+ || is_exactly_a<ncmul>(base) || is_exactly_a<power>(base)
+ || is_a<indexed>(base);
if (is_tex)
c.s << "{";
if (need_parens)
return _ex0;
// If the base object is a product, pull out the numeric factor
- if (is_ex_exactly_of_type(base, mul) && is_ex_exactly_of_type(base.op(base.nops() - 1), numeric)) {
+ if (is_exactly_a<mul>(base) && is_exactly_a<numeric>(base.op(base.nops() - 1))) {
exvector v(seq);
ex f = ex_to<numeric>(base.op(base.nops() - 1));
v[0] = seq[0] / f;
{
GINAC_ASSERT(seq.size() > 0);
- if ((options & expand_options::expand_indexed) && is_ex_exactly_of_type(seq[0], add)) {
+ if ((options & expand_options::expand_indexed) && is_exactly_a<add>(seq[0])) {
// expand_indexed expands (a+b).i -> a.i + b.i
const ex & base = seq[0];
exvector::const_iterator it=seq.begin() + 1, itend = seq.end();
- if (is_of_type(c, print_latex)) {
+ if (is_a<print_latex>(c)) {
// TeX output: group by variance
bool first = true;
bool covariant = true;
while (it != itend) {
- bool cur_covariant = (is_ex_of_type(*it, varidx) ? ex_to<varidx>(*it).is_covariant() : true);
+ bool cur_covariant = (is_a<varidx>(*it) ? ex_to<varidx>(*it).is_covariant() : true);
if (first || cur_covariant != covariant) { // Variance changed
// The empty {} prevents indices from ending up on top of each other
if (!first)
GINAC_ASSERT(seq.size() > 0);
exvector::const_iterator it = seq.begin() + 1, itend = seq.end();
while (it != itend) {
- if (!is_ex_of_type(*it, idx))
+ if (!is_a<idx>(*it))
throw(std::invalid_argument("indices of indexed object must be of type idx"));
it++;
}
if (!symtree.is_zero()) {
- if (!is_ex_exactly_of_type(symtree, symmetry))
+ if (!is_exactly_a<symmetry>(symtree))
throw(std::invalid_argument("symmetry of indexed object must be of type symmetry"));
const_cast<symmetry &>(ex_to<symmetry>(symtree)).validate(seq.size() - 1);
}
{
// Remember whether the product was commutative or noncommutative
// (because we chop it into factors and need to reassemble later)
- bool non_commutative = is_ex_exactly_of_type(e, ncmul);
+ bool non_commutative = is_exactly_a<ncmul>(e);
// Collect factors in an exvector, store squares twice
exvector v;
v.reserve(e.nops() * 2);
- if (is_ex_exactly_of_type(e, power)) {
+ if (is_exactly_a<power>(e)) {
// We only get called for simple squares, split a^2 -> a*a
GINAC_ASSERT(e.op(1).is_equal(_ex2));
v.push_back(e.op(0));
} else {
for (unsigned i=0; i<e.nops(); i++) {
ex f = e.op(i);
- if (is_ex_exactly_of_type(f, power) && f.op(1).is_equal(_ex2)) {
+ if (is_exactly_a<power>(f) && f.op(1).is_equal(_ex2)) {
v.push_back(f.op(0));
v.push_back(f.op(0));
- } else if (is_ex_exactly_of_type(f, ncmul)) {
+ } else if (is_exactly_a<ncmul>(f)) {
// Noncommutative factor found, split it as well
non_commutative = true; // everything becomes noncommutative, ncmul will sort out the commutative factors later
for (unsigned j=0; j<f.nops(); j++)
for (it1 = v.begin(); it1 != next_to_last; it1++) {
try_again:
- if (!is_ex_of_type(*it1, indexed))
+ if (!is_a<indexed>(*it1))
continue;
bool first_noncommutative = (it1->return_type() != return_types::commutative);
exvector::iterator it2;
for (it2 = it1 + 1; it2 != itend; it2++) {
- if (!is_ex_of_type(*it2, indexed))
+ if (!is_a<indexed>(*it2))
continue;
bool second_noncommutative = (it2->return_type() != return_types::commutative);
if (contracted) {
contraction_done:
if (first_noncommutative || second_noncommutative
- || is_ex_exactly_of_type(*it1, add) || is_ex_exactly_of_type(*it2, add)
- || is_ex_exactly_of_type(*it1, mul) || is_ex_exactly_of_type(*it2, mul)
- || is_ex_exactly_of_type(*it1, ncmul) || is_ex_exactly_of_type(*it2, ncmul)) {
+ || is_exactly_a<add>(*it1) || is_exactly_a<add>(*it2)
+ || is_exactly_a<mul>(*it1) || is_exactly_a<mul>(*it2)
+ || is_exactly_a<ncmul>(*it1) || is_exactly_a<ncmul>(*it2)) {
// One of the factors became a sum or product:
// re-expand expression and run again
it1 = v.begin(); itend = v.end();
while (it1 != itend) {
exvector free_indices_of_factor;
- if (is_ex_of_type(*it1, indexed)) {
+ if (is_a<indexed>(*it1)) {
exvector dummy_indices_of_factor;
find_free_and_dummy(ex_to<indexed>(*it1).seq.begin() + 1, ex_to<indexed>(*it1).seq.end(), free_indices_of_factor, dummy_indices_of_factor);
individual_dummy_indices.insert(individual_dummy_indices.end(), dummy_indices_of_factor.begin(), dummy_indices_of_factor.end());
r = rename_dummy_indices(r, dummy_indices, local_dummy_indices);
// Product of indexed object with a scalar?
- if (is_ex_exactly_of_type(r, mul) && r.nops() == 2
- && is_ex_exactly_of_type(r.op(1), numeric) && is_ex_of_type(r.op(0), indexed))
+ if (is_exactly_a<mul>(r) && r.nops() == 2
+ && is_exactly_a<numeric>(r.op(1)) && is_a<indexed>(r.op(0)))
return ex_to<basic>(r.op(0).op(0)).scalar_mul_indexed(r.op(0), ex_to<numeric>(r.op(1)));
else
return r;
// Simplification of single indexed object: just find the free indices
// and perform dummy index renaming
- if (is_ex_of_type(e_expanded, indexed)) {
+ if (is_a<indexed>(e_expanded)) {
const indexed &i = ex_to<indexed>(e_expanded);
exvector local_dummy_indices;
find_free_and_dummy(i.seq.begin() + 1, i.seq.end(), free_indices, local_dummy_indices);
// Simplification of sum = sum of simplifications, check consistency of
// free indices in each term
- if (is_ex_exactly_of_type(e_expanded, add)) {
+ if (is_exactly_a<add>(e_expanded)) {
bool first = true;
ex sum = _ex0;
free_indices.clear();
} else {
if (!indices_consistent(free_indices, free_indices_of_term))
throw (std::runtime_error("simplify_indexed: inconsistent indices in sum"));
- if (is_ex_of_type(sum, indexed) && is_ex_of_type(term, indexed))
+ if (is_a<indexed>(sum) && is_a<indexed>(term))
sum = ex_to<basic>(sum.op(0)).add_indexed(sum, term);
else
sum += term;
}
// Simplification of products
- if (is_ex_exactly_of_type(e_expanded, mul)
- || is_ex_exactly_of_type(e_expanded, ncmul)
- || (is_ex_exactly_of_type(e_expanded, power) && is_ex_of_type(e_expanded.op(0), indexed) && e_expanded.op(1).is_equal(_ex2)))
+ if (is_exactly_a<mul>(e_expanded)
+ || is_exactly_a<ncmul>(e_expanded)
+ || (is_exactly_a<power>(e_expanded) && is_a<indexed>(e_expanded.op(0)) && e_expanded.op(1).is_equal(_ex2)))
return simplify_indexed_product(e_expanded, free_indices, dummy_indices, sp);
// Cannot do anything
spmapkey scalar_products::make_key(const ex & v1, const ex & v2)
{
// If indexed, extract base objects
- ex s1 = is_ex_of_type(v1, indexed) ? v1.op(0) : v1;
- ex s2 = is_ex_of_type(v2, indexed) ? v2.op(0) : v2;
+ ex s1 = is_a<indexed>(v1) ? v1.op(0) : v1;
+ ex s2 = is_a<indexed>(v2) ? v2.op(0) : v2;
// Enforce canonical order in pair
if (s1.compare(s2) > 0)
static ex abs_eval(const ex & arg)
{
- if (is_ex_exactly_of_type(arg, numeric))
+ if (is_exactly_a<numeric>(arg))
return abs(ex_to<numeric>(arg));
else
return abs(arg).hold();
static ex csgn_eval(const ex & arg)
{
- if (is_ex_exactly_of_type(arg, numeric))
+ if (is_exactly_a<numeric>(arg))
return csgn(ex_to<numeric>(arg));
- else if (is_ex_of_type(arg, mul) &&
- is_ex_of_type(arg.op(arg.nops()-1),numeric)) {
+ else if (is_a<mul>(arg) &&
+ is_a<numeric>(arg.op(arg.nops()-1))) {
numeric oc = ex_to<numeric>(arg.op(arg.nops()-1));
if (oc.is_real()) {
if (oc > 0)
static ex factorial_eval(const ex & x)
{
- if (is_ex_exactly_of_type(x, numeric))
+ if (is_exactly_a<numeric>(x))
return factorial(ex_to<numeric>(x));
else
return factorial(x).hold();
static ex binomial_eval(const ex & x, const ex &y)
{
- if (is_ex_exactly_of_type(x, numeric) && is_ex_exactly_of_type(y, numeric))
+ if (is_exactly_a<numeric>(x) && is_exactly_a<numeric>(y))
return binomial(ex_to<numeric>(x), ex_to<numeric>(y));
else
return binomial(x, y).hold();
static ex Order_eval(const ex & x)
{
- if (is_ex_exactly_of_type(x, numeric)) {
+ if (is_exactly_a<numeric>(x)) {
// O(c) -> O(1) or 0
if (!x.is_zero())
return Order(_ex1).hold();
else
return _ex0;
- } else if (is_ex_exactly_of_type(x, mul)) {
+ } else if (is_exactly_a<mul>(x)) {
const mul &m = ex_to<mul>(x);
// O(c*expr) -> O(expr)
- if (is_ex_exactly_of_type(m.op(m.nops() - 1), numeric))
+ if (is_exactly_a<numeric>(m.op(m.nops() - 1)))
return Order(x / m.op(m.nops() - 1)).hold();
}
return Order(x).hold();
GINAC_ASSERT(self.nops() == 2 || self.nops() == 3);
// Only add two matrices
- if (is_ex_of_type(other.op(0), matrix)) {
+ if (is_a<matrix>(other.op(0))) {
GINAC_ASSERT(other.nops() == 2 || other.nops() == 3);
const matrix &self_matrix = ex_to<matrix>(self.op(0));
GINAC_ASSERT(is_a<matrix>(self->op(0)));
// Only contract with other matrices
- if (!is_ex_of_type(other->op(0), matrix))
+ if (!is_a<matrix>(other->op(0)))
return false;
GINAC_ASSERT(other->nops() == 2 || other->nops() == 3);
if (col!=row)
throw (std::logic_error("matrix::pow(): matrix not square"));
- if (is_ex_exactly_of_type(expn, numeric)) {
+ if (is_exactly_a<numeric>(expn)) {
// Integer cases are computed by successive multiplication, using the
// obvious shortcut of storing temporaries, like A^4 == (A*A)*(A*A).
if (expn.info(info_flags::integer)) {
GINAC_ASSERT((!is_exactly_a<mul>(i->rest)) ||
(!(ex_to<numeric>(i->coeff).is_integer())));
GINAC_ASSERT(!(i->is_canonical_numeric()));
- if (is_ex_exactly_of_type(recombine_pair_to_ex(*i), numeric))
+ if (is_exactly_a<numeric>(recombine_pair_to_ex(*i)))
print(print_tree(std::cerr));
GINAC_ASSERT(!is_exactly_a<numeric>(recombine_pair_to_ex(*i)));
/* for paranoia */
// *(x;1) -> x
return recombine_pair_to_ex(*(seq.begin()));
} else if ((seq_size==1) &&
- is_ex_exactly_of_type((*seq.begin()).rest,add) &&
+ is_exactly_a<add>((*seq.begin()).rest) &&
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);
{
// numeric*matrix
if (seq.size() == 1 && seq[0].coeff.is_equal(_ex1)
- && is_ex_of_type(seq[0].rest, matrix))
+ && is_a<matrix>(seq[0].rest))
return ex_to<matrix>(seq[0].rest).mul(ex_to<numeric>(overall_coeff));
// Evaluate children first, look whether there are any matrices at all
while (i != end) {
const ex &m = recombine_pair_to_ex(*i).evalm();
s->push_back(split_ex_to_pair(m));
- if (is_ex_of_type(m, matrix)) {
+ if (is_a<matrix>(m)) {
have_matrix = true;
the_matrix = s->end() - 1;
}
expair mul::split_ex_to_pair(const ex & e) const
{
- if (is_ex_exactly_of_type(e,power)) {
+ if (is_exactly_a<power>(e)) {
const power & powerref = ex_to<power>(e);
- if (is_ex_exactly_of_type(powerref.exponent,numeric))
+ if (is_exactly_a<numeric>(powerref.exponent))
return expair(powerref.basis,powerref.exponent);
}
return expair(e,_ex1);
bool mul::expair_needs_further_processing(epp it)
{
- if (is_ex_exactly_of_type((*it).rest,mul) &&
+ if (is_exactly_a<mul>((*it).rest) &&
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));
return true;
}
- if (is_ex_exactly_of_type((*it).rest,numeric)) {
+ if (is_exactly_a<numeric>((*it).rest)) {
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
non_adds.reserve(expanded_seq.size());
epvector::const_iterator cit = expanded_seq.begin(), last = expanded_seq.end();
while (cit != last) {
- if (is_ex_exactly_of_type(cit->rest, add) &&
+ if (is_exactly_a<add>(cit->rest) &&
(cit->coeff.is_equal(_ex1))) {
++number_of_adds;
- if (is_ex_exactly_of_type(last_expanded, add)) {
+ if (is_exactly_a<add>(last_expanded)) {
const add & add1 = ex_to<add>(last_expanded);
const add & add2 = ex_to<add>(cit->rest);
int n1 = add1.nops();
// Now the only remaining thing to do is to multiply the factors which
// were not sums into the "last_expanded" sum
- if (is_ex_exactly_of_type(last_expanded, add)) {
+ if (is_exactly_a<add>(last_expanded)) {
const add & finaladd = ex_to<add>(last_expanded);
exvector distrseq;
int n = finaladd.nops();
unsigned ncmul::count_factors(const ex & e) const
{
- if ((is_ex_exactly_of_type(e,mul)&&(e.return_type()!=return_types::commutative))||
- (is_ex_exactly_of_type(e,ncmul))) {
+ if ((is_exactly_a<mul>(e)&&(e.return_type()!=return_types::commutative))||
+ (is_exactly_a<ncmul>(e))) {
unsigned factors=0;
for (unsigned i=0; i<e.nops(); i++)
factors += count_factors(e.op(i));
void ncmul::append_factors(exvector & v, const ex & e) const
{
- if ((is_ex_exactly_of_type(e,mul)&&(e.return_type()!=return_types::commutative))||
- (is_ex_exactly_of_type(e,ncmul))) {
+ if ((is_exactly_a<mul>(e)&&(e.return_type()!=return_types::commutative))||
+ (is_exactly_a<ncmul>(e))) {
for (unsigned i=0; i<e.nops(); i++)
append_factors(v,e.op(i));
} else
// If there are only matrices, simply multiply them
it = s->begin(); itend = s->end();
- if (is_ex_of_type(*it, matrix)) {
+ if (is_a<matrix>(*it)) {
matrix prod(ex_to<matrix>(*it));
it++;
while (it != itend) {
- if (!is_ex_of_type(*it, matrix))
+ if (!is_a<matrix>(*it))
goto no_matrix;
prod = prod.mul(ex_to<matrix>(*it));
it++;
* @return "false" if no symbol was found, "true" otherwise */
static bool get_first_symbol(const ex &e, const symbol *&x)
{
- if (is_ex_exactly_of_type(e, symbol)) {
+ if (is_exactly_a<symbol>(e)) {
x = &ex_to<symbol>(e);
return true;
- } else if (is_ex_exactly_of_type(e, add) || is_ex_exactly_of_type(e, mul)) {
+ } else if (is_exactly_a<add>(e) || is_exactly_a<mul>(e)) {
for (unsigned i=0; i<e.nops(); i++)
if (get_first_symbol(e.op(i), x))
return true;
- } else if (is_ex_exactly_of_type(e, power)) {
+ } else if (is_exactly_a<power>(e)) {
if (get_first_symbol(e.op(0), x))
return true;
}
// Collect all symbols of an expression (used internally by get_symbol_stats())
static void collect_symbols(const ex &e, sym_desc_vec &v)
{
- if (is_ex_exactly_of_type(e, symbol)) {
+ if (is_exactly_a<symbol>(e)) {
add_symbol(&ex_to<symbol>(e), v);
- } else if (is_ex_exactly_of_type(e, add) || is_ex_exactly_of_type(e, mul)) {
+ } else if (is_exactly_a<add>(e) || is_exactly_a<mul>(e)) {
for (unsigned i=0; i<e.nops(); i++)
collect_symbols(e.op(i), v);
- } else if (is_ex_exactly_of_type(e, power)) {
+ } else if (is_exactly_a<power>(e)) {
collect_symbols(e.op(0), v);
}
}
{
if (e.info(info_flags::rational))
return lcm(ex_to<numeric>(e).denom(), l);
- else if (is_ex_exactly_of_type(e, add)) {
+ else if (is_exactly_a<add>(e)) {
numeric c = _num1;
for (unsigned i=0; i<e.nops(); i++)
c = lcmcoeff(e.op(i), c);
return lcm(c, l);
- } else if (is_ex_exactly_of_type(e, mul)) {
+ } else if (is_exactly_a<mul>(e)) {
numeric c = _num1;
for (unsigned i=0; i<e.nops(); i++)
c *= lcmcoeff(e.op(i), _num1);
return lcm(c, l);
- } else if (is_ex_exactly_of_type(e, power)) {
- if (is_ex_exactly_of_type(e.op(0), symbol))
+ } else if (is_exactly_a<power>(e)) {
+ if (is_exactly_a<symbol>(e.op(0)))
return l;
else
return pow(lcmcoeff(e.op(0), l), ex_to<numeric>(e.op(1)));
* @param lcm LCM to multiply in */
static ex multiply_lcm(const ex &e, const numeric &lcm)
{
- if (is_ex_exactly_of_type(e, mul)) {
+ if (is_exactly_a<mul>(e)) {
unsigned num = e.nops();
exvector v; v.reserve(num + 1);
numeric lcm_accum = _num1;
}
v.push_back(lcm / lcm_accum);
return (new mul(v))->setflag(status_flags::dynallocated);
- } else if (is_ex_exactly_of_type(e, add)) {
+ } else if (is_exactly_a<add>(e)) {
unsigned num = e.nops();
exvector v; v.reserve(num);
for (unsigned i=0; i<num; i++)
v.push_back(multiply_lcm(e.op(i), lcm));
return (new add(v))->setflag(status_flags::dynallocated);
- } else if (is_ex_exactly_of_type(e, power)) {
- if (is_ex_exactly_of_type(e.op(0), symbol))
+ } else if (is_exactly_a<power>(e)) {
+ if (is_exactly_a<symbol>(e.op(0)))
return e * lcm;
else
return pow(multiply_lcm(e.op(0), lcm.power(ex_to<numeric>(e.op(1)).inverse())), e.op(1));
{
if (b.is_zero())
throw(std::overflow_error("quo: division by zero"));
- if (is_ex_exactly_of_type(a, numeric) && is_ex_exactly_of_type(b, numeric))
+ if (is_exactly_a<numeric>(a) && is_exactly_a<numeric>(b))
return a / b;
#if FAST_COMPARE
if (a.is_equal(b))
int bdeg = b.degree(x);
int rdeg = r.degree(x);
ex blcoeff = b.expand().coeff(x, bdeg);
- bool blcoeff_is_numeric = is_ex_exactly_of_type(blcoeff, numeric);
+ bool blcoeff_is_numeric = is_exactly_a<numeric>(blcoeff);
exvector v; v.reserve(std::max(rdeg - bdeg + 1, 0));
while (rdeg >= bdeg) {
ex term, rcoeff = r.coeff(x, rdeg);
{
if (b.is_zero())
throw(std::overflow_error("rem: division by zero"));
- if (is_ex_exactly_of_type(a, numeric)) {
- if (is_ex_exactly_of_type(b, numeric))
+ if (is_exactly_a<numeric>(a)) {
+ if (is_exactly_a<numeric>(b))
return _ex0;
else
return a;
int bdeg = b.degree(x);
int rdeg = r.degree(x);
ex blcoeff = b.expand().coeff(x, bdeg);
- bool blcoeff_is_numeric = is_ex_exactly_of_type(blcoeff, numeric);
+ bool blcoeff_is_numeric = is_exactly_a<numeric>(blcoeff);
while (rdeg >= bdeg) {
ex term, rcoeff = r.coeff(x, rdeg);
if (blcoeff_is_numeric)
ex nd = numer_denom(a);
ex numer = nd.op(0), denom = nd.op(1);
ex q = quo(numer, denom, x);
- if (is_ex_exactly_of_type(q, fail))
+ if (is_exactly_a<fail>(q))
return a;
else
return q + rem(numer, denom, x) / denom;
{
if (b.is_zero())
throw(std::overflow_error("prem: division by zero"));
- if (is_ex_exactly_of_type(a, numeric)) {
- if (is_ex_exactly_of_type(b, numeric))
+ if (is_exactly_a<numeric>(a)) {
+ if (is_exactly_a<numeric>(b))
return _ex0;
else
return b;
{
if (b.is_zero())
throw(std::overflow_error("prem: division by zero"));
- if (is_ex_exactly_of_type(a, numeric)) {
- if (is_ex_exactly_of_type(b, numeric))
+ if (is_exactly_a<numeric>(a)) {
+ if (is_exactly_a<numeric>(b))
return _ex0;
else
return b;
q = _ex0;
return true;
}
- if (is_ex_exactly_of_type(b, numeric)) {
+ if (is_exactly_a<numeric>(b)) {
q = a / b;
return true;
- } else if (is_ex_exactly_of_type(a, numeric))
+ } else if (is_exactly_a<numeric>(a))
return false;
#if FAST_COMPARE
if (a.is_equal(b)) {
int bdeg = b.degree(*x);
int rdeg = r.degree(*x);
ex blcoeff = b.expand().coeff(*x, bdeg);
- bool blcoeff_is_numeric = is_ex_exactly_of_type(blcoeff, numeric);
+ bool blcoeff_is_numeric = is_exactly_a<numeric>(blcoeff);
exvector v; v.reserve(std::max(rdeg - bdeg + 1, 0));
while (rdeg >= bdeg) {
ex term, rcoeff = r.coeff(*x, rdeg);
q = a;
return true;
}
- if (is_ex_exactly_of_type(a, numeric)) {
- if (is_ex_exactly_of_type(b, numeric)) {
+ if (is_exactly_a<numeric>(a)) {
+ if (is_exactly_a<numeric>(b)) {
q = a / b;
return q.info(info_flags::integer);
} else
ex ex::unit(const symbol &x) const
{
ex c = expand().lcoeff(x);
- if (is_ex_exactly_of_type(c, numeric))
+ if (is_exactly_a<numeric>(c))
return c < _ex0 ? _ex_1 : _ex1;
else {
const symbol *y;
{
if (is_zero())
return _ex0;
- if (is_ex_exactly_of_type(*this, numeric))
+ if (is_exactly_a<numeric>(*this))
return info(info_flags::negative) ? -*this : *this;
ex e = expand();
if (e.is_zero())
{
if (is_zero())
return _ex0;
- if (is_ex_exactly_of_type(*this, numeric))
+ if (is_exactly_a<numeric>(*this))
return _ex1;
ex c = content(x);
if (c.is_zero())
return _ex0;
ex u = unit(x);
- if (is_ex_exactly_of_type(c, numeric))
+ if (is_exactly_a<numeric>(c))
return *this / (c * u);
else
return quo(*this, c * u, x, false);
return _ex0;
if (c.is_zero())
return _ex0;
- if (is_ex_exactly_of_type(*this, numeric))
+ if (is_exactly_a<numeric>(*this))
return _ex1;
ex u = unit(x);
- if (is_ex_exactly_of_type(c, numeric))
+ if (is_exactly_a<numeric>(c))
return *this / (c * u);
else
return quo(*this, c * u, x, false);
throw(std::runtime_error("invalid expression in red_gcd(), division failed"));
ddeg = d.degree(*x);
if (ddeg == 0) {
- if (is_ex_exactly_of_type(r, numeric))
+ if (is_exactly_a<numeric>(r))
return gamma;
else
return gamma * r.primpart(*x);
throw(std::runtime_error("invalid expression in sr_gcd(), division failed"));
ddeg = d.degree(x);
if (ddeg == 0) {
- if (is_ex_exactly_of_type(r, numeric))
+ if (is_exactly_a<numeric>(r))
return gamma;
else
return gamma * r.primpart(x);
return (new fail())->setflag(status_flags::dynallocated);
// GCD of two numeric values -> CLN
- if (is_ex_exactly_of_type(a, numeric) && is_ex_exactly_of_type(b, numeric)) {
+ if (is_exactly_a<numeric>(a) && is_exactly_a<numeric>(b)) {
numeric g = gcd(ex_to<numeric>(a), ex_to<numeric>(b));
if (ca)
*ca = ex_to<numeric>(a) / g;
// Apply evaluation homomorphism and calculate GCD
ex cp, cq;
ex gamma = heur_gcd(p.subs(x == xi), q.subs(x == xi), &cp, &cq, var+1).expand();
- if (!is_ex_exactly_of_type(gamma, fail)) {
+ if (!is_exactly_a<fail>(gamma)) {
// Reconstruct polynomial from GCD of mapped polynomials
ex g = interpolate(gamma, xi, x, maxdeg);
if (divide_in_z(p, g, ca ? *ca : dummy, var) && divide_in_z(q, g, cb ? *cb : dummy, var)) {
g *= gc;
ex lc = g.lcoeff(x);
- if (is_ex_exactly_of_type(lc, numeric) && ex_to<numeric>(lc).is_negative())
+ if (is_exactly_a<numeric>(lc) && ex_to<numeric>(lc).is_negative())
return -g;
else
return g;
if (ca)
*ca = cp;
ex lc = g.lcoeff(x);
- if (is_ex_exactly_of_type(lc, numeric) && ex_to<numeric>(lc).is_negative())
+ if (is_exactly_a<numeric>(lc) && ex_to<numeric>(lc).is_negative())
return -g;
else
return g;
if (cb)
*cb = cq;
ex lc = g.lcoeff(x);
- if (is_ex_exactly_of_type(lc, numeric) && ex_to<numeric>(lc).is_negative())
+ if (is_exactly_a<numeric>(lc) && ex_to<numeric>(lc).is_negative())
return -g;
else
return g;
#endif
// GCD of numerics -> CLN
- if (is_ex_exactly_of_type(a, numeric) && is_ex_exactly_of_type(b, numeric)) {
+ if (is_exactly_a<numeric>(a) && is_exactly_a<numeric>(b)) {
numeric g = gcd(ex_to<numeric>(a), ex_to<numeric>(b));
if (ca || cb) {
if (g.is_zero()) {
}
// Partially factored cases (to avoid expanding large expressions)
- if (is_ex_exactly_of_type(a, mul)) {
- if (is_ex_exactly_of_type(b, mul) && b.nops() > a.nops())
+ if (is_exactly_a<mul>(a)) {
+ if (is_exactly_a<mul>(b) && b.nops() > a.nops())
goto factored_b;
factored_a:
unsigned num = a.nops();
if (cb)
*cb = part_b;
return (new mul(g))->setflag(status_flags::dynallocated);
- } else if (is_ex_exactly_of_type(b, mul)) {
- if (is_ex_exactly_of_type(a, mul) && a.nops() > b.nops())
+ } else if (is_exactly_a<mul>(b)) {
+ if (is_exactly_a<mul>(a) && a.nops() > b.nops())
goto factored_a;
factored_b:
unsigned num = b.nops();
#if FAST_COMPARE
// Input polynomials of the form poly^n are sometimes also trivial
- if (is_ex_exactly_of_type(a, power)) {
+ if (is_exactly_a<power>(a)) {
ex p = a.op(0);
- if (is_ex_exactly_of_type(b, power)) {
+ if (is_exactly_a<power>(b)) {
if (p.is_equal(b.op(0))) {
// a = p^n, b = p^m, gcd = p^min(n, m)
ex exp_a = a.op(1), exp_b = b.op(1);
return p;
}
}
- } else if (is_ex_exactly_of_type(b, power)) {
+ } else if (is_exactly_a<power>(b)) {
ex p = b.op(0);
if (p.is_equal(a)) {
// a = p, b = p^n, gcd = p
} catch (gcdheu_failed) {
g = fail();
}
- if (is_ex_exactly_of_type(g, fail)) {
+ if (is_exactly_a<fail>(g)) {
//std::clog << "heuristics failed" << std::endl;
#if STATISTICS
heur_gcd_failed++;
* @return the LCM as a new expression */
ex lcm(const ex &a, const ex &b, bool check_args)
{
- if (is_ex_exactly_of_type(a, numeric) && is_ex_exactly_of_type(b, numeric))
+ if (is_exactly_a<numeric>(a) && is_exactly_a<numeric>(b))
return lcm(ex_to<numeric>(a), ex_to<numeric>(b));
if (check_args && (!a.info(info_flags::rational_polynomial) || !b.info(info_flags::rational_polynomial)))
throw(std::invalid_argument("lcm: arguments must be polynomials over the rationals"));
}
// Find the symbol to factor in at this stage
- if (!is_ex_of_type(args.op(0), symbol))
+ if (!is_a<symbol>(args.op(0)))
throw (std::runtime_error("sqrfree(): invalid factorization variable"));
const symbol &x = ex_to<symbol>(args.op(0));
* sign as a multiplicative factor. */
bool numeric::has(const ex &other) const
{
- if (!is_ex_exactly_of_type(other, numeric))
+ if (!is_exactly_a<numeric>(other))
return false;
const numeric &o = ex_to<numeric>(other);
if (this->is_equal(o) || this->is_equal(-o))
{
if (is_equal(ex_to<basic>(s)))
return 1;
- else if (is_ex_exactly_of_type(exponent, numeric) && ex_to<numeric>(exponent).is_integer()) {
+ else if (is_exactly_a<numeric>(exponent) && ex_to<numeric>(exponent).is_integer()) {
if (basis.is_equal(s))
return ex_to<numeric>(exponent).to_int();
else
{
if (is_equal(ex_to<basic>(s)))
return 1;
- else if (is_ex_exactly_of_type(exponent, numeric) && ex_to<numeric>(exponent).is_integer()) {
+ else if (is_exactly_a<numeric>(exponent) && ex_to<numeric>(exponent).is_integer()) {
if (basis.is_equal(s))
return ex_to<numeric>(exponent).to_int();
else
return _ex0;
} else {
// basis equal to s
- if (is_ex_exactly_of_type(exponent, numeric) && ex_to<numeric>(exponent).is_integer()) {
+ if (is_exactly_a<numeric>(exponent) && ex_to<numeric>(exponent).is_integer()) {
// integer exponent
int int_exp = ex_to<numeric>(exponent).to_int();
if (n == int_exp)
const numeric *num_basis;
const numeric *num_exponent;
- if (is_ex_exactly_of_type(ebasis, numeric)) {
+ if (is_exactly_a<numeric>(ebasis)) {
basis_is_numerical = true;
num_basis = &ex_to<numeric>(ebasis);
}
- if (is_ex_exactly_of_type(eexponent, numeric)) {
+ if (is_exactly_a<numeric>(eexponent)) {
exponent_is_numerical = true;
num_exponent = &ex_to<numeric>(eexponent);
}
// ^(^(x,c1),c2) -> ^(x,c1*c2)
// (c1, c2 numeric(), c2 integer or -1 < c1 <= 1,
// case c1==1 should not happen, see below!)
- if (is_ex_exactly_of_type(ebasis,power)) {
+ if (is_exactly_a<power>(ebasis)) {
const power & sub_power = ex_to<power>(ebasis);
const ex & sub_basis = sub_power.basis;
const ex & sub_exponent = sub_power.exponent;
- if (is_ex_exactly_of_type(sub_exponent,numeric)) {
+ if (is_exactly_a<numeric>(sub_exponent)) {
const numeric & num_sub_exponent = ex_to<numeric>(sub_exponent);
GINAC_ASSERT(num_sub_exponent!=numeric(1));
if (num_exponent->is_integer() || (abs(num_sub_exponent) - _num1).is_negative())
}
// ^(*(x,y,z),c1) -> *(x^c1,y^c1,z^c1) (c1 integer)
- if (num_exponent->is_integer() && is_ex_exactly_of_type(ebasis,mul)) {
+ if (num_exponent->is_integer() && is_exactly_a<mul>(ebasis)) {
return expand_mul(ex_to<mul>(ebasis), *num_exponent);
}
// ^(*(...,x;c1),c2) -> *(^(*(...,x;1),c2),c1^c2) (c1, c2 numeric(), c1>0)
// ^(*(...,x;c1),c2) -> *(^(*(...,x;-1),c2),(-c1)^c2) (c1, c2 numeric(), c1<0)
- if (is_ex_exactly_of_type(ebasis,mul)) {
+ if (is_exactly_a<mul>(ebasis)) {
GINAC_ASSERT(!num_exponent->is_integer()); // should have been handled above
const mul & mulref = ex_to<mul>(ebasis);
if (!mulref.overall_coeff.is_equal(_ex1)) {
// ^(nc,c1) -> ncmul(nc,nc,...) (c1 positive integer, unless nc is a matrix)
if (num_exponent->is_pos_integer() &&
ebasis.return_type() != return_types::commutative &&
- !is_ex_of_type(ebasis,matrix)) {
+ !is_a<matrix>(ebasis)) {
return ncmul(exvector(num_exponent->to_int(), ebasis), true);
}
}
{
const ex ebasis = basis.evalm();
const ex eexponent = exponent.evalm();
- if (is_ex_of_type(ebasis,matrix)) {
- if (is_ex_of_type(eexponent,numeric)) {
+ if (is_a<matrix>(ebasis)) {
+ if (is_a<numeric>(eexponent)) {
return (new matrix(ex_to<matrix>(ebasis).pow(eexponent)))->setflag(status_flags::dynallocated);
}
}
const ex expanded_exponent = exponent.expand(options);
// x^(a+b) -> x^a * x^b
- if (is_ex_exactly_of_type(expanded_exponent, add)) {
+ if (is_exactly_a<add>(expanded_exponent)) {
const add &a = ex_to<add>(expanded_exponent);
exvector distrseq;
distrseq.reserve(a.seq.size() + 1);
if (ex_to<numeric>(a.overall_coeff).is_integer()) {
const numeric &num_exponent = ex_to<numeric>(a.overall_coeff);
int int_exponent = num_exponent.to_int();
- if (int_exponent > 0 && is_ex_exactly_of_type(expanded_basis, add))
+ if (int_exponent > 0 && is_exactly_a<add>(expanded_basis))
distrseq.push_back(expand_add(ex_to<add>(expanded_basis), int_exponent));
else
distrseq.push_back(power(expanded_basis, a.overall_coeff));
return r.expand();
}
- if (!is_ex_exactly_of_type(expanded_exponent, numeric) ||
+ if (!is_exactly_a<numeric>(expanded_exponent) ||
!ex_to<numeric>(expanded_exponent).is_integer()) {
if (are_ex_trivially_equal(basis,expanded_basis) && are_ex_trivially_equal(exponent,expanded_exponent)) {
return this->hold();
int int_exponent = num_exponent.to_int();
// (x+y)^n, n>0
- if (int_exponent > 0 && is_ex_exactly_of_type(expanded_basis,add))
+ if (int_exponent > 0 && is_exactly_a<add>(expanded_basis))
return expand_add(ex_to<add>(expanded_basis), int_exponent);
// (x*y)^n -> x^n * y^n
- if (is_ex_exactly_of_type(expanded_basis,mul))
+ if (is_exactly_a<mul>(expanded_basis))
return expand_mul(ex_to<mul>(expanded_basis), num_exponent);
// cannot expand further
!is_exactly_a<add>(ex_to<power>(b).basis) ||
!is_exactly_a<mul>(ex_to<power>(b).basis) ||
!is_exactly_a<power>(ex_to<power>(b).basis));
- if (is_ex_exactly_of_type(b,mul))
+ if (is_exactly_a<mul>(b))
term.push_back(expand_mul(ex_to<mul>(b),numeric(k[l])));
else
term.push_back(power(b,k[l]));
!is_exactly_a<add>(ex_to<power>(b).basis) ||
!is_exactly_a<mul>(ex_to<power>(b).basis) ||
!is_exactly_a<power>(ex_to<power>(b).basis));
- if (is_ex_exactly_of_type(b,mul))
+ if (is_exactly_a<mul>(b))
term.push_back(expand_mul(ex_to<mul>(b),numeric(n-k_cum[m-2])));
else
term.push_back(power(b,n-k_cum[m-2]));
!is_exactly_a<power>(ex_to<power>(r).basis));
if (are_ex_trivially_equal(c,_ex1)) {
- if (is_ex_exactly_of_type(r,mul)) {
+ if (is_exactly_a<mul>(r)) {
sum.push_back(expair(expand_mul(ex_to<mul>(r),_num2),
_ex1));
} else {
_ex1));
}
} else {
- if (is_ex_exactly_of_type(r,mul)) {
+ if (is_exactly_a<mul>(r)) {
sum.push_back(expair(expand_mul(ex_to<mul>(r),_num2),
ex_to<numeric>(c).power_dyn(_num2)));
} else {
epvector::const_iterator last = m.seq.end();
epvector::const_iterator cit = m.seq.begin();
while (cit!=last) {
- if (is_ex_exactly_of_type((*cit).rest,numeric)) {
+ if (is_exactly_a<numeric>((*cit).rest)) {
distrseq.push_back(m.combine_pair_with_coeff_to_pair(*cit,n));
} else {
// it is safe not to call mul::combine_pair_with_coeff_to_pair()
epvector::const_iterator itend = seq.end();
for (; it!=itend; ++it) {
ex op;
- if (is_ex_exactly_of_type(it->rest, pseries))
+ if (is_exactly_a<pseries>(it->rest))
op = it->rest;
else
op = it->rest.series(r, order, options);
ex power::series(const relational & r, int order, unsigned options) const
{
// If basis is already a series, just power it
- if (is_ex_exactly_of_type(basis, pseries))
+ if (is_exactly_a<pseries>(basis))
return ex_to<pseries>(basis).power_const(ex_to<numeric>(exponent), order);
// Basis is not a series, may there be a singularity?
ex e;
relational rel_;
- if (is_ex_exactly_of_type(r,relational))
+ if (is_exactly_a<relational>(r))
rel_ = ex_to<relational>(r);
- else if (is_ex_exactly_of_type(r,symbol))
+ else if (is_exactly_a<symbol>(r))
rel_ = relational(r,_ex0);
else
throw (std::logic_error("ex::series(): expansion point has unknown type"));
relational::operator relational::safe_bool() const
{
const ex df = lh-rh;
- if (!is_ex_exactly_of_type(df,numeric))
+ if (!is_exactly_a<numeric>(df))
// cannot decide on non-numerical results
return o==not_equal ? make_safe_bool(true) : make_safe_bool(false);
$is_equal_statements=generate(' if (!m_${MEMBER}.is_equal(o.m_${MEMBER})) return false;',"\n");
$types_ok_statements=generate(
'#ifndef SKIP_TYPE_CHECK_FOR_${TYPE}'."\n".
-' if (!is_ex_exactly_of_type(m_${MEMBER},${TYPE})) return false;'."\n".
+' if (!is_exactly_a<${TYPE}>(m_${MEMBER})) return false;'."\n".
'#endif // ndef SKIP_TYPE_CHECK_FOR_${TYPE}',"\n");
$interface=<<END_OF_INTERFACE;
int ${STRUCTURE}::compare_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other,${STRUCTURE}));
+ GINAC_ASSERT(is_a<${STRUCTURE}>(other));
${STRUCTURE} const &o = static_cast<const ${STRUCTURE} &>(other);
int cmpval;
${compare_statements}
bool ${STRUCTURE}::is_equal_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other,${STRUCTURE}));
+ GINAC_ASSERT(is_a<${STRUCTURE}>(other));
${STRUCTURE} const &o = static_cast<const ${STRUCTURE} &>(other);
${is_equal_statements}
return true;
// public
#define SKIP_TYPE_CHECK_FOR_ex
-// this is a hack since there is no meaningful
-// is_ex_exactly_of_type(...,ex) macro definition
+// this is a hack since there is no meaningful is_a<ex>(...) definition
bool ${STRUCTURE}::types_ok(void) const
{
// If symbol is in sym_lst, return the existing symbol
for (unsigned i=0; i<sym_lst.nops(); i++) {
- if (is_ex_of_type(sym_lst.op(i), symbol) && (ex_to<symbol>(sym_lst.op(i)).name == ex_to<symbol>(s).name))
+ if (is_a<symbol>(sym_lst.op(i)) && (ex_to<symbol>(sym_lst.op(i)).name == ex_to<symbol>(s).name))
return sym_lst.op(i);
}
return s;
if (minkowski) {
for (unsigned j=1; j<i.nops(); j++) {
const ex & x = i.op(j);
- if (!is_ex_of_type(x, varidx))
+ if (!is_a<varidx>(x))
throw(std::runtime_error("indices of epsilon tensor in Minkowski space must be of type varidx"));
if (ex_to<varidx>(x).is_covariant())
if (ex_to<idx>(x).get_value().is_zero())
// If contracting with the delta tensor, let the delta do it
// (don't raise/lower delta indices)
- if (is_ex_of_type(other->op(0), tensdelta))
+ if (is_a<tensdelta>(other->op(0)))
return false;
// Try to contract first index
GINAC_ASSERT(is_a<spinmetric>(self->op(0)));
// Contractions between spinor metrics
- if (is_ex_of_type(other->op(0), spinmetric)) {
+ if (is_a<spinmetric>(other->op(0))) {
const idx &self_i1 = ex_to<idx>(self->op(1));
const idx &self_i2 = ex_to<idx>(self->op(2));
const idx &other_i1 = ex_to<idx>(other->op(1));
// If contracting with the delta tensor, let the delta do it
// (don't raise/lower delta indices)
- if (is_ex_of_type(other->op(0), tensdelta))
+ if (is_a<tensdelta>(other->op(0)))
return false;
// Try to contract first index
GINAC_ASSERT(is_a<tensepsilon>(self->op(0)));
unsigned num = self->nops() - 1;
- if (is_ex_exactly_of_type(other->op(0), tensepsilon) && num+1 == other->nops()) {
+ if (is_exactly_a<tensepsilon>(other->op(0)) && num+1 == other->nops()) {
// Contraction of two epsilon tensors is a determinant
ex dim = ex_to<idx>(self->op(1)).get_dim();
ex delta_tensor(const ex & i1, const ex & i2)
{
- if (!is_ex_of_type(i1, idx) || !is_ex_of_type(i2, idx))
+ if (!is_a<idx>(i1) || !is_a<idx>(i2))
throw(std::invalid_argument("indices of delta tensor must be of type idx"));
return indexed(tensdelta(), sy_symm(), i1, i2);
ex metric_tensor(const ex & i1, const ex & i2)
{
- if (!is_ex_of_type(i1, varidx) || !is_ex_of_type(i2, varidx))
+ if (!is_a<varidx>(i1) || !is_a<varidx>(i2))
throw(std::invalid_argument("indices of metric tensor must be of type varidx"));
return indexed(tensmetric(), sy_symm(), i1, i2);
ex lorentz_g(const ex & i1, const ex & i2, bool pos_sig)
{
- if (!is_ex_of_type(i1, varidx) || !is_ex_of_type(i2, varidx))
+ if (!is_a<varidx>(i1) || !is_a<varidx>(i2))
throw(std::invalid_argument("indices of metric tensor must be of type varidx"));
return indexed(minkmetric(pos_sig), sy_symm(), i1, i2);
ex spinor_metric(const ex & i1, const ex & i2)
{
- if (!is_ex_of_type(i1, spinidx) || !is_ex_of_type(i2, spinidx))
+ if (!is_a<spinidx>(i1) || !is_a<spinidx>(i2))
throw(std::invalid_argument("indices of spinor metric must be of type spinidx"));
if (!ex_to<idx>(i1).get_dim().is_equal(2) || !ex_to<idx>(i2).get_dim().is_equal(2))
throw(std::runtime_error("index dimension for spinor metric must be 2"));
ex epsilon_tensor(const ex & i1, const ex & i2)
{
- if (!is_ex_of_type(i1, idx) || !is_ex_of_type(i2, idx))
+ if (!is_a<idx>(i1) || !is_a<idx>(i2))
throw(std::invalid_argument("indices of epsilon tensor must be of type idx"));
ex dim = ex_to<idx>(i1).get_dim();
ex epsilon_tensor(const ex & i1, const ex & i2, const ex & i3)
{
- if (!is_ex_of_type(i1, idx) || !is_ex_of_type(i2, idx) || !is_ex_of_type(i3, idx))
+ if (!is_a<idx>(i1) || !is_a<idx>(i2) || !is_a<idx>(i3))
throw(std::invalid_argument("indices of epsilon tensor must be of type idx"));
ex dim = ex_to<idx>(i1).get_dim();
ex lorentz_eps(const ex & i1, const ex & i2, const ex & i3, const ex & i4, bool pos_sig)
{
- if (!is_ex_of_type(i1, varidx) || !is_ex_of_type(i2, varidx) || !is_ex_of_type(i3, varidx) || !is_ex_of_type(i4, varidx))
+ if (!is_a<varidx>(i1) || !is_a<varidx>(i2) || !is_a<varidx>(i3) || !is_a<varidx>(i4))
throw(std::invalid_argument("indices of Lorentz epsilon tensor must be of type varidx"));
ex dim = ex_to<idx>(i1).get_dim();
ex eps0123(const ex & i1, const ex & i2, const ex & i3, const ex & i4, bool pos_sig)
{
- if (!is_ex_of_type(i1, varidx) || !is_ex_of_type(i2, varidx) || !is_ex_of_type(i3, varidx) || !is_ex_of_type(i4, varidx))
+ if (!is_a<varidx>(i1) || !is_a<varidx>(i2) || !is_a<varidx>(i3) || !is_a<varidx>(i4))
throw(std::invalid_argument("indices of epsilon tensor must be of type varidx"));
ex dim = ex_to<idx>(i1).get_dim();
c.s << text; \
}
-// Obsolete convenience macros. TO BE PHASED OUT SOON!
-// Use the inlined template functions in basic.h instead. (FIXME: remove them)
-
-#define is_of_type(OBJ,TYPE) \
- (dynamic_cast<const TYPE *>(&OBJ)!=0)
-
-#define is_exactly_of_type(OBJ,TYPE) \
- ((OBJ).tinfo()==GiNaC::TINFO_##TYPE)
-
-#define is_ex_of_type(OBJ,TYPE) \
- (dynamic_cast<const TYPE *>((OBJ).bp)!=0)
-
-#define is_ex_exactly_of_type(OBJ,TYPE) \
- ((*(OBJ).bp).tinfo()==GiNaC::TINFO_##TYPE)
-
} // namespace GiNaC