diff options
Diffstat (limited to 'vendor/github.com/dexon-foundation/mcl/include/cybozu/array.hpp')
-rw-r--r-- | vendor/github.com/dexon-foundation/mcl/include/cybozu/array.hpp | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/vendor/github.com/dexon-foundation/mcl/include/cybozu/array.hpp b/vendor/github.com/dexon-foundation/mcl/include/cybozu/array.hpp new file mode 100644 index 000000000..30df3667d --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/include/cybozu/array.hpp @@ -0,0 +1,197 @@ +#pragma once + +/** + @file + @brief scoped array and aligned array + + @author MITSUNARI Shigeo(@herumi) +*/ +#include <new> +#include <utility> +#ifdef _WIN32 + #include <malloc.h> +#else + #include <stdlib.h> +#endif +#include <cybozu/inttype.hpp> + +namespace cybozu { + +inline void *AlignedMalloc(size_t size, size_t alignment) +{ +#ifdef _WIN32 + return _aligned_malloc(size, alignment); +#else + void *p; + int ret = posix_memalign(&p, alignment, size); + return (ret == 0) ? p : 0; +#endif +} + +inline void AlignedFree(void *p) +{ +#ifdef _WIN32 + if (p == 0) return; + _aligned_free(p); +#else + free(p); +#endif +} + +template<class T> +class ScopedArray { + T *p_; + size_t size_; + ScopedArray(const ScopedArray&); + void operator=(const ScopedArray&); +public: + explicit ScopedArray(size_t size) + : p_(new T[size]) + , size_(size) + { + } + ~ScopedArray() + { + delete[] p_; + } + T& operator[](size_t idx) CYBOZU_NOEXCEPT { return p_[idx]; } + const T& operator[](size_t idx) const CYBOZU_NOEXCEPT { return p_[idx]; } + size_t size() const CYBOZU_NOEXCEPT { return size_; } + bool empty() const CYBOZU_NOEXCEPT { return size_ == 0; } + T* begin() CYBOZU_NOEXCEPT { return p_; } + T* end() CYBOZU_NOEXCEPT { return p_ + size_; } + const T* begin() const CYBOZU_NOEXCEPT { return p_; } + const T* end() const CYBOZU_NOEXCEPT { return p_ + size_; } + T* data() CYBOZU_NOEXCEPT { return p_; } + const T* data() const CYBOZU_NOEXCEPT { return p_; } +}; + +/** + T must be POD type + 16byte aligment array +*/ +template<class T, size_t N = 16, bool defaultDoClear = true> +class AlignedArray { + T *p_; + size_t size_; + size_t allocSize_; + T *alloc(size_t size) const + { + T *p = static_cast<T*>(AlignedMalloc(size * sizeof(T), N)); + if (p == 0) throw std::bad_alloc(); + return p; + } + void copy(T *dst, const T *src, size_t n) const + { + for (size_t i = 0; i < n; i++) dst[i] = src[i]; + } + void setZero(T *p, size_t n) const + { + for (size_t i = 0; i < n; i++) p[i] = 0; + } + /* + alloc allocN and copy [p, p + copyN) to new p_ + don't modify size_ + */ + void allocCopy(size_t allocN, const T *p, size_t copyN) + { + T *q = alloc(allocN); + copy(q, p, copyN); + AlignedFree(p_); + p_ = q; + allocSize_ = allocN; + } +public: + /* + don't clear buffer with zero if doClear is false + */ + explicit AlignedArray(size_t size = 0, bool doClear = defaultDoClear) + : p_(0) + , size_(0) + , allocSize_(0) + { + resize(size, doClear); + } + AlignedArray(const AlignedArray& rhs) + : p_(0) + , size_(0) + , allocSize_(0) + { + *this = rhs; + } + AlignedArray& operator=(const AlignedArray& rhs) + { + if (allocSize_ < rhs.size_) { + allocCopy(rhs.size_, rhs.p_, rhs.size_); + } else { + copy(p_, rhs.p_, rhs.size_); + } + size_ = rhs.size_; + return *this; + } +#if (CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11) + AlignedArray(AlignedArray&& rhs) CYBOZU_NOEXCEPT + : p_(rhs.p_) + , size_(rhs.size_) + , allocSize_(rhs.allocSize_) + { + rhs.p_ = 0; + rhs.size_ = 0; + rhs.allocSize_ = 0; + } + AlignedArray& operator=(AlignedArray&& rhs) CYBOZU_NOEXCEPT + { + swap(rhs); + rhs.clear(); + return *this; + } +#endif + /* + don't clear buffer with zero if doClear is false + @note don't free if shrinked + */ + void resize(size_t size, bool doClear = defaultDoClear) + { + // shrink + if (size <= size_) { + size_ = size; + return; + } + // realloc if necessary + if (size > allocSize_) { + allocCopy(size, p_, size_); + } + if (doClear) setZero(p_ + size_, size - size_); + size_ = size; + } + void clear() // not free + { + size_ = 0; + } + ~AlignedArray() + { + AlignedFree(p_); + } + void swap(AlignedArray& rhs) CYBOZU_NOEXCEPT + { + std::swap(p_, rhs.p_); + std::swap(size_, rhs.size_); + std::swap(allocSize_, rhs.allocSize_); + } + T& operator[](size_t idx) CYBOZU_NOEXCEPT { return p_[idx]; } + const T& operator[](size_t idx) const CYBOZU_NOEXCEPT { return p_[idx]; } + size_t size() const CYBOZU_NOEXCEPT { return size_; } + bool empty() const CYBOZU_NOEXCEPT { return size_ == 0; } + T* begin() CYBOZU_NOEXCEPT { return p_; } + T* end() CYBOZU_NOEXCEPT { return p_ + size_; } + const T* begin() const CYBOZU_NOEXCEPT { return p_; } + const T* end() const CYBOZU_NOEXCEPT { return p_ + size_; } + T* data() CYBOZU_NOEXCEPT { return p_; } + const T* data() const CYBOZU_NOEXCEPT { return p_; } +#if (CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11) + const T* cbegin() const CYBOZU_NOEXCEPT { return p_; } + const T* cend() const CYBOZU_NOEXCEPT { return p_ + size_; } +#endif +}; + +} // cybozu |