aimstil  5.0.5
numeric_array.h
Go to the documentation of this file.
1 #ifndef TIL_NUMERIC_ARRAY_H
2 #define TIL_NUMERIC_ARRAY_H
3 
4 // includes from BOOST
5 #include "boost/array.hpp"
6 #include "boost/call_traits.hpp"
7 
8 // includes from TIL
9 #include "til/basic_iterator.h"
10 #include "til/basic_range.h"
11 #include "til/cat2type.h"
12 #include "til/labels.h"
13 #include "til/std_wrap.h"
14 #include "til/traits.h"
15 
16 // Self mental note: the idea here is to have an extra layer over
17 // standard containers. In this layer, we define all the operators
18 // we want. The idea here is that choices of a best iterating method
19 // for a given storage type and a given mathematical operation are done
20 // here, so that at the upper levels, no iterators are used.
21 
22 // this may seem odd, but actually I've come to think that I come to
23 // a point where genericity has a limit, and this limit is in the flexibility.
24 // Clearly, sparse containers must have a standard face, that can fill in
25 // the gaps and produce a value for every index. Still, these iterators
26 // must certainly not be used when operating on them. The efficient way
27 // would be to use a sparse iterator -- and then, we would not take
28 // long before realizing that all the for loops, ++i1, ++i2, that are
29 // at the core of stl algorithms, won't do. This would be true for
30 // RLE as well.
31 
32 // In short: for any storage strategy, we are left redesigning not only
33 // the iterators, but also the loops, because more often than not, we
34 // cannot simply ++i1, ++i2 when operating on two containers. This means
35 // that unfortunately, there is no generic algorithms that would actually
36 // do for us.
37 
38 // This becomes even worse when storage types are mixed.
39 // Consider a sparse matrix and a non-sparse matrix: what iterators to
40 // use to compute an operation between them? Well, that depends: if
41 // it is a multiplication, probably
42 
43 
44 namespace til
45 {
46 
47  //--------------------------------------------------------------------------
48 
49  //----------------------//
50  // numeric_array_impl //
51  //----------------------//
52 
53  namespace detail
54  {
56  template < typename T, std::size_t D >
58  : public boost::array<T,D>
59  , public numeric_container_label
60  {
61  public: // typedefs
62 
65  typedef typename Base::reverse_iterator reverse_iterator;
66  typedef typename Base::const_reverse_iterator const_reverse_iterator;
67 
68  public: // classes
69 
70  class iterator;
71  class const_iterator;
72  class range;
73  class const_range;
74 
75  public: // constructors & destructor
76 
79 
82  //explicit numeric_array_impl(std::size_t d);
83 
84  //numeric_array_impl(std::size_t d, typename boost::call_traits<T>::param_type t);
85 
86  /*
88  template < typename X >
89  explicit numeric_array_impl(const X & v) { functor::CastTo<Self,X>()(*this, v); }
90  */
91 
92  public: // initialization
93 
94  /*
95  template < typename X >
96  inline void operator=(const X & v)
97  {
98  functor::CastTo<X,Self>()(v,*this);
99  }
100  */
101 
102  public: // standard interface
103 
105  std::size_t size() const { return D; }
106 
107  public: // iterators
108 
109  iterator begin() { return iterator(this->Base::begin()); }
110  iterator end() { return iterator(this->Base::end()); }
111  const_iterator begin() const { return const_iterator(this->Base::begin()); }
112  const_iterator end() const { return const_iterator(this->Base::end()); }
113 
114  reverse_iterator rbegin() { return this->Base::rbegin(); }
115  reverse_iterator rend() { return this->Base::rend(); }
116  const_reverse_iterator rbegin() const { return this->Base::rbegin(); }
117  const_reverse_iterator rend() const { return this->Base::rend(); }
118 
119  public: // range
120 
121  range whole_range() { return range(this->begin(), this->end()); }
122  const_range whole_range() const { return const_range(this->begin(), this->end()); }
123 
124  public: // set & get
125 
127  inline const T & operator[](std::size_t n) const
128  {
129  assert(n < D);
130  return this->elems[n];
131  }
133  inline T & operator[](std::size_t n)
134  {
135  assert(n < D);
136  return this->elems[n];
137  }
138 
139  public: // artithmetic operators
140 
141  // arithmetic with other vectors
142  #define TIL_DEFINE(op) \
143  template < typename T2 > \
144  void operator op (const numeric_array_impl<T2,D> & v) \
145  { for (std::size_t i = 0; i < D; ++i) (*this)[i] op v[i]; } \
146 
147  TIL_DEFINE(+=)
148  TIL_DEFINE(-=)
149  TIL_DEFINE(*=)
150  TIL_DEFINE(/=)
151 
152  #undef TIL_DEFINE
153 
154  // arithmetic with constants
155  // deliberately not templated!
156  void operator+=(const T & x)
157  { for (std::size_t i = 0; i < D; ++i) (*this)[i] += x; }
158  void operator-=(const T & x)
159  { for (std::size_t i = 0; i < D; ++i) (*this)[i] -= x; }
160  void operator*=(const T & x)
161  { for (std::size_t i = 0; i < D; ++i) (*this)[i] *= x; }
162 
163  void operator/=(const T & x)
164  { this->divide(x, cat2type<is_floating_point, T>()); }
165  //{ this->operator*=(1/x); }
166 
167  private: // functions
168 
170  template < typename X >
171  void divide(const X & x, label::Passed<is_floating_point>)
172  { this->operator*=(1/x); }
173 
175  template < typename X >
176  void divide(const X & x, label::Failed<is_floating_point>)
177  { for (std::size_t i = 0; i < D; ++i) (*this)[i] /= x; }
178 
179 
180  /*
181  void operator/=(const T & v)
182  { this->divide(v, cat2type<is_integer,T>()); }
183 
184  private: // functions
185 
186 
187  void divide(const T & x, label::Passed<is_integer>)
188  {
189  }
190 
191  void divide(const T & x, label::Failed<is_integer>)
192  {
193  }
194  */
195  };
196 
197 
198  //--------------------------------------------------------------------------
199 
200  /*
201  template < typename T, std::size_D >
202  inline typename numeric_array<T,D>::iterator
203  begin(numeric_array<T,D> & x)
204  { return typename numeric_array<T,D>::iterator(x.begin()); }
205 
206  template < typename T, std::size_D >
207  inline typename numeric_array<T,D>::const_iterator
208  begin(const numeric_array<T,D> & x)
209  { return typename numeric_array<T,D>::iterator(x.begin()); }
210  */
211 
212  //--------------------------------------------------------------------------
213 
214  template < typename T, std::size_t D >
216  : public basic_iterator<T>
217  {
218  public: // typedefs
220  public: // constructors & destructor
221  iterator() : Base() {}
222  iterator(T* p) : Base(p) {}
223  };
224 
225  //--------------------------------------------------------------------------
226 
227  template < typename T, std::size_t D >
229  : public basic_iterator<const T>
230  {
231  public: // typedefs
233  public: // constructors & destructor
234  const_iterator() : Base() {}
235  const_iterator(const T * p) : Base(p) {}
236  const_iterator(iterator i) : Base(i) {}
237  };
238 
239  //-------------------------------------------------------------------------
240 
241  template < typename T, std::size_t D >
243  : public basic_range<typename numeric_array_impl<T,D>::iterator>
244  {
245  public: // typedefs
248  public: // constructors
249  range(iterator begin, iterator end) : Base(begin, end) {}
250  };
251 
252  template < typename T, std::size_t D >
253  class numeric_array_impl<T,D>::const_range : public basic_range<const_iterator>
254  {
255  public: // typedefs
257  public: // constructors
259  };
260 
261  //-------------------------------------------------------------------------
262 
263  } // namespace detail
264 
265 
266  //---------------------------------------------------------------------------
267 
268  template < typename T, std::size_t D >
270  : public detail::numeric_array_impl<T,D>
271  {
272  public: // typedefs
274  public: // constructors
275  numeric_array() : Base() {}
276  //explicit numeric_array(std::size_t d) : Base(d) {}
277  //numeric_array(std::size_t d, T t) : Base(d,t) {}
278  numeric_array(const numeric_array<T,D> & x) : Base(x) {}
279  //template < typename X >
280  //numeric_array(const X & x) : Base(x) {}
281  /*
282  public: // operators
283  template < typename X >
284  void operator=(const X & x) { this->Base::operator=(x); }
285  */
286  };
287 
288  //---------------------------------------------------------------------------
289 
290  template < typename T >
291  class numeric_array<T,3>
292  : public detail::numeric_array_impl<T,3>
293  {
294  public: // typedefs
296  public: // constructors
297 
298  // TODO: find a way that would enable us to initialize like a({2,3}).
299  // That would avoid overloading problems, esp. for 2D vectors, with
300  // the "standard" form COnstructor(size, value).
301 
302  numeric_array() : Base() {}
303  //explicit numeric_array(std::size_t d) : Base(d) {}
304  //numeric_array(std::size_t d, T t) : Base(d,t) {}
305  //template < typename X >
306  //numeric_array(const X & x) : Base(x) {}
307  numeric_array(T x, T y, T z) : Base() { this->init(x,y,z); }
308  numeric_array(const numeric_array<T,3> & x) : Base(x) {}
309  public: // initialization
310  void init(T x, T y, T z) { (*this)[0] = x; (*this)[1] = y; (*this)[2] = z; }
311  /*
312  public: // operators
313  template < typename X >
314  void operator=(const X & x) { this->Base::operator=(x); }
315  */
316  };
317 
318  //---------------------------------------------------------------------------
319 
320 } // namespace til
321 
322 // Package includes
323 #include "til/numeric_array.tpp"
325 #include "til/numeric_array_tools.h"
326 
327 
328 #endif
329 
An implementation of a numeric array.
Definition: numeric_array.h:57
numeric_array_impl< T, D >::iterator iterator
Base::const_reverse_iterator const_reverse_iterator
Definition: numeric_array.h:66
numeric_array(T x, T y, T z)
const_iterator begin() const
detail::numeric_array_impl< T, 3 > Base
Belongs to package Box Do not include directly, include til/Box.h instead.
Definition: Accumulator.h:10
const_reverse_iterator rbegin() const
numeric_array(const numeric_array< T, 3 > &x)
const T & operator[](std::size_t n) const
Read access to n-th value.
Defines empty classes that serves as labels.
const_range whole_range() const
A simple wrapper around T*.
#define TIL_DEFINE(op)
boost::array< T, D > Base
Definition: numeric_array.h:64
range(iterator begin, iterator end)
const_reverse_iterator rend() const
basic_range< const_iterator > Base
numeric_array_impl()
Default constructor.
void init(T x, T y, T z)
numeric_array_impl< T, D > Self
Definition: numeric_array.h:63
T & operator[](std::size_t n)
Read-write access to n-th value.
A label corresponding to a positive answer of a specific is_a test.
Definition: cat2type.h:24
const_range(const_iterator begin, const_iterator end)
numeric_array(const numeric_array< T, D > &x)
const_iterator end() const
A simple range made out of a couple of iterators.
Definition: basic_range.h:18
Base::reverse_iterator reverse_iterator
Definition: numeric_array.h:65
std::size_t size() const
Standard constructors.
detail::numeric_array_impl< T, D > Base
A label corresponding to a negative answer of a specific is_a test.
Definition: cat2type.h:29