419 lines
11 KiB
C++
419 lines
11 KiB
C++
/*//////////////////////////////////////////////////////////////////////////////
|
|
// CMT Cosmic Muon Tomography project //////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova
|
|
All rights reserved
|
|
|
|
Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it >
|
|
|
|
------------------------------------------------------------------
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 3.0 of the License, or (at your option) any later version.
|
|
|
|
This library 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
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library.
|
|
|
|
//////////////////////////////////////////////////////////////////////////////*/
|
|
|
|
#ifndef U_CORE_VECTOR_H
|
|
#define U_CORE_VECTOR_H
|
|
|
|
#include <iostream>
|
|
#include <map>
|
|
#include <mutex>
|
|
#include <vector>
|
|
|
|
#include <Core/DataAllocator.h>
|
|
|
|
#include <Core/CommaInitializer.h>
|
|
#include <Core/SmartPointer.h>
|
|
#include <Core/StaticInterface.h>
|
|
|
|
namespace uLib {
|
|
|
|
// MetaAllocator Implementation ...
|
|
template <typename T> class MetaAllocator {
|
|
public:
|
|
using value_type = T;
|
|
using pointer = T *;
|
|
using const_pointer = const T *;
|
|
using reference = T &;
|
|
using const_reference = const T &;
|
|
using size_type = std::size_t;
|
|
using difference_type = std::ptrdiff_t;
|
|
|
|
template <class U> struct rebind {
|
|
using other = MetaAllocator<U>;
|
|
};
|
|
|
|
MetaAllocator() noexcept = default;
|
|
|
|
template <class U>
|
|
constexpr MetaAllocator(const MetaAllocator<U> &) noexcept {}
|
|
|
|
T *allocate(std::size_t n) {
|
|
if (n == 0)
|
|
return nullptr;
|
|
|
|
DataAllocator<T> *da = new DataAllocator<T>(n, false);
|
|
T *ptr = da->GetRAMData();
|
|
|
|
std::lock_guard<std::mutex> lock(GetMutex());
|
|
GetAllocationMap()[ptr] = da;
|
|
return ptr;
|
|
}
|
|
|
|
void deallocate(T *p, std::size_t /*n*/) noexcept {
|
|
if (!p)
|
|
return;
|
|
|
|
std::lock_guard<std::mutex> lock(GetMutex());
|
|
auto &map = GetAllocationMap();
|
|
auto it = map.find(p);
|
|
if (it != map.end()) {
|
|
delete it->second;
|
|
map.erase(it);
|
|
}
|
|
}
|
|
|
|
static DataAllocator<T> *GetDataAllocator(T *p) {
|
|
if (!p)
|
|
return nullptr;
|
|
std::lock_guard<std::mutex> lock(GetMutex());
|
|
auto &map = GetAllocationMap();
|
|
auto it = map.find(p);
|
|
if (it != map.end()) {
|
|
return it->second;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
private:
|
|
static std::map<T *, DataAllocator<T> *> &GetAllocationMap() {
|
|
static std::map<T *, DataAllocator<T> *> allocMap;
|
|
return allocMap;
|
|
}
|
|
|
|
static std::mutex &GetMutex() {
|
|
static std::mutex mtx;
|
|
return mtx;
|
|
}
|
|
};
|
|
|
|
template <class T, class U>
|
|
bool operator==(const MetaAllocator<T> &, const MetaAllocator<U> &) {
|
|
return true;
|
|
}
|
|
template <class T, class U>
|
|
bool operator!=(const MetaAllocator<T> &, const MetaAllocator<U> &) {
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Vector Implemetation ... wraps std::vector
|
|
template <typename T> class Vector : public std::vector<T, MetaAllocator<T>> {
|
|
typedef std::vector<T, MetaAllocator<T>> BaseClass;
|
|
typedef MetaAllocator<T> Allocator;
|
|
|
|
public:
|
|
typedef T TypeData;
|
|
typedef __gnu_cxx::__normal_iterator<T *, BaseClass> Iterator;
|
|
typedef __gnu_cxx::__normal_iterator<const T *, BaseClass> ConstIterator;
|
|
|
|
typedef CommaInitializer<Vector<T>, T> VectorCommaInit;
|
|
typedef typename BaseClass::iterator iterator;
|
|
typedef typename BaseClass::const_iterator const_iterator;
|
|
typedef typename BaseClass::size_type size_type;
|
|
typedef typename BaseClass::reference reference;
|
|
|
|
Vector(unsigned int size) : BaseClass(size) {}
|
|
Vector(unsigned int size, T &value) : BaseClass(size, value) {}
|
|
Vector() : BaseClass(0) {}
|
|
Vector(std::initializer_list<T> init) : BaseClass(init) {}
|
|
|
|
inline VectorCommaInit operator<<(T scalar) {
|
|
return VectorCommaInit(this, scalar);
|
|
}
|
|
|
|
void MoveToVRAM() {
|
|
if (auto alloc = MetaAllocator<T>::GetDataAllocator(BaseClass::data())) {
|
|
alloc->MoveToVRAM();
|
|
}
|
|
}
|
|
|
|
void MoveToRAM() {
|
|
if (auto alloc = MetaAllocator<T>::GetDataAllocator(BaseClass::data())) {
|
|
alloc->MoveToRAM();
|
|
}
|
|
}
|
|
|
|
T *GetVRAMData() {
|
|
if (auto alloc = MetaAllocator<T>::GetDataAllocator(BaseClass::data())) {
|
|
return alloc->GetVRAMData();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
const T *GetVRAMData() const {
|
|
if (auto alloc = MetaAllocator<T>::GetDataAllocator(
|
|
const_cast<T *>(BaseClass::data()))) {
|
|
return alloc->GetVRAMData();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
inline void PrintSelf(std::ostream &o);
|
|
|
|
// Overrides for auto-sync //
|
|
T &operator[](size_t i) {
|
|
this->MoveToRAM();
|
|
return BaseClass::operator[](i);
|
|
}
|
|
const T &operator[](size_t i) const {
|
|
const_cast<Vector *>(this)->MoveToRAM();
|
|
return BaseClass::operator[](i);
|
|
}
|
|
T &at(size_t i) {
|
|
this->MoveToRAM();
|
|
return BaseClass::at(i);
|
|
}
|
|
const T &at(size_t i) const {
|
|
const_cast<Vector *>(this)->MoveToRAM();
|
|
return BaseClass::at(i);
|
|
}
|
|
T &front() {
|
|
this->MoveToRAM();
|
|
return BaseClass::front();
|
|
}
|
|
const T &front() const {
|
|
const_cast<Vector *>(this)->MoveToRAM();
|
|
return BaseClass::front();
|
|
}
|
|
T &back() {
|
|
this->MoveToRAM();
|
|
return BaseClass::back();
|
|
}
|
|
const T &back() const {
|
|
const_cast<Vector *>(this)->MoveToRAM();
|
|
return BaseClass::back();
|
|
}
|
|
T *data() noexcept {
|
|
this->MoveToRAM();
|
|
return BaseClass::data();
|
|
}
|
|
const T *data() const noexcept {
|
|
const_cast<Vector *>(this)->MoveToRAM();
|
|
return BaseClass::data();
|
|
}
|
|
Iterator begin() noexcept {
|
|
this->MoveToRAM();
|
|
return BaseClass::begin();
|
|
}
|
|
ConstIterator begin() const noexcept {
|
|
const_cast<Vector *>(this)->MoveToRAM();
|
|
return BaseClass::begin();
|
|
}
|
|
Iterator end() noexcept {
|
|
this->MoveToRAM();
|
|
return BaseClass::end();
|
|
}
|
|
ConstIterator end() const noexcept {
|
|
const_cast<Vector *>(this)->MoveToRAM();
|
|
return BaseClass::end();
|
|
}
|
|
auto rbegin() noexcept {
|
|
this->MoveToRAM();
|
|
return BaseClass::rbegin();
|
|
}
|
|
auto rbegin() const noexcept {
|
|
const_cast<Vector *>(this)->MoveToRAM();
|
|
return BaseClass::rbegin();
|
|
}
|
|
auto rend() noexcept {
|
|
this->MoveToRAM();
|
|
return BaseClass::rend();
|
|
}
|
|
auto rend() const noexcept {
|
|
const_cast<Vector *>(this)->MoveToRAM();
|
|
return BaseClass::rend();
|
|
}
|
|
|
|
void push_back(const T &x) {
|
|
this->MoveToRAM();
|
|
BaseClass::push_back(x);
|
|
}
|
|
void push_back(T &&x) {
|
|
this->MoveToRAM();
|
|
BaseClass::push_back(std::move(x));
|
|
}
|
|
template <typename... Args> reference emplace_back(Args &&...args) {
|
|
this->MoveToRAM();
|
|
return BaseClass::emplace_back(std::forward<Args>(args)...);
|
|
}
|
|
void pop_back() {
|
|
this->MoveToRAM();
|
|
BaseClass::pop_back();
|
|
}
|
|
|
|
template <typename... Args>
|
|
iterator emplace(const_iterator pos, Args &&...args) {
|
|
this->MoveToRAM();
|
|
return BaseClass::emplace(pos, std::forward<Args>(args)...);
|
|
}
|
|
iterator insert(const_iterator pos, const T &x) {
|
|
this->MoveToRAM();
|
|
return BaseClass::insert(pos, x);
|
|
}
|
|
iterator insert(const_iterator pos, T &&x) {
|
|
this->MoveToRAM();
|
|
return BaseClass::insert(pos, std::move(x));
|
|
}
|
|
template <typename InputIt>
|
|
iterator insert(const_iterator pos, InputIt first, InputIt last) {
|
|
this->MoveToRAM();
|
|
return BaseClass::insert(pos, first, last);
|
|
}
|
|
iterator erase(const_iterator pos) {
|
|
this->MoveToRAM();
|
|
return BaseClass::erase(pos);
|
|
}
|
|
iterator erase(const_iterator first, const_iterator last) {
|
|
this->MoveToRAM();
|
|
return BaseClass::erase(first, last);
|
|
}
|
|
|
|
void resize(size_t n) {
|
|
this->MoveToRAM();
|
|
BaseClass::resize(n);
|
|
}
|
|
void resize(size_t n, const T &x) {
|
|
this->MoveToRAM();
|
|
BaseClass::resize(n, x);
|
|
}
|
|
void reserve(size_t n) {
|
|
this->MoveToRAM();
|
|
BaseClass::reserve(n);
|
|
}
|
|
void clear() noexcept {
|
|
this->MoveToRAM();
|
|
BaseClass::clear();
|
|
}
|
|
template <typename InputIt> void assign(InputIt first, InputIt last) {
|
|
this->MoveToRAM();
|
|
BaseClass::assign(first, last);
|
|
}
|
|
void assign(size_type count, const T &value) {
|
|
this->MoveToRAM();
|
|
BaseClass::assign(count, value);
|
|
}
|
|
|
|
void remove_element(unsigned int index) {
|
|
this->MoveToRAM();
|
|
std::swap(this->at(index), this->back());
|
|
this->pop_back();
|
|
}
|
|
|
|
void remove_element(T &t) {
|
|
this->MoveToRAM();
|
|
std::swap(t, this->back());
|
|
this->pop_back();
|
|
}
|
|
};
|
|
|
|
template <typename T> void Vector<T>::PrintSelf(std::ostream &o) {
|
|
o << " *** uLib Vector *** \n";
|
|
o << " n. of items = " << this->size() << "\n";
|
|
for (int i = 0; i < this->size(); ++i)
|
|
o << (T)this->at(i) << " ";
|
|
o << "\n";
|
|
}
|
|
|
|
template <typename T>
|
|
std::ostream &operator<<(std::ostream &o, const Vector<T> &v) {
|
|
for (int i = 0; i < v.size(); ++i)
|
|
o << (T)v.at(i) << " ";
|
|
o << "\n";
|
|
return o;
|
|
}
|
|
|
|
template <typename T>
|
|
std::ofstream &operator<<(std::ofstream &o, const Vector<T> &v) {
|
|
for (int i = 0; i < v.size(); ++i)
|
|
o << (T)v.at(i) << " ";
|
|
return o;
|
|
}
|
|
|
|
template <typename T> std::istream &operator>>(std::istream &is, Vector<T> &v) {
|
|
T value;
|
|
while (is >> value) {
|
|
if (is.fail())
|
|
v.push_back(0);
|
|
else
|
|
v.push_back(value);
|
|
}
|
|
return is;
|
|
}
|
|
|
|
// Smart pointer Vector Implementation //
|
|
|
|
template <typename T> class SmartVector : public SmartPointer<Vector<T>> {
|
|
typedef SmartPointer<Vector<T>> Base;
|
|
|
|
public:
|
|
SmartVector() : Base(new Vector<T>()) {}
|
|
SmartVector(const SmartVector ©) : Base(copy) {}
|
|
SmartVector(unsigned int size) : Base(new Vector<T>((int)size)) {}
|
|
|
|
virtual ~SmartVector() {}
|
|
|
|
T &operator[](int p) { return Base::get()->at(p); }
|
|
|
|
void swap_elements(unsigned int first, unsigned int second) {
|
|
std::swap(Base::get()->at(first), Base::get()->at(second));
|
|
}
|
|
|
|
void remove_element(unsigned int index) {
|
|
std::swap(Base::get()->at(index), Base::get()->back());
|
|
Base::get()->pop_back();
|
|
}
|
|
|
|
void remove_element(T &t) {
|
|
std::swap(t, Base::get()->back());
|
|
Base::get()->pop_back();
|
|
}
|
|
};
|
|
|
|
// ------ Utils ------------------------------------------------------------- //
|
|
|
|
// RIFARE con iteratore !
|
|
template <typename _Tp, class _CmpT>
|
|
inline unsigned long VectorSplice(const _Tp &_it, const _Tp &_end,
|
|
const float value, _CmpT _comp) {
|
|
_Tp it = _it;
|
|
_Tp end = _end - 1;
|
|
for (; it != end;) {
|
|
if (_comp(*it, value))
|
|
++it;
|
|
else if (_comp(*end, value))
|
|
std::swap(*it, *end--);
|
|
else
|
|
--end;
|
|
}
|
|
return it - _it;
|
|
}
|
|
|
|
} // namespace uLib
|
|
|
|
#endif // VECTOR_H
|