1 // Copyright 2002 The Trustees of Indiana University.
2 
3 // Use, modification and distribution is subject to the Boost Software
4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 
7 //  Boost.MultiArray Library
8 //  Authors: Ronald Garcia
9 //           Jeremy Siek
10 //           Andrew Lumsdaine
11 //  See http://www.boost.org/libs/multi_array for documentation.
12 
13 #ifndef BOOST_STORAGE_ORDER_RG071801_HPP
14 #define BOOST_STORAGE_ORDER_RG071801_HPP
15 
16 #include "boost/multi_array/types.hpp"
17 #include "boost/array.hpp"
18 #include "boost/multi_array/algorithm.hpp"
19 #include <algorithm>
20 #include <cstddef>
21 #include <functional>
22 #include <numeric>
23 #include <vector>
24 
25 namespace boost {
26 
27   // RG - This is to make things work with VC++. So sad, so sad.
28   class c_storage_order;
29   class fortran_storage_order;
30 
31   template <std::size_t NumDims>
32   class general_storage_order
33   {
34   public:
35     typedef detail::multi_array::size_type size_type;
36     template <typename OrderingIter, typename AscendingIter>
general_storage_order(OrderingIter ordering,AscendingIter ascending)37     general_storage_order(OrderingIter ordering,
38                           AscendingIter ascending) {
39       boost::detail::multi_array::copy_n(ordering,NumDims,ordering_.begin());
40       boost::detail::multi_array::copy_n(ascending,NumDims,ascending_.begin());
41     }
42 
43     // RG - ideally these would not be necessary, but some compilers
44     // don't like template conversion operators.  I suspect that not
45     // too many folk will feel the need to use customized
46     // storage_order objects, I sacrifice that feature for compiler support.
general_storage_order(const c_storage_order &)47     general_storage_order(const c_storage_order&) {
48       for (size_type i=0; i != NumDims; ++i) {
49         ordering_[i] = NumDims - 1 - i;
50       }
51       ascending_.assign(true);
52     }
53 
general_storage_order(const fortran_storage_order &)54     general_storage_order(const fortran_storage_order&) {
55       for (size_type i=0; i != NumDims; ++i) {
56         ordering_[i] = i;
57       }
58       ascending_.assign(true);
59     }
60 
ordering(size_type dim) const61     size_type ordering(size_type dim) const { return ordering_[dim]; }
ascending(size_type dim) const62     bool ascending(size_type dim) const { return ascending_[dim]; }
63 
all_dims_ascending() const64     bool all_dims_ascending() const {
65       return std::accumulate(ascending_.begin(),ascending_.end(),true,
66                       std::logical_and<bool>());
67     }
68 
operator ==(general_storage_order const & rhs) const69     bool operator==(general_storage_order const& rhs) const {
70       return (ordering_ == rhs.ordering_) &&
71         (ascending_ == rhs.ascending_);
72     }
73 
74   protected:
75     boost::array<size_type,NumDims> ordering_;
76     boost::array<bool,NumDims> ascending_;
77   };
78 
79   class c_storage_order
80   {
81     typedef detail::multi_array::size_type size_type;
82   public:
83     // This is the idiom for creating your own custom storage orders.
84     // Not supported by all compilers though!
85 #ifndef __MWERKS__ // Metrowerks screams "ambiguity!"
86     template <std::size_t NumDims>
operator general_storage_order<NumDims>() const87     operator general_storage_order<NumDims>() const {
88       boost::array<size_type,NumDims> ordering;
89       boost::array<bool,NumDims> ascending;
90 
91       for (size_type i=0; i != NumDims; ++i) {
92         ordering[i] = NumDims - 1 - i;
93         ascending[i] = true;
94       }
95       return general_storage_order<NumDims>(ordering.begin(),
96                                             ascending.begin());
97     }
98 #endif
99   };
100 
101   class fortran_storage_order
102   {
103     typedef detail::multi_array::size_type size_type;
104   public:
105     // This is the idiom for creating your own custom storage orders.
106     // Not supported by all compilers though!
107 #ifndef __MWERKS__ // Metrowerks screams "ambiguity!"
108     template <std::size_t NumDims>
operator general_storage_order<NumDims>() const109     operator general_storage_order<NumDims>() const {
110       boost::array<size_type,NumDims> ordering;
111       boost::array<bool,NumDims> ascending;
112 
113       for (size_type i=0; i != NumDims; ++i) {
114         ordering[i] = i;
115         ascending[i] = true;
116       }
117       return general_storage_order<NumDims>(ordering.begin(),
118                                             ascending.begin());
119     }
120 #endif
121   };
122 
123 } // namespace boost
124 
125 #endif // BOOST_ARRAY_STORAGE_RG071801_HPP
126