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_MULTI_ARRAY_STORAGE_ORDER_HPP
14#define BOOST_MULTI_ARRAY_STORAGE_ORDER_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
25namespace 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>
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.
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
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
61 size_type ordering(size_type dim) const { return ordering_[dim]; }
62 bool ascending(size_type dim) const { return ascending_[dim]; }
63
64 bool all_dims_ascending() const {
65 return std::accumulate(ascending_.begin(),ascending_.end(),true,
66 std::logical_and<bool>());
67 }
68
69 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>
87 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>
109 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
126

source code of include/boost/multi_array/storage_order.hpp