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