Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r76279 - in sandbox/big_number: boost/multiprecision libs/multiprecision/performance
From: john_at_[hidden]
Date: 2012-01-02 12:45:50


Author: johnmaddock
Date: 2012-01-02 12:45:49 EST (Mon, 02 Jan 2012)
New Revision: 76279
URL: http://svn.boost.org/trac/boost/changeset/76279

Log:
Add initial performance test program for testing basic arithmetic.
Fix header include on packed_cpp_int.hpp and add numeric_limits min/max values.
Added:
   sandbox/big_number/libs/multiprecision/performance/performance_test.cpp (contents, props changed)
Text files modified:
   sandbox/big_number/boost/multiprecision/packed_cpp_int.hpp | 50 +++++++++++++++++++++++++++++++--------
   1 files changed, 39 insertions(+), 11 deletions(-)

Modified: sandbox/big_number/boost/multiprecision/packed_cpp_int.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/packed_cpp_int.hpp (original)
+++ sandbox/big_number/boost/multiprecision/packed_cpp_int.hpp 2012-01-02 12:45:49 EST (Mon, 02 Jan 2012)
@@ -3,8 +3,8 @@
 // Software License, Version 1.0. (See accompanying file
 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
 
-#ifndef BOOST_MATH_RATIONAL_ADAPTER_HPP
-#define BOOST_MATH_RATIONAL_ADAPTER_HPP
+#ifndef BOOST_MP_PACKED_INT_HPP
+#define BOOST_MP_PACKED_INT_HPP
 
 #include <iostream>
 #include <iomanip>
@@ -838,6 +838,17 @@
 class numeric_limits<boost::multiprecision::mp_number<boost::multiprecision::packed_cpp_int<Bits, Signed> > >
 {
    typedef boost::multiprecision::mp_number<boost::multiprecision::packed_cpp_int<Bits, Signed> > number_type;
+
+ struct initializer
+ {
+ initializer()
+ {
+ (std::numeric_limits<boost::multiprecision::mp_number<boost::multiprecision::packed_cpp_int<Bits, Signed> > >::min)();
+ (std::numeric_limits<boost::multiprecision::mp_number<boost::multiprecision::packed_cpp_int<Bits, Signed> > >::max)();
+ }
+ void do_nothing()const{}
+ };
+ static const initializer init;
 public:
    BOOST_STATIC_CONSTEXPR bool is_specialized = true;
    //
@@ -845,12 +856,26 @@
    // to zero:
    //
    BOOST_STATIC_CONSTEXPR number_type (min)() BOOST_MP_NOEXCEPT
- {
- return number_type();
+ {
+ static bool init = false;
+ static number_type val;
+ if(!init)
+ {
+ init = true;
+ val = Signed ? number_type(1) << Bits - 1 : 0;
+ }
+ return val;
    }
    BOOST_STATIC_CONSTEXPR number_type (max)() BOOST_MP_NOEXCEPT
    {
- return number_type();
+ static bool init = false;
+ static number_type val;
+ if(!init)
+ {
+ init = true;
+ val = Signed ? number_type(~(number_type(1) << Bits - 1)) : number_type(~number_type(0));
+ }
+ return val;
    }
    BOOST_STATIC_CONSTEXPR number_type lowest() BOOST_MP_NOEXCEPT { return (min)(); }
    BOOST_STATIC_CONSTEXPR int digits = Bits;
@@ -860,8 +885,8 @@
    BOOST_STATIC_CONSTEXPR bool is_integer = true;
    BOOST_STATIC_CONSTEXPR bool is_exact = true;
    BOOST_STATIC_CONSTEXPR int radix = 2;
- BOOST_STATIC_CONSTEXPR number_type epsilon() BOOST_MP_NOEXCEPT { return number_type(); }
- BOOST_STATIC_CONSTEXPR number_type round_error() BOOST_MP_NOEXCEPT { return number_type(); }
+ BOOST_STATIC_CONSTEXPR number_type epsilon() BOOST_MP_NOEXCEPT { return 0; }
+ BOOST_STATIC_CONSTEXPR number_type round_error() BOOST_MP_NOEXCEPT { return 0; }
    BOOST_STATIC_CONSTEXPR int min_exponent = 0;
    BOOST_STATIC_CONSTEXPR int min_exponent10 = 0;
    BOOST_STATIC_CONSTEXPR int max_exponent = 0;
@@ -871,10 +896,10 @@
    BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false;
    BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent;
    BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false;
- BOOST_STATIC_CONSTEXPR number_type infinity() BOOST_MP_NOEXCEPT { return number_type(); }
- BOOST_STATIC_CONSTEXPR number_type quiet_NaN() BOOST_MP_NOEXCEPT { return number_type(); }
- BOOST_STATIC_CONSTEXPR number_type signaling_NaN() BOOST_MP_NOEXCEPT { return number_type(); }
- BOOST_STATIC_CONSTEXPR number_type denorm_min() BOOST_MP_NOEXCEPT { return number_type(); }
+ BOOST_STATIC_CONSTEXPR number_type infinity() BOOST_MP_NOEXCEPT { return 0; }
+ BOOST_STATIC_CONSTEXPR number_type quiet_NaN() BOOST_MP_NOEXCEPT { return 0; }
+ BOOST_STATIC_CONSTEXPR number_type signaling_NaN() BOOST_MP_NOEXCEPT { return 0; }
+ BOOST_STATIC_CONSTEXPR number_type denorm_min() BOOST_MP_NOEXCEPT { return 0; }
    BOOST_STATIC_CONSTEXPR bool is_iec559 = false;
    BOOST_STATIC_CONSTEXPR bool is_bounded = true;
    BOOST_STATIC_CONSTEXPR bool is_modulo = true;
@@ -883,6 +908,9 @@
    BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero;
 };
 
+template <unsigned Bits, bool Signed>
+typename numeric_limits<boost::multiprecision::mp_number<boost::multiprecision::packed_cpp_int<Bits, Signed> > >::initializer
+ typename numeric_limits<boost::multiprecision::mp_number<boost::multiprecision::packed_cpp_int<Bits, Signed> > >::init;
 }
 
 #endif

Added: sandbox/big_number/libs/multiprecision/performance/performance_test.cpp
==============================================================================
--- (empty file)
+++ sandbox/big_number/libs/multiprecision/performance/performance_test.cpp 2012-01-02 12:45:49 EST (Mon, 02 Jan 2012)
@@ -0,0 +1,347 @@
+///////////////////////////////////////////////////////////////
+// Copyright 2011 John Maddock. 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_
+
+#define BOOST_CHRONO_HEADER_ONLY
+
+#ifdef _MSC_VER
+# define _SCL_SECURE_NO_WARNINGS
+#endif
+
+#if !defined(TEST_MPF) && !defined(TEST_MPZ) && \
+ !defined(TEST_CPP_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPQ) \
+ && !defined(TEST_TOMMATH) && !defined(TEST_TOMMATH_BOOST_RATIONAL) && !defined(TEST_MPZ_BOOST_RATIONAL)\
+ && !defined(TEST_PACKED_INT)
+# define TEST_MPF
+# define TEST_MPZ
+# define TEST_MPFR
+# define TEST_CPP_FLOAT
+# define TEST_MPQ
+# define TEST_TOMMATH
+# define TEST_PACKED_INT
+
+#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_MPF) || defined(TEST_MPZ) || defined(TEST_MPQ) || defined(TEST_MPZ_BOOST_RATIONAL)
+#include <boost/multiprecision/gmp.hpp>
+#include <boost/multiprecision/rational_adapter.hpp>
+#endif
+#ifdef TEST_CPP_FLOAT
+#include <boost/multiprecision/cpp_float.hpp>
+#endif
+#if defined(TEST_MPFR)
+#include <boost/multiprecision/mpfr.hpp>
+#endif
+#if defined(TEST_TOMMATH) || defined(TEST_TOMMATH_BOOST_RATIONAL)
+#include <boost/multiprecision/tommath.hpp>
+#include <boost/multiprecision/rational_adapter.hpp>
+#endif
+#if defined(TEST_PACKED_INT)
+#include <boost/multiprecision/packed_cpp_int.hpp>
+#endif
+
+#include <boost/chrono.hpp>
+#include <vector>
+#include <boost/random/mersenne_twister.hpp>
+#include <boost/random/uniform_int.hpp>
+
+template <class Clock>
+struct stopwatch
+{
+ typedef typename Clock::duration duration;
+ stopwatch()
+ {
+ m_start = Clock::now();
+ }
+ duration elapsed()
+ {
+ return Clock::now() - m_start;
+ }
+ void reset()
+ {
+ m_start = Clock::now();
+ }
+
+private:
+ typename Clock::time_point m_start;
+};
+
+unsigned bits_wanted; // for integer types
+
+template <class T, int Type>
+struct tester
+{
+ tester()
+ {
+ a.assign(500, 0);
+ for(int i = 0; i < 500; ++i)
+ {
+ b.push_back(generate_random());
+ c.push_back(generate_random());
+ small.push_back(gen());
+ }
+ }
+ double test_add()
+ {
+ stopwatch<boost::chrono::high_resolution_clock> w;
+ for(unsigned i = 0; i < 1000; ++i)
+ {
+ for(unsigned i = 0; i < b.size(); ++i)
+ a[i] = b[i] + c[i];
+ }
+ return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
+ }
+ double test_subtract()
+ {
+ stopwatch<boost::chrono::high_resolution_clock> w;
+ for(unsigned i = 0; i < 1000; ++i)
+ {
+ for(unsigned i = 0; i < b.size(); ++i)
+ a[i] = b[i] - c[i];
+ }
+ return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
+ }
+ double test_multiply()
+ {
+ stopwatch<boost::chrono::high_resolution_clock> w;
+ for(unsigned i = 0; i < 1000; ++i)
+ {
+ for(unsigned i = 0; i < b.size(); ++i)
+ a[i] = b[i] * c[i];
+ }
+ return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
+ }
+ double test_divide()
+ {
+ stopwatch<boost::chrono::high_resolution_clock> w;
+ for(unsigned i = 0; i < 1000; ++i)
+ {
+ for(unsigned i = 0; i < b.size(); ++i)
+ a[i] = b[i] / c[i] + b[i] / small[i];
+ }
+ return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
+ }
+ double test_str()
+ {
+ stopwatch<boost::chrono::high_resolution_clock> w;
+ for(unsigned i = 0; i < b.size(); ++i)
+ a[i] = b[i].str();
+ return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
+ }
+ //
+ // The following tests only work for ineteger types:
+ //
+ double test_mod()
+ {
+ stopwatch<boost::chrono::high_resolution_clock> w;
+ for(unsigned i = 0; i < 1000; ++i)
+ {
+ for(unsigned i = 0; i < b.size(); ++i)
+ a[i] = b[i] % c[i] + b[i] % small[i];
+ }
+ return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
+ }
+ double test_or()
+ {
+ stopwatch<boost::chrono::high_resolution_clock> w;
+ for(unsigned i = 0; i < 1000; ++i)
+ {
+ for(unsigned i = 0; i < b.size(); ++i)
+ a[i] = b[i] | c[i];
+ }
+ return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
+ }
+ double test_and()
+ {
+ stopwatch<boost::chrono::high_resolution_clock> w;
+ for(unsigned i = 0; i < 1000; ++i)
+ {
+ for(unsigned i = 0; i < b.size(); ++i)
+ a[i] = b[i] & c[i];
+ }
+ return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
+ }
+ double test_xor()
+ {
+ stopwatch<boost::chrono::high_resolution_clock> w;
+ for(unsigned i = 0; i < 1000; ++i)
+ {
+ for(unsigned i = 0; i < b.size(); ++i)
+ a[i] = b[i] ^ c[i];
+ }
+ return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
+ }
+ double test_complement()
+ {
+ stopwatch<boost::chrono::high_resolution_clock> w;
+ for(unsigned i = 0; i < 1000; ++i)
+ {
+ for(unsigned i = 0; i < b.size(); ++i)
+ a[i] = ~b[i];
+ }
+ return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
+ }
+ double test_left_shift()
+ {
+ int shift = std::numeric_limits<T>::is_bounded ? std::numeric_limits<T>::digits : bits_wanted;
+ shift /= 2;
+ stopwatch<boost::chrono::high_resolution_clock> w;
+ for(unsigned i = 0; i < 1000; ++i)
+ {
+ for(unsigned i = 0; i < b.size(); ++i)
+ a[i] = b[i] << shift;
+ }
+ return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
+ }
+ double test_right_shift()
+ {
+ int shift = std::numeric_limits<T>::is_bounded ? std::numeric_limits<T>::digits : bits_wanted;
+ shift /= 2;
+ stopwatch<boost::chrono::high_resolution_clock> w;
+ for(unsigned i = 0; i < 1000; ++i)
+ {
+ for(unsigned i = 0; i < b.size(); ++i)
+ a[i] = b[i] >> shift;
+ }
+ return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
+ }
+private:
+ T generate_random()
+ {
+ return generate_random(boost::mpl::int_<Type>());
+ }
+ T generate_random(const boost::mpl::int_<boost::multiprecision::number_kind_floating_point>&)
+ {
+ T val = gen();
+ T prev_val = -1;
+ while(val != prev_val)
+ {
+ val *= (gen.max)();
+ prev_val = val;
+ val += gen();
+ }
+ int e;
+ val = frexp(val, &e);
+
+ typedef typename T::backend_type::exponent_type e_type;
+ static boost::random::uniform_int_distribution<e_type> ui(0, std::numeric_limits<T>::max_exponent - 10);
+ return ldexp(val, ui(gen));
+ }
+ T generate_random(const boost::mpl::int_<boost::multiprecision::number_kind_integer>&)
+ {
+ typedef boost::random::mt19937::result_type random_type;
+
+ T max_val;
+ unsigned digits;
+ if(std::numeric_limits<T>::is_bounded)
+ {
+ max_val = (std::numeric_limits<T>::max)();
+ digits = std::numeric_limits<T>::digits;
+ }
+ else
+ {
+ max_val = T(1) << bits_wanted;
+ digits = bits_wanted;
+ }
+
+ unsigned bits_per_r_val = std::numeric_limits<random_type>::digits - 1;
+ while((random_type(1) << bits_per_r_val) > (gen.max)()) --bits_per_r_val;
+
+ unsigned terms_needed = digits / bits_per_r_val + 1;
+
+ T val = 0;
+ for(unsigned i = 0; i < terms_needed; ++i)
+ {
+ val *= (gen.max)();
+ val += gen();
+ }
+ val %= max_val;
+ return val;
+ }
+ std::vector<T> a, b, c, small;
+ static boost::random::mt19937 gen;
+};
+
+template <class N, int V>
+boost::random::mt19937 tester<N, V>::gen;
+
+template <class Number, int N>
+void test_int_ops(tester<Number, N>& t, const char* type, unsigned precision, const boost::mpl::int_<boost::multiprecision::number_kind_integer>&)
+{
+ std::cout << std::left << std::setw(15) << type << std::setw(10) << precision << std::setw(5) << "%" << t.test_mod() << std::endl;
+ std::cout << std::left << std::setw(15) << type << std::setw(10) << precision << std::setw(5) << "|" << t.test_or() << std::endl;
+ std::cout << std::left << std::setw(15) << type << std::setw(10) << precision << std::setw(5) << "&" << t.test_and() << std::endl;
+ std::cout << std::left << std::setw(15) << type << std::setw(10) << precision << std::setw(5) << "^" << t.test_xor() << std::endl;
+ //std::cout << std::left << std::setw(15) << type << std::setw(10) << precision << std::setw(5) << "~" << t.test_complement() << std::endl;
+ std::cout << std::left << std::setw(15) << type << std::setw(10) << precision << std::setw(5) << "<<" << t.test_left_shift() << std::endl;
+ std::cout << std::left << std::setw(15) << type << std::setw(10) << precision << std::setw(5) << ">>" << t.test_right_shift() << std::endl;
+}
+template <class Number, int N, class U>
+void test_int_ops(tester<Number, N>& t, const char* type, unsigned precision, const U&)
+{
+}
+
+template <class Number>
+void test(const char* type, unsigned precision)
+{
+ bits_wanted = precision;
+ tester<Number, boost::multiprecision::number_category<Number>::value> t;
+ std::cout << std::left << std::setw(15) << type << std::setw(10) << precision << std::setw(5) << "+" << t.test_add() << std::endl;
+ std::cout << std::left << std::setw(15) << type << std::setw(10) << precision << std::setw(5) << "-" << t.test_subtract() << std::endl;
+ std::cout << std::left << std::setw(15) << type << std::setw(10) << precision << std::setw(5) << "*" << t.test_multiply() << std::endl;
+ std::cout << std::left << std::setw(15) << type << std::setw(10) << precision << std::setw(5) << "/" << t.test_divide() << std::endl;
+ std::cout << std::left << std::setw(15) << type << std::setw(10) << precision << std::setw(5) << "str" << t.test_str() << std::endl;
+
+ test_int_ops(t, type, precision, typename boost::multiprecision::number_category<Number>::type());
+}
+
+
+int main()
+{
+#ifdef TEST_MPF
+ test<boost::multiprecision::mpf_float_50>("gmp_float", 50);
+ test<boost::multiprecision::mpf_float_100>("gmp_float", 100);
+ test<boost::multiprecision::mpf_float_500>("gmp_float", 500);
+#endif
+#ifdef TEST_MPZ
+ test<boost::multiprecision::mpz_int>("gmp_int", 64);
+ test<boost::multiprecision::mpz_int>("gmp_int", 128);
+ test<boost::multiprecision::mpz_int>("gmp_int", 256);
+ test<boost::multiprecision::mpz_int>("gmp_int", 512);
+ test<boost::multiprecision::mpz_int>("gmp_int", 1024);
+#endif
+#ifdef TEST_TOMMATH
+ test<boost::multiprecision::mp_int>("tommath_int", 64);
+ test<boost::multiprecision::mp_int>("tommath_int", 128);
+ test<boost::multiprecision::mp_int>("tommath_int", 256);
+ test<boost::multiprecision::mp_int>("tommath_int", 512);
+ test<boost::multiprecision::mp_int>("tommath_int", 1024);
+#endif
+#ifdef TEST_PACKED_INT
+ test<boost::multiprecision::mp_int64_t>("mp_int64_t", 64);
+ test<boost::multiprecision::mp_int128_t>("mp_int128_t", 128);
+ test<boost::multiprecision::mp_int256_t>("mp_int256_t", 256);
+ test<boost::multiprecision::mp_int512_t>("mp_int512_t", 512);
+ test<boost::multiprecision::mp_number<boost::multiprecision::packed_cpp_int<1024, true> > >("mp_int1024_t", 1024);
+#endif
+#ifdef TEST_CPP_FLOAT
+ test<boost::multiprecision::cpp_float_50>("cpp_float", 50);
+ test<boost::multiprecision::cpp_float_100>("cpp_float", 100);
+ test<boost::multiprecision::mp_number<boost::multiprecision::cpp_float<500> > >("cpp_float", 500);
+#endif
+#ifdef TEST_MPFR
+ test<boost::multiprecision::mpfr_float_50>("mpfr_float", 50);
+ test<boost::multiprecision::mpfr_float_100>("mpfr_float", 100);
+ test<boost::multiprecision::mpfr_float_500>("mpfr_float", 500);
+#endif
+ return 0;
+}
+


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk