- ...a new function paranoia_check10.
ex f = e.normal();
// The bug caused a division by zero in normal(), so the following
- // check is actually bogus...
+ // check is actually quite bogus...
if (!f.is_equal(e)) {
clog << "normal(-x/(x+1)) returns " << f << " instead of -x/(x+1)\n";
++result;
// This one was a result of a modification to frac_cancel() & Co. to avoid
// expanding the numerator and denominator when bringing them from Q[X] to
// Z[X]. multiply_lcm() forgot to multiply the x-linear term with the LCM of
-// the coefficient's denominators (2 in this case). Introduced on Jan 25th
+// the coefficient's denominators (2 in this case). Introduced on Jan 25th
// 2000 and fixed on Jan 31th.
static unsigned paranoia_check9(void)
{
return result;
}
+// I have no idea when this broke. It has been working long ago, before 0.4.0
+// and on Feb 13th 2000 I found out that things like 2^(3/2) throw an exception
+// "power::eval(): pow(0,0) is undefined" instead of simplifying to 2*2^(1/2).
+// It was fixed that same day.
+static unsigned paranoia_check10(void)
+{
+ unsigned result = 0;
+
+ ex b = numeric(2);
+ ex e = numeric(3,2);
+ ex r;
+
+ try {
+ r = pow(b,e).eval();
+ if (!(r-2*sqrt(ex(2))).is_zero()) {
+ clog << "2^(3/2) erroneously returned " << r << " instead of 2*sqrt(2)" << endl;
+ ++result;
+ }
+ } catch (const exception &e) {
+ clog << "2^(3/2) throws " << e.what() << endl;
+ ++result;
+ }
+ return result;
+}
+
unsigned paranoia_check(void)
{
unsigned result = 0;
result += paranoia_check7();
result += paranoia_check8();
result += paranoia_check9();
+ result += paranoia_check10();
if (!result) {
cout << " passed ";
(*cit).printraw(cout);
}
cout << endl;
- cout.flush();
*/
}
// and their cumulative number of operands
int nexpairseqs=0;
int noperands=0;
- cit=v.begin();
+
+ cit = v.begin();
while (cit!=citend) {
if (cit->rest.bp->tinfo()==tinfo()) {
nexpairseqs++;
- noperands+=ex_to_expairseq((*cit).rest).seq.size();
+ noperands += ex_to_expairseq((*cit).rest).seq.size();
}
++cit;
}
seq.reserve(v.size()+noperands-nexpairseqs);
// copy elements and split off numerical part
- cit=v.begin();
+ cit = v.begin();
while (cit!=citend) {
if ((cit->rest.bp->tinfo()==tinfo())&&can_make_flat(*cit)) {
const expairseq & subseqref=ex_to_expairseq((*cit).rest);
vector<bool> & touched,
unsigned & number_of_zeroes);
bool has_coeff_0(void) const;
- void add_numerics_to_hashtab(epvector::iterator first_numeric, epvector::const_iterator last_non_zero);
+ void add_numerics_to_hashtab(epvector::iterator first_numeric,
+ epvector::const_iterator last_non_zero);
#endif // def EXPAIRSEQ_USE_HASHTAB
bool is_canonical() const;
epvector * expandchildren(unsigned options) const;
{
debugmsg("mul constructor from ex,ex",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_mul;
- overall_coeff=_ex1();
+ overall_coeff = _ex1();
construct_from_2_ex(lh,rh);
GINAC_ASSERT(is_canonical());
}
{
debugmsg("mul constructor from exvector",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_mul;
- overall_coeff=_ex1();
+ overall_coeff = _ex1();
construct_from_exvector(v);
GINAC_ASSERT(is_canonical());
}
-/*
-mul::mul(const epvector & v, bool do_not_canonicalize)
-{
- debugmsg("mul constructor from epvector,bool",LOGLEVEL_CONSTRUCT);
- tinfo_key = TINFO_mul;
- if (do_not_canonicalize) {
- seq=v;
-#ifdef EXPAIRSEQ_USE_HASHTAB
- combine_same_terms(); // to build hashtab
-#endif // def EXPAIRSEQ_USE_HASHTAB
- } else {
- construct_from_epvector(v);
- }
- GINAC_ASSERT(is_canonical());
-}
-*/
-
mul::mul(const epvector & v)
{
debugmsg("mul constructor from epvector",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_mul;
- overall_coeff=_ex1();
+ overall_coeff = _ex1();
construct_from_epvector(v);
GINAC_ASSERT(is_canonical());
}
{
debugmsg("mul constructor from epvector,ex",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_mul;
- overall_coeff=oc;
+ overall_coeff = oc;
construct_from_epvector(v);
GINAC_ASSERT(is_canonical());
}
debugmsg("mul constructor from epvector *,ex",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_mul;
GINAC_ASSERT(vp!=0);
- overall_coeff=oc;
+ overall_coeff = oc;
construct_from_epvector(*vp);
delete vp;
GINAC_ASSERT(is_canonical());
factors.push_back(lh);
factors.push_back(mh);
factors.push_back(rh);
- overall_coeff=_ex1();
+ overall_coeff = _ex1();
construct_from_exvector(factors);
GINAC_ASSERT(is_canonical());
}
const ex & ebasis = level==1 ? basis : basis.eval(level-1);
const ex & eexponent = level==1 ? exponent : exponent.eval(level-1);
- bool basis_is_numerical=0;
- bool exponent_is_numerical=0;
+ bool basis_is_numerical = 0;
+ bool exponent_is_numerical = 0;
numeric * num_basis;
numeric * num_exponent;
if (is_exactly_of_type(*ebasis.bp,numeric)) {
- basis_is_numerical=1;
- num_basis=static_cast<numeric *>(ebasis.bp);
+ basis_is_numerical = 1;
+ num_basis = static_cast<numeric *>(ebasis.bp);
}
if (is_exactly_of_type(*eexponent.bp,numeric)) {
- exponent_is_numerical=1;
- num_exponent=static_cast<numeric *>(eexponent.bp);
+ exponent_is_numerical = 1;
+ num_exponent = static_cast<numeric *>(eexponent.bp);
}
// ^(x,0) -> 1 (0^0 also handled here)
if (basis_is_crational && exponent_is_crational
&& num_exponent->is_real()
&& !num_exponent->is_integer()) {
- numeric r, q, n, m;
- n = num_exponent->numer();
- m = num_exponent->denom();
- q = iquo(n, m, r);
+ numeric n = num_exponent->numer();
+ numeric m = num_exponent->denom();
+ numeric r;
+ numeric q = iquo(n, m, r);
if (r.is_negative()) {
r = r.add(m);
q = q.sub(_num1());
if (q.is_zero()) // the exponent was in the allowed range 0<(n/m)<1
return this->hold();
else {
- epvector res(2);
+ epvector res;
+ res.reserve(1);
res.push_back(expair(ebasis,r.div(m)));
- res.push_back(expair(ex(num_basis->power(q)),_ex1()));
- return (new mul(res))->setflag(status_flags::dynallocated | status_flags::evaluated);
- /*return mul(num_basis->power(q),
- power(ex(*num_basis),ex(r.div(m)))).hold();
- */
- /* return (new mul(num_basis->power(q),
- power(*num_basis,r.div(m)).hold()))->setflag(status_flags::dynallocated | status_flags::evaluated);
- */
+ return (new mul(res,ex(num_basis->power(q))))->setflag(status_flags::dynallocated | status_flags::evaluated);
}
}
}
// ^(^(x,c1),c2) -> ^(x,c1*c2)
// (c1, c2 numeric(), c2 integer or -1 < c1 <= 1,
- // case c1=1 should not happen, see below!)
+ // case c1==1 should not happen, see below!)
if (exponent_is_numerical && is_ex_exactly_of_type(ebasis,power)) {
- const power & sub_power=ex_to_power(ebasis);
- const ex & sub_basis=sub_power.basis;
- const ex & sub_exponent=sub_power.exponent;
+ 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)) {
- const numeric & num_sub_exponent=ex_to_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)<1) {
return power(sub_basis,num_sub_exponent.mul(*num_exponent));