Page MenuHomec4science

array.hh
No OneTemporary

File Metadata

Created
Fri, Jul 5, 20:15

array.hh

/*
* SPDX-License-Indentifier: AGPL-3.0-or-later
*
* Copyright (©) 2016-2022 EPFL (École Polytechnique Fédérale de Lausanne),
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
* Copyright (©) 2020-2022 Lucas Frérot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef ARRAY_HH
#define ARRAY_HH
/* -------------------------------------------------------------------------- */
#include "allocator.hh"
#include "logger.hh"
#include "span.hh"
#include "tamaas.hh"
#include <memory>
#include <thrust/copy.h>
#include <thrust/fill.h>
#include <utility>
/* -------------------------------------------------------------------------- */
namespace tamaas {
/// Generic storage class with wrapping capacities
template <typename T>
struct Array final {
/// Default
Array() = default;
/// Empty array of given size
Array(UInt size) : Array() { resize(size); }
/// Copy constructor (deep)
Array(const Array& v) : Array() {
resize(v.size());
thrust::copy(v.view_.begin(), v.view_.end(), view_.begin());
}
/// Move constructor (transfers data ownership)
Array(Array&& v) noexcept : Array() {
view_ = std::exchange(v.view_, span<T>{});
reserved_ = std::exchange(v.reserved_, 0);
wrapped_ = std::exchange(v.wrapped_, false);
}
/// Wrap array on data
Array(T* data, UInt size) noexcept : Array() { wrap(data, size); }
/// Wrap on span
Array(span<T> view) noexcept : Array() { wrap(view); }
/// Destructor
~Array() {
if (not wrapped_)
alloc_.deallocate(view_);
}
/// Copy operator
Array& operator=(const Array& v) {
wrapped_ = false;
resize(v.size());
thrust::copy(v.view_.begin(), v.view_.end(), view_.begin());
return *this;
}
/// Move operator
Array& operator=(Array&& v) noexcept {
if (this == &v)
return *this;
if (not wrapped_)
alloc_.deallocate(view_);
view_ = std::exchange(v.view_, span<T>{});
reserved_ = std::exchange(v.reserved_, 0);
wrapped_ = std::exchange(v.wrapped_, false);
return *this;
}
/// Wrap on view
Array& operator=(span<T> v) noexcept { wrap(v); }
/// Wrap array
void wrap(const Array& other) noexcept { wrap(other.view_); }
/// Wrap view
void wrap(span<T> view) noexcept {
view_ = view;
wrapped_ = true;
reserved_ = 0;
}
/// Wrap a memory pointer
void wrap(T* data, UInt size) noexcept { wrap(span<T>{data, size}); }
/// Data pointer access (const)
const T* data() const { return view_.data(); }
/// Data pointer access (non-const)
T* data() { return view_.data(); }
/// Resize array
void resize(UInt new_size, const T& value = T()) {
if (wrapped_)
TAMAAS_EXCEPTION("cannot resize wrapped array");
// Erase array
if (new_size == 0) {
alloc_.deallocate(view_);
view_ = span<T>{};
reserved_ = 0;
return;
}
// Do nothing
if (new_size == size())
return;
// Allocate new data
alloc_.deallocate(view_);
view_ = alloc_.allocate(new_size);
reserved_ = new_size;
if (not wrapped_)
thrust::fill(view_.begin(), view_.end(), value);
}
/// Reserve storage space
void reserve(UInt size) {
if (reserved_ >= size)
return;
auto new_view = alloc_.allocate(size);
if (new_view.data() != view_.data()) {
thrust::copy(view_.begin(), view_.end(), new_view.begin());
alloc_.deallocate(view_);
view_ = {new_view.data(), view_.size()};
reserved_ = view_.size();
} else {
reserved_ = size;
}
}
/// Access operator
inline T& operator[](UInt i) { return view_[i]; }
/// Access operator (const)
inline const T& operator[](UInt i) const { return view_[i]; }
/// Get size of array
inline UInt size() const { return view_.size(); }
span<T> view() const { return view_; }
private:
span<T> view_;
typename span<T>::size_type reserved_ = 0;
bool wrapped_ = false;
Allocator<T> alloc_;
};
} // namespace tamaas
/* -------------------------------------------------------------------------- */
#endif /* ARRAY_HH */

Event Timeline