Program Listing for File array.hpp#
↰ Return to documentation for file (source/pele/array.hpp)
#ifndef PYGMIN_ARRAY_H
#define PYGMIN_ARRAY_H
#include <algorithm>
#include <cassert>
#include <cmath>
#include <initializer_list>
#include <iostream>
#include <memory>
#include <numeric>
#include <stdexcept>
#include <vector>
namespace pele {
template <typename dtype>
class _ArrayMemory {
std::vector<dtype> _vector;
dtype
*_data;
size_t _size;
public:
_ArrayMemory() : _vector(), _data(_vector.data()), _size(_vector.size()) {}
_ArrayMemory(size_t size)
: _vector(size), _data(_vector.data()), _size(_vector.size()) {}
_ArrayMemory(size_t size, dtype const &val)
: _vector(size, val), _data(_vector.data()), _size(_vector.size()) {}
_ArrayMemory(dtype *data, size_t size)
: _vector(), _data(data), _size(size) {}
inline size_t size() const { return _size; }
inline dtype *data() { return _data; }
inline dtype const *data() const { return _data; }
};
template <typename dtype>
class Array {
protected:
std::shared_ptr<_ArrayMemory<dtype>> _memory;
dtype *_data;
size_t _size;
public:
Array()
: _memory(new _ArrayMemory<dtype>()),
_data(_memory->data()),
_size(_memory->size()) {}
Array(size_t size)
: _memory(new _ArrayMemory<dtype>(size)),
_data(_memory->data()),
_size(_memory->size()) {}
Array(size_t size, dtype const &val)
: _memory(new _ArrayMemory<dtype>(size, val)),
_data(_memory->data()),
_size(_memory->size())
{}
Array(std::initializer_list<dtype> data)
: _memory(new _ArrayMemory<dtype>(data.size())),
_data(_memory->data()),
_size(_memory->size()) {
std::copy(data.begin(), data.end(), _data);
}
Array(dtype *data, size_t size)
: _memory(new _ArrayMemory<dtype>(data, size)),
_data(_memory->data()),
_size(_memory->size()) {}
Array(dtype *data_begin, dtype *data_end)
: _memory(new _ArrayMemory<dtype>(data_begin, data_end - data_begin)),
_data(_memory->data()),
_size(_memory->size()) {}
Array(std::vector<dtype> &x)
: _memory(new _ArrayMemory<dtype>(x.data(), x.size())),
_data(_memory->data()),
_size(_memory->size()) {}
inline void wrap(Array<dtype> x) {
_memory = x._memory;
_data = x._data;
_size = x._size;
}
inline dtype *data() { return _data; }
inline dtype const *data() const { return _data; }
inline size_t size() const { return _size; }
inline dtype &operator[](const size_t i) { return data()[i]; }
inline dtype const &operator[](const size_t i) const { return data()[i]; }
typedef dtype *iterator;
typedef dtype const *const_iterator;
inline iterator begin() { return data(); }
inline iterator end() { return data() + size(); }
inline const_iterator begin() const { return data(); }
inline const_iterator end() const { return data() + size(); }
/*
* Assignment operator: WRAP the data
*
* This is commented because it just duplicates the default assignment
operator
*
Array<dtype> &operator=(const Array<dtype> & rhs){
_memory = rhs._memory;
_data = rhs._data;
_size = rhs._size;
}
*/
inline bool operator==(Array<dtype> const rhs) const {
return data() == rhs.data() and size() == rhs.size();
}
inline bool operator!=(Array<dtype> const rhs) const {
return !operator==(rhs);
}
Array<dtype> &assign(const Array<dtype> &rhs) {
// check for self assignment
if ((*this) != rhs) {
if (size() != rhs.size()) {
throw std::runtime_error(
"arrays must have the same size during assignment");
}
std::copy(rhs.begin(), rhs.end(), begin());
}
return *this;
}
Array<dtype> &assign(dtype const &d) {
std::fill(begin(), end(), d);
return *this;
}
// Inactive pointer-assignment prototype.
// Array<dtype> &assign(dtype const * const d) {
// std::copy(rhs.begin(), rhs.end(), begin());
// for (size_t i = 0; i < size(); ++i) {
//
// }
// return *this;
// }
Array<dtype> copy() const {
Array<dtype> newarray(size());
newarray.assign(*this);
return newarray;
}
inline void free() {
_memory = std::make_shared<_ArrayMemory<dtype>>();
_data = _memory->data();
_size = _memory->size();
}
inline bool empty() const { return size() == 0; }
inline long int reference_count() const { return _memory.use_count(); }
Array<dtype> operator+(const Array<dtype> &rhs) {
if (size() != rhs.size()) {
throw std::runtime_error("operator+: arrays must have the same size");
}
Array<dtype> newarray(size());
const_iterator iter = rhs.begin();
const_iterator iternew = (*this).begin();
for (dtype &val : newarray) {
val = *iternew + *iter;
++iter;
++iternew;
}
return newarray;
}
Array<dtype> operator-(const Array<dtype> &rhs) {
if (size() != rhs.size()) {
throw std::runtime_error("operator+: arrays must have the same size");
}
Array<dtype> newarray(size());
const_iterator iter = rhs.begin();
const_iterator iternew = (*this).begin();
for (dtype &val : newarray) {
val = *iternew - *iter;
++iter;
++iternew;
}
return newarray;
}
Array<dtype> operator-() {
Array<dtype> newarray(size());
const_iterator iter = (*this).begin();
for (dtype &val : newarray) {
val = -*iter;
++iter;
}
return newarray;
}
Array<dtype> &operator+=(const Array<dtype> &rhs) {
if (size() != rhs.size()) {
throw std::runtime_error("operator+=: arrays must have the same size");
}
const_iterator iter = rhs.begin();
for (dtype &val : *this) {
val += *iter;
++iter;
}
return *this;
}
Array<dtype> &operator+=(const dtype &rhs) {
for (dtype &val : (*this)) {
val += rhs;
}
return *this;
}
Array<dtype> &operator-=(const Array<dtype> &rhs) {
if (size() != rhs.size()) {
throw std::runtime_error("operator-=: arrays must have the same size");
}
const_iterator iter = rhs.begin();
for (dtype &val : *this) {
val -= *iter;
++iter;
}
return *this;
}
Array<dtype> &operator-=(const dtype &rhs) {
for (dtype &val : (*this)) {
val -= rhs;
}
return *this;
}
Array<dtype> &operator*=(const Array<dtype> &rhs) {
if (size() != rhs.size()) {
throw std::runtime_error("operator*=: arrays must have the same size");
}
const_iterator iter = rhs.begin();
for (dtype &val : *this) {
val *= *iter;
++iter;
}
return *this;
}
Array<dtype> &operator*=(const dtype &rhs) {
for (dtype &val : (*this)) {
val *= rhs;
}
return *this;
}
Array<dtype> operator*(const dtype rhs) {
Array<dtype> result = this->copy();
return (result *= rhs).copy();
}
Array<dtype> &operator/=(const Array<dtype> &rhs) {
if (size() != rhs.size()) {
throw std::runtime_error("operator/=: arrays must have the same size");
}
const_iterator iter = rhs.begin();
for (dtype &val : *this) {
val /= *iter;
++iter;
}
return *this;
}
Array<dtype> &operator/=(const dtype &rhs) {
for (dtype &val : (*this)) {
val /= rhs;
}
return *this;
}
/*SOME OTHER ARITHMETIC UTILITIES*/
dtype sum() const {
if (empty()) {
throw std::runtime_error(
"array::sum(): array is empty, can't sum array elements");
}
return std::accumulate(begin(), end(), dtype(0));
}
dtype prod() const {
if (empty()) {
throw std::runtime_error(
"array::prod(): array is empty, can't take "
"product of array elements");
}
return std::accumulate(begin(), end(), dtype(1), std::multiplies<dtype>());
}
std::vector<dtype> to_std_vector_copy() const {
// copy the data into a new std::vector
std::vector<dtype> std_vec(_size);
std::copy(begin(), end(), std_vec.begin());
return std_vec;
}
Array<dtype> view(size_t ibegin, size_t iend) const {
if (iend <= ibegin) {
throw std::invalid_argument("iend must larger than ibegin");
}
if (iend > size()) {
throw std::invalid_argument("iend cannot be larger than array size");
}
Array<dtype> newarray(*this);
newarray._data += ibegin;
newarray._size = iend - ibegin;
return newarray;
}
dtype get_max() const { return *std::max_element(begin(), end()); }
dtype get_min() const { return *std::min_element(begin(), end()); }
};
// for array printing
template <class dtype>
inline std::ostream &operator<<(std::ostream &out, const Array<dtype> &a) {
for (size_t i = 0; i < a.size(); ++i) {
if (i > 0) out << ", ";
out << a[i];
}
out << std::endl;
return out;
}
inline double dot(Array<double> const &v1, Array<double> const &v2) {
assert(v1.size() == v2.size());
return std::inner_product(v1.begin(), v1.end(), v2.begin(), double(0));
}
inline double norm(Array<double> const &v) { return sqrt(dot(v, v)); }
template <class T, class U>
Array<T> operator*(const U rhs, const Array<T> &lhs) {
Array<T> result = lhs.copy();
return (result *= rhs).copy();
}
} // namespace pele
#endif // #ifndef PYGMIN_ARRAY_H