Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r49572 - in sandbox/mp_math: boost/mp_math/mp_int libs/mp_math/test libs/mp_math/tools/benchmark
From: baraclese_at_[hidden]
Date: 2008-11-03 14:18:44


Author: baraclese
Date: 2008-11-03 14:18:42 EST (Mon, 03 Nov 2008)
New Revision: 49572
URL: http://svn.boost.org/trac/boost/changeset/49572

Log:
* Removed char* and wchar_t* overloads and replaced them by a templatized
  version.
* Added new nth_root overload.
* Added a new mode to the benchmark tool meant to benchmark large numbers. On
  the way I fixed a few bugs in it.
* some other minor changes

Added:
   sandbox/mp_math/libs/mp_math/tools/benchmark/modes.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/tools/benchmark/modes.hpp (contents, props changed)
Text files modified:
   sandbox/mp_math/boost/mp_math/mp_int/jacobi.hpp | 8
   sandbox/mp_math/boost/mp_math/mp_int/mp_int.hpp | 91 +++-------
   sandbox/mp_math/boost/mp_math/mp_int/operators.hpp | 245 +++++++-----------------------
   sandbox/mp_math/boost/mp_math/mp_int/root.hpp | 70 ++++++++
   sandbox/mp_math/libs/mp_math/test/integral_ops.cpp | 6
   sandbox/mp_math/libs/mp_math/test/jamfile.v2 | 1
   sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark.cpp | 33 ----
   sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark.hpp | 9
   sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_runner.cpp | 319 +++------------------------------------
   sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_runner.hpp | 55 +-----
   sandbox/mp_math/libs/mp_math/tools/benchmark/jamfile.v2 | 7
   sandbox/mp_math/libs/mp_math/tools/benchmark/main.cpp | 143 ++++++++++++++---
   12 files changed, 318 insertions(+), 669 deletions(-)

Modified: sandbox/mp_math/boost/mp_math/mp_int/jacobi.hpp
==============================================================================
--- sandbox/mp_math/boost/mp_math/mp_int/jacobi.hpp (original)
+++ sandbox/mp_math/boost/mp_math/mp_int/jacobi.hpp 2008-11-03 14:18:42 EST (Mon, 03 Nov 2008)
@@ -29,10 +29,10 @@
   if (a == digit_type(1))
     return 1;
 
- /* default */
+ // default
   int s = 0;
 
- /* write a = a1 * 2**k */
+ // write a = a1 * 2**k
   mp_int<A,T> a1(a);
 
   // find largest power of two that divides a1
@@ -40,7 +40,7 @@
   // now divide by it
   a1.shift_right(k,0);
 
- /* if k is even set s=1 */
+ // if k is even set s=1
   if ((k & 1) == 0)
     s = 1;
   else
@@ -54,7 +54,7 @@
       s = -1;
   }
 
- /* if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */
+ // if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s
   if (((p[0] & 3) == 3) && ((a1[0] & 3) == 3))
     s = -s;
 

Modified: sandbox/mp_math/boost/mp_math/mp_int/mp_int.hpp
==============================================================================
--- sandbox/mp_math/boost/mp_math/mp_int/mp_int.hpp (original)
+++ sandbox/mp_math/boost/mp_math/mp_int/mp_int.hpp 2008-11-03 14:18:42 EST (Mon, 03 Nov 2008)
@@ -84,20 +84,14 @@
   template<typename IntegralT>
   mp_int& operator = (IntegralT rhs);
 
- mp_int& operator = (const char*);
-
- #ifndef BOOST_NO_CWCHAR
- mp_int& operator = (const wchar_t*);
- #endif
+ template<typename charT>
+ mp_int& operator = (const charT*);
 
   template<typename charT, class traits, class Alloc>
   mp_int& operator = (const std::basic_string<charT,traits,Alloc>&);
 
- void assign(const char*, std::ios_base::fmtflags);
-
- #ifndef BOOST_NO_CWCHAR
- void assign(const wchar_t*, std::ios_base::fmtflags);
- #endif
+ template<typename charT>
+ void assign(const charT*, std::ios_base::fmtflags);
 
   template<typename charT, class traits, class Alloc>
   void assign(const std::basic_string<charT,traits,Alloc>&,
@@ -139,25 +133,14 @@
   template<typename IntegralT> mp_int& operator &= (IntegralT);
   template<typename IntegralT> mp_int& operator ^= (IntegralT);
 
- mp_int& operator += (const char*);
- mp_int& operator -= (const char*);
- mp_int& operator *= (const char*);
- mp_int& operator /= (const char*);
- mp_int& operator %= (const char*);
- mp_int& operator |= (const char*);
- mp_int& operator &= (const char*);
- mp_int& operator ^= (const char*);
-
- #ifndef BOOST_NO_CWCHAR
- mp_int& operator += (const wchar_t*);
- mp_int& operator -= (const wchar_t*);
- mp_int& operator *= (const wchar_t*);
- mp_int& operator /= (const wchar_t*);
- mp_int& operator %= (const wchar_t*);
- mp_int& operator |= (const wchar_t*);
- mp_int& operator &= (const wchar_t*);
- mp_int& operator ^= (const wchar_t*);
- #endif
+ template<typename charT> mp_int& operator += (const charT*);
+ template<typename charT> mp_int& operator -= (const charT*);
+ template<typename charT> mp_int& operator *= (const charT*);
+ template<typename charT> mp_int& operator /= (const charT*);
+ template<typename charT> mp_int& operator %= (const charT*);
+ template<typename charT> mp_int& operator |= (const charT*);
+ template<typename charT> mp_int& operator &= (const charT*);
+ template<typename charT> mp_int& operator ^= (const charT*);
 
   template<typename charT, class traits, class Alloc>
   mp_int& operator += (const std::basic_string<charT,traits,Alloc>&);
@@ -453,22 +436,13 @@
 }
 
 template<class A, class T>
-mp_int<A,T>& mp_int<A,T>::operator = (const char* s)
-{
- size_ = 0;
- init(s, s + std::strlen(s));
- return *this;
-}
-
-#ifndef BOOST_NO_CWCHAR
-template<class A, class T>
-mp_int<A,T>& mp_int<A,T>::operator = (const wchar_t* s)
+template<typename charT>
+mp_int<A,T>& mp_int<A,T>::operator = (const charT* s)
 {
   size_ = 0;
- init(s, s + std::wcslen(s));
+ init(s, s + std::char_traits<charT>::length(s));
   return *this;
 }
-#endif
 
 template<class A, class T>
 template<typename charT, class traits, class Alloc>
@@ -480,21 +454,13 @@
 }
 
 template<class A, class T>
+template<typename charT>
 inline void
-mp_int<A,T>::assign(const char* s, std::ios_base::fmtflags f)
+mp_int<A,T>::assign(const charT* s, std::ios_base::fmtflags f)
 {
- assign(s, s + std::strlen(s), f);
+ assign(s, s + std::char_traits<charT>::length(s), f);
 }
 
-#ifndef BOOST_NO_CWCHAR
-template<class A, class T>
-inline void
-mp_int<A,T>::assign(const wchar_t* s, std::ios_base::fmtflags f)
-{
- assign(s, s + std::wcslen(s), f);
-}
-#endif
-
 template<class A, class T>
 template<typename charT, class traits, class Alloc>
 inline void
@@ -606,16 +572,19 @@
 {
   if (capacity() < n)
   {
- if (n >= sign_bit)
+ if (n < sign_bit)
+ {
+ const size_type new_cap = capacity() + capacity();
+ if (new_cap > n)
+ n = new_cap;
+ digit_type* d = this->allocate(n, digits_);
+ std::memcpy(d, digits_, sizeof(digit_type) * size_);
+ this->deallocate(digits_, capacity());
+ digits_ = d;
+ set_capacity(n);
+ }
+ else
       throw std::bad_alloc();
- const size_type new_cap = capacity() + capacity();
- if (new_cap > n)
- n = new_cap;
- digit_type* d = this->allocate(n, digits_);
- std::memcpy(d, digits_, sizeof(digit_type) * size_);
- this->deallocate(digits_, capacity());
- digits_ = d;
- set_capacity(n);
   }
 }
 

Modified: sandbox/mp_math/boost/mp_math/mp_int/operators.hpp
==============================================================================
--- sandbox/mp_math/boost/mp_math/mp_int/operators.hpp (original)
+++ sandbox/mp_math/boost/mp_math/mp_int/operators.hpp 2008-11-03 14:18:42 EST (Mon, 03 Nov 2008)
@@ -111,108 +111,55 @@
 operator >= (IntegralT lhs, const mp_int<A,T>& rhs) { return rhs <= lhs; }
 
 
-// compare mp_int to const char*
-template<class A, class T>
+// compare mp_int to character string
+template<class A, class T, typename charT>
 inline bool
-operator == (const mp_int<A,T>& lhs, const char* rhs) { return lhs == mp_int<A,T>(rhs); }
+operator == (const mp_int<A,T>& lhs, const charT* rhs) { return lhs == mp_int<A,T>(rhs); }
 
-template<class A, class T>
+template<class A, class T, typename charT>
 inline bool
-operator != (const mp_int<A,T>& lhs, const char* rhs) { return lhs != mp_int<A,T>(rhs); }
+operator != (const mp_int<A,T>& lhs, const charT* rhs) { return lhs != mp_int<A,T>(rhs); }
 
-template<class A, class T>
+template<class A, class T, typename charT>
 inline bool
-operator < (const mp_int<A,T>& lhs, const char* rhs) { return lhs < mp_int<A,T>(rhs); }
+operator < (const mp_int<A,T>& lhs, const charT* rhs) { return lhs < mp_int<A,T>(rhs); }
 
-template<class A, class T>
+template<class A, class T, typename charT>
 inline bool
-operator > (const mp_int<A,T>& lhs, const char* rhs) { return lhs > mp_int<A,T>(rhs); }
+operator > (const mp_int<A,T>& lhs, const charT* rhs) { return lhs > mp_int<A,T>(rhs); }
 
-template<class A, class T>
+template<class A, class T, typename charT>
 inline bool
-operator <= (const mp_int<A,T>& lhs, const char* rhs) { return lhs <= mp_int<A,T>(rhs); }
+operator <= (const mp_int<A,T>& lhs, const charT* rhs) { return lhs <= mp_int<A,T>(rhs); }
 
-template<class A, class T>
+template<class A, class T, typename charT>
 inline bool
-operator >= (const mp_int<A,T>& lhs, const char* rhs) { return lhs >= mp_int<A,T>(rhs); }
+operator >= (const mp_int<A,T>& lhs, const charT* rhs) { return lhs >= mp_int<A,T>(rhs); }
 
 // compare const char* to mp_int
-template<class A, class T>
+template<class A, class T, typename charT>
 inline bool
-operator == (const char* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) == rhs; }
+operator == (const charT* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) == rhs; }
 
-template<class A, class T>
+template<class A, class T, typename charT>
 inline bool
-operator != (const char* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) != rhs; }
+operator != (const charT* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) != rhs; }
 
-template<class A, class T>
+template<class A, class T, typename charT>
 inline bool
-operator < (const char* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) < rhs; }
+operator < (const charT* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) < rhs; }
 
-template<class A, class T>
+template<class A, class T, typename charT>
 inline bool
-operator > (const char* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) > rhs; }
+operator > (const charT* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) > rhs; }
 
-template<class A, class T>
+template<class A, class T, typename charT>
 inline bool
-operator <= (const char* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) <= rhs; }
+operator <= (const charT* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) <= rhs; }
 
-template<class A, class T>
+template<class A, class T, typename charT>
 inline bool
-operator >= (const char* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) >= rhs; }
-
-
-#ifndef BOOST_NO_CWCHAR
-// compare mp_int to const wchar_t*
-template<class A, class T>
-inline bool
-operator == (const mp_int<A,T>& lhs, const wchar_t* rhs) { return lhs == mp_int<A,T>(rhs); }
-
-template<class A, class T>
-inline bool
-operator != (const mp_int<A,T>& lhs, const wchar_t* rhs) { return lhs != mp_int<A,T>(rhs); }
-
-template<class A, class T>
-inline bool
-operator < (const mp_int<A,T>& lhs, const wchar_t* rhs) { return lhs < mp_int<A,T>(rhs); }
-
-template<class A, class T>
-inline bool
-operator > (const mp_int<A,T>& lhs, const wchar_t* rhs) { return lhs > mp_int<A,T>(rhs); }
-
-template<class A, class T>
-inline bool
-operator <= (const mp_int<A,T>& lhs, const wchar_t* rhs) { return lhs <= mp_int<A,T>(rhs); }
-
-template<class A, class T>
-inline bool
-operator >= (const mp_int<A,T>& lhs, const wchar_t* rhs) { return lhs >= mp_int<A,T>(rhs); }
-
-// compare const wchar_t* to mp_int
-template<class A, class T>
-inline bool
-operator == (const wchar_t* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) == rhs; }
-
-template<class A, class T>
-inline bool
-operator != (const wchar_t* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) != rhs; }
-
-template<class A, class T>
-inline bool
-operator < (const wchar_t* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) < rhs; }
-
-template<class A, class T>
-inline bool
-operator > (const wchar_t* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) > rhs; }
-
-template<class A, class T>
-inline bool
-operator <= (const wchar_t* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) <= rhs; }
-
-template<class A, class T>
-inline bool
-operator >= (const wchar_t* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) >= rhs; }
-#endif // BOOST_NO_CWCHAR
+operator >= (const charT* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) >= rhs; }
 
 
 // compare mp_int to basic_string
@@ -748,170 +695,94 @@
 }
 
 
-// Arithmetic and bitwise operators involving const char*
-template<class A, class T>
-inline mp_int<A,T>& mp_int<A,T>::operator += (const char* s) { return *this += mp_int<A,T>(s); }
-template<class A, class T>
-inline mp_int<A,T>& mp_int<A,T>::operator -= (const char* s) { return *this -= mp_int<A,T>(s); }
-template<class A, class T>
-inline mp_int<A,T>& mp_int<A,T>::operator *= (const char* s) { return *this *= mp_int<A,T>(s); }
-template<class A, class T>
-inline mp_int<A,T>& mp_int<A,T>::operator /= (const char* s) { return *this /= mp_int<A,T>(s); }
-template<class A, class T>
-inline mp_int<A,T>& mp_int<A,T>::operator %= (const char* s) { return *this %= mp_int<A,T>(s); }
-template<class A, class T>
-inline mp_int<A,T>& mp_int<A,T>::operator |= (const char* s) { return *this |= mp_int<A,T>(s); }
-template<class A, class T>
-inline mp_int<A,T>& mp_int<A,T>::operator &= (const char* s) { return *this &= mp_int<A,T>(s); }
-template<class A, class T>
-inline mp_int<A,T>& mp_int<A,T>::operator ^= (const char* s) { return *this ^= mp_int<A,T>(s); }
-
-template<class A, class T>
-inline mp_int<A,T> operator + (const mp_int<A,T>& lhs, const char* rhs)
-{
- mp_int<A,T> nrv(lhs);
- nrv += mp_int<A,T>(rhs);
- return nrv;
-}
-
-template<class A, class T>
-inline mp_int<A,T> operator - (const mp_int<A,T>& lhs, const char* rhs)
-{
- mp_int<A,T> nrv(lhs);
- nrv -= mp_int<A,T>(rhs);
- return nrv;
-}
-
+// Arithmetic and bitwise operators involving character strings
 template<class A, class T>
-inline mp_int<A,T> operator * (const mp_int<A,T>& lhs, const char* rhs)
-{
- mp_int<A,T> nrv(lhs);
- nrv *= mp_int<A,T>(rhs);
- return nrv;
-}
-
+template<typename charT>
+inline mp_int<A,T>& mp_int<A,T>::operator += (const charT* s) { return *this += mp_int<A,T>(s); }
 template<class A, class T>
-inline mp_int<A,T> operator / (const mp_int<A,T>& lhs, const char* rhs)
-{
- mp_int<A,T> nrv(lhs);
- nrv /= mp_int<A,T>(rhs);
- return nrv;
-}
+template<typename charT>
+inline mp_int<A,T>& mp_int<A,T>::operator -= (const charT* s) { return *this -= mp_int<A,T>(s); }
 template<class A, class T>
-inline mp_int<A,T> operator % (const mp_int<A,T>& lhs, const char* rhs)
-{
- mp_int<A,T> nrv(lhs);
- nrv %= mp_int<A,T>(rhs);
- return nrv;
-}
-
+template<typename charT>
+inline mp_int<A,T>& mp_int<A,T>::operator *= (const charT* s) { return *this *= mp_int<A,T>(s); }
 template<class A, class T>
-inline mp_int<A,T> operator | (const mp_int<A,T>& lhs, const char* rhs)
-{
- mp_int<A,T> nrv(lhs);
- nrv |= mp_int<A,T>(rhs);
- return nrv;
-}
-
-template<class A, class T>
-inline mp_int<A,T> operator & (const mp_int<A,T>& lhs, const char* rhs)
-{
- mp_int<A,T> nrv(lhs);
- nrv &= mp_int<A,T>(rhs);
- return nrv;
-}
-
-template<class A, class T>
-inline mp_int<A,T> operator ^ (const mp_int<A,T>& lhs, const char* rhs)
-{
- mp_int<A,T> nrv(lhs);
- nrv ^= mp_int<A,T>(rhs);
- return nrv;
-}
-
-
-#ifndef BOOST_NO_CWCHAR
-// Arithmetic and bitwise operators involving const wchar_t*
-template<class A, class T>
-inline mp_int<A,T>& mp_int<A,T>::operator += (const wchar_t* s) { return *this += mp_int<A,T>(s); }
+template<typename charT>
+inline mp_int<A,T>& mp_int<A,T>::operator /= (const charT* s) { return *this /= mp_int<A,T>(s); }
 template<class A, class T>
-inline mp_int<A,T>& mp_int<A,T>::operator -= (const wchar_t* s) { return *this -= mp_int<A,T>(s); }
+template<typename charT>
+inline mp_int<A,T>& mp_int<A,T>::operator %= (const charT* s) { return *this %= mp_int<A,T>(s); }
 template<class A, class T>
-inline mp_int<A,T>& mp_int<A,T>::operator *= (const wchar_t* s) { return *this *= mp_int<A,T>(s); }
+template<typename charT>
+inline mp_int<A,T>& mp_int<A,T>::operator |= (const charT* s) { return *this |= mp_int<A,T>(s); }
 template<class A, class T>
-inline mp_int<A,T>& mp_int<A,T>::operator /= (const wchar_t* s) { return *this /= mp_int<A,T>(s); }
+template<typename charT>
+inline mp_int<A,T>& mp_int<A,T>::operator &= (const charT* s) { return *this &= mp_int<A,T>(s); }
 template<class A, class T>
-inline mp_int<A,T>& mp_int<A,T>::operator %= (const wchar_t* s) { return *this %= mp_int<A,T>(s); }
-template<class A, class T>
-inline mp_int<A,T>& mp_int<A,T>::operator |= (const wchar_t* s) { return *this |= mp_int<A,T>(s); }
-template<class A, class T>
-inline mp_int<A,T>& mp_int<A,T>::operator &= (const wchar_t* s) { return *this &= mp_int<A,T>(s); }
-template<class A, class T>
-inline mp_int<A,T>& mp_int<A,T>::operator ^= (const wchar_t* s) { return *this ^= mp_int<A,T>(s); }
+template<typename charT>
+inline mp_int<A,T>& mp_int<A,T>::operator ^= (const charT* s) { return *this ^= mp_int<A,T>(s); }
 
-template<class A, class T>
-inline mp_int<A,T> operator + (const mp_int<A,T>& lhs, const wchar_t* rhs)
+template<class A, class T, typename charT>
+inline mp_int<A,T> operator + (const mp_int<A,T>& lhs, const charT* rhs)
 {
   mp_int<A,T> nrv(lhs);
   nrv += mp_int<A,T>(rhs);
   return nrv;
 }
 
-template<class A, class T>
-inline mp_int<A,T> operator - (const mp_int<A,T>& lhs, const wchar_t* rhs)
+template<class A, class T, typename charT>
+inline mp_int<A,T> operator - (const mp_int<A,T>& lhs, const charT* rhs)
 {
   mp_int<A,T> nrv(lhs);
   nrv -= mp_int<A,T>(rhs);
   return nrv;
 }
 
-template<class A, class T>
-inline mp_int<A,T> operator * (const mp_int<A,T>& lhs, const wchar_t* rhs)
+template<class A, class T, typename charT>
+inline mp_int<A,T> operator * (const mp_int<A,T>& lhs, const charT* rhs)
 {
   mp_int<A,T> nrv(lhs);
   nrv *= mp_int<A,T>(rhs);
   return nrv;
 }
 
-template<class A, class T>
-inline mp_int<A,T> operator / (const mp_int<A,T>& lhs, const wchar_t* rhs)
+template<class A, class T, typename charT>
+inline mp_int<A,T> operator / (const mp_int<A,T>& lhs, const charT* rhs)
 {
   mp_int<A,T> nrv(lhs);
   nrv /= mp_int<A,T>(rhs);
   return nrv;
 }
-template<class A, class T>
-inline mp_int<A,T> operator % (const mp_int<A,T>& lhs, const wchar_t* rhs)
+template<class A, class T, typename charT>
+inline mp_int<A,T> operator % (const mp_int<A,T>& lhs, const charT* rhs)
 {
   mp_int<A,T> nrv(lhs);
   nrv %= mp_int<A,T>(rhs);
   return nrv;
 }
 
-template<class A, class T>
-inline mp_int<A,T> operator | (const mp_int<A,T>& lhs, const wchar_t* rhs)
+template<class A, class T, typename charT>
+inline mp_int<A,T> operator | (const mp_int<A,T>& lhs, const charT* rhs)
 {
   mp_int<A,T> nrv(lhs);
   nrv |= mp_int<A,T>(rhs);
   return nrv;
 }
 
-template<class A, class T>
-inline mp_int<A,T> operator & (const mp_int<A,T>& lhs, const wchar_t* rhs)
+template<class A, class T, typename charT>
+inline mp_int<A,T> operator & (const mp_int<A,T>& lhs, const charT* rhs)
 {
   mp_int<A,T> nrv(lhs);
   nrv &= mp_int<A,T>(rhs);
   return nrv;
 }
 
-template<class A, class T>
-inline mp_int<A,T> operator ^ (const mp_int<A,T>& lhs, const wchar_t* rhs)
+template<class A, class T, typename charT>
+inline mp_int<A,T> operator ^ (const mp_int<A,T>& lhs, const charT* rhs)
 {
   mp_int<A,T> nrv(lhs);
   nrv ^= mp_int<A,T>(rhs);
   return nrv;
 }
-#endif // BOOST_NO_CWCHAR
 
 
 // Arithmetic and bitwise operators involving basic_string

Modified: sandbox/mp_math/boost/mp_math/mp_int/root.hpp
==============================================================================
--- sandbox/mp_math/boost/mp_math/mp_int/root.hpp (original)
+++ sandbox/mp_math/boost/mp_math/mp_int/root.hpp 2008-11-03 14:18:42 EST (Mon, 03 Nov 2008)
@@ -61,8 +61,6 @@
 template<class A, class T>
 mp_int<A,T> nth_root(const mp_int<A,T>& x, typename mp_int<A,T>::digit_type n)
 {
- mp_int<A,T> t1, t2, t3;
-
   if ((n & 1) == 0 && x.is_negative())
     throw std::domain_error("nth_root: argument must be positive if n is even");
 
@@ -70,7 +68,8 @@
   const int neg = x.sign();
   const_cast<mp_int<A,T>*>(&x)->set_sign(1);
 
- // t2 = 2
+ mp_int<A,T> t1, t2, t3;
+
   t2 = typename mp_int<A,T>::digit_type(2);
 
   do
@@ -105,7 +104,70 @@
     t2 = pow(t1, n);
 
     if (t2 > x)
- t1.sub_digit(1);
+ --t1;
+ else
+ break;
+ }
+
+ // reset the sign of x first
+ const_cast<mp_int<A,T>*>(&x)->set_sign(neg);
+
+ // set the sign of the result
+ t1.set_sign(neg);
+
+ return t1;
+}
+
+template<class A, class T>
+mp_int<A,T> nth_root(const mp_int<A,T>& x, const mp_int<A,T>& n)
+{
+ if (n.is_odd() && x.is_negative())
+ throw std::domain_error("nth_root: argument must be positive if n is even");
+
+ if (n.size() == 1)
+ return nth_root(x, n[0]);
+
+ // if x is negative fudge the sign but keep track
+ const int neg = x.sign();
+ const_cast<mp_int<A,T>*>(&x)->set_sign(1);
+
+ mp_int<A,T> t1, t2, t3;
+
+ t2 = typename mp_int<A,T>::digit_type(2);
+
+ do
+ {
+ t1 = t2;
+
+ // t2 = t1 - ((t1**n - x) / (n * t1**(n-1)))
+
+ // t3 = t1**(n-1)
+ t3 = pow(t1, n-1);
+
+ // numerator
+ // t2 = t1**n
+ t2 = t3 * t1;
+
+ // t2 = t1**n - x
+ t2 -= x;
+
+ // denominator
+ // t3 = t1**(n-1) * n
+ t3 *= n;
+
+ // t3 = (t1**n - x)/(n * t1**(n-1))
+ t3 = t2 / t3;
+
+ t2 = t1 - t3;
+ } while (t1 != t2);
+
+ // result can be off by a few so check
+ for (;;)
+ {
+ t2 = pow(t1, n);
+
+ if (t2 > x)
+ --t1;
     else
       break;
   }

Modified: sandbox/mp_math/libs/mp_math/test/integral_ops.cpp
==============================================================================
--- sandbox/mp_math/libs/mp_math/test/integral_ops.cpp (original)
+++ sandbox/mp_math/libs/mp_math/test/integral_ops.cpp 2008-11-03 14:18:42 EST (Mon, 03 Nov 2008)
@@ -6,6 +6,12 @@
 #include <boost/test/unit_test.hpp>
 #include "prerequisite.hpp"
 
+BOOST_AUTO_TEST_CASE_TEMPLATE(construct_from_zero, mp_int_type, mp_int_types)
+{
+ const mp_int_type x(0);
+ BOOST_CHECK_EQUAL(x.is_zero(), true);
+}
+
 BOOST_AUTO_TEST_CASE_TEMPLATE(equal_signed_char_min, mp_int_type, mp_int_types)
 {
   const signed char x = std::numeric_limits<signed char>::min();

Modified: sandbox/mp_math/libs/mp_math/test/jamfile.v2
==============================================================================
--- sandbox/mp_math/libs/mp_math/test/jamfile.v2 (original)
+++ sandbox/mp_math/libs/mp_math/test/jamfile.v2 2008-11-03 14:18:42 EST (Mon, 03 Nov 2008)
@@ -13,7 +13,6 @@
     : requirements
       <include>../../..
       <link>static
- <toolset>gcc:<cxxflags>-std=c++0x
       <define>BOOST_TEST_DYN_LINK
       <define>BOOST_TEST_MAIN
       #<define>BOOST_MP_MATH_MP_INT_USE_ASM

Modified: sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark.cpp
==============================================================================
--- sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark.cpp (original)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark.cpp 2008-11-03 14:18:42 EST (Mon, 03 Nov 2008)
@@ -6,39 +6,6 @@
 #include "benchmark.hpp"
 #include <iostream>
 #include <stdexcept>
-#include <boost/random.hpp>
-
-std::string create_random_hex_string(int size_in_bits)
-{
- std::string s;
- boost::mt19937 r;
- boost::uniform_smallint<char> u(0,15);
- boost::variate_generator<boost::mt19937&, boost::uniform_smallint<char> > vg(r, u);
- // one hex digit can occupy 4 bits
- for (int i = 0; i < size_in_bits/4; ++i)
- {
- char tmp = vg();
- if (tmp < 10)
- tmp = '0' + tmp;
- else
- tmp = 'a' + (tmp-10);
- s.push_back(tmp);
- }
- return s;
-}
-
-std::string create_random_dec_string(int size_in_digits)
-{
- std::string s;
- boost::mt19937 r;
- boost::uniform_smallint<char> u(0,9);
- boost::variate_generator<boost::mt19937&, boost::uniform_smallint<char> > vg(r, u);
-
- for (int i = 0; i < size_in_digits; ++i)
- s.push_back('0' + vg());
-
- return s;
-}
 
 
 const char* to_string(op_type op)

Modified: sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark.hpp
==============================================================================
--- sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark.hpp (original)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark.hpp 2008-11-03 14:18:42 EST (Mon, 03 Nov 2008)
@@ -11,11 +11,6 @@
 #include <boost/shared_ptr.hpp>
 #include <boost/timer.hpp>
 
-
-std::string create_random_hex_string(int size_in_bits);
-std::string create_random_dec_string(int size_in_digits);
-
-
 enum op_type
 {
   op_ctor_dec,
@@ -158,8 +153,8 @@
     op_time.restart();
     for (; op_time.elapsed() < sample_time; ++num_ops_executed)
       f(i);
- // push the number of ops per millisecond
- r.ops.push_back(1.0/(op_time.elapsed() * 1000.0 / num_ops_executed));
+ // push the number of ops per sample_time
+ r.ops.push_back(num_ops_executed/op_time.elapsed());
   }
   r.total_time = total.elapsed();
   // clear dst vector for next test

Modified: sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_runner.cpp
==============================================================================
--- sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_runner.cpp (original)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_runner.cpp 2008-11-03 14:18:42 EST (Mon, 03 Nov 2008)
@@ -3,179 +3,40 @@
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#include <cmath>
-#include <fstream>
 #include <iostream>
-#include <numeric> // accumulate
 #include <stdexcept>
-#include <sstream>
 #include "benchmark_runner.hpp"
 
 
 void benchmark_runner::run(const std::vector<std::string>& ops,
- double sample_time)
+ double sample_time,
+ const std::vector<std::string>& vec1,
+ const std::vector<std::string>& vec2,
+ const std::vector<std::string>& hex_str_vec,
+ const std::vector<std::string>& dec_str_vec)
 {
- init_libs();
+ if (vec1.size() != vec2.size())
+ throw std::runtime_error("input vectors must have same length");
 
- for (std::vector<std::string>::const_iterator op = ops.begin(); op != ops.end(); ++op)
- execute_bench_op(*op, sample_time);
-
- std::cout << "creating data files..." << std::endl;
- create_data_files();
-}
-
-unsigned long
-benchmark_runner::get_operand1_size(unsigned int sample_number) const
-{
- // linear growth
- const double m = static_cast<double>(end_ - beg_) /
- static_cast<double>(num_input_samples_);
- return (m * sample_number) + beg_;
-}
-
-unsigned long
-benchmark_runner::get_operand2_size(unsigned int sample_number) const
-{
- // modified sine curve
- const double pi = 3.141592654;
- const double sample_num_to_rad = num_input_samples_ / (4.5 * pi);
-
- // scale sample_number into the range [0...4.5*PI]
- const double x = sample_number / sample_num_to_rad;
-
- const double y_val = std::sin(x) + 1.0;
-
- const double y_top = get_operand1_size(sample_number);
- const double p0 = pi;
- double y_bottom;
- if (x <= p0)
- y_bottom = y_top / (x / p0 * 2.0 + 1.0) + 1.0;
- else
- y_bottom = y_top / 3.0;
-
- // we want to scale the curve at the point p1 to be above y_top at x = 2.5*pi
- const double p1 = 2.5 * pi;
-
- // here we use a function of the form y = -ax^2 + b to scale the curve at (and
- // around) p1
- const double a = 1.0/(p1 * p1);
- double adjust = -a * ((x-p1) * (x-p1)) + 1.0;
- // scale to be 10% above p1
- adjust *= 1.1;
- // stop scaling once we're past p1 and 'adjust' falls below 1.0
- if (x > p1 && adjust < 1.0)
- adjust = 1.0;
-
- return static_cast<unsigned long>(y_bottom * adjust * y_val + y_bottom);
-}
+ unsigned int stepsize = vec1.size() / 10;
 
-benchmark_runner::benchmark_runner(unsigned int num_input_samples,
- unsigned long operand_size_beg,
- unsigned long operand_size_end)
-:
- num_input_samples_(num_input_samples),
- beg_(operand_size_beg ? operand_size_beg : 1), // zero length not allowed
- end_(operand_size_end)
-{
-}
+ if (stepsize == 0)
+ stepsize = 1;
 
-void benchmark_runner::add_library(const boost::shared_ptr<benchmark_base>& b)
-{
- libs_.push_back(b);
-}
-
-void benchmark_runner::create_input_vectors(unsigned long min, unsigned long max)
-{
- std::ofstream iv_file("input_vecs.dat");
- if (!iv_file.is_open())
- throw std::runtime_error("couldn't open file input_vecs.dat");
-
- std::cout << "Creating " << num_input_samples_
- << " operand indices for numbers between "
- << min << " and " << max << " bits."
- << std::endl;
-
- const std::string rn = create_random_hex_string(max);
-
- std::cout << "creating input vectors";
- std::cout.flush();
-
- // create input vector where number size is determined by the sine function
- const unsigned int stepsize = num_input_samples_ / 10;
- for (unsigned int i = 0; i < num_input_samples_; ++i)
- {
- const unsigned long size1 = get_operand1_size(i);
- const unsigned long size2 = get_operand2_size(i);
-
- // divide by 4 because rn has max/4 hex digits
- string_vec1_.push_back(rn.substr(0, size1/4));
- string_vec2_.push_back(rn.substr(0, size2/4));
-
- // output the input sizes for a graph here
- iv_file << size1 << "\t" << size2 << "\n";
-
- if (((i+1) % stepsize) == 0)
- {
- std::cout << ".";
- std::cout.flush();
- }
- }
-
- std::cout << std::endl;
-
- iv_file.close();
-}
-
-void benchmark_runner::write_input_vector_plotfile(unsigned int x, unsigned int y) const
-{
- std::ofstream pf("input_vecs.plt");
- if (!pf.is_open())
- throw std::runtime_error("couldn't open plotfile");
- pf << "set term png size " << x << "," << y << "\n"
- "set output \"input_vecs.png\"\n"
- "set title \"input size of operands\"\n"
- "set key left\n"
- "set xlabel \"operand number\"\n"
- "set ylabel \"size in bits\"\n"
- "plot \"input_vecs.dat\" using 0:1 title \"operand 1 size\" with lines,\\\n"
- " \"input_vecs.dat\" using 0:2 title \"operand 2 size\" with lines";
-}
-
-void benchmark_runner::init_libs()
-{
- const unsigned long min_size =
- std::min(get_operand1_size(0),
- get_operand2_size(0));
-
- const unsigned long max_size =
- std::max(get_operand1_size(num_input_samples_),
- get_operand2_size(num_input_samples_));
-
- create_input_vectors(min_size, max_size);
-
- const unsigned int stepsize = num_input_samples_ / 10;
   for (library_vec::iterator lib = libs_.begin(); lib != libs_.end(); ++lib)
   {
- (*lib)->set_num_input_samples(num_input_samples_);
+ (*lib)->set_num_input_samples(vec1.size());
     
     // init ctor strings
- std::string hex_s = create_random_hex_string(max_size);
- std::string dec_s = create_random_dec_string(max_size);
+ (*lib)->hex_str = hex_str_vec;
+ (*lib)->dec_str = dec_str_vec;
 
- for (unsigned int i = 0; i < num_input_samples_; ++i)
- {
- (*lib)->hex_str.push_back(hex_s.substr(0, get_operand1_size(i)/4));
- (*lib)->dec_str.push_back(dec_s.substr(0, get_operand1_size(i)));
- }
-
-
- std::cout << (*lib)->name() << "->"
- << "constructing operand 1 input vector";
+ std::cout << (*lib)->name() << "->constructing operand 1 input vector";
     std::cout.flush();
 
- for (unsigned int i = 0; i < num_input_samples_; ++i)
+ for (unsigned int i = 0; i < vec1.size(); ++i)
     {
- (*lib)->construct_operand_1(string_vec1_[i], i);
+ (*lib)->construct_operand_1(vec1[i], i);
       if (((i+1) % stepsize) == 0)
       {
         std::cout << ".";
@@ -184,13 +45,12 @@
     }
     std::cout << std::endl;
 
- std::cout << (*lib)->name() << "->"
- << "constructing operand 2 input vector";
+ std::cout << (*lib)->name() << "->constructing operand 2 input vector";
     std::cout.flush();
 
- for (unsigned int i = 0; i < num_input_samples_; ++i)
+ for (unsigned int i = 0; i < vec2.size(); ++i)
     {
- (*lib)->construct_operand_2(string_vec2_[i], i);
+ (*lib)->construct_operand_2(vec2[i], i);
       if (((i+1) % stepsize) == 0)
       {
         std::cout << ".";
@@ -199,6 +59,16 @@
     }
     std::cout << std::endl;
   }
+
+ results_.clear();
+
+ for (std::vector<std::string>::const_iterator op = ops.begin(); op != ops.end(); ++op)
+ execute_bench_op(*op, sample_time);
+}
+
+void benchmark_runner::add_library(const boost::shared_ptr<benchmark_base>& b)
+{
+ libs_.push_back(b);
 }
 
 void benchmark_runner::execute_bench_op(const std::string& op, double sample_time)
@@ -217,134 +87,3 @@
   }
 }
 
-void benchmark_runner::create_data_files()
-{
- result_list::const_iterator r = results_.begin();
-
- // expects result list to be sorted by op name
- while (r != results_.end())
- {
- data_file d;
- result_list::const_iterator cur = r;
- while (r != results_.end() && r->op == cur->op)
- {
- data_file::column c;
-
- c.libname = r->libname;
- c.data = r->ops;
-
- // scale from ops per sample_time_ to ops per second
- /*const double scale = 1.0 / r->sample_time;
- for (std::vector<double>::iterator it = c.data.begin();
- it != c.data.end(); ++it)
- *it *= scale;*/
-
- c.total_ops = std::accumulate(r->ops.begin(), r->ops.end(), 0.);
- d.cols.push_back(c);
- ++r;
- }
-
- d.op = cur->op;
-
- d.cols.sort();
- dfiles_.push_back(d);
- }
-}
-
-void benchmark_runner::write_data_files() const
-{
- for (std::list<data_file>::const_iterator it = dfiles_.begin();
- it != dfiles_.end(); ++it)
- it->write();
-}
-
-void benchmark_runner::write_gnuplot_scripts(unsigned int x, unsigned int y) const
-{
- write_input_vector_plotfile(x, y);
- for (std::list<data_file>::const_iterator it = dfiles_.begin();
- it != dfiles_.end(); ++it)
- it->write_gnuplot_script(x, y);
-}
-
-void benchmark_runner::write_summary_file() const
-{
- std::ostringstream s;
- for (std::list<data_file>::const_iterator d = dfiles_.begin();
- d != dfiles_.end(); ++d)
- {
- s << d->op << "\n";
- for (std::list<data_file::column>::const_iterator c = d->cols.begin();
- c != d->cols.end(); ++ c)
- {
- s << c->libname << " total ops = " << c->total_ops << "\n";
- }
- }
-
- std::cout << s.str();
-
- std::ofstream file("summary.txt");
- if (!file.is_open())
- throw std::runtime_error("couldn't open summary.txt file");
- file << s.str();
-}
-
-void benchmark_runner::write_results(unsigned int x, unsigned int y) const
-{
- std::cout << "writing data files..." << std::endl;
- write_data_files();
- std::cout << "writing gnuplot scripts..." << std::endl;
- write_gnuplot_scripts(x, y);
- write_summary_file();
-}
-
-
-void data_file::write() const
-{
- const std::string filename(op + ".dat");
- std::ofstream file(filename.c_str());
- if (!file.is_open())
- throw std::runtime_error("couldn't open data file");
-
- const unsigned int col_len = cols.front().data.size();
- for (unsigned int i = 0; i < col_len; ++i)
- {
- std::list<column>::const_iterator it = cols.begin();
-
- while (it != cols.end())
- {
- file << it->data.at(i);
-
- if (++it != cols.end())
- file << "\t";
- }
- file << "\n";
- }
-}
-
-void data_file::write_gnuplot_script(unsigned int x, unsigned int y) const
-{
- const std::string filename(op + ".plt");
- std::ofstream file(filename.c_str());
- if (!file.is_open())
- throw std::runtime_error("couldn't open plot file");
-
- file << "set title \"" << op << "\"\n"
- "set xlabel " << "\"operand index\"\n"
- "set ylabel " << "\"ops/msec\"\n"
- "set autoscale\n"
- "set term png size " << x << "," << y << "\n"
- "set output \"" << op << ".png\"\n";
- file << "plot \\\n";
-
- std::list<column>::const_iterator it = cols.begin();
- int count = 1;
- while (it != cols.end())
- {
- file << '"' << op << ".dat\" using 0:" << count++ << " title \""
- << it->libname << "\" with lines";
- if (++it != cols.end())
- file << ",\\\n";
- }
- file << std::endl;
-}
-

Modified: sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_runner.hpp
==============================================================================
--- sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_runner.hpp (original)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_runner.hpp 2008-11-03 14:18:42 EST (Mon, 03 Nov 2008)
@@ -10,69 +10,30 @@
 #include "benchmark.hpp"
 
 
-struct data_file
-{
- struct column
- {
- std::string libname;
- std::vector<double> data;
- double total_ops;
- bool operator < (const column& rhs) const { return libname < rhs.libname; }
- };
-
- std::string op;
-
- std::list<column> cols;
-
- void write() const;
- void write_gnuplot_script(unsigned int x, unsigned int y) const;
-};
-
-
 struct benchmark_runner
 {
- benchmark_runner(unsigned int num_input_samples,
- unsigned long operand_size_beg,
- unsigned long operand_size_end);
-
   // add a library
   void add_library(const boost::shared_ptr<benchmark_base>& b);
   
   // benches all operations given in ops
- void run(const std::vector<std::string>& ops, double sample_time);
-
- void write_data_files() const;
- void write_gnuplot_scripts(unsigned int x, unsigned int y) const;
- void write_summary_file() const;
-
- void write_results(unsigned int x, unsigned int y) const;
+ void run(const std::vector<std::string>& ops,
+ double sample_time,
+ const std::vector<std::string>& vec1,
+ const std::vector<std::string>& vec2,
+ const std::vector<std::string>& hex_str_vec,
+ const std::vector<std::string>& dec_str_vec);
 
   void execute_bench_op(const std::string& op, double sample_time);
 
-private:
-
- void init_libs();
+ std::list<benchmark_result>& get_results() { return results_; }
 
- void create_data_files();
-
- void create_input_vectors(unsigned long min, unsigned long max);
- void write_input_vector_plotfile(unsigned int x, unsigned int y) const;
+private:
 
- unsigned long get_operand1_size(unsigned int) const;
- unsigned long get_operand2_size(unsigned int) const;
-
   typedef std::vector<boost::shared_ptr<benchmark_base> > library_vec;
   typedef std::list<benchmark_result> result_list;
 
- const unsigned int num_input_samples_;
- const unsigned long beg_;
- const unsigned long end_;
- std::vector<std::string> string_vec1_;
- std::vector<std::string> string_vec2_;
   library_vec libs_;
   result_list results_;
-
- std::list<data_file> dfiles_;
 };
 
 

Modified: sandbox/mp_math/libs/mp_math/tools/benchmark/jamfile.v2
==============================================================================
--- sandbox/mp_math/libs/mp_math/tools/benchmark/jamfile.v2 (original)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/jamfile.v2 2008-11-03 14:18:42 EST (Mon, 03 Nov 2008)
@@ -12,13 +12,12 @@
     <include>../../../..
     <include>.
     <link>static
- <toolset>gcc:<cxxflags>"-march=i686 -mtune=generic"
   ;
 
 
 
-# GMP (GNU Multiple Precision Arithmetic, http://gmplib.org/) library need to be
-# installed for the benchmark to work
+# GMP (GNU Multiple Precision Arithmetic, http://gmplib.org/) library needs to
+# be installed for the benchmark to work
 # gmpxx is the library for the C++ bindings of gmp
 lib gmpxx : : <name>gmpxx ;
 lib gmp : : <name>gmp ;
@@ -33,13 +32,13 @@
     benchmark_libtom.cpp
     benchmark_gmp.cpp
     main.cpp
+ modes.cpp
     tommath
     gmpxx gmp
     boost_fs
     boost_po
   :
     <variant>release
- <toolset>gcc:<cxxflags>-std=c++0x #-DBOOST_MP_MATH_MP_INT_USE_ASM"
   ;
 
 

Modified: sandbox/mp_math/libs/mp_math/tools/benchmark/main.cpp
==============================================================================
--- sandbox/mp_math/libs/mp_math/tools/benchmark/main.cpp (original)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/main.cpp 2008-11-03 14:18:42 EST (Mon, 03 Nov 2008)
@@ -15,18 +15,38 @@
 #include "benchmark_libtom.hpp"
 #include "benchmark_gmp.hpp"
 
+#include "modes.hpp"
 
-const char* version = "0.3";
+
+const char* version = "0.4";
 
 
 struct config
 {
- unsigned int graph_x, graph_y;
+ // mode can be 0, 1 or 2 which is:
+ // 0) run all modes
+ // 1) run with continuously sized operands, this benchmark takes long because
+ // it uses num_input_samples (default = 1000) operands, so it should be
+ // used for smaller numbers.
+ // 2) run benchmark with operands that are a power of two, this should be used
+ // to get a 'quick' look into how the functions perform for very large
+ // numbers.
+ unsigned int mode;
+
+ // mode 1 options
   unsigned int num_input_samples;
   double max_error;
   double sample_time;
   std::pair<unsigned int, unsigned int> range;
 
+ // mode 2 options
+ unsigned int pow_from;
+ unsigned int pow_to;
+ unsigned int pow_step;
+
+ // general options
+ unsigned int graph_x, graph_y;
+
   typedef std::vector<std::string> string_list;
   // we receive these two strings from the cmdline and need to tokenize them
   std::string ops_string;
@@ -75,7 +95,18 @@
 
 double config::estimated_run_time() const
 {
- return sample_time * num_input_samples * ops.size() * libs.size();
+ const double mode1_time =
+ sample_time * num_input_samples * ops.size() * libs.size();
+
+ const double mode2_time = 0.05 * ops.size() * libs.size();
+
+ double sum = 0.0;
+ if (mode == 0 || mode == 1)
+ sum += mode1_time;
+ if (mode == 0 || mode == 2)
+ sum += mode2_time;
+
+ return sum;
 }
 
 
@@ -86,7 +117,7 @@
   double st = 0.01;
   
   int verified = 0;
- while (true)
+ for (;;)
   {
     for (int k = 0; k < vec_length; ++k)
     {
@@ -167,10 +198,39 @@
 
     ("version,v", "print version")
 
+ ("mode,m",
+ value(&c.mode)->default_value(1),
+ "0 = run all benchmarks\n"
+ "1 = run benchmark meant to test small numbers\n"
+ "2 = run benchmark meant to test large numbers")
+
+ ("ops",
+ value(&c.ops_string),
+ "the operations to benchmark")
+
+ ("libs",
+ value(&c.libs_string),
+ "the libraries to benchmark")
+
+ ("list-ops", "lists available operations")
+
+ ("list-libs", "lists available libraries")
+
+ ("x",
+ value(&c.graph_x)->default_value(1024),
+ "width of graphs created by gnuplot")
+ ("y",
+ value(&c.graph_y)->default_value(768),
+ "height of graphs created by gnuplot")
+ ;
+
+ options_description mode1_opts("Mode 1 options");
+
+ mode1_opts.add_options()
     ("num-input-samples,n",
         value(&c.num_input_samples)->default_value(1000),
           "number of input samples to create")
-
+
     ("max-error,e",
         value(&c.max_error)->default_value(0.1, "0.1"),
           "this value is used to calculate the sample time, you should not "
@@ -188,27 +248,28 @@
     ("range-end,b",
         value(&c.range.second)->default_value(3072),
           "range of numbers, measured in bits")
-
- ("ops",
- value(&c.ops_string),
- "the operations to benchmark")
-
- ("libs",
- value(&c.libs_string),
- "the libraries to benchmark")
-
- ("list-ops", "lists available operations")
-
- ("list-libs", "lists available libraries")
+ ;
 
- ("x",
- value(&c.graph_x)->default_value(1024),
- "width of graphs created by gnuplot")
- ("y",
- value(&c.graph_y)->default_value(768),
- "height of graphs created by gnuplot")
+ options_description mode2_opts("Mode 2 options");
+
+ mode2_opts.add_options()
+
+ ("pow-from,f",
+ value(&c.pow_from)->default_value(7),
+ "the first power of two to use")
+
+ ("pow-to,t",
+ value(&c.pow_to)->default_value(21),
+ "the last power of two to use")
+
+ ("pow-step,q",
+ value(&c.pow_step)->default_value(1),
+ "the stepsize used to iterate through the powers of two")
     ;
 
+ opts.add(mode1_opts);
+ opts.add(mode2_opts);
+
   variables_map vm;
 
   store(parse_command_line(argc, argv, opts), vm);
@@ -271,7 +332,7 @@
   boost::filesystem::current_path(timestring);
 
 
- benchmark_runner b_runner(c.num_input_samples, c.range.first, c.range.second);
+ benchmark_runner b_runner;
 
   std::cout << "Libraries that we are about to benchmark:\n";
   for (string_list::const_iterator lib = c.libs.begin();
@@ -282,7 +343,7 @@
     b_runner.add_library(p);
   }
 
- if (!vm.count("sample-time"))
+ if (vm.count("sample-time") && c.sample_time == 0.0)
   {
     std::cout << "calibrating sample time..." << std::endl;
     c.sample_time = calibrate_sample_time(c.max_error);
@@ -290,13 +351,33 @@
     
   std::cout << "Sample time is: " << c.sample_time << " sec" << std::endl;
 
- const double runtime = c.estimated_run_time();
+ const unsigned long runtime =
+ static_cast<unsigned long>(c.estimated_run_time()/60.0);
   std::cout << "Estimated run time of benchmark is at least "
- << (long)(runtime/60.0) << " minutes, but could be much longer for "
+ << runtime << " minute(s), but will be much longer for "
             << "very large numbers." << std::endl;
 
- b_runner.run(c.ops, c.sample_time);
- b_runner.write_results(c.graph_x, c.graph_y);
+ if (c.mode == 0 || c.mode == 1)
+ {
+ std::cout << "Entering mode 1..." << std::endl;
+ mode1 m1(c.num_input_samples, c.range.first, c.range.second);
+ b_runner.run(c.ops, c.sample_time,
+ m1.vec1, m1.vec2,
+ m1.hex_str_vec, m1.dec_str_vec);
+ m1.create_data_files(b_runner.get_results());
+ m1.write_results(c.graph_x, c.graph_y);
+ }
+
+ if (c.mode == 0 || c.mode == 2)
+ {
+ std::cout << "Entering mode 2..." << std::endl;
+ mode2 m2(c.pow_from, c.pow_to, c.pow_step);
+ b_runner.run(c.ops, 0.05,
+ m2.vec1, m2.vec2,
+ m2.hex_str_vec, m2.dec_str_vec);
+ m2.create_data_files(b_runner.get_results());
+ m2.write_results(c.graph_x, c.graph_y);
+ }
 
   std::cout << "done with benchmarking!" << std::endl;
 
@@ -304,8 +385,8 @@
   std::cout << "calling \'gnuplot *.plt\'" << std::endl;
   const int ret = std::system("gnuplot *.plt");
   if (ret)
- std::cout << "something went wrong, received the error code " << ret
- << std::endl;
+ std::cout << "something went wrong, gnuplot call exited with code " << ret
+ << std::endl;
   else
     std::cout << "done" << std::endl;
 

Added: sandbox/mp_math/libs/mp_math/tools/benchmark/modes.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/modes.cpp 2008-11-03 14:18:42 EST (Mon, 03 Nov 2008)
@@ -0,0 +1,426 @@
+// Copyright Kevin Sopp 2008.
+// 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 <cmath>
+#include <fstream>
+#include <iostream>
+#include <numeric> // accumulate
+#include <sstream>
+#include <stdexcept>
+#include <boost/random.hpp>
+#include <boost/mp_math/mp_int.hpp>
+
+#include "modes.hpp"
+
+std::string create_random_hex_string(unsigned size_in_bits)
+{
+ std::string s;
+ s.reserve(size_in_bits/4);
+
+ boost::mt19937 r;
+ boost::uniform_smallint<char> u(0,15);
+ boost::variate_generator<boost::mt19937&, boost::uniform_smallint<char> > vg(r, u);
+ // one hex digit occupies 4 bits
+ for (unsigned i = 0; i < (size_in_bits+3)/4; ++i)
+ {
+ char tmp = vg();
+ if (tmp < 10)
+ tmp = '0' + tmp;
+ else
+ tmp = 'a' + (tmp-10);
+ s.push_back(tmp);
+ }
+ return s;
+}
+
+std::string create_random_dec_string(unsigned size_in_digits)
+{
+ std::string s;
+ s.reserve(size_in_digits);
+
+ boost::mt19937 r;
+ boost::uniform_smallint<char> u(0,9);
+ boost::variate_generator<boost::mt19937&, boost::uniform_smallint<char> > vg(r, u);
+
+ for (unsigned i = 0; i < size_in_digits; ++i)
+ s.push_back('0' + vg());
+
+ return s;
+}
+
+
+void data_file::write(const std::string& prefix) const
+{
+ const std::string filename(prefix + op + ".dat");
+ std::ofstream file(filename.c_str());
+ if (!file.is_open())
+ throw std::runtime_error("couldn't open data file");
+
+ for (unsigned int i = 0; i < cols.front().data.size(); ++i)
+ {
+ file << x_values.at(i) << "\t";
+
+ std::list<column>::const_iterator it = cols.begin();
+
+ while (it != cols.end())
+ {
+ file << it->data.at(i);
+
+ if (++it != cols.end())
+ file << "\t";
+ }
+ file << "\n";
+ }
+}
+
+
+void write_gnuplot_scripts(unsigned int x, unsigned int y,
+ const std::string& modeprefix,
+ const std::string& xlabel,
+ const std::string& ylabel,
+ const std::list<data_file>& dfiles)
+{
+ for (std::list<data_file>::const_iterator df = dfiles.begin();
+ df != dfiles.end(); ++df)
+ {
+ const std::string filename(modeprefix + df->op + ".plt");
+ std::ofstream file(filename.c_str());
+ if (!file.is_open())
+ throw std::runtime_error("couldn't open plot file");
+
+ file << "set title \"" << df->op << "\"\n"
+ "set xlabel " << "\"" << xlabel << "\"\n"
+ "set ylabel " << "\"" << ylabel << "\"\n"
+ "set autoscale\n"
+ "set term png size " << x << "," << y << "\n"
+ "set output \"" << modeprefix << df->op << ".png\"\n";
+ file << "plot \\\n";
+
+ std::list<data_file::column>::const_iterator c = df->cols.begin();
+ int count = 2;
+ while (c != df->cols.end())
+ {
+ file << '"' << modeprefix << df->op << ".dat\" using 1:" << count++
+ << " title \"" << c->libname << "\" with lines";
+ if (++c != df->cols.end())
+ file << ",\\\n";
+ }
+ file << std::endl;
+ }
+}
+
+void write_data_files(const std::string& modeprefix,
+ const std::list<data_file>& dfiles)
+{
+ for (std::list<data_file>::const_iterator it = dfiles.begin();
+ it != dfiles.end(); ++it)
+ it->write(modeprefix);
+}
+
+
+mode1::mode1(unsigned int num_input_samples,
+ unsigned long operand_size_beg,
+ unsigned long operand_size_end)
+:
+ beg_(operand_size_beg ? operand_size_beg : 1), // zero length not allowed
+ end_(operand_size_end),
+ num_input_samples_(num_input_samples)
+{
+ std::ofstream iv_file("mode1_input_vecs.dat");
+ if (!iv_file.is_open())
+ throw std::runtime_error("couldn't open file mode1_input_vecs.dat");
+
+ const unsigned long min_size =
+ std::min(get_operand1_size(0),
+ get_operand2_size(0));
+
+ const unsigned long max_size =
+ std::max(get_operand1_size(num_input_samples_),
+ get_operand2_size(num_input_samples_));
+
+ std::cout << "Creating " << num_input_samples_
+ << " operand indices for numbers between "
+ << min_size << " and " << max_size << " bits."
+ << std::endl;
+
+ const std::string hex_s = create_random_hex_string(max_size);
+
+ std::cout << "creating input vectors";
+ std::cout.flush();
+
+ vec1.reserve(num_input_samples_);
+ vec2.reserve(num_input_samples_);
+ hex_str_vec.reserve(num_input_samples_);
+ dec_str_vec.reserve(num_input_samples_);
+
+ // create input vector where number size is determined by the sine function
+ const unsigned int stepsize = num_input_samples_ / 10;
+ for (unsigned int i = 0; i < num_input_samples_; ++i)
+ {
+ const unsigned long size1 = get_operand1_size(i);
+ const unsigned long size2 = get_operand2_size(i);
+
+ // divide by 4 because hex_s has max/4 hex digits
+ vec1.push_back(hex_s.substr(0, size1/4));
+ vec2.push_back(hex_s.substr(0, size2/4));
+
+ // output the input sizes for a graph here
+ iv_file << size1 << "\t" << size2 << "\n";
+
+ if (((i+1) % stepsize) == 0)
+ {
+ std::cout << ".";
+ std::cout.flush();
+ }
+ }
+
+ std::cout << std::endl;
+
+ iv_file.close();
+
+ // init ctor strings
+ for (unsigned int i = 0; i < num_input_samples_; ++i)
+ {
+ hex_str_vec.push_back(hex_s.substr(0, (get_operand1_size(i)+3)/4));
+ // use mp_int to ensure decimal string results in the same number of bits as
+ // the hex string
+ boost::mp_math::mp_int<> tmp(hex_str_vec.back(), std::ios::hex);
+ dec_str_vec.push_back(tmp.to_string<std::string>());
+ }
+}
+
+void mode1::create_data_files(std::list<benchmark_result>& results)
+{
+ std::list<benchmark_result>::const_iterator r = results.begin();
+
+ // expects result list to be sorted by op name
+ while (r != results.end())
+ {
+ data_file d;
+
+ for (unsigned i = 0; i < num_input_samples_; ++i)
+ d.x_values.push_back(i);
+
+ std::list<benchmark_result>::const_iterator cur = r;
+ while (r != results.end() && r->op == cur->op)
+ {
+ data_file::column c;
+
+ c.libname = r->libname;
+ c.data = r->ops;
+
+ // scale from ops per sample_time to ops per millisecond
+ for (std::vector<double>::iterator it = c.data.begin();
+ it != c.data.end(); ++it)
+ *it /= (r->sample_time * 1000.0);
+
+ c.sum = std::accumulate(r->ops.begin(), r->ops.end(), 0.);
+ d.cols.push_back(c);
+ ++r;
+ }
+
+ d.op = cur->op;
+
+ d.cols.sort();
+
+ dfiles_.push_back(d);
+ }
+}
+
+void mode1::write_input_vector_plotfile(unsigned int x, unsigned int y) const
+{
+ std::ofstream pf("mode1_input_vecs.plt");
+ if (!pf.is_open())
+ throw std::runtime_error("couldn't open plotfile");
+ pf << "set term png size " << x << "," << y << "\n"
+ "set output \"mode1_input_vecs.png\"\n"
+ "set title \"input size of operands\"\n"
+ "set key left\n"
+ "set xlabel \"operand number\"\n"
+ "set ylabel \"size in bits\"\n"
+ "plot \"mode1_input_vecs.dat\" using 0:1 title \"operand 1 size\" with lines,\\\n"
+ " \"mode1_input_vecs.dat\" using 0:2 title \"operand 2 size\" with lines";
+}
+
+void mode1::write_summary_file() const
+{
+ std::ostringstream s;
+ for (std::list<data_file>::const_iterator d = dfiles_.begin();
+ d != dfiles_.end(); ++d)
+ {
+ s << d->op << "------------------------------------\n";
+ for (std::list<data_file::column>::const_iterator c = d->cols.begin();
+ c != d->cols.end(); ++ c)
+ {
+ s << c->libname << " total ops = " << c->sum << "\n";
+ }
+ }
+
+ std::cout << s.str();
+
+ std::ofstream file("mode1_summary.txt");
+ if (!file.is_open())
+ throw std::runtime_error("couldn't open mode1_summary.txt file");
+ file << s.str();
+}
+
+void mode1::write_results(unsigned int x, unsigned int y) const
+{
+ write_input_vector_plotfile(x, y);
+
+ std::cout << "writing data files..." << std::endl;
+ write_data_files("mode1_", dfiles_);
+
+ std::cout << "writing gnuplot scripts..." << std::endl;
+ write_gnuplot_scripts(x, y, "mode1_", "operand index", "ops/msec", dfiles_);
+
+ write_summary_file();
+}
+
+
+unsigned long mode1::get_operand1_size(unsigned int sample_number) const
+{
+ // linear growth
+ const double m = static_cast<double>(end_ - beg_) /
+ static_cast<double>(num_input_samples_);
+ return (m * sample_number) + beg_;
+}
+
+unsigned long mode1::get_operand2_size(unsigned int sample_number) const
+{
+ // modified sine curve
+ const double pi = 3.141592654;
+ const double sample_num_to_rad = num_input_samples_ / (4.5 * pi);
+
+ // scale sample_number into the range [0...4.5*PI]
+ const double x = sample_number / sample_num_to_rad;
+
+ const double y_val = std::sin(x) + 1.0;
+
+ const double y_top = get_operand1_size(sample_number);
+ const double p0 = pi;
+ double y_bottom;
+ if (x <= p0)
+ y_bottom = y_top / (x / p0 * 2.0 + 1.0) + 1.0;
+ else
+ y_bottom = y_top / 3.0;
+
+ // we want to scale the curve at the point p1 to be above y_top at x = 2.5*pi
+ const double p1 = 2.5 * pi;
+
+ // here we use a function of the form y = -ax^2 + b to scale the curve at (and
+ // around) p1
+ const double a = 1.0/(p1 * p1);
+ double adjust = -a * ((x-p1) * (x-p1)) + 1.0;
+ // scale to be 10% above p1
+ adjust *= 1.1;
+ // stop scaling once we're past p1 and 'adjust' falls below 1.0
+ if (x > p1 && adjust < 1.0)
+ adjust = 1.0;
+
+ return static_cast<unsigned long>(y_bottom * adjust * y_val + y_bottom);
+}
+
+
+mode2::mode2(unsigned int pow_from, unsigned int pow_to, unsigned int stepsize)
+:
+ pow_from_(pow_from),
+ pow_to_(pow_to),
+ pow_step_(stepsize)
+{
+ const unsigned long max_size = 1UL << pow_to;
+
+ const std::string hex_s = create_random_hex_string((max_size+3)/4);
+
+ for (; pow_from < pow_to; pow_from += stepsize)
+ {
+ const unsigned long size = 1UL << pow_from;
+
+ vec1.push_back(hex_s.substr(0, size/4));
+
+ hex_str_vec.push_back(hex_s.substr(0, (size+3)/4));
+
+ boost::mp_math::mp_int<> tmp(hex_str_vec.back(), std::ios::hex);
+ dec_str_vec.push_back(tmp.to_string<std::string>());
+ }
+
+ vec2 = vec1;
+}
+
+
+void mode2::create_data_files(std::list<benchmark_result>& results)
+{
+ std::list<benchmark_result>::const_iterator r = results.begin();
+
+ // expects result list to be sorted by op name
+ while (r != results.end())
+ {
+ data_file d;
+
+ for (unsigned i = pow_from_; i < pow_to_; i += pow_step_)
+ d.x_values.push_back(i);
+
+ std::list<benchmark_result>::const_iterator cur = r;
+ while (r != results.end() && r->op == cur->op)
+ {
+ data_file::column c;
+
+ c.libname = r->libname;
+ c.data = r->ops;
+
+ // scale from ops per sample_time to seconds per op
+ for (std::vector<double>::iterator it = c.data.begin();
+ it != c.data.end(); ++it)
+ {
+ *it /= r->sample_time;
+ *it = 1.0 / *it;
+ }
+
+ c.sum = std::accumulate(r->ops.begin(), r->ops.end(), 0.);
+ d.cols.push_back(c);
+ ++r;
+ }
+
+ d.op = cur->op;
+
+ d.cols.sort();
+ dfiles_.push_back(d);
+ }
+}
+
+void mode2::write_summary_file() const
+{
+ std::ostringstream s;
+ for (std::list<data_file>::const_iterator d = dfiles_.begin();
+ d != dfiles_.end(); ++d)
+ {
+ s << d->op << "------------------------------------\n";
+ for (std::list<data_file::column>::const_iterator c = d->cols.begin();
+ c != d->cols.end(); ++ c)
+ {
+ s << c->libname << " total seconds = " << c->sum << "\n";
+ }
+ }
+
+ std::cout << s.str();
+
+ std::ofstream file("mode2_summary.txt");
+ if (!file.is_open())
+ throw std::runtime_error("couldn't open mode2_summary.txt file");
+ file << s.str();
+}
+
+void mode2::write_results(unsigned int x, unsigned int y) const
+{
+ std::cout << "writing data files..." << std::endl;
+ write_data_files("mode2_", dfiles_);
+
+ std::cout << "writing gnuplot scripts..." << std::endl;
+ write_gnuplot_scripts(x, y, "mode2_", "operand size (2^x)", "seconds/op",
+ dfiles_);
+
+ write_summary_file();
+}
+

Added: sandbox/mp_math/libs/mp_math/tools/benchmark/modes.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/modes.hpp 2008-11-03 14:18:42 EST (Mon, 03 Nov 2008)
@@ -0,0 +1,99 @@
+// Copyright Kevin Sopp 2008.
+// 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)
+
+#ifndef BOOST_MP_MATH_TOOLS_MODES_HPP
+#define BOOST_MP_MATH_TOOLS_MODES_HPP
+
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark.hpp"
+
+
+std::string create_random_hex_string(unsigned size_in_bits);
+std::string create_random_dec_string(unsigned size_in_digits);
+
+
+struct data_file
+{
+ struct column
+ {
+ std::string libname;
+ std::vector<double> data;
+ double sum;
+ bool operator < (const column& rhs) const { return libname < rhs.libname; }
+ };
+
+ std::string op;
+
+ std::vector<unsigned> x_values;
+ std::list<column> cols; // the y-values
+
+ void write(const std::string& prefix) const;
+};
+
+
+void write_gnuplot_scripts(unsigned int x, unsigned int y,
+ const std::string& modeprefix,
+ const std::string& xlabel,
+ const std::string& ylabel,
+ const std::list<data_file>& dfiles);
+
+void write_data_files(const std::string& modeprefix,
+ const std::list<data_file>& dfiles);
+
+
+struct mode1
+{
+ mode1(unsigned int num_input_samples,
+ unsigned long operand_size_beg,
+ unsigned long operand_size_end);
+
+ void create_data_files(std::list<benchmark_result>&);
+ void write_input_vector_plotfile(unsigned int x, unsigned int y) const;
+ void write_summary_file() const;
+
+ void write_results(unsigned int x, unsigned int y) const;
+
+ std::vector<std::string> hex_str_vec; // hex ctor strings
+ std::vector<std::string> dec_str_vec; // dec ctor strings
+ std::vector<std::string> vec1;
+ std::vector<std::string> vec2;
+
+private:
+
+ unsigned long get_operand1_size(unsigned int sample_numer) const;
+ unsigned long get_operand2_size(unsigned int sample_numer) const;
+
+ unsigned long beg_, end_;
+ unsigned int num_input_samples_;
+ std::list<data_file> dfiles_;
+};
+
+
+struct mode2
+{
+ mode2(unsigned int pow_from, unsigned int pow_to, unsigned int stepsize);
+
+ void create_data_files(std::list<benchmark_result>&);
+ void write_summary_file() const;
+
+ void write_results(unsigned int x, unsigned int y) const;
+
+ std::vector<std::string> hex_str_vec; // hex ctor strings
+ std::vector<std::string> dec_str_vec; // dec ctor strings
+ std::vector<std::string> vec1;
+ std::vector<std::string> vec2;
+
+private:
+
+ unsigned int pow_from_, pow_to_, pow_step_;
+ std::list<data_file> dfiles_;
+};
+
+
+#endif
+


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