Files
multiprecision/test/test_rational_io.cpp
John Maddock 8433c69175 Disable expression templates for fixed precision types.
Restrict integer functions to integer types.
Improve Miller Rabin performance by filtering out small primes etc.
Improve Miller Rabin tests.
Change mp_int to tom_int to avoid conflict with global ::mp_Int type.

[SVN r77471]
2012-03-22 10:29:30 +00:00

139 lines
3.5 KiB
C++

// Copyright John Maddock 2011.
// Use, modification and distribution are subject to 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)
#ifdef _MSC_VER
# define _SCL_SECURE_NO_WARNINGS
#endif
#if !defined(TEST_MPQ) && !defined(TEST_TOMMATH)
# define TEST_MPQ
# define TEST_TOMMATH
#ifdef _MSC_VER
#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!")
#endif
#ifdef __GNUC__
#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!"
#endif
#endif
#if defined(TEST_MPQ)
#include <boost/multiprecision/gmp.hpp>
#endif
#if defined(TEST_TOMMATH)
#include <boost/multiprecision/tommath.hpp>
#endif
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int.hpp>
#include <boost/rational.hpp>
#include <boost/multiprecision/rational_adapter.hpp>
#include "test.hpp"
#include <iostream>
#include <iomanip>
template <class T>
T generate_random()
{
static boost::random::uniform_int_distribution<unsigned> ui(0, 20);
static boost::random::mt19937 gen;
T val = T(gen());
unsigned lim = ui(gen);
for(unsigned i = 0; i < lim; ++i)
{
val *= (gen.max)();
val += gen();
}
T denom = T(gen());
lim = ui(gen);
for(unsigned i = 0; i < lim; ++i)
{
denom *= (gen.max)();
denom += gen();
}
return val / denom;
}
template <class T>
void do_round_trip(const T& val, std::ios_base::fmtflags f, const boost::mpl::true_&)
{
std::stringstream ss;
#ifndef BOOST_NO_NUMERIC_LIMITS_LOWEST
ss << std::setprecision(std::numeric_limits<T>::max_digits10);
#else
ss << std::setprecision(std::numeric_limits<T>::digits10 + 5);
#endif
ss.flags(f);
ss << val;
T new_val = ss.str();
BOOST_CHECK_EQUAL(new_val, val);
new_val = val.str(0, f);
BOOST_CHECK_EQUAL(new_val, val);
}
template <class T>
void do_round_trip(const T& val, std::ios_base::fmtflags f, const boost::mpl::false_&)
{
std::stringstream ss;
ss << std::setprecision(std::numeric_limits<T>::digits10 + 4);
ss.flags(f);
ss << val;
T new_val;
ss >> new_val;
BOOST_CHECK_EQUAL(new_val, val);
}
template <class T>
struct is_mp_number : public boost::mpl::false_{};
template <class T>
struct is_mp_number<boost::multiprecision::mp_number<T> > : public boost::mpl::true_{};
template <class T>
void do_round_trip(const T& val, std::ios_base::fmtflags f)
{
do_round_trip(val, f, is_mp_number<T>());
}
template <class T>
void do_round_trip(const T& val)
{
do_round_trip(val, std::ios_base::fmtflags(0));
if(val >= 0)
{
do_round_trip(val, std::ios_base::fmtflags(std::ios_base::showbase|std::ios_base::hex));
do_round_trip(val, std::ios_base::fmtflags(std::ios_base::showbase|std::ios_base::oct));
}
}
template <class T>
void test_round_trip()
{
for(unsigned i = 0; i < 1000; ++i)
{
T val = generate_random<T>();
do_round_trip(val);
do_round_trip(T(-val));
}
}
int main()
{
#ifdef TEST_MPQ
test_round_trip<boost::multiprecision::mpq_rational>();
test_round_trip<boost::rational<boost::multiprecision::mpz_int> >();
test_round_trip<boost::multiprecision::mp_number<boost::multiprecision::rational_adapter<boost::multiprecision::gmp_int> > >();
#endif
#ifdef TEST_TOMMATH
test_round_trip<boost::rational<boost::multiprecision::tom_int> >();
test_round_trip<boost::multiprecision::tom_rational >();
#endif
return boost::report_errors();
}