TiledArray  0.7.0
val_array.h
Go to the documentation of this file.
1 /*
2  * This file is a part of TiledArray.
3  * Copyright (C) 2014 Virginia Tech
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * Justus Calvin
19  * Department of Chemistry, Virginia Tech
20  *
21  * val_array.h
22  * Feb 17, 2014
23  *
24  */
25 
26 #ifndef TILEDARRAY_SHARED_BUFFER_H__INCLUDED
27 #define TILEDARRAY_SHARED_BUFFER_H__INCLUDED
28 
29 #include <TiledArray/size_array.h>
30 
31 #ifndef TILEDARRAY_DEFAULT_ALIGNMENT
32 #define TILEDARRAY_DEFAULT_ALIGNMENT 16
33 #endif // TILEDARRAY_ALIGNMENT
34 
35 namespace TiledArray {
36  namespace detail {
37 
39 
43  template <typename T>
44  class ValArray : private SizeArray<T> {
45  public:
46 
52  typedef typename SizeArray<T>::pointer pointer;
55  typedef typename SizeArray<T>::iterator iterator;
57 
58  static const std::size_t alignment = TILEDARRAY_DEFAULT_ALIGNMENT;
59 
60  private:
61 
62  mutable madness::AtomicInt* counter_;
63 
64  template <typename U>
65  typename std::enable_if<std::is_scalar<U>::value>::type
66  default_construct(const size_type, U* MADNESS_RESTRICT) { }
67 
68  template <typename U>
69  typename std::enable_if<! std::is_scalar<U>::value>::type
70  default_construct(const size_type n, U* MADNESS_RESTRICT u) {
71  size_type i = 0ul;
72  try {
73  for(; i < n; ++i)
74  new(u + i) U();
75  } catch(...) {
77  throw;
78  }
79  }
80 
81  void deallocate() {
82  if(counter_) {
83  const int count = (*counter_)--;
84  if(count == 1) {
86  free(counter_);
87  }
88  }
89  }
90 
91  void init(const size_type n) {
92  typedef std::integral_constant<size_type,
93  sizeof(madness::AtomicInt) + ((alignment - (sizeof(madness::AtomicInt) & (alignment - 1ul))) & ~alignment)
94  > sizeof_aligned_atomic_int;
95 
96  // Allocate buffer
97  void* buffer = NULL;
98  if(posix_memalign(& buffer, alignment, (n * sizeof(value_type)) + sizeof_aligned_atomic_int::value) != 0)
99  throw std::bad_alloc();
100 
101  // Initialize counter
102  counter_ = reinterpret_cast<madness::AtomicInt*>(buffer);
103  new(counter_) madness::AtomicInt;
104  *counter_ = 1;
105 
106  // Initialize the array
107  pointer const array = reinterpret_cast<pointer>(reinterpret_cast<char*>(buffer) + sizeof_aligned_atomic_int::value);
108  SizeArray<T>::set(array, n);
109  }
110 
111  public:
112 
113  ValArray() : SizeArray<T>(), counter_(NULL) { }
114 
115  explicit ValArray(const size_type n) :
116  SizeArray<T>(), counter_(NULL)
117  {
118  init(n);
119  default_construct(n, SizeArray<T>::data());
120  }
121 
122  template <typename Value,
123  typename std::enable_if<
124  std::is_convertible<value_type, Value>::value
125  >::type* = nullptr>
126  ValArray(const size_type n, const Value& value) :
127  SizeArray<T>(), counter_(NULL)
128  {
129  init(n);
131  }
132 
133  template <typename Arg>
134  ValArray(const size_type n, const Arg* const arg) :
135  SizeArray<T>(), counter_(NULL)
136  {
137  init(n);
139  }
140 
141  template <typename Arg, typename Op>
142  ValArray(const size_type n, const Arg* MADNESS_RESTRICT const arg, const Op& op) :
143  SizeArray<T>(), counter_(NULL)
144  {
145  init(n);
147  }
148 
149  template <typename U, typename Op>
150  ValArray(const ValArray<U>& arg, const Op& op) :
151  SizeArray<T>(), counter_(NULL)
152  {
153  init(arg.size());
155  }
156 
157  template <typename Left, typename Right, typename Op>
158  ValArray(const size_type n, const Left* MADNESS_RESTRICT const left,
159  const Right* MADNESS_RESTRICT const right, const Op& op) :
160  SizeArray<T>(), counter_(NULL)
161  {
162  init(n);
164  }
165 
166  template <typename U, typename V, typename Op>
167  ValArray(const ValArray<U>& left, const ValArray<V>& right, const Op& op) :
168  SizeArray<T>(), counter_(NULL)
169  {
170  TA_ASSERT(left.size() == right.size());
171  init(left.size());
173  right.data(), SizeArray<T>::data(), op);
174  }
175 
176  ValArray(const ValArray_& other) :
177  SizeArray<T>(const_cast<pointer>(other.begin()), const_cast<pointer>(other.end())),
178  counter_(other.counter_)
179  {
180  if(counter_)
181  (*counter_)++;
182  }
183 
184  ValArray_& operator=(const ValArray_& other) {
185  if(counter_ != other.counter_) {
186  // Cache pointers from other
187  madness::AtomicInt* const counter = other.counter_;
188  pointer const first = const_cast<pointer>(other.begin());
189  pointer const last = const_cast<pointer>(other.end());
190 
191  // Increment the reference counter for other
192  if(counter)
193  (*counter)++;
194 
195  // Destroy this object
196  deallocate();
197 
198  // Set the data
199  counter_ = counter;
200  SizeArray<T>::set(first, last);
201  }
202 
203  return *this;
204  }
205 
206  ~ValArray() { deallocate(); }
207 
208  // Import SizeArray interface
209 
210  using SizeArray<T>::begin;
211  using SizeArray<T>::end;
212  using SizeArray<T>::rbegin;
213  using SizeArray<T>::rend;
214  using SizeArray<T>::operator[];
215  using SizeArray<T>::at;
216  using SizeArray<T>::front;
217  using SizeArray<T>::back;
218  using SizeArray<T>::size;
219  using SizeArray<T>::empty;
221  using SizeArray<T>::data;
222  using SizeArray<T>::assign;
223  using SizeArray<T>::binary;
224  using SizeArray<T>::unary;
225  using SizeArray<T>::reduce;
228  using SizeArray<T>::outer;
230 
231 
232  // ValArray wrappers for vector operations
233 
235 
245  template <typename U, typename Op>
246  void binary(const ValArray<U>& arg, const Op& op) {
247  TA_ASSERT(arg.size() == SizeArray<T>::size());
248  SizeArray<T>::binary(arg.data(), op);
249  }
250 
252 
263  template <typename U, typename V, typename Op>
264  void binary(const ValArray<U>& left, const ValArray<V>& right, const Op& op) {
265  TA_ASSERT(left.size() == SizeArray<T>::size());
266  TA_ASSERT(right.size() == SizeArray<T>::size());
267  SizeArray<T>::binary(left.data(), right.data(), op);
268  }
269 
271 
280  template <typename U, typename Op>
281  void unary(const ValArray<U>& arg, const Op& op) {
282  TA_ASSERT(arg.size() == SizeArray<T>::size());
283  SizeArray<T>::unary(arg.data(), op);
284  }
285 
287 
299  template <typename U, typename Result, typename Op>
300  Result reduce(const ValArray<U>& arg, Result& result, const Op& op) {
301  TA_ASSERT(arg.size() == SizeArray<T>::size());
302  return SizeArray<T>::reduce(arg.data(), result, op);
303  }
304 
306 
317  template <typename U, typename V, typename Op>
318  void row_reduce(const ValArray<U>& left, const ValArray<V>& right, const Op& op) {
319  TA_ASSERT(left.size() == (SizeArray<T>::size() * right.size()));
320  SizeArray<T>::row_reduce(right.size(), left.data(), right.data(), op);
321  }
322 
324 
333  template <typename U, typename Op>
334  void row_reduce(const ValArray<U>& arg, const Op& op) {
335  TA_ASSERT((arg.size() % SizeArray<T>::size()) == 0ul);
337  }
338 
340 
351  template <typename U, typename V, typename Op>
352  void col_reduce(const ValArray<U>& left, const ValArray<V>& right, const Op& op) {
353  TA_ASSERT(left.size() == (SizeArray<T>::size() * right.size()));
354  SizeArray<T>::col_reduce(right.size(), left.data(), right.data(), op);
355  }
356 
358 
367  template <typename U, typename Op>
368  void col_reduce(const ValArray<U>& arg, const Op& op) {
369  TA_ASSERT((arg.size() % SizeArray<T>::size()) == 0ul);
371  }
372 
374 
385  template <typename U, typename V, typename Op>
386  void outer(const ValArray<U>& left, const ValArray<V>& right, const Op& op) {
387  TA_ASSERT(SizeArray<T>::size() == (left.size() * right.size()));
388  SizeArray<T>::outer(left.size(), right.size(), left.data(), right.data(), op);
389  }
390 
392 
403  template <typename U, typename V, typename Op>
404  void outer_fill(const ValArray<U>& left, const ValArray<V>& right, const Op& op) {
405  TA_ASSERT(SizeArray<T>::size() == (left.size() * right.size()));
406  SizeArray<T>::outer_fill(left.size(), right.size(), left.data(), right.data(), op);
407  }
408 
410 
422  template <typename U, typename V, typename A, typename Op>
423  void outer_fill(const ValArray<U>& left, const ValArray<V>& right,
424  const ValArray<A>& a, const Op& op)
425  {
426  TA_ASSERT(SizeArray<T>::size() == (left.size() * right.size()));
428  SizeArray<T>::outer_fill(left.size(), right.size(), left.data(), right.data(), a.data(), op);
429  }
430 
431 
432  void swap(ValArray_& other) {
433  std::swap(counter_, other.counter_);
434  pointer const first = other.begin();
435  pointer const last = other.end();
436  other.set(begin(), end());
437  SizeArray<T>::set(first, last);
438  }
439 
440 
441  // Comparison operators
442  template <typename U>
443  bool operator==(const ValArray<U>& other) const {
444  return SizeArray<T>::operator==(other);
445  }
446 
447  template <typename U>
448  bool operator!=(const ValArray<U>& other) const {
449  return SizeArray<T>::operator!=(other);
450  }
451 
452  }; // class ValArray
453 
454 
455  template <typename T>
456  inline std::ostream& operator<<(std::ostream& os, const ValArray<T>& val_array) {
457  print_array(os, val_array);
458  return os;
459  }
460 
461  } // namespace detail
462 } // namespace TiledArray
463 
464 #endif // TILEDARRAY_SHARED_BUFFER_H__INCLUDED
void outer_fill(const ValArray< U > &left, const ValArray< V > &right, const Op &op)
Outer fill operation.
Definition: val_array.h:404
ValArray(const ValArray< U > &left, const ValArray< V > &right, const Op &op)
Definition: val_array.h:167
std::enable_if<!(std::is_scalar< Left >::value &&std::is_scalar< Right >::value &&std::is_scalar< Result >::value)>::type uninitialized_binary_vector_op(const std::size_t n, const Left *const left, const Right *const right, Result *const result, Op &&op)
Definition: vector_op.h:752
void outer_fill(const size_type m, const size_type n, const Left *const left, const Right *const right, const Op &op)
Outer fill operation.
Definition: size_array.h:401
ValArray(const ValArray_ &other)
Definition: val_array.h:176
SizeArray< T >::const_pointer const_pointer
Const data pointer type.
Definition: val_array.h:53
ValArray(const size_type n, const Value &value)
Definition: val_array.h:126
void outer_fill(const ValArray< U > &left, const ValArray< V > &right, const ValArray< A > &a, const Op &op)
Outer operation.
Definition: val_array.h:423
void swap(Bitset< B > &b0, Bitset< B > &b1)
Definition: bitset.h:593
std::enable_if<!(std::is_scalar< Arg >::value &&std::is_scalar< Result >::value)>::type uninitialized_copy_vector(const std::size_t n, const Arg *const arg, Result *const result)
Definition: vector_op.h:688
SizeArray< T >::size_type size_type
size type
Definition: val_array.h:48
void col_reduce(const ValArray< U > &arg, const Op &op)
Reduce column operation.
Definition: val_array.h:368
void set(pointer const first, const size_type n)
Definition: size_array.h:71
void binary(const ValArray< U > &arg, const Op &op)
Binary vector operation.
Definition: val_array.h:246
ValArray(const size_type n, const Arg *const arg)
Definition: val_array.h:134
ValArray_ & operator=(const ValArray_ &other)
Definition: val_array.h:184
void col_reduce(const ValArray< U > &left, const ValArray< V > &right, const Op &op)
Reduce column operation.
Definition: val_array.h:352
void col_reduce(const size_type m, const Left *const left, const Right *right, const Op &op)
Column reduce operation.
Definition: size_array.h:350
std::ptrdiff_t difference_type
Definition: size_array.h:54
SizeArray< T >::const_reference const_reference
Const reference type.
Definition: val_array.h:51
ValArray(const size_type n, const Arg *MADNESS_RESTRICT const arg, const Op &op)
Definition: val_array.h:142
const_pointer data() const
Definition: size_array.h:170
SizeArray< T >::reference reference
Reference type.
Definition: val_array.h:50
void row_reduce(const size_type n, const Left *const left, const Right *right, const Op &op)
Row reduce operation.
Definition: size_array.h:319
ValArray< T > ValArray_
This object type.
Definition: val_array.h:47
Result reduce(const ValArray< U > &arg, Result &result, const Op &op)
Binary reduce operation.
Definition: val_array.h:300
ValArray(const size_type n)
Definition: val_array.h:115
std::enable_if<! std::is_scalar< Arg >::value >::type destroy_vector(const std::size_t n, Arg *const arg)
Definition: vector_op.h:720
void swap(ValArray_ &other)
Definition: val_array.h:432
SizeArray< T >::iterator iterator
Iterator type.
Definition: val_array.h:55
void outer(const ValArray< U > &left, const ValArray< V > &right, const Op &op)
Outer operation.
Definition: val_array.h:386
ValArray(const size_type n, const Left *MADNESS_RESTRICT const left, const Right *MADNESS_RESTRICT const right, const Op &op)
Definition: val_array.h:158
void print_array(std::ostream &out, const A &a, const std::size_t n)
Print the content of an array like object.
Definition: utility.h:153
SizeArray< T >::pointer pointer
Data pointer type.
Definition: val_array.h:52
#define TA_ASSERT(a)
Definition: error.h:107
void row_reduce(const ValArray< U > &arg, const Op &op)
Reduce row operation.
Definition: val_array.h:334
SizeArray< T >::value_type value_type
Element type.
Definition: val_array.h:49
size_type size() const
Definition: size_array.h:160
void unary(const ValArray< U > &arg, const Op &op)
Unary vector operation.
Definition: val_array.h:281
SizeArray< T >::difference_type difference_type
Difference type.
Definition: val_array.h:54
bool operator!=(const ValArray< U > &other) const
Definition: val_array.h:448
void binary(const Arg *const arg, const Op &op)
Binary vector operation.
Definition: size_array.h:222
#define TILEDARRAY_DEFAULT_ALIGNMENT
Definition: val_array.h:32
Result reduce(const Arg *const arg, Result result, const ReduceOp &reduce_op, const JoinOp &join_op) const
Binary reduction operation.
Definition: size_array.h:283
bool operator!=(const SizeArray< U > &other) const
Definition: size_array.h:196
void row_reduce(const ValArray< U > &left, const ValArray< V > &right, const Op &op)
Reduce row operation.
Definition: val_array.h:318
void unary(const Op &op)
Unary vector operation.
Definition: size_array.h:249
void outer(const size_type m, const size_type n, const Left *const left, const Right *const right, const Op &op)
Outer operation.
Definition: size_array.h:381
SizeArray< T >::const_iterator const_iterator
Const iterator type.
Definition: val_array.h:56
bool operator==(const SizeArray< U > &other) const
Definition: size_array.h:180
void binary(const ValArray< U > &left, const ValArray< V > &right, const Op &op)
Binary vector operation.
Definition: val_array.h:264
static const std::size_t alignment
Definition: val_array.h:58
std::enable_if<!(std::is_scalar< Arg >::value &&std::is_scalar< Result >::value)>::type uninitialized_unary_vector_op(const std::size_t n, const Arg *const arg, Result *const result, Op &&op)
Definition: vector_op.h:732
ValArray(const ValArray< U > &arg, const Op &op)
Definition: val_array.h:150
bool operator==(const ValArray< U > &other) const
Definition: val_array.h:443
std::enable_if<!(std::is_scalar< Arg >::value &&std::is_scalar< Result >::value)>::type uninitialized_fill_vector(const std::size_t n, const Arg &arg, Result *const result)
Definition: vector_op.h:703