LIBINT  2.6.0
array_adaptor.h
1 /*
2  * Copyright (C) 2004-2019 Edward F. Valeev
3  *
4  * This file is part of Libint.
5  *
6  * Libint is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Libint is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with Libint. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #ifndef INCLUDE_LIBINT2_UTIL_ARRAY_ADAPTOR_H_
22 #define INCLUDE_LIBINT2_UTIL_ARRAY_ADAPTOR_H_
23 
24 #include <cassert>
25 #include <cstdlib>
26 #include <cstddef>
27 #include <type_traits>
28 #include <vector>
29 
30 namespace libint2 {
31 namespace detail {
32 
35 template <class T, std::size_t N>
37  public:
38  using value_type = T;
39  using pointer = T*;
40  using difference_type =
41  typename std::pointer_traits<pointer>::difference_type;
42  using size_type = typename std::make_unsigned<difference_type>::type;
43  using propagate_on_container_copy_assignment = std::true_type;
44  using propagate_on_container_move_assignment = std::true_type;
45 
46  static auto constexpr size = N;
47  typedef T array_type[N];
48 
49  private:
50  T* stack_; // stack-allocated storage
51  T* free_; // ptr to the first free element on stack
52 
53  public:
54  ext_stack_allocator() noexcept : stack_(nullptr), free_(stack_) {}
55  ext_stack_allocator(const ext_stack_allocator& other) = default;
57  : stack_(other.stack_), free_(other.free_) {}
58  ext_stack_allocator& operator=(const ext_stack_allocator& other) = default;
59  ext_stack_allocator& operator=(ext_stack_allocator&& other) noexcept {
60  stack_ = other.stack_;
61  free_ = other.free_;
62  return *this;
63  }
64 
65  explicit ext_stack_allocator(array_type& array) noexcept
66  : stack_(&array[0]), free_(stack_) {}
67  template <typename U, typename = typename std::enable_if<std::is_same<const U,T>::value>>
68  explicit ext_stack_allocator(U (&array)[N]) noexcept
69  : stack_(const_cast<T*>(&array[0])), free_(stack_) {}
70 
71  template <class _Up>
72  struct rebind {
74  };
75 
76  T* allocate(std::size_t n) {
77  assert(stack_ != nullptr && "array_view_allocator not initialized");
78  if (stack_ + N - free_ >=
79  static_cast<std::ptrdiff_t>(n)) { // have free space on stack
80  const auto result = free_;
81  free_ += n;
82  return result;
83  } else {
84  return new T[n];
85  }
86  }
87  void deallocate(T* p, std::size_t n) noexcept {
88  if (pointer_on_stack(p)) {
89  assert(p + n == free_ && "stack deallocation out of order");
90  free_ -= n;
91  } else {
92  delete[] p;
93  }
94  }
95 
96  template <class T1, std::size_t N1>
97  friend bool operator==(const ext_stack_allocator<T1, N1>& x,
98  const ext_stack_allocator<T1, N1>& y) noexcept;
99 
100  private:
101  bool pointer_on_stack(T* ptr) const {
102  return stack_ <= ptr && ptr < stack_ + N;
103  }
104 };
105 
106 template <class T, std::size_t N>
107 inline bool operator==(const ext_stack_allocator<T, N>& x,
108  const ext_stack_allocator<T, N>& y) noexcept {
109  return x.stack_ == y.stack_ && x.free_ == y.free_;
110 }
111 
112 template <class T, std::size_t N>
113 inline bool operator!=(const ext_stack_allocator<T, N>& x,
114  const ext_stack_allocator<T, N>& y) noexcept {
115  return !(x == y);
116 }
117 } // namespace detail
118 } // namespace libint2
119 
120 #endif // INCLUDE_LIBINT2_UTIL_ARRAY_ADAPTOR_H_
Definition: array_adaptor.h:72
Defaults definitions for various parameters assumed by Libint.
Definition: algebra.cc:24
allocator that uses an externally-managed stack-allocated array for allocations up to max_size,...
Definition: array_adaptor.h:36