* Implementation of GiNaC's symbolic integral. */
/*
- * GiNaC Copyright (C) 1999-2005 Johannes Gutenberg University Mainz, Germany
+ * GiNaC Copyright (C) 1999-2009 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
//////////
integral::integral()
- : inherited(TINFO_integral),
+ :
x((new symbol())->setflag(status_flags::dynallocated))
{}
// public
integral::integral(const ex & x_, const ex & a_, const ex & b_, const ex & f_)
- : inherited(TINFO_integral), x(x_), a(a_), b(b_), f(f_)
+ : x(x_), a(a_), b(b_), f(f_)
{
if (!is_a<symbol>(x)) {
throw(std::invalid_argument("first argument of integral must be of type symbol"));
// archiving
//////////
-integral::integral(const archive_node & n, lst & sym_lst) : inherited(n, sym_lst)
+void integral::read_archive(const archive_node& n, lst& sym_lst)
{
+ inherited::read_archive(n, sym_lst);
n.find_ex("x", x, sym_lst);
n.find_ex("a", a, sym_lst);
n.find_ex("b", b, sym_lst);
n.add_ex("f", f);
}
-DEFAULT_UNARCHIVE(integral)
-
//////////
// functions overriding virtual functions from base classes
//////////
ex result = fun.subs(var==value).evalf();
if (is_a<numeric>(result))
return result;
- throw logic_error("integrant does not evaluate to numeric");
+ throw logic_error("integrand does not evaluate to numeric");
}
+struct error_and_integral
+{
+ error_and_integral(const ex &err, const ex &integ)
+ :error(err), integral(integ){}
+ ex error;
+ ex integral;
+};
+
+struct error_and_integral_is_less
+{
+ bool operator()(const error_and_integral &e1,const error_and_integral &e2) const
+ {
+ int c = e1.integral.compare(e2.integral);
+ if(c < 0)
+ return true;
+ if(c > 0)
+ return false;
+ return ex_is_less()(e1.error, e2.error);
+ }
+};
+
+typedef map<error_and_integral, ex, error_and_integral_is_less> lookup_map;
+
/** Numeric integration routine based upon the "Adaptive Quadrature" one
* in "Numerical Analysis" by Burden and Faires. Parameters are integration
* variable, left boundary, right boundary, function to be integrated and
* after substituting the integration variable by a number. Another thing
* to note is that this implementation is no good at integrating functions
* with discontinuities. */
-ex adaptivesimpson(const ex & x, const ex & a, const ex & b, const ex & f, const ex & error)
+ex adaptivesimpson(const ex & x, const ex & a_in, const ex & b_in, const ex & f, const ex & error)
{
- // use lookup table to be potentially much faster.
- static exmap lookup;
+ // Check whether boundaries and error are numbers.
+ ex a = is_exactly_a<numeric>(a_in) ? a_in : a_in.evalf();
+ ex b = is_exactly_a<numeric>(b_in) ? b_in : b_in.evalf();
+ if(!is_exactly_a<numeric>(a) || !is_exactly_a<numeric>(b))
+ throw std::runtime_error("For numerical integration the boundaries of the integral should evalf into numbers.");
+ if(!is_exactly_a<numeric>(error))
+ throw std::runtime_error("For numerical integration the error should be a number.");
+
+ // Use lookup table to be potentially much faster.
+ static lookup_map lookup;
static symbol ivar("ivar");
ex lookupex = integral(ivar,a,b,f.subs(x==ivar));
- exmap::iterator emi = lookup.find(lookupex);
+ lookup_map::iterator emi = lookup.find(error_and_integral(error, lookupex));
if (emi!=lookup.end())
return emi->second;
fbvec[i] = subsvalue(x, b, f);
svec[i] = hvec[i]*(favec[i]+4*fcvec[i]+fbvec[i])/3;
lvec[i] = 1;
- errorvec[i] = integral::relative_integration_error*svec[i];
+ errorvec[i] = error*abs(svec[i]);
while (i>0) {
ex fd = subsvalue(x, avec[i]+hvec[i]/2, f);
ex nu4 = fbvec[i];
ex nu5 = hvec[i];
// hopefully prevents a crash if the function is zero sometimes.
- ex nu6 = max(errorvec[i], (s1+s2)*integral::relative_integration_error);
+ ex nu6 = max(errorvec[i], abs(s1+s2)*error);
ex nu7 = svec[i];
int nu8 = lvec[i];
--i;
}
}
- lookup[lookupex]=app;
+ lookup[error_and_integral(error, lookupex)]=app;
return app;
}
return f.return_type();
}
-unsigned integral::return_type_tinfo() const
+return_type_t integral::return_type_tinfo() const
{
return f.return_type_tinfo();
}
return *this;
}
+GINAC_BIND_UNARCHIVER(integral);
} // namespace GiNaC