126 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			126 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | // Copyright 2002 The Trustees of Indiana University. | ||
|  | 
 | ||
|  | // Use, modification and distribution is 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) | ||
|  | 
 | ||
|  | //  Boost.MultiArray Library | ||
|  | //  Authors: Ronald Garcia | ||
|  | //           Jeremy Siek | ||
|  | //           Andrew Lumsdaine | ||
|  | //  See http://www.boost.org/libs/multi_array for documentation. | ||
|  | 
 | ||
|  | #ifndef BOOST_STORAGE_ORDER_RG071801_HPP | ||
|  | #define BOOST_STORAGE_ORDER_RG071801_HPP | ||
|  | 
 | ||
|  | #include "boost/multi_array/types.hpp" | ||
|  | #include "boost/array.hpp" | ||
|  | #include "boost/multi_array/algorithm.hpp" | ||
|  | #include <algorithm> | ||
|  | #include <cstddef> | ||
|  | #include <functional> | ||
|  | #include <numeric> | ||
|  | #include <vector> | ||
|  | 
 | ||
|  | namespace boost { | ||
|  | 
 | ||
|  |   // RG - This is to make things work with VC++. So sad, so sad. | ||
|  |   class c_storage_order;  | ||
|  |   class fortran_storage_order; | ||
|  | 
 | ||
|  |   template <std::size_t NumDims> | ||
|  |   class general_storage_order | ||
|  |   { | ||
|  |   public: | ||
|  |     typedef detail::multi_array::size_type size_type; | ||
|  |     template <typename OrderingIter, typename AscendingIter> | ||
|  |     general_storage_order(OrderingIter ordering, | ||
|  |                           AscendingIter ascending) { | ||
|  |       boost::detail::multi_array::copy_n(ordering,NumDims,ordering_.begin()); | ||
|  |       boost::detail::multi_array::copy_n(ascending,NumDims,ascending_.begin()); | ||
|  |     } | ||
|  | 
 | ||
|  |     // RG - ideally these would not be necessary, but some compilers | ||
|  |     // don't like template conversion operators.  I suspect that not | ||
|  |     // too many folk will feel the need to use customized | ||
|  |     // storage_order objects, I sacrifice that feature for compiler support. | ||
|  |     general_storage_order(const c_storage_order&) { | ||
|  |       for (size_type i=0; i != NumDims; ++i) { | ||
|  |         ordering_[i] = NumDims - 1 - i; | ||
|  |       } | ||
|  |       ascending_.assign(true); | ||
|  |     } | ||
|  | 
 | ||
|  |     general_storage_order(const fortran_storage_order&) { | ||
|  |       for (size_type i=0; i != NumDims; ++i) { | ||
|  |         ordering_[i] = i; | ||
|  |       } | ||
|  |       ascending_.assign(true); | ||
|  |     } | ||
|  | 
 | ||
|  |     size_type ordering(size_type dim) const { return ordering_[dim]; } | ||
|  |     bool ascending(size_type dim) const { return ascending_[dim]; } | ||
|  | 
 | ||
|  |     bool all_dims_ascending() const { | ||
|  |       return std::accumulate(ascending_.begin(),ascending_.end(),true, | ||
|  |                       std::logical_and<bool>()); | ||
|  |     } | ||
|  | 
 | ||
|  |     bool operator==(general_storage_order const& rhs) const { | ||
|  |       return (ordering_ == rhs.ordering_) && | ||
|  |         (ascending_ == rhs.ascending_); | ||
|  |     } | ||
|  | 
 | ||
|  |   protected: | ||
|  |     boost::array<size_type,NumDims> ordering_; | ||
|  |     boost::array<bool,NumDims> ascending_; | ||
|  |   }; | ||
|  | 
 | ||
|  |   class c_storage_order  | ||
|  |   { | ||
|  |     typedef detail::multi_array::size_type size_type; | ||
|  |   public: | ||
|  |     // This is the idiom for creating your own custom storage orders. | ||
|  |     // Not supported by all compilers though! | ||
|  | #ifndef __MWERKS__ // Metrowerks screams "ambiguity!" | ||
|  |     template <std::size_t NumDims> | ||
|  |     operator general_storage_order<NumDims>() const { | ||
|  |       boost::array<size_type,NumDims> ordering; | ||
|  |       boost::array<bool,NumDims> ascending; | ||
|  | 
 | ||
|  |       for (size_type i=0; i != NumDims; ++i) { | ||
|  |         ordering[i] = NumDims - 1 - i; | ||
|  |         ascending[i] = true; | ||
|  |       } | ||
|  |       return general_storage_order<NumDims>(ordering.begin(), | ||
|  |                                             ascending.begin()); | ||
|  |     } | ||
|  | #endif | ||
|  |   }; | ||
|  | 
 | ||
|  |   class fortran_storage_order | ||
|  |   { | ||
|  |     typedef detail::multi_array::size_type size_type; | ||
|  |   public: | ||
|  |     // This is the idiom for creating your own custom storage orders. | ||
|  |     // Not supported by all compilers though!  | ||
|  | #ifndef __MWERKS__ // Metrowerks screams "ambiguity!" | ||
|  |     template <std::size_t NumDims> | ||
|  |     operator general_storage_order<NumDims>() const { | ||
|  |       boost::array<size_type,NumDims> ordering; | ||
|  |       boost::array<bool,NumDims> ascending; | ||
|  | 
 | ||
|  |       for (size_type i=0; i != NumDims; ++i) { | ||
|  |         ordering[i] = i; | ||
|  |         ascending[i] = true; | ||
|  |       } | ||
|  |       return general_storage_order<NumDims>(ordering.begin(), | ||
|  |                                             ascending.begin()); | ||
|  |     } | ||
|  | #endif | ||
|  |   }; | ||
|  | 
 | ||
|  | } // namespace boost | ||
|  | 
 | ||
|  | #endif // BOOST_ARRAY_STORAGE_RG071801_HPP |