IMP logo
IMP Reference Guide  2.19.0
The Integrative Modeling Platform
Array.h
Go to the documentation of this file.
1 /**
2  * \file IMP/Array.h
3  * \brief Classes to handle static sized arrays of things.
4  *
5  * Copyright 2007-2022 IMP Inventors. All rights reserved.
6  *
7  */
8 
9 #ifndef IMPKERNEL_ARRAY_H
10 #define IMPKERNEL_ARRAY_H
11 
12 #include <IMP/kernel_config.h>
13 #include "Value.h"
14 #include "comparison_macros.h"
15 #include "hash_macros.h"
16 #include "check_macros.h"
17 #include "showable_macros.h"
18 #include <array>
19 #include <type_traits>
20 #include <cereal/access.hpp>
21 #include <cereal/types/array.hpp>
22 
23 IMPKERNEL_BEGIN_NAMESPACE
24 
25 //! A class to store a fixed array of same-typed values.
26 /** Only the constructor with the correct number of arguments for the
27  dimensionality can be used.
28 
29  \note These are mapped to/from Python tuples, so there is
30  no need to use types that are typedefs of this on the Python side.
31 
32  \see ConstVector
33  */
34 template <unsigned int D, class Data, class SwigData = Data>
35 class Array : public Value {
36  typedef std::array<Data, D> Storage;
37  Storage d_;
38 
39  friend class cereal::access;
40  template<class Archive> void serialize(Archive &ar) {
41  ar(d_);
42  }
43 
44  int compare(const Array<D, Data, SwigData>& o) const {
45  for (unsigned int i = 0; i < D; ++i) {
46  if (d_[i] < o.get(i))
47  return -1;
48  else if (d_[i] > o.get(i))
49  return 1;
50  }
51  return 0;
52  }
53 
54  public:
55 #ifndef IMP_DOXYGEN
56  typedef SwigData value_type;
57 #endif
58  unsigned int get_dimension() {
59  return D;
60  };
61  Array() {}
62 
63  template<int DT=D, typename std::enable_if<DT == 2>::type* = nullptr>
64  Array(SwigData x, SwigData y) {
65  d_[0] = x;
66  d_[1] = y;
67  }
68 
69  template<int DT=D, typename std::enable_if<DT == 3>::type* = nullptr>
70  Array(SwigData x, SwigData y, SwigData z) {
71  d_[0] = x;
72  d_[1] = y;
73  d_[2] = z;
74  }
75 
76  template<int DT=D, typename std::enable_if<DT == 4>::type* = nullptr>
77  Array(SwigData x0, SwigData x1, SwigData x2, SwigData x3) {
78  d_[0] = x0;
79  d_[1] = x1;
80  d_[2] = x2;
81  d_[3] = x3;
82  }
83 
84  SwigData get(unsigned int i) const { return d_[i]; }
85 
86  IMP_HASHABLE_INLINE(Array, std::size_t seed = 0;
87  for (unsigned int i = 0; i < D; ++i) {
88  boost::hash_combine(seed, d_[i]);
89  } return seed;);
91 #ifndef SWIG
92  const Data operator[](unsigned int i) const {
93  IMP_USAGE_CHECK(i < D, "Out of range");
94  return d_[i];
95  }
96  Data& operator[](unsigned int i) {
97  IMP_USAGE_CHECK(i < D, "Out of range");
98  return d_[i];
99  }
100 #ifndef IMP_DOXYGEN
101  void set_item(unsigned int i, SwigData v) const {
102  IMP_USAGE_CHECK(i < D, "Out of range");
103  d_[i] = v;
104  }
105 #endif
106 #endif
107 #ifndef IMP_DOXYGEN
108  SwigData __getitem__(unsigned int i) const {
109  if (i >= D) IMP_THROW("Out of bound " << i << " vs " << D, IndexException);
110  return operator[](i);
111  }
112  unsigned int __len__() const { return D; }
113 #endif
114 #ifndef SWIG
115  unsigned int size() const { return D; }
116 #endif
117  std::string get_name() const {
118  std::ostringstream oss;
119  oss << "\"";
120  for (unsigned int i = 0; i < D; ++i) {
121  if (i > 0) {
122  oss << "\" and \"";
123  }
124  oss << d_[i];
125  }
126  oss << "\"";
127  return oss.str();
128  }
129  IMP_SHOWABLE_INLINE(Array, { out << get_name(); });
130  typedef typename Storage::iterator iterator;
131  iterator begin() { return d_.begin(); }
132  iterator end() { return d_.end(); }
133  typedef typename Storage::const_iterator const_iterator;
134  const_iterator begin() const { return d_.begin(); }
135  const_iterator end() const { return d_.end(); }
136 
137  Data* data() {
138  if (d_.empty()) {
139  return NULL;
140  } else {
141  return &d_.front();
142  }
143  }
144 
145  const Data* data() const {
146  if (d_.empty()) {
147  return NULL;
148  } else {
149  return &d_.front();
150  }
151  }
152 };
153 
154 #if !defined(IMP_DOXYGEN) && !defined(SWIG)
155 template <unsigned int D, class Data, class SwigData>
156 inline std::size_t hash_value(const Array<D, Data, SwigData> &t) {
157  return t.__hash__();
158 }
159 #endif
160 
161 IMPKERNEL_END_NAMESPACE
162 
163 #endif /* IMPKERNEL_ARRAY_H */
#define IMP_SHOWABLE_INLINE(Name, how_to_show)
Declare the methods needed by an object that can be printed.
Helper macros for implementing comparisons of IMP objects.
A class to store a fixed array of same-typed values.
Definition: Array.h:35
#define IMP_HASHABLE_INLINE(name, hashret)
Definition: hash_macros.h:18
#define IMP_COMPARISONS(Name)
Implement comparison in a class using a compare function.
Base class for a simple primitive-like type.
Definition: Value.h:23
int compare(const VectorD< D > &a, const VectorD< D > &b)
lexicographic comparison of two vectors
Definition: VectorD.h:183
Helper macros for implementing hashable classes.
An exception for a request for an invalid member of a container.
Definition: exception.h:156
#define IMP_THROW(message, exception_name)
Throw an exception with a message.
Definition: check_macros.h:50
Helper macros for throwing and handling exceptions.
Base class for a simple primitive-like type.
#define IMP_USAGE_CHECK(expr, message)
A runtime test for incorrect usage of a class or method.
Definition: check_macros.h:168
Macros to help with objects that can be printed to a stream.