diff options
Diffstat (limited to 'boost/math/tools/test_data.hpp')
-rw-r--r-- | boost/math/tools/test_data.hpp | 767 |
1 files changed, 0 insertions, 767 deletions
diff --git a/boost/math/tools/test_data.hpp b/boost/math/tools/test_data.hpp deleted file mode 100644 index 56bae051b4..0000000000 --- a/boost/math/tools/test_data.hpp +++ /dev/null @@ -1,767 +0,0 @@ -// (C) Copyright John Maddock 2006. -// 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) - -#ifndef BOOST_MATH_TOOLS_TEST_DATA_HPP -#define BOOST_MATH_TOOLS_TEST_DATA_HPP - -#ifdef _MSC_VER -#pragma once -#endif - -#include <boost/math/tools/config.hpp> -#include <boost/assert.hpp> -#ifdef BOOST_MSVC -# pragma warning(push) -# pragma warning(disable: 4127 4701 4512) -# pragma warning(disable: 4130) // '==' : logical operation on address of string constant. -#endif -#include <boost/algorithm/string/trim.hpp> -#include <boost/lexical_cast.hpp> -#ifdef BOOST_MSVC -#pragma warning(pop) -#endif -#include <boost/type_traits/is_floating_point.hpp> -#include <boost/type_traits/is_convertible.hpp> -#include <boost/type_traits/integral_constant.hpp> -#include <boost/tr1/random.hpp> -#include <boost/math/tools/tuple.hpp> -#include <boost/math/tools/real_cast.hpp> - -#include <set> -#include <vector> -#include <iostream> - -#ifdef BOOST_MSVC -# pragma warning(push) -# pragma warning(disable: 4130) // '==' : logical operation on address of string constant. -// Used as a warning with BOOST_ASSERT -#endif - -namespace boost{ namespace math{ namespace tools{ - -enum parameter_type -{ - random_in_range = 0, - periodic_in_range = 1, - power_series = 2, - dummy_param = 0x80 -}; - -parameter_type operator | (parameter_type a, parameter_type b) -{ - return static_cast<parameter_type>((int)a|(int)b); -} -parameter_type& operator |= (parameter_type& a, parameter_type b) -{ - a = static_cast<parameter_type>(a|b); - return a; -} - -// -// If type == random_in_range then -// z1 and r2 are the endpoints of the half open range and n1 is the number of points. -// -// If type == periodic_in_range then -// z1 and r2 are the endpoints of the half open range and n1 is the number of points. -// -// If type == power_series then -// n1 and n2 are the endpoints of the exponents (closed range) and z1 is the basis. -// -// If type & dummy_param then this data is ignored and not stored in the output, it -// is passed to the generator function however which can do with it as it sees fit. -// -template <class T> -struct parameter_info -{ - parameter_type type; - T z1, z2; - int n1, n2; -}; - -template <class T> -inline parameter_info<T> make_random_param(T start_range, T end_range, int n_points) -{ - parameter_info<T> result = { random_in_range, start_range, end_range, n_points, 0 }; - return result; -} - -template <class T> -inline parameter_info<T> make_periodic_param(T start_range, T end_range, int n_points) -{ - parameter_info<T> result = { periodic_in_range, start_range, end_range, n_points, 0 }; - return result; -} - -template <class T> -inline parameter_info<T> make_power_param(T basis, int start_exponent, int end_exponent) -{ - parameter_info<T> result = { power_series, basis, 0, start_exponent, end_exponent }; - return result; -} - -namespace detail{ - -template <class Seq, class Item, int N> -inline void unpack_and_append_tuple(Seq& s, - const Item& data, - const boost::integral_constant<int, N>&, - const boost::false_type&) -{ - // termimation condition nothing to do here -} - -template <class Seq, class Item, int N> -inline void unpack_and_append_tuple(Seq& s, - const Item& data, - const boost::integral_constant<int, N>&, - const boost::true_type&) -{ - // extract the N'th element, append, and recurse: - typedef typename Seq::value_type value_type; - value_type val = boost::math::get<N>(data); - s.push_back(val); - - typedef boost::integral_constant<int, N+1> next_value; - typedef boost::integral_constant<bool, (boost::math::tuple_size<Item>::value > N+1)> terminate; - - unpack_and_append_tuple(s, data, next_value(), terminate()); -} - -template <class Seq, class Item> -inline void unpack_and_append(Seq& s, const Item& data, const boost::true_type&) -{ - s.push_back(data); -} - -template <class Seq, class Item> -inline void unpack_and_append(Seq& s, const Item& data, const boost::false_type&) -{ - // Item had better be a tuple-like type or we've had it!!!! - typedef boost::integral_constant<int, 0> next_value; - typedef boost::integral_constant<bool, (boost::math::tuple_size<Item>::value > 0)> terminate; - - unpack_and_append_tuple(s, data, next_value(), terminate()); -} - -template <class Seq, class Item> -inline void unpack_and_append(Seq& s, const Item& data) -{ - typedef typename Seq::value_type value_type; - unpack_and_append(s, data, ::boost::is_convertible<Item, value_type>()); -} - -} // detail - -template <class T> -class test_data -{ -public: - typedef std::vector<T> row_type; - typedef row_type value_type; -private: - typedef std::set<row_type> container_type; -public: - typedef typename container_type::reference reference; - typedef typename container_type::const_reference const_reference; - typedef typename container_type::iterator iterator; - typedef typename container_type::const_iterator const_iterator; - typedef typename container_type::difference_type difference_type; - typedef typename container_type::size_type size_type; - - // creation: - test_data(){} - template <class F> - test_data(F func, const parameter_info<T>& arg1) - { - insert(func, arg1); - } - - // insertion: - template <class F> - test_data& insert(F func, const parameter_info<T>& arg1) - { - // generate data for single argument functor F - - typedef typename std::set<T>::const_iterator it_type; - - std::set<T> points; - create_test_points(points, arg1); - it_type a = points.begin(); - it_type b = points.end(); - row_type row; - while(a != b) - { - if((arg1.type & dummy_param) == 0) - row.push_back(*a); - try{ - // domain_error exceptions from func are swallowed - // and this data point is ignored: - boost::math::tools::detail::unpack_and_append(row, func(*a)); - m_data.insert(row); - } - catch(const std::domain_error&){} - row.clear(); - ++a; - } - return *this; - } - - template <class F> - test_data& insert(F func, const parameter_info<T>& arg1, const parameter_info<T>& arg2) - { - // generate data for 2-argument functor F - - typedef typename std::set<T>::const_iterator it_type; - - std::set<T> points1, points2; - create_test_points(points1, arg1); - create_test_points(points2, arg2); - it_type a = points1.begin(); - it_type b = points1.end(); - row_type row; - while(a != b) - { - it_type c = points2.begin(); - it_type d = points2.end(); - while(c != d) - { - if((arg1.type & dummy_param) == 0) - row.push_back(*a); - if((arg2.type & dummy_param) == 0) - row.push_back(*c); - try{ - // domain_error exceptions from func are swallowed - // and this data point is ignored: - detail::unpack_and_append(row, func(*a, *c)); - m_data.insert(row); - } - catch(const std::domain_error&){} - row.clear(); - ++c; - } - ++a; - } - return *this; - } - - template <class F> - test_data& insert(F func, const parameter_info<T>& arg1, const parameter_info<T>& arg2, const parameter_info<T>& arg3) - { - // generate data for 3-argument functor F - - typedef typename std::set<T>::const_iterator it_type; - - std::set<T> points1, points2, points3; - create_test_points(points1, arg1); - create_test_points(points2, arg2); - create_test_points(points3, arg3); - it_type a = points1.begin(); - it_type b = points1.end(); - row_type row; - while(a != b) - { - it_type c = points2.begin(); - it_type d = points2.end(); - while(c != d) - { - it_type e = points3.begin(); - it_type f = points3.end(); - while(e != f) - { - if((arg1.type & dummy_param) == 0) - row.push_back(*a); - if((arg2.type & dummy_param) == 0) - row.push_back(*c); - if((arg3.type & dummy_param) == 0) - row.push_back(*e); - try{ - // domain_error exceptions from func are swallowed - // and this data point is ignored: - detail::unpack_and_append(row, func(*a, *c, *e)); - m_data.insert(row); - } - catch(const std::domain_error&){} - row.clear(); - ++e; - } - ++c; - } - ++a; - } - return *this; - } - - void clear(){ m_data.clear(); } - - // access: - iterator begin() { return m_data.begin(); } - iterator end() { return m_data.end(); } - const_iterator begin()const { return m_data.begin(); } - const_iterator end()const { return m_data.end(); } - bool operator==(const test_data& d)const{ return m_data == d.m_data; } - bool operator!=(const test_data& d)const{ return m_data != d.m_data; } - void swap(test_data& other){ m_data.swap(other.m_data); } - size_type size()const{ return m_data.size(); } - size_type max_size()const{ return m_data.max_size(); } - bool empty()const{ return m_data.empty(); } - - bool operator < (const test_data& dat)const{ return m_data < dat.m_data; } - bool operator <= (const test_data& dat)const{ return m_data <= dat.m_data; } - bool operator > (const test_data& dat)const{ return m_data > dat.m_data; } - bool operator >= (const test_data& dat)const{ return m_data >= dat.m_data; } - -private: - void create_test_points(std::set<T>& points, const parameter_info<T>& arg1); - std::set<row_type> m_data; - - static float extern_val; - static float truncate_to_float(float const * pf); - static float truncate_to_float(float c){ return truncate_to_float(&c); } -}; - -// -// This code exists to bemuse the compiler's optimizer and force a -// truncation to float-precision only: -// -template <class T> -inline float test_data<T>::truncate_to_float(float const * pf) -{ - BOOST_MATH_STD_USING - int expon; - float f = floor(ldexp(frexp(*pf, &expon), 22)); - f = ldexp(f, expon - 22); - return f; - - //extern_val = *pf; - //return *pf; -} - -template <class T> -float test_data<T>::extern_val = 0; - -template <class T> -void test_data<T>::create_test_points(std::set<T>& points, const parameter_info<T>& arg1) -{ - BOOST_MATH_STD_USING - // - // Generate a set of test points as requested, try and generate points - // at only float precision: otherwise when testing float versions of functions - // there will be a rounding error in our input values which throws off the results - // (Garbage in garbage out etc). - // - switch(arg1.type & 0x7F) - { - case random_in_range: - { - BOOST_ASSERT(arg1.z1 < arg1.z2); - BOOST_ASSERT(arg1.n1 > 0); - typedef float random_type; - - std::tr1::mt19937 rnd; - std::tr1::uniform_real<random_type> ur_a(real_cast<random_type>(arg1.z1), real_cast<random_type>(arg1.z2)); - std::tr1::variate_generator<std::tr1::mt19937, std::tr1::uniform_real<random_type> > gen(rnd, ur_a); - - for(int i = 0; i < arg1.n1; ++i) - { - random_type r = gen(); - points.insert(truncate_to_float(r)); - } - } - break; - case periodic_in_range: - { - BOOST_ASSERT(arg1.z1 < arg1.z2); - BOOST_ASSERT(arg1.n1 > 0); - float interval = real_cast<float>((arg1.z2 - arg1.z1) / arg1.n1); - T val = arg1.z1; - while(val < arg1.z2) - { - points.insert(truncate_to_float(real_cast<float>(val))); - val += interval; - } - } - break; - case power_series: - { - BOOST_ASSERT(arg1.n1 < arg1.n2); - - typedef float random_type; - typedef typename boost::mpl::if_< - ::boost::is_floating_point<T>, - T, long double>::type power_type; - - std::tr1::mt19937 rnd; - std::tr1::uniform_real<random_type> ur_a(1.0, 2.0); - std::tr1::variate_generator<std::tr1::mt19937, std::tr1::uniform_real<random_type> > gen(rnd, ur_a); - - for(int power = arg1.n1; power <= arg1.n2; ++power) - { - random_type r = gen(); - power_type p = ldexp(static_cast<power_type>(r), power); - points.insert(truncate_to_float(real_cast<float>(arg1.z1 + p))); - } - } - break; - default: - BOOST_ASSERT(0 == "Invalid parameter_info object"); - // Assert will fail if get here. - // Triggers warning 4130) // '==' : logical operation on address of string constant. - } -} - -// -// Prompt a user for information on a parameter range: -// -template <class T> -bool get_user_parameter_info(parameter_info<T>& info, const char* param_name) -{ -#ifdef BOOST_MSVC -# pragma warning(push) -# pragma warning(disable: 4127) -#endif - std::string line; - do{ - std::cout << "What kind of distribution do you require for parameter " << param_name << "?\n" - "Choices are:\n" - " r Random values in a half open range\n" - " p Evenly spaced periodic values in a half open range\n" - " e Exponential power series at a particular point: a + 2^b for some range of b\n" - "[Default=r]"; - - std::getline(std::cin, line); - boost::algorithm::trim(line); - - if(line == "r") - { - info.type = random_in_range; - break; - } - else if(line == "p") - { - info.type = periodic_in_range; - break; - } - else if(line == "e") - { - info.type = power_series; - break; - } - else if(line == "") - { - info.type = random_in_range; - break; - } - // - // Ooops, not a valid input.... - // - std::cout << "Sorry don't recognise \"" << line << "\" as a valid input\n" - "do you want to try again [y/n]?"; - std::getline(std::cin, line); - boost::algorithm::trim(line); - if(line == "n") - return false; - else if(line == "y") - continue; - std::cout << "Sorry don't recognise that either, giving up...\n\n"; - return false; - }while(true); - - switch(info.type & ~dummy_param) - { - case random_in_range: - case periodic_in_range: - // get start and end points of range: - do{ - std::cout << "Data will be in the half open range a <= x < b,\n" - "enter value for the start point fo the range [default=0]:"; - std::getline(std::cin, line); - boost::algorithm::trim(line); - if(line == "") - { - info.z1 = 0; - break; - } - try{ - info.z1 = boost::lexical_cast<T>(line); - break; - } - catch(const boost::bad_lexical_cast&) - { - std::cout << "Sorry, that was not valid input, try again [y/n]?"; - std::getline(std::cin, line); - boost::algorithm::trim(line); - if(line == "y") - continue; - if(line == "n") - return false; - std::cout << "Sorry don't recognise that either, giving up...\n\n"; - return false; - } - }while(true); - do{ - std::cout << "Enter value for the end point fo the range [default=1]:"; - std::getline(std::cin, line); - boost::algorithm::trim(line); - if(line == "") - { - info.z2 = 1; - } - else - { - try - { - info.z2 = boost::lexical_cast<T>(line); - } - catch(const boost::bad_lexical_cast&) - { - std::cout << "Sorry, that was not valid input, try again [y/n]?"; - std::getline(std::cin, line); - boost::algorithm::trim(line); - if(line == "y") - continue; - if(line == "n") - return false; - std::cout << "Sorry don't recognise that either, giving up...\n\n"; - return false; - } - } - if(info.z1 >= info.z2) - { - std::cout << "The end point of the range was <= the start point\n" - "try a different value for the endpoint [y/n]?"; - std::getline(std::cin, line); - boost::algorithm::trim(line); - if(line == "y") - continue; - if(line == "n") - return false; - std::cout << "Sorry don't recognise that either, giving up...\n\n"; - return false; - } - break; - }while(true); - do{ - // get the number of points: - std::cout << "How many data points do you want?"; - std::getline(std::cin, line); - boost::algorithm::trim(line); - try{ - info.n1 = boost::lexical_cast<int>(line); - info.n2 = 0; - if(info.n1 <= 0) - { - std::cout << "The number of points should be > 0\n" - "try again [y/n]?"; - std::getline(std::cin, line); - boost::algorithm::trim(line); - if(line == "y") - continue; - if(line == "n") - return false; - std::cout << "Sorry don't recognise that either, giving up...\n\n"; - return false; - } - break; - } - catch(const boost::bad_lexical_cast&) - { - std::cout << "Sorry, that was not valid input, try again [y/n]?"; - std::getline(std::cin, line); - boost::algorithm::trim(line); - if(line == "y") - continue; - if(line == "n") - return false; - std::cout << "Sorry don't recognise that either, giving up...\n\n"; - return false; - } - }while(true); - break; - case power_series: - // get start and end points of range: - info.z2 = 0; - do{ - std::cout << "Data will be in the form a + r*2^b\n" - "for random value r,\n" - "enter value for the point a [default=0]:"; - std::getline(std::cin, line); - boost::algorithm::trim(line); - if(line == "") - { - info.z1 = 0; - break; - } - try{ - info.z1 = boost::lexical_cast<T>(line); - break; - } - catch(const boost::bad_lexical_cast&) - { - std::cout << "Sorry, that was not valid input, try again [y/n]?"; - std::getline(std::cin, line); - boost::algorithm::trim(line); - if(line == "y") - continue; - if(line == "n") - return false; - std::cout << "Sorry don't recognise that either, giving up...\n\n"; - return false; - } - }while(true); - - do{ - std::cout << "Data will be in the form a + r*2^b\n" - "for random value r,\n" - "enter value for the starting exponent b:"; - std::getline(std::cin, line); - boost::algorithm::trim(line); - try{ - info.n1 = boost::lexical_cast<int>(line); - break; - } - catch(const boost::bad_lexical_cast&) - { - std::cout << "Sorry, that was not valid input, try again [y/n]?"; - std::getline(std::cin, line); - boost::algorithm::trim(line); - if(line == "y") - continue; - if(line == "n") - return false; - std::cout << "Sorry don't recognise that either, giving up...\n\n"; - return false; - } - }while(true); - - do{ - std::cout << "Data will be in the form a + r*2^b\n" - "for random value r,\n" - "enter value for the ending exponent b:"; - std::getline(std::cin, line); - boost::algorithm::trim(line); - try{ - info.n2 = boost::lexical_cast<int>(line); - break; - } - catch(const boost::bad_lexical_cast&) - { - std::cout << "Sorry, that was not valid input, try again [y/n]?"; - std::getline(std::cin, line); - boost::algorithm::trim(line); - if(line == "y") - continue; - if(line == "n") - return false; - std::cout << "Sorry don't recognise that either, giving up...\n\n"; - return false; - } - }while(true); - - break; - default: - BOOST_ASSERT(0); // should never get here!! - } - - return true; -#ifdef BOOST_MSVC -# pragma warning(pop) -#endif -} - -template <class charT, class traits, class T> -inline std::basic_ostream<charT, traits>& write_csv(std::basic_ostream<charT, traits>& os, - const test_data<T>& data) -{ - const charT defarg[] = { ',', ' ', '\0' }; - return write_csv(os, data, defarg); -} - -template <class charT, class traits, class T> -std::basic_ostream<charT, traits>& write_csv(std::basic_ostream<charT, traits>& os, - const test_data<T>& data, - const charT* separator) -{ - typedef typename test_data<T>::const_iterator it_type; - typedef typename test_data<T>::value_type value_type; - typedef typename value_type::const_iterator value_type_iterator; - it_type a, b; - a = data.begin(); - b = data.end(); - while(a != b) - { - value_type_iterator x, y; - bool sep = false; - x = a->begin(); - y = a->end(); - while(x != y) - { - if(sep) - os << separator; - os << *x; - sep = true; - ++x; - } - os << std::endl; - ++a; - } - return os; -} - -template <class T> -std::ostream& write_code(std::ostream& os, - const test_data<T>& data, - const char* name) -{ - typedef typename test_data<T>::const_iterator it_type; - typedef typename test_data<T>::value_type value_type; - typedef typename value_type::const_iterator value_type_iterator; - - BOOST_ASSERT(os.good()); - - it_type a, b; - a = data.begin(); - b = data.end(); - if(a == b) - return os; - - os << "#ifndef SC_\n# define SC_(x) static_cast<T>(BOOST_JOIN(x, L))\n#endif\n" - " static const boost::array<boost::array<T, " - << a->size() << ">, " << data.size() << "> " << name << " = {{\n"; - - while(a != b) - { - if(a != data.begin()) - os << ", \n"; - - value_type_iterator x, y; - x = a->begin(); - y = a->end(); - os << " { "; - while(x != y) - { - if(x != a->begin()) - os << ", "; - os << "SC_(" << *x << ")"; - ++x; - } - os << " }"; - ++a; - } - os << "\n }};\n//#undef SC_\n\n"; - return os; -} - -} // namespace tools -} // namespace math -} // namespace boost - -#ifdef BOOST_MSVC -#pragma warning(pop) -#endif - - -#endif // BOOST_MATH_TOOLS_TEST_DATA_HPP - - |