From 8710d5f6a98d68ceb4fabbe7c7ca242dd44ca85f Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 5 Mar 2001 20:01:01 +0000 Subject: [PATCH] Join ralf_grosse_kunstleve with HEAD [SVN r9444] --- algo_opt_examples.cpp | 424 ---------------------------------------- numeric_traits_test.cpp | 12 +- 2 files changed, 10 insertions(+), 426 deletions(-) delete mode 100644 algo_opt_examples.cpp diff --git a/algo_opt_examples.cpp b/algo_opt_examples.cpp deleted file mode 100644 index c30587c..0000000 --- a/algo_opt_examples.cpp +++ /dev/null @@ -1,424 +0,0 @@ - -/* - * - * Copyright (c) 1999 - * Dr John Maddock - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Dr John Maddock makes no representations - * about the suitability of this software for any purpose. - * It is provided "as is" without express or implied warranty. - * - * This file provides some example of type_traits usage - - * by "optimising" various algorithms: - * - * opt::copy - optimised for trivial copy (cf std::copy) - * opt::fill - optimised for trivial copy/small types (cf std::fill) - * opt::destroy_array - an example of optimisation based upon omitted destructor calls - * opt::iter_swap - uses type_traits to determine whether the iterator is a proxy - * in which case it uses a "safe" approach, otherwise calls swap - * on the assumption that swap may be specialised for the pointed-to type. - * - */ - -/* Release notes: - 23rd July 2000: - Added explicit failure for broken compilers that don't support these examples. - Fixed broken gcc support (broken using directive). - Reordered tests slightly. -*/ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -using std::cout; -using std::endl; -using std::cin; - -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -#error "Sorry, without template partial specialisation support there isn't anything to test here..." -#endif - -namespace opt{ - -// -// algorithm destroy_array: -// The reverse of std::unitialized_copy, takes a block of -// unitialized memory and calls destructors on all objects therein. -// - -namespace detail{ - -template -struct array_destroyer -{ - template - static void destroy_array(T* i, T* j){ do_destroy_array(i, j); } -}; - -template <> -struct array_destroyer -{ - template - static void destroy_array(T*, T*){} -}; - -template -void do_destroy_array(T* first, T* last) -{ - while(first != last) - { - first->~T(); - ++first; - } -} - -}; // namespace detail - -template -inline void destroy_array(T* p1, T* p2) -{ - detail::array_destroyer::value>::destroy_array(p1, p2); -} - -// -// unoptimised versions of destroy_array: -// -template -void destroy_array1(T* first, T* last) -{ - while(first != last) - { - first->~T(); - ++first; - } -} -template -void destroy_array2(T* first, T* last) -{ - for(; first != last; ++first) first->~T(); -} - - -// -// opt::copy -// same semantics as std::copy -// calls memcpy where appropiate. -// - -namespace detail{ - -template -struct copier -{ - template - static I2 do_copy(I1 first, I1 last, I2 out); -}; - -template -template -I2 copier::do_copy(I1 first, I1 last, I2 out) -{ - while(first != last) - { - *out = *first; - ++out; - ++first; - } - return out; -} - -template <> -struct copier -{ - template - static I2* do_copy(I1* first, I1* last, I2* out) - { - memcpy(out, first, (last-first)*sizeof(I2)); - return out+(last-first); - } -}; - - -} - -template -inline I2 copy(I1 first, I1 last, I2 out) -{ - typedef typename boost::remove_cv::value_type>::type v1_t; - typedef typename boost::remove_cv::value_type>::type v2_t; - enum{ can_opt = boost::is_same::value - && boost::is_pointer::value - && boost::is_pointer::value - && boost::has_trivial_assign::value }; - return detail::copier::do_copy(first, last, out); -} - -// -// fill -// same as std::fill, uses memset where appropriate, along with call_traits -// to "optimise" parameter passing. -// -namespace detail{ - -template -struct filler -{ - template - static void do_fill(I first, I last, typename boost::call_traits::param_type val); - }; - -template -template -void filler::do_fill(I first, I last, typename boost::call_traits::param_type val) -{ - while(first != last) - { - *first = val; - ++first; - } -} - -template <> -struct filler -{ - template - static void do_fill(I first, I last, T val) - { - std::memset(first, val, last-first); - } -}; - -} - -template -inline void fill(I first, I last, const T& val) -{ - enum{ can_opt = boost::is_pointer::value - && boost::is_arithmetic::value - && (sizeof(T) == 1) }; - typedef detail::filler filler_t; - filler_t::template do_fill(first, last, val); -} - -// -// iter_swap: -// tests whether iterator is a proxying iterator or not, and -// uses optimal form accordingly: -// -namespace detail{ - -template -struct swapper -{ - template - static void do_swap(I one, I two) - { - typedef typename std::iterator_traits::value_type v_t; - v_t v = *one; - *one = *two; - *two = v; - } -}; - -#ifdef __GNUC__ -using std::swap; -#endif - -template <> -struct swapper -{ - template - static void do_swap(I one, I two) - { - using std::swap; - swap(*one, *two); - } -}; - -} - -template -inline void iter_swap(I1 one, I2 two) -{ - typedef typename std::iterator_traits::reference r1_t; - typedef typename std::iterator_traits::reference r2_t; - enum{ can_opt = boost::is_reference::value && boost::is_reference::value && boost::is_same::value }; - detail::swapper::do_swap(one, two); -} - - -}; // namespace opt - -// -// define some global data: -// -const int array_size = 1000; -int i_array[array_size] = {0,}; -const int ci_array[array_size] = {0,}; -char c_array[array_size] = {0,}; -const char cc_array[array_size] = { 0,}; - -const int iter_count = 1000000; - - -int main() -{ - // - // test destroy_array, - // compare destruction time of an array of ints - // with unoptimised form. - // - cout << "Measuring times in micro-seconds per 1000 elements processed" << endl << endl; - cout << "testing destroy_array...\n" - "[Some compilers may be able to optimise the \"unoptimised\"\n versions as well as type_traits does.]" << endl; - /*cache load*/ opt::destroy_array(i_array, i_array + array_size); - boost::timer t; - double result; - int i; - for(i = 0; i < iter_count; ++i) - { - opt::destroy_array(i_array, i_array + array_size); - } - result = t.elapsed(); - cout << "destroy_array: " << result << endl; - /*cache load*/ opt::destroy_array1(i_array, i_array + array_size); - t.restart(); - for(i = 0; i < iter_count; ++i) - { - opt::destroy_array1(i_array, i_array + array_size); - } - result = t.elapsed(); - cout << "destroy_array(unoptimised#1): " << result << endl; - /*cache load*/ opt::destroy_array2(i_array, i_array + array_size); - t.restart(); - for(i = 0; i < iter_count; ++i) - { - opt::destroy_array2(i_array, i_array + array_size); - } - result = t.elapsed(); - cout << "destroy_array(unoptimised#2): " << result << endl << endl; - - cout << "testing fill(char)...\n" - "[Some standard library versions may already perform this optimisation.]" << endl; - /*cache load*/ opt::fill(c_array, c_array + array_size, (char)3); - t.restart(); - for(i = 0; i < iter_count; ++i) - { - opt::fill(c_array, c_array + array_size, (char)3); - } - result = t.elapsed(); - cout << "opt::fill: " << result << endl; - /*cache load*/ std::fill(c_array, c_array + array_size, (char)3); - t.restart(); - for(i = 0; i < iter_count; ++i) - { - std::fill(c_array, c_array + array_size, (char)3); - } - result = t.elapsed(); - cout << "std::fill: " << result << endl << endl; - - cout << "testing fill(int)...\n" - "[Tests the effect of call_traits pass-by-value optimisation -\nthe value of this optimisation may depend upon hardware characteristics.]" << endl; - /*cache load*/ opt::fill(i_array, i_array + array_size, 3); - t.restart(); - for(i = 0; i < iter_count; ++i) - { - opt::fill(i_array, i_array + array_size, 3); - } - result = t.elapsed(); - cout << "opt::fill: " << result << endl; - /*cache load*/ std::fill(i_array, i_array + array_size, 3); - t.restart(); - for(i = 0; i < iter_count; ++i) - { - std::fill(i_array, i_array + array_size, 3); - } - result = t.elapsed(); - cout << "std::fill: " << result << endl << endl; - - cout << "testing copy...\n" - "[Some standard library versions may already perform this optimisation.]" << endl; - /*cache load*/ opt::copy(ci_array, ci_array + array_size, i_array); - t.restart(); - for(i = 0; i < iter_count; ++i) - { - opt::copy(ci_array, ci_array + array_size, i_array); - } - result = t.elapsed(); - cout << "opt::copy: " << result << endl; - /*cache load*/ std::copy(ci_array, ci_array + array_size, i_array); - t.restart(); - for(i = 0; i < iter_count; ++i) - { - std::copy(ci_array, ci_array + array_size, i_array); - } - result = t.elapsed(); - cout << "std::copy: " << result << endl; - /*cache load*/ opt::detail::copier::template do_copy(ci_array, ci_array + array_size, i_array); - t.restart(); - for(i = 0; i < iter_count; ++i) - { - opt::detail::copier::template do_copy(ci_array, ci_array + array_size, i_array); - } - result = t.elapsed(); - cout << "standard \"unoptimised\" copy: " << result << endl << endl; - - /*cache load*/ opt::copy(cc_array, cc_array + array_size, c_array); - t.restart(); - for(i = 0; i < iter_count; ++i) - { - opt::copy(cc_array, cc_array + array_size, c_array); - } - result = t.elapsed(); - cout << "opt::copy: " << result << endl; - /*cache load*/ std::copy(cc_array, cc_array + array_size, c_array); - t.restart(); - for(i = 0; i < iter_count; ++i) - { - std::copy(cc_array, cc_array + array_size, c_array); - } - result = t.elapsed(); - cout << "std::copy: " << result << endl; - /*cache load*/ opt::detail::copier::template do_copy(cc_array, cc_array + array_size, c_array); - t.restart(); - for(i = 0; i < iter_count; ++i) - { - opt::detail::copier::template do_copy(cc_array, cc_array + array_size, c_array); - } - result = t.elapsed(); - cout << "standard \"unoptimised\" copy: " << result << endl << endl; - - - // - // testing iter_swap - // really just a check that it does in fact compile... - std::vector v1; - v1.push_back(0); - v1.push_back(1); - std::vector v2; - v2.push_back(0); - v2.push_back(1); - opt::iter_swap(v1.begin(), v1.begin()+1); - opt::iter_swap(v2.begin(), v2.begin()+1); - - cout << "Press any key to exit..."; - cin.get(); -} - - - - - - diff --git a/numeric_traits_test.cpp b/numeric_traits_test.cpp index 0bc0ca5..3b169bf 100644 --- a/numeric_traits_test.cpp +++ b/numeric_traits_test.cpp @@ -7,6 +7,7 @@ // See http://www.boost.org for most recent version including documentation. // Revision History +// 11 Feb 2001 Fixes for Borland (David Abrahams) // 23 Jan 2001 Added test for wchar_t (David Abrahams) // 23 Jan 2001 Now statically selecting a test for signed numbers to avoid // warnings with fancy compilers. Added commentary and @@ -349,8 +350,15 @@ void test(Number* = 0) << "digits: " << std::numeric_limits::digits << "\n" #endif << "..." << std::flush; - typedef typename boost::detail::numeric_traits::difference_type difference_type; - BOOST_STATIC_ASSERT(boost::detail::is_signed::value); + + // factoring out difference_type for the assert below confused Borland :( + typedef boost::detail::is_signed< +#ifndef BOOST_MSVC + typename +#endif + boost::detail::numeric_traits::difference_type + > is_signed; + BOOST_STATIC_ASSERT(is_signed::value); typedef typename boost::detail::if_true< boost::detail::is_signed::value