$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: john_at_[hidden]
Date: 2007-12-22 14:01:38
Author: johnmaddock
Date: 2007-12-22 14:01:37 EST (Sat, 22 Dec 2007)
New Revision: 42244
URL: http://svn.boost.org/trac/boost/changeset/42244
Log:
Added trunc, round and fmod family of functions.
Added:
   sandbox/math_toolkit/boost/math/special_functions/modf.hpp   (contents, props changed)
   sandbox/math_toolkit/boost/math/special_functions/round.hpp   (contents, props changed)
   sandbox/math_toolkit/boost/math/special_functions/trunc.hpp   (contents, props changed)
   sandbox/math_toolkit/libs/math/test/test_round.cpp   (contents, props changed)
Text files modified: 
   sandbox/math_toolkit/libs/math/test/Jamfile.v2 |     1 +                                       
   1 files changed, 1 insertions(+), 0 deletions(-)
Added: sandbox/math_toolkit/boost/math/special_functions/modf.hpp
==============================================================================
--- (empty file)
+++ sandbox/math_toolkit/boost/math/special_functions/modf.hpp	2007-12-22 14:01:37 EST (Sat, 22 Dec 2007)
@@ -0,0 +1,50 @@
+//  Copyright John Maddock 2007.
+//  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_MODF_HPP
+#define BOOST_MATH_MODF_HPP
+
+#ifdef _MSC_VER
+#pragma once
+#endif
+
+#include <boost/math/tools/config.hpp>
+#include <boost/math/special_functions/trunc.hpp>
+
+namespace boost{ namespace math{
+
+template <class T>
+inline T modf(const T& v, T* ipart)
+{
+   *ipart = trunc(v);
+   return v - *ipart;
+}
+
+template <class T>
+inline T modf(const T& v, int* ipart)
+{
+   *ipart = itrunc(v);
+   return v - *ipart;
+}
+
+template <class T>
+inline T modf(const T& v, long* ipart)
+{
+   *ipart = ltrunc(v);
+   return v - *ipart;
+}
+
+#ifdef BOOST_HAS_LONG_LONG
+template <class T>
+inline T modf(const T& v, long long* ipart)
+{
+   *ipart = lltrunc(v);
+   return v - *ipart;
+}
+#endif
+
+}} // namespaces
+
+#endif // BOOST_MATH_MODF_HPP
Added: sandbox/math_toolkit/boost/math/special_functions/round.hpp
==============================================================================
--- (empty file)
+++ sandbox/math_toolkit/boost/math/special_functions/round.hpp	2007-12-22 14:01:37 EST (Sat, 22 Dec 2007)
@@ -0,0 +1,56 @@
+//  Copyright John Maddock 2007.
+//  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_ROUND_HPP
+#define BOOST_MATH_ROUND_HPP
+
+#ifdef _MSC_VER
+#pragma once
+#endif
+
+#include <boost/math/tools/config.hpp>
+
+namespace boost{ namespace math{
+
+template <class T>
+inline T round(const T& v)
+{
+   BOOST_MATH_STD_USING
+   return floor(v + 0.5f);
+}
+//
+// The following functions will not compile unless T has an
+// implicit convertion to the integer types.  For user-defined
+// number types this will likely not be the case.  In that case
+// these functions should either be specialized for the UDT in
+// question, or else overloads should be placed in the same 
+// namespace as the UDT: these will then be found via argument
+// dependent lookup.  See our concept archetypes for examples.
+//
+template <class T>
+inline int iround(const T& v)
+{
+   return static_cast<int>(boost::math::round(v));
+}
+
+template <class T>
+inline long lround(const T& v)
+{
+   return static_cast<long int>(boost::math::round(v));
+}
+
+#ifdef BOOST_HAS_LONG_LONG
+
+template <class T>
+inline long long llround(const T& v)
+{
+   return static_cast<long long>(boost::math::round(v));
+}
+
+#endif
+
+}} // namespaces
+
+#endif // BOOST_MATH_ROUND_HPP
Added: sandbox/math_toolkit/boost/math/special_functions/trunc.hpp
==============================================================================
--- (empty file)
+++ sandbox/math_toolkit/boost/math/special_functions/trunc.hpp	2007-12-22 14:01:37 EST (Sat, 22 Dec 2007)
@@ -0,0 +1,56 @@
+//  Copyright John Maddock 2007.
+//  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_TRUNC_HPP
+#define BOOST_MATH_TRUNC_HPP
+
+#ifdef _MSC_VER
+#pragma once
+#endif
+
+#include <boost/math/tools/config.hpp>
+
+namespace boost{ namespace math{
+
+template <class T>
+inline T trunc(const T& v)
+{
+   BOOST_MATH_STD_USING
+   return (v >= 0) ? floor(v) : ceil(v);
+}
+//
+// The following functions will not compile unless T has an
+// implicit convertion to the integer types.  For user-defined
+// number types this will likely not be the case.  In that case
+// these functions should either be specialized for the UDT in
+// question, or else overloads should be placed in the same 
+// namespace as the UDT: these will then be found via argument
+// dependent lookup.  See our concept archetypes for examples.
+//
+template <class T>
+inline int itrunc(const T& v)
+{
+   return static_cast<int>(boost::math::trunc(v));
+}
+
+template <class T>
+inline long ltrunc(const T& v)
+{
+   return static_cast<long int>(boost::math::trunc(v));
+}
+
+#ifdef BOOST_HAS_LONG_LONG
+
+template <class T>
+inline long long lltrunc(const T& v)
+{
+   return static_cast<long long>(boost::math::trunc(v));
+}
+
+#endif
+
+}} // namespaces
+
+#endif // BOOST_MATH_TRUNC_HPP
Modified: sandbox/math_toolkit/libs/math/test/Jamfile.v2
==============================================================================
--- sandbox/math_toolkit/libs/math/test/Jamfile.v2	(original)
+++ sandbox/math_toolkit/libs/math/test/Jamfile.v2	2007-12-22 14:01:37 EST (Sat, 22 Dec 2007)
@@ -299,6 +299,7 @@
 
 run test_remez.cpp ;
 run test_roots.cpp ;
+run test_round.cpp ;
 run test_spherical_harmonic.cpp ;
 run test_students_t.cpp ;
 run test_tgamma_ratio.cpp ;
Added: sandbox/math_toolkit/libs/math/test/test_round.cpp
==============================================================================
--- (empty file)
+++ sandbox/math_toolkit/libs/math/test/test_round.cpp	2007-12-22 14:01:37 EST (Sat, 22 Dec 2007)
@@ -0,0 +1,176 @@
+//  (C) Copyright John Maddock 2007.
+//  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)
+
+#include <boost/math/concepts/real_concept.hpp>
+#include <boost/test/included/test_exec_monitor.hpp>
+#include <boost/test/floating_point_comparison.hpp>
+#include <boost/math/special_functions/round.hpp>
+#include <boost/math/special_functions/trunc.hpp>
+#include <boost/math/special_functions/modf.hpp>
+#include <boost/math/special_functions/sign.hpp>
+#include <boost/random/mersenne_twister.hpp>
+
+boost::mt19937 rng;
+
+template <class T>
+T get_random()
+{
+   //
+   // Fill all the bits in T with random values, 
+   // likewise set the exponent to a random value
+   // that will still fit inside a T, and always
+   // have a remainder as well as an integer part.
+   //
+   int bits = boost::math::tools::digits<T>();
+   int shift = 0;
+   int exponent = rng() % (bits - 4);
+   T result = 0;
+   while(bits > 0)
+   {
+      result += ldexp(static_cast<T>(rng()), shift);
+      shift += std::numeric_limits<int>::digits;
+      bits -= std::numeric_limits<int>::digits;
+   }
+   return rng() & 1u ? -ldexp(frexp(result, &bits), exponent) : ldexp(frexp(result, &bits), exponent);
+}
+
+template <class T, class U>
+void check_within_half(T a, U u)
+{
+   if(fabs(a-u) > 0.5f)
+   {
+      BOOST_ERROR("Rounded result differed by more than 0.5 from the original");
+      std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
+         << std::left << a << u << std::endl;
+   }
+}
+
+//
+// We may not have an abs overload for long long so provide a fall back:
+//
+template <class T>
+inline T safe_abs(T const& v ...)
+{
+   return v < 0 ? -v : v;
+}
+
+template <class T, class U>
+void check_trunc_result(T a, U u)
+{
+   BOOST_MATH_STD_USING
+   using ::abs;
+   if(fabs(a-u) >= 1)
+   {
+      BOOST_ERROR("Rounded result differed by more than 1 from the original");
+      std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
+         << std::left << a << u << std::endl;
+   }
+   if(abs(a) < safe_abs(u))
+   {
+      BOOST_ERROR("Truncated result had larger absolute value than the original");
+      std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
+         << std::left << a << u << std::endl;
+   }
+}
+
+template <class T, class U>
+void check_modf_result(T a, T fract, U ipart)
+{
+   BOOST_MATH_STD_USING
+   if(fract + ipart != a)
+   {
+      BOOST_ERROR("Fractional and integer results do not add up to the original value");
+      std::cerr << "Values were: " << std::setprecision(35) << " "
+         << std::left << a << ipart << " " << fract << std::endl;
+   }
+   if((boost::math::sign(a) != boost::math::sign(fract)) && boost::math::sign(fract))
+   {
+      BOOST_ERROR("Original and fractional parts have differing signs");
+      std::cerr << "Values were: " << std::setprecision(35) << " "
+         << std::left << a << ipart << " " << fract << std::endl;
+   }
+   if((boost::math::sign(a) != boost::math::sign(ipart)) && boost::math::sign(ipart))
+   {
+      BOOST_ERROR("Original and integer parts have differing signs");
+      std::cerr << "Values were: " << std::setprecision(35) << " "
+         << std::left << a << ipart << " " << ipart << std::endl;
+   }
+   if(fabs(a-ipart) >= 1)
+   {
+      BOOST_ERROR("Rounded result differed by more than 1 from the original");
+      std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
+         << std::left << a << ipart << std::endl;
+   }
+}
+
+template <class T>
+void test_round(T, const char* name)
+{
+   BOOST_MATH_STD_USING
+
+   for(int i = 0; i < 1000; ++i)
+   {
+      T arg = get_random<T>();
+      T r = boost::math::round(arg);
+      check_within_half(arg, r);
+      r = boost::math::trunc(arg);
+      check_trunc_result(arg, r);
+      T frac = boost::math::modf(arg, &r);
+      check_modf_result(arg, frac, r);
+
+      if(abs(r) < (std::numeric_limits<int>::max)())
+      {
+         int i = boost::math::iround(arg);
+         check_within_half(arg, i);
+         i = boost::math::itrunc(arg);
+         check_trunc_result(arg, i);
+         r = boost::math::modf(arg, &i);
+         check_modf_result(arg, r, i);
+      }
+      
+      if(abs(r) < (std::numeric_limits<long>::max)())
+      {
+         long l = boost::math::lround(arg);
+         check_within_half(arg, l);
+         l = boost::math::ltrunc(arg);
+         check_trunc_result(arg, l);
+         r = boost::math::modf(arg, &l);
+         check_modf_result(arg, r, l);
+      }
+
+#ifdef BOOST_HAS_LONG_LONG
+      if(abs(r) < (std::numeric_limits<long long>::max)())
+      {
+         long long ll = boost::math::llround(arg);
+         check_within_half(arg, ll);
+         ll = boost::math::lltrunc(arg);
+         check_trunc_result(arg, ll);
+         r = boost::math::modf(arg, &ll);
+         check_modf_result(arg, r, ll);
+      }
+#endif
+   }
+}
+
+int test_main(int, char* [])
+{
+   test_round(0.1F, "float");
+   test_round(0.1, "double");
+#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
+   test_round(0.1L, "long double");
+   //test_round(boost::math::concepts::real_concept(0.1), "real_concept");
+#else
+   std::cout << "<note>The long double tests have been disabled on this platform "
+      "either because the long double overloads of the usual math functions are "
+      "not available at all, or because they are too inaccurate for these tests "
+      "to pass.</note>" << std::cout;
+#endif
+   return 0;
+}
+
+
+
+
+