ALPSCore reference
multi_array.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1998-2018 ALPS Collaboration. See COPYRIGHT.TXT
3  * All rights reserved. Use is subject to license terms. See LICENSE.TXT
4  * For use in publications, see ACKNOWLEDGE.TXT
5  */
6 
7 #ifndef ALPS_HDF5_BOOST_MULTI_ARRAY_HPP
8 #define ALPS_HDF5_BOOST_MULTI_ARRAY_HPP
9 
10 #include <alps/hdf5/archive.hpp>
11 
12 // #include <alps/multi_array.hpp>
13 
14 #include <boost/multi_array.hpp>
15 
16 namespace alps {
17  namespace hdf5 {
18 
19  template<typename T, std::size_t N, typename A> struct scalar_type<boost::multi_array<T, N, A> > {
21  };
22  // template<typename T, std::size_t N, typename A> struct scalar_type<alps::multi_array<T, N, A> >
23  // : public scalar_type<boost::multi_array<T, N, A> >
24  // {};
25 
26  template<typename T, std::size_t N, typename A> struct is_content_continuous<boost::multi_array<T, N, A> >
27  : public is_continuous<T>
28  {};
29  // template<typename T, std::size_t N, typename A> struct is_content_continuous<alps::multi_array<T, N, A> >
30  // : public is_continuous<T>
31  // {};
32 
33  template<typename T, std::size_t N, typename A> struct has_complex_elements<boost::multi_array<T, N, A> >
34  : public has_complex_elements<typename alps::detail::remove_cvr<T>::type>
35  {};
36  // template<typename T, std::size_t N, typename A> struct has_complex_elements<alps::multi_array<T, N, A> >
37  // : public has_complex_elements<boost::multi_array<T, N, A> >
38  // {};
39 
40  namespace detail {
41 
42  template<typename T, std::size_t N, typename A> struct get_extent<boost::multi_array<T, N, A> > {
43  static std::vector<std::size_t> apply(boost::multi_array<T, N, A> const & value) {
45  std::vector<std::size_t> result(value.shape(), value.shape() + boost::multi_array<T, N, A>::dimensionality);
46  if (value.num_elements()) {
47  std::vector<std::size_t> extent(get_extent(*value.data()));
48  for (std::size_t i = 1; i < value.num_elements(); ++i)
49  if (!std::equal(extent.begin(), extent.end(), get_extent(value.data()[i]).begin()))
50  throw archive_error("no rectangular matrix");
51  std::copy(extent.begin(), extent.end(), std::back_inserter(result));
52  }
53  return result;
54  }
55  };
56  // template<typename T, std::size_t N, typename A> struct get_extent<alps::multi_array<T, N, A> >
57  // : public get_extent<boost::multi_array<T, N, A> >
58  // {};
59 
60  template<typename T, std::size_t N, typename A> struct set_extent<boost::multi_array<T, N, A> > {
61  static void apply(boost::multi_array<T, N, A> & value, std::vector<std::size_t> const & size) {
63  if (boost::multi_array<T, N, A>::dimensionality > size.size())
64  throw archive_error("invalid data size");
65  if (!std::equal(value.shape(), value.shape() + boost::multi_array<T, N, A>::dimensionality, size.begin())) {
66  typename boost::multi_array<T, N, A>::extent_gen extents;
67  gen_extent(value, extents, size);
68  }
69  if (!is_continuous<T>::value && boost::multi_array<T, N, A>::dimensionality < size.size())
70  for (std::size_t i = 0; i < value.num_elements(); ++i)
71  set_extent(value.data()[i], std::vector<std::size_t>(size.begin() + boost::multi_array<T, N, A>::dimensionality, size.end()));
72  }
73  private:
74  template<std::size_t M> static void gen_extent(boost::multi_array<T, N, A> & value, boost::detail::multi_array::extent_gen<M> extents, std::vector<std::size_t> const & size) {
75  gen_extent(value, extents[size.front()], std::vector<std::size_t>(size.begin() + 1, size.end()));
76  }
77  static void gen_extent(boost::multi_array<T, N, A> & value, typename boost::detail::multi_array::extent_gen<N> extents, std::vector<std::size_t> const & /*size*/) {
78  value.resize(extents);
79  }
80  };
81  // template<typename T, std::size_t N, typename A> struct set_extent<alps::multi_array<T, N, A> >
82  // : public set_extent<boost::multi_array<T, N, A> >
83  // {};
84 
85  template<typename T, std::size_t N, typename A> struct is_vectorizable<boost::multi_array<T, N, A> > {
86  static bool apply(boost::multi_array<T, N, A> const & value) {
89  std::vector<std::size_t> size(get_extent(*value.data()));
90  for (std::size_t i = 1; i < value.num_elements(); ++i)
91  if (!is_vectorizable(value.data()[i]) || !std::equal(size.begin(), size.end(), get_extent(value.data()[i]).begin()))
92  return false;
93  return true;
94  }
95  };
96  // template<typename T, std::size_t N, typename A> struct is_vectorizable<alps::multi_array<T, N, A> >
97  // : public is_vectorizable<boost::multi_array<T, N, A> >
98  // {};
99 
100  template<typename T, std::size_t N, typename A> struct get_pointer<boost::multi_array<T, N, A> > {
101  static typename alps::hdf5::scalar_type<boost::multi_array<T, N, A> >::type * apply(boost::multi_array<T, N, A> & value) {
103  return get_pointer(*value.data());
104  }
105  };
106  // template<typename T, std::size_t N, typename A> struct get_pointer<alps::multi_array<T, N, A> >
107  // : public get_pointer<boost::multi_array<T, N, A> >
108  // {};
109 
110  template<typename T, std::size_t N, typename A> struct get_pointer<boost::multi_array<T, N, A> const> {
111  static typename alps::hdf5::scalar_type<boost::multi_array<T, N, A> >::type const * apply(boost::multi_array<T, N, A> const & value) {
113  return get_pointer(*value.data());
114  }
115  };
116  // template<typename T, std::size_t N, typename A> struct get_pointer<alps::multi_array<T, N, A> const>
117  // : public get_pointer<boost::multi_array<T, N, A> const>
118  // {};
119 
120  }
121 
122  template<typename T, std::size_t N, typename A> void save(
123  archive & ar
124  , std::string const & path
125  , boost::multi_array<T, N, A> const & value
126  , std::vector<std::size_t> size = std::vector<std::size_t>()
127  , std::vector<std::size_t> chunk = std::vector<std::size_t>()
128  , std::vector<std::size_t> offset = std::vector<std::size_t>()
129  ) {
131  std::vector<std::size_t> extent(get_extent(value));
132  std::copy(extent.begin(), extent.end(), std::back_inserter(size));
133  std::copy(extent.begin(), extent.end(), std::back_inserter(chunk));
134  std::fill_n(std::back_inserter(offset), extent.size(), 0);
135  ar.write(path, get_pointer(value), size, chunk, offset);
136  } else if (is_vectorizable(value)) {
137  std::copy(value.shape(), value.shape() + boost::multi_array<T, N, A>::dimensionality, std::back_inserter(size));
138  std::fill_n(std::back_inserter(chunk), value.num_elements(), 1);
139  for (std::size_t i = 1; i < value.num_elements(); ++i) {
140  std::vector<std::size_t> local_offset(offset);
141  local_offset.push_back(i / value.num_elements() * *value.shape());
142  for (
143  typename boost::multi_array<T, N, A>::size_type const * it = value.shape() + 1;
144  it != value.shape() + boost::multi_array<T, N, A>::dimensionality;
145  ++it
146  )
147  local_offset.push_back((i % std::accumulate(
148  it, value.shape() + boost::multi_array<T, N, A>::dimensionality, std::size_t(1), std::multiplies<std::size_t>()
149  )) / std::accumulate(
150  it + 1, value.shape() + boost::multi_array<T, N, A>::dimensionality, std::size_t(1), std::multiplies<std::size_t>()
151  ));
152  save(ar, path, value.data()[i], size, chunk, local_offset);
153  }
154  } else
155  throw wrong_type("invalid type");
156  }
157  // template<typename T, std::size_t N, typename A> void save(
158  // archive & ar
159  // , std::string const & path
160  // , alps::multi_array<T, N, A> const & value
161  // , std::vector<std::size_t> size = std::vector<std::size_t>()
162  // , std::vector<std::size_t> chunk = std::vector<std::size_t>()
163  // , std::vector<std::size_t> offset = std::vector<std::size_t>()
164  // ) {
165  // save(ar, path, static_cast<boost::multi_array<T, N, A> const &>(value), size, chunk, offset);
166  // }
167 
168  template<typename T, std::size_t N, typename A> void load(
169  archive & ar
170  , std::string const & path
171  , boost::multi_array<T, N, A> & value
172  , std::vector<std::size_t> chunk = std::vector<std::size_t>()
173  , std::vector<std::size_t> offset = std::vector<std::size_t>()
174  ) {
175  if (ar.is_group(path))
176  throw invalid_path("invalid path");
177  else {
179  throw archive_error("no complex value in archive" + ALPS_STACKTRACE);
180  std::vector<std::size_t> size(ar.extent(path));
181  if (boost::multi_array<T, N, A>::dimensionality <= size.size())
182  set_extent(value, std::vector<std::size_t>(size.begin() + chunk.size(), size.end()));
184  std::copy(size.begin() + chunk.size(), size.end(), std::back_inserter(chunk));
185  std::fill_n(std::back_inserter(offset), size.size() - offset.size(), 0);
186  ar.read(path, get_pointer(value), chunk, offset);
187  } else {
188  std::fill_n(std::back_inserter(chunk), value.num_elements(), 1);
189  for (std::size_t i = 1; i < value.num_elements(); ++i) {
190  std::vector<std::size_t> local_offset(offset);
191  local_offset.push_back(i / value.num_elements() * *value.shape());
192  for (
193  typename boost::multi_array<T, N, A>::size_type const * it = value.shape() + 1;
194  it != value.shape() + boost::multi_array<T, N, A>::dimensionality;
195  ++it
196  )
197  local_offset.push_back((i % std::accumulate(
198  it, value.shape() + boost::multi_array<T, N, A>::dimensionality, std::size_t(1), std::multiplies<std::size_t>()
199  )) / std::accumulate(
200  it + 1, value.shape() + boost::multi_array<T, N, A>::dimensionality, std::size_t(1), std::multiplies<std::size_t>()
201  ));
202  load(ar, path, value.data()[i], chunk, local_offset);
203  }
204  }
205  }
206  }
207  // template<typename T, std::size_t N, typename A> void load(
208  // archive & ar
209  // , std::string const & path
210  // , alps::multi_array<T, N, A> & value
211  // , std::vector<std::size_t> chunk = std::vector<std::size_t>()
212  // , std::vector<std::size_t> offset = std::vector<std::size_t>()
213  // ) {
214  // load(ar, path, static_cast<boost::multi_array<T, N, A> &>(value), chunk, offset);
215  // }
216  }
217 }
218 
219 #endif
void load(archive &ar, std::string const &path, T &value, std::vector< std::size_t > chunk=std::vector< std::size_t >(), std::vector< std::size_t >=std::vector< std::size_t >())
Definition: archive.hpp:309
bool is_vectorizable(T const &value)
Definition: archive.hpp:288
void set_extent(T &value, std::vector< std::size_t > const &size)
Definition: archive.hpp:284
std::enable_if<!is_sequence< T >::value, std::size_t >::type size(T const &)
Definition: size.hpp:20
scalar_type< typename boost::remove_reference< typename boost::remove_cv< T >::type >::type >::type type
Definition: multi_array.hpp:20
std::vector< std::size_t > get_extent(T const &value)
Definition: archive.hpp:280
scalar_type< T >::type * get_pointer(T &value)
Definition: archive.hpp:272
std::vector< std::size_t > extent(std::string path) const
Definition: archive.cpp:291
auto read(std::string path, T *, std::vector< std::size_t >, std::vector< std::size_t >=std::vector< std::size_t >()) const -> typename std::enable_if<!is_native_type< T >::value, void >::type
Definition: archive.hpp:163
auto write(std::string path, T const *value, std::vector< std::size_t > size, std::vector< std::size_t > chunk=std::vector< std::size_t >(), std::vector< std::size_t > offset=std::vector< std::size_t >()) const -> typename std::enable_if<!is_native_type< T >::value, void >::type
Definition: archive.hpp:172
#define ALPS_STACKTRACE
Definition: stacktrace.hpp:37
traits< Acc >::result_type result(const Acc &acc)
Definition: util.hpp:53
bool is_group(std::string path) const
Definition: archive.cpp:189
bool is_complex(std::string path) const
Definition: archive.cpp:242
void save(archive &ar, std::string const &path, T const &value, std::vector< std::size_t >=std::vector< std::size_t >(), std::vector< std::size_t > chunk=std::vector< std::size_t >(), std::vector< std::size_t >=std::vector< std::size_t >())
Definition: archive.hpp:292