Squashed 'boost/' content from commit b4feb19f2

git-subtree-dir: boost
git-subtree-split: b4feb19f287ee92d87a9624b5d36b7cf46aeadeb
This commit is contained in:
Bill Somerville
2018-06-09 21:48:32 +01:00
commit 4ebe6417a5
12444 changed files with 2327021 additions and 0 deletions
+208
View File
@@ -0,0 +1,208 @@
/* Boost example/filter.cpp
* two examples of filters for computing the sign of a determinant
* the second filter is based on an idea presented in
* "Interval arithmetic yields efficient dynamic filters for computational
* geometry" by Brönnimann, Burnikel and Pion, 2001
*
* Copyright 2003 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/numeric/interval.hpp>
#include <iostream>
namespace dummy {
using namespace boost;
using namespace numeric;
using namespace interval_lib;
typedef save_state<rounded_arith_opp<double> > R;
typedef checking_no_nan<double, checking_no_empty<double> > P;
typedef interval<double, policies<R, P> > I;
}
template<class T>
class vector {
T* ptr;
public:
vector(int d) { ptr = (T*)malloc(sizeof(T) * d); }
~vector() { free(ptr); }
const T& operator[](int i) const { return ptr[i]; }
T& operator[](int i) { return ptr[i]; }
};
template<class T>
class matrix {
int dim;
T* ptr;
public:
matrix(int d): dim(d) { ptr = (T*)malloc(sizeof(T) * dim * dim); }
~matrix() { free(ptr); }
int get_dim() const { return dim; }
void assign(const matrix<T> &a) { memcpy(ptr, a.ptr, sizeof(T) * dim * dim); }
const T* operator[](int i) const { return &(ptr[i * dim]); }
T* operator[](int i) { return &(ptr[i * dim]); }
};
typedef dummy::I I_dbl;
/* compute the sign of a determinant using an interval LU-decomposition; the
function answers 1 or -1 if the determinant is positive or negative (and
more importantly, the result must be provable), or 0 if the algorithm was
unable to get a correct sign */
int det_sign_algo1(const matrix<double> &a) {
int dim = a.get_dim();
vector<int> p(dim);
for(int i = 0; i < dim; i++) p[i] = i;
int sig = 1;
I_dbl::traits_type::rounding rnd;
typedef boost::numeric::interval_lib::unprotect<I_dbl>::type I;
matrix<I> u(dim);
for(int i = 0; i < dim; i++) {
const double* line1 = a[i];
I* line2 = u[i];
for(int j = 0; j < dim; j++)
line2[j] = line1[j];
}
// computation of L and U
for(int i = 0; i < dim; i++) {
// partial pivoting
{
int pivot = i;
double max = 0;
for(int j = i; j < dim; j++) {
const I &v = u[p[j]][i];
if (zero_in(v)) continue;
double m = norm(v);
if (m > max) { max = m; pivot = j; }
}
if (max == 0) return 0;
if (pivot != i) {
sig = -sig;
int tmp = p[i];
p[i] = p[pivot];
p[pivot] = tmp;
}
}
// U[i,?]
{
I *line1 = u[p[i]];
const I &pivot = line1[i];
if (boost::numeric::interval_lib::cerlt(pivot, 0.)) sig = -sig;
for(int k = i + 1; k < dim; k++) {
I *line2 = u[p[k]];
I fact = line2[i] / pivot;
for(int j = i + 1; j < dim; j++) line2[j] -= fact * line1[j];
}
}
}
return sig;
}
/* compute the sign of a determinant using a floating-point LU-decomposition
and an a posteriori interval validation; the meaning of the answer is the
same as previously */
int det_sign_algo2(const matrix<double> &a) {
int dim = a.get_dim();
vector<int> p(dim);
for(int i = 0; i < dim; i++) p[i] = i;
int sig = 1;
matrix<double> lui(dim);
{
// computation of L and U
matrix<double> lu(dim);
lu.assign(a);
for(int i = 0; i < dim; i++) {
// partial pivoting
{
int pivot = i;
double max = std::abs(lu[p[i]][i]);
for(int j = i + 1; j < dim; j++) {
double m = std::abs(lu[p[j]][i]);
if (m > max) { max = m; pivot = j; }
}
if (max == 0) return 0;
if (pivot != i) {
sig = -sig;
int tmp = p[i];
p[i] = p[pivot];
p[pivot] = tmp;
}
}
// L[?,i] and U[i,?]
{
double *line1 = lu[p[i]];
double pivot = line1[i];
if (pivot < 0) sig = -sig;
for(int k = i + 1; k < dim; k++) {
double *line2 = lu[p[k]];
double fact = line2[i] / pivot;
line2[i] = fact;
for(int j = i + 1; j < dim; j++) line2[j] -= line1[j] * fact;
}
}
}
// computation of approximate inverses: Li and Ui
for(int j = 0; j < dim; j++) {
for(int i = j + 1; i < dim; i++) {
double *line = lu[p[i]];
double s = - line[j];
for(int k = j + 1; k < i; k++) s -= line[k] * lui[k][j];
lui[i][j] = s;
}
lui[j][j] = 1 / lu[p[j]][j];
for(int i = j - 1; i >= 0; i--) {
double *line = lu[p[i]];
double s = 0;
for(int k = i + 1; k <= j; k++) s -= line[k] * lui[k][j];
lui[i][j] = s / line[i];
}
}
}
// norm of PAUiLi-I computed with intervals
{
I_dbl::traits_type::rounding rnd;
typedef boost::numeric::interval_lib::unprotect<I_dbl>::type I;
vector<I> m1(dim);
vector<I> m2(dim);
for(int i = 0; i < dim; i++) {
for(int j = 0; j < dim; j++) m1[j] = 0;
const double *l1 = a[p[i]];
for(int j = 0; j < dim; j++) {
double v = l1[j]; // PA[i,j]
double *l2 = lui[j]; // Ui[j,?]
for(int k = j; k < dim; k++) {
using boost::numeric::interval_lib::mul;
m1[k] += mul<I>(v, l2[k]); // PAUi[i,k]
}
}
for(int j = 0; j < dim; j++) m2[j] = m1[j]; // PAUi[i,j] * Li[j,j]
for(int j = 1; j < dim; j++) {
const I &v = m1[j]; // PAUi[i,j]
double *l2 = lui[j]; // Li[j,?]
for(int k = 0; k < j; k++)
m2[k] += v * l2[k]; // PAUiLi[i,k]
}
m2[i] -= 1; // PAUiLi-I
double ss = 0;
for(int i = 0; i < dim; i++) ss = rnd.add_up(ss, norm(m2[i]));
if (ss >= 1) return 0;
}
}
return sig;
}
int main() {
int dim = 20;
matrix<double> m(dim);
for(int i = 0; i < dim; i++) for(int j = 0; j < dim; j++)
m[i][j] = /*1 / (i-j-0.001)*/ cos(1+i*sin(1 + j)) /*1./(1+i+j)*/;
// compute the sign of the determinant of a "strange" matrix with the two
// algorithms, the first should fail and the second succeed
std::cout << det_sign_algo1(m) << " " << det_sign_algo2(m) << std::endl;
}
@@ -0,0 +1,170 @@
/* Boost example/findroot_demo.cpp
* find zero points of some function by dichotomy
*
* Copyright 2000 Jens Maurer
* Copyright 2002-2003 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*
* The idea and the 2D function are based on RVInterval,
* which contains the following copyright notice:
This file is copyrighted 1996 by Ronald Van Iwaarden.
Permission is hereby granted, without written agreement and
without license or royalty fees, to use, copy, modify, and
distribute this software and its documentation for any
purpose, subject to the following conditions:
The above license notice and this permission notice shall
appear in all copies or substantial portions of this software.
The name "RVInterval" cannot be used for any modified form of
this software that does not originate from the authors.
Nevertheless, the name "RVInterval" may and should be used to
designate the optimization software implemented and described
in this package, even if embedded in any other system, as long
as any portion of this code remains.
The authors specifically disclaim any warranties, including,
but not limited to, the implied warranties of merchantability
and fitness for a particular purpose. The software provided
hereunder is on an "as is" basis, and the authors have no
obligation to provide maintenance, support, updates,
enhancements, or modifications. In no event shall the authors
be liable to any party for direct, indirect, special,
incidental, or consequential damages arising out of the use of
this software and its documentation.
*/
#include <boost/numeric/interval.hpp> // must be first for <limits> workaround
#include <list>
#include <deque>
#include <vector>
#include <fstream>
#include <iostream>
template<class T>
struct test_func2d
{
T operator()(T x, T y) const
{
return sin(x)*cos(y) - exp(x*y)/45.0 * (pow(x+y, 2)+100.0) -
cos(sin(y))*y/4.0;
}
};
template <class T>
struct test_func1d
{
T operator()(T x) const
{
return sin(x)/(x*x+1.0);
}
};
template<class T>
struct test_func1d_2
{
T operator()(T x) const
{
using std::sqrt;
return sqrt(x*x-1.0);
}
};
template<class Function, class I>
void find_zeros(std::ostream & os, Function f, I searchrange)
{
std::list<I> l, done;
l.push_back(searchrange);
while(!l.empty()) {
I range = l.front();
l.pop_front();
I val = f(range);
if (zero_in(val)) {
if(width(range) < 1e-6) {
os << range << '\n';
continue;
}
// there's still a solution hidden somewhere
std::pair<I,I> p = bisect(range);
l.push_back(p.first);
l.push_back(p.second);
}
}
}
template<class T>
std::ostream &operator<<(std::ostream &os, const std::pair<T, T> &x) {
os << "(" << x.first << ", " << x.second << ")";
return os;
}
template<class T, class Policies>
std::ostream &operator<<(std::ostream &os,
const boost::numeric::interval<T, Policies> &x) {
os << "[" << x.lower() << ", " << x.upper() << "]";
return os;
}
static const double epsilon = 5e-3;
template<class Function, class I>
void find_zeros(std::ostream & os, Function f, I rx, I ry)
{
typedef std::pair<I, I> rectangle;
typedef std::deque<rectangle> container;
container l, done;
// l.reserve(50);
l.push_back(std::make_pair(rx, ry));
for(int i = 1; !l.empty(); ++i) {
rectangle rect = l.front();
l.pop_front();
I val = f(rect.first, rect.second);
if (zero_in(val)) {
if(width(rect.first) < epsilon && width(rect.second) < epsilon) {
os << median(rect.first) << " " << median(rect.second) << " "
<< lower(rect.first) << " " << upper(rect.first) << " "
<< lower(rect.second) << " " << upper(rect.second)
<< '\n';
} else {
if(width(rect.first) > width(rect.second)) {
std::pair<I,I> p = bisect(rect.first);
l.push_back(std::make_pair(p.first, rect.second));
l.push_back(std::make_pair(p.second, rect.second));
} else {
std::pair<I,I> p = bisect(rect.second);
l.push_back(std::make_pair(rect.first, p.first));
l.push_back(std::make_pair(rect.first, p.second));
}
}
}
if(i % 10000 == 0)
std::cerr << "\rIteration " << i << ", l.size() = " << l.size();
}
std::cerr << '\n';
}
int main()
{
using namespace boost;
using namespace numeric;
using namespace interval_lib;
typedef interval<double,
policies<save_state<rounded_transc_opp<double> >,
checking_base<double> > > I;
std::cout << "Zero points of sin(x)/(x*x+1)\n";
find_zeros(std::cout, test_func1d<I>(), I(-11, 10));
std::cout << "Zero points of sqrt(x*x-1)\n";
find_zeros(std::cout, test_func1d_2<I>(), I(-5, 6));
std::cout << "Zero points of Van Iwaarden's 2D function\n";
std::ofstream f("func2d.data");
find_zeros(f, test_func2d<I>(), I(-20, 20), I(-20, 20));
std::cout << "Use gnuplot, command 'plot \"func2d.data\" with dots' to plot\n";
}
+47
View File
@@ -0,0 +1,47 @@
/* Boost example/horner.cpp
* example of unprotecting rounding for a whole function computation
*
* Copyright 2002-2003 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/numeric/interval.hpp>
#include <iostream>
// I is an interval class, the polynom is a simple array
template<class I>
I horner(const I& x, const I p[], int n) {
// initialize and restore the rounding mode
typename I::traits_type::rounding rnd;
// define the unprotected version of the interval type
typedef typename boost::numeric::interval_lib::unprotect<I>::type R;
const R& a = x;
R y = p[n - 1];
for(int i = n - 2; i >= 0; i--) {
y = y * a + (const R&)(p[i]);
}
return y;
// restore the rounding mode with the destruction of rnd
}
template<class T, class Policies>
std::ostream &operator<<(std::ostream &os,
const boost::numeric::interval<T, Policies> &x) {
os << "[" << x.lower() << ", " << x.upper() << "]";
return os;
}
int main() {
typedef boost::numeric::interval<double> I;
I p[3] = { -1.0, 0, 1.0 };
I x = 1.0;
std::cout << horner(x, p, 3) << std::endl;
return 0;
}
+172
View File
@@ -0,0 +1,172 @@
/* Boost examples/io.cpp
* show some exampleso of i/o operators
* thanks to all the people who commented on this point, particularly on
* the Boost mailing-list
*
* Copyright 2003 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/numeric/interval.hpp>
#include <boost/io/ios_state.hpp>
#include <cmath>
#include <cassert>
namespace io_std {
template<class T, class Policies, class CharType, class CharTraits>
std::basic_ostream<CharType, CharTraits> &operator<<
(std::basic_ostream<CharType, CharTraits> &stream,
const boost::numeric::interval<T, Policies> &value)
{
if (empty(value)) {
return stream << "[]";
} else {
return stream << '[' << lower(value) << ',' << upper(value) << ']';
}
}
} // namespace io_std
namespace io_sngl {
template<class T, class Policies, class CharType, class CharTraits>
std::basic_ostream<CharType, CharTraits> &operator<<
(std::basic_ostream<CharType, CharTraits> &stream,
const boost::numeric::interval<T, Policies> &value)
{
if (empty(value)) {
return stream << "[]";
} else if (singleton(value)) {
return stream << '[' << lower(value) << ']';
} else {
return stream << '[' << lower(value) << ',' << upper(value) << ']';
}
}
} // namespace io_sngl
namespace io_wdth {
template<class T, class Policies, class CharType, class CharTraits>
std::basic_ostream<CharType, CharTraits> &operator<<
(std::basic_ostream<CharType, CharTraits> &stream,
const boost::numeric::interval<T, Policies> &value)
{
if (empty(value)) {
return stream << "nothing";
} else {
return stream << median(value) << " ± " << width(value) / 2;
}
}
} // namespace io_wdth
namespace io_prec {
template<class T, class Policies, class CharType, class CharTraits>
std::basic_ostream<CharType, CharTraits> &operator<<
(std::basic_ostream<CharType, CharTraits> &stream,
const boost::numeric::interval<T, Policies> &value)
{
if (empty(value)) {
return stream << "nothing";
} else if (singleton(value)) {
boost::io::ios_precision_saver state(stream, std::numeric_limits<T>::digits10);
return stream << lower(value);
} else if (zero_in(value)) {
return stream << "0~";
} else {
const T rel = width(value) / norm(value);
int range = - (int)std::log10(rel);
boost::io::ios_precision_saver state(stream, range);
return stream << median(value);
}
}
} // namespace io_prec
namespace io_wide {
template<class T, class Policies, class CharType, class CharTraits>
std::basic_ostream<CharType, CharTraits> &operator<<
(std::basic_ostream<CharType, CharTraits> &stream,
const boost::numeric::interval<T, Policies> &value)
{
if (empty(value)) {
return stream << "nothing";
} else if (singleton(value)) {
boost::io::ios_precision_saver state(stream, std::numeric_limits<T>::digits10);
return stream << lower(value);
} else if (zero_in(value)) {
return stream << "0~";
} else {
std::streamsize p = stream.precision();
// FIXME poor man's power of 10, only up to 1E-15
p = (p > 15) ? 15 : p - 1;
double eps = 1.0; for(; p > 0; --p) { eps /= 10; }
T eps2 = static_cast<T>(eps / 2) * norm(value);
boost::numeric::interval<T, Policies> r = widen(value, eps2);
return stream << '[' << lower(r) << ',' << upper(r) << ']';
}
}
} // namespace io_wide
template<class T, class Policies, class CharType, class CharTraits> inline
std::basic_istream<CharType, CharTraits> &operator>>
(std::basic_istream<CharType, CharTraits> &stream,
boost::numeric::interval<T, Policies> &value)
{
T l, u;
char c = 0;
stream >> c;
if (c == '[') {
stream >> l >> c;
if (c == ',') stream >> u >> c; else u = l;
if (c != ']') stream.setstate(stream.failbit);
} else {
stream.putback(c);
stream >> l;
u = l;
}
if (stream)
value.assign(l, u);
else
value = boost::numeric::interval<T, Policies>::empty();
return stream;
}
// Test program
#include <iostream>
int main()
{
using namespace boost;
using namespace numeric;
using namespace interval_lib;
typedef interval<double,
policies<rounded_math<double>,
checking_base<double> > > I;
I tab[] = { I::empty(), I(1,1), I(1,2), I(-1,1), I(12.34,12.35),
I(1234.56,1234.57), I(123456.78, 123456.79), I::empty() };
unsigned int len = sizeof(tab) / sizeof(I);
std::cout << "Enter an interval: (it will be the last shown)\n";
std::cin >> tab[len - 1];
for(unsigned int i = 0; i < len; ++i) {
{ using namespace io_std; std::cout << tab[i] << '\n'; }
{ using namespace io_sngl; std::cout << tab[i] << '\n'; }
{ using namespace io_wdth; std::cout << tab[i] << '\n'; }
{ using namespace io_prec; std::cout << tab[i] << '\n'; }
{ using namespace io_wide; std::cout << tab[i] << '\n'; }
std::cout << '\n';
}
}
@@ -0,0 +1,146 @@
/* Boost example/newton-raphson.cpp
* Newton iteration for intervals
*
* Copyright 2003 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/numeric/interval.hpp>
#include <vector>
#include <algorithm>
#include <utility>
#include <iostream>
#include <iomanip>
template <class I> I f(const I& x)
{ return x * (x - 1.) * (x - 2.) * (x - 3.) * (x - 4.); }
template <class I> I f_diff(const I& x)
{ return (((5. * x - 40.) * x + 105.) * x - 100.) * x + 24.; }
static const double max_width = 1e-10;
static const double alpha = 0.75;
using namespace boost;
using namespace numeric;
using namespace interval_lib;
// First method: no empty intervals
typedef interval<double> I1_aux;
typedef unprotect<I1_aux>::type I1;
std::vector<I1> newton_raphson(const I1& xs) {
std::vector<I1> l, res;
I1 vf, vd, x, x1, x2;
l.push_back(xs);
while (!l.empty()) {
x = l.back();
l.pop_back();
bool x2_used;
double xx = median(x);
vf = f<I1>(xx);
vd = f_diff<I1>(x);
if (zero_in(vf) && zero_in(vd)) {
x1 = I1::whole();
x2_used = false;
} else {
x1 = xx - division_part1(vf, vd, x2_used);
if (x2_used) x2 = xx - division_part2(vf, vd);
}
if (overlap(x1, x)) x1 = intersect(x, x1);
else if (x2_used) { x1 = x2; x2_used = false; }
else continue;
if (x2_used) {
if (overlap(x2, x)) x2 = intersect(x, x2);
else x2_used = false;
}
if (x2_used && width(x2) > width(x1)) std::swap(x1, x2);
if (!zero_in(f(x1))) {
if (x2_used) { x1 = x2; x2_used = false; }
else continue;
}
if (width(x1) < max_width) res.push_back(x1);
else if (width(x1) > alpha * width(x)) {
std::pair<I1, I1> p = bisect(x);
if (zero_in(f(p.first))) l.push_back(p.first);
x2 = p.second;
x2_used = true;
} else l.push_back(x1);
if (x2_used && zero_in(f(x2))) {
if (width(x2) < max_width) res.push_back(x2);
else l.push_back(x2);
}
}
return res;
}
// Second method: with empty intervals
typedef change_checking<I1_aux, checking_no_nan<double> >::type I2_aux;
typedef unprotect<I2_aux>::type I2;
std::vector<I2> newton_raphson(const I2& xs) {
std::vector<I2> l, res;
I2 vf, vd, x, x1, x2;
l.push_back(xs);
while (!l.empty()) {
x = l.back();
l.pop_back();
double xx = median(x);
vf = f<I2>(xx);
vd = f_diff<I2>(x);
if (zero_in(vf) && zero_in(vd)) {
x1 = x;
x2 = I2::empty();
} else {
bool x2_used;
x1 = intersect(x, xx - division_part1(vf, vd, x2_used));
x2 = intersect(x, xx - division_part2(vf, vd, x2_used));
}
if (width(x2) > width(x1)) std::swap(x1, x2);
if (empty(x1) || !zero_in(f(x1))) {
if (!empty(x2)) { x1 = x2; x2 = I2::empty(); }
else continue;
}
if (width(x1) < max_width) res.push_back(x1);
else if (width(x1) > alpha * width(x)) {
std::pair<I2, I2> p = bisect(x);
if (zero_in(f(p.first))) l.push_back(p.first);
x2 = p.second;
} else l.push_back(x1);
if (!empty(x2) && zero_in(f(x2))) {
if (width(x2) < max_width) res.push_back(x2);
else l.push_back(x2);
}
}
return res;
}
template<class T, class Policies>
std::ostream &operator<<(std::ostream &os,
const boost::numeric::interval<T, Policies> &x) {
os << "[" << x.lower() << ", " << x.upper() << "]";
return os;
}
int main() {
{
I1_aux::traits_type::rounding rnd;
std::vector<I1> res = newton_raphson(I1(-1, 5.1));
std::cout << "Results: " << std::endl << std::setprecision(12);
for(std::vector<I1>::const_iterator i = res.begin(); i != res.end(); ++i)
std::cout << " " << *i << std::endl;
std::cout << std::endl;
}
{
I2_aux::traits_type::rounding rnd;
std::vector<I2> res = newton_raphson(I2(-1, 5.1));
std::cout << "Results: " << std::endl << std::setprecision(12);
for(std::vector<I2>::const_iterator i = res.begin(); i != res.end(); ++i)
std::cout << " " << *i << std::endl;
std::cout << std::endl;
}
}
@@ -0,0 +1,43 @@
/* Boost example/rational.cpp
* example program of how to use interval< rational<> >
*
* Copyright 2002-2003 Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
// it would have been enough to only include:
// <boost/numeric/interval.hpp>
// but it's a bit overkill to include processor intrinsics
// and transcendental functions, so we do it by ourselves
#include <boost/numeric/interval/interval.hpp> // base class
#include <boost/numeric/interval/rounded_arith.hpp> // default arithmetic rounding policy
#include <boost/numeric/interval/checking.hpp> // default checking policy
#include <boost/numeric/interval/arith.hpp> // += *= -= etc
#include <boost/numeric/interval/policies.hpp> // default policy
#include <boost/rational.hpp>
#include <iostream>
typedef boost::rational<int> Rat;
typedef boost::numeric::interval<Rat> Interval;
std::ostream& operator<<(std::ostream& os, const Interval& r) {
os << "[" << r.lower() << "," << r.upper() << "]";
return os;
}
int main() {
Rat p(2, 3), q(3, 4);
Interval z(4, 5);
Interval a(p, q);
a += z;
z *= q;
a -= p;
a /= q;
std::cout << z << std::endl;
std::cout << a << std::endl;
}
+90
View File
@@ -0,0 +1,90 @@
/* Boost example/transc.cpp
* how to use an external library (GMP/MPFR in this case) in order to
* get correct transcendental functions on intervals
*
* Copyright 2003 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/numeric/interval.hpp>
//extern "C" {
#include <gmp.h>
#include <mpfr.h>
//}
#include <iostream>
struct full_rounding:
boost::numeric::interval_lib::rounded_arith_opp<double>
{
private:
typedef int mpfr_func(mpfr_t, const __mpfr_struct*, mp_rnd_t);
double invoke_mpfr(double x, mpfr_func f, mp_rnd_t r) {
mpfr_t xx;
mpfr_init_set_d(xx, x, GMP_RNDN);
f(xx, xx, r);
double res = mpfr_get_d(xx, r);
mpfr_clear(xx);
return res;
}
public:
# define GENR_FUNC(name) \
double name##_down(double x) { return invoke_mpfr(x, mpfr_##name, GMP_RNDD); } \
double name##_up (double x) { return invoke_mpfr(x, mpfr_##name, GMP_RNDU); }
GENR_FUNC(exp)
GENR_FUNC(log)
GENR_FUNC(sin)
GENR_FUNC(cos)
GENR_FUNC(tan)
GENR_FUNC(asin)
GENR_FUNC(acos)
GENR_FUNC(atan)
GENR_FUNC(sinh)
GENR_FUNC(cosh)
GENR_FUNC(tanh)
GENR_FUNC(asinh)
GENR_FUNC(acosh)
GENR_FUNC(atanh)
};
namespace dummy {
using namespace boost;
using namespace numeric;
using namespace interval_lib;
typedef save_state<full_rounding> R;
typedef checking_strict<double> P;
typedef interval<double, policies<R, P> > I;
};
typedef dummy::I I;
template<class os_t>
os_t& operator<<(os_t &os, const I &a) {
os << '[' << a.lower() << ',' << a.upper() << ']';
return os;
}
int main() {
I x(0.5, 2.5);
std::cout << "x = " << x << std::endl;
std::cout.precision(16);
# define GENR_TEST(name) \
std::cout << #name "(x) = " << name(x) << std::endl
GENR_TEST(exp);
GENR_TEST(log);
GENR_TEST(sin);
GENR_TEST(cos);
GENR_TEST(tan);
GENR_TEST(asin);
GENR_TEST(acos);
GENR_TEST(atan);
GENR_TEST(sinh);
GENR_TEST(cosh);
GENR_TEST(tanh);
GENR_TEST(asinh);
GENR_TEST(acosh);
GENR_TEST(atanh);
return 0;
}