#ifndef ZFP_VIEW2_HPP #define ZFP_VIEW2_HPP // 2D array views namespace zfp { namespace internal { namespace dim2 { // abstract view of 2D array (base class) template class preview { public: typedef Container container_type; typedef typename container_type::value_type value_type; // rate in bits per value double rate() const { return array->rate(); } // dimensions of (sub)array size_t size() const { return nx * ny; } // local to global array indices size_t global_x(size_t i) const { return x + i; } size_t global_y(size_t j) const { return y + j; } protected: // construction and assignment--perform shallow copy of (sub)array explicit preview(container_type* array) : array(array), x(0), y(0), nx(array->size_x()), ny(array->size_y()) {} explicit preview(container_type* array, size_t x, size_t y, size_t nx, size_t ny) : array(array), x(x), y(y), nx(nx), ny(ny) {} preview& operator=(container_type* a) { array = a; x = y = 0; nx = a->nx; ny = a->ny; return *this; } // global index bounds for iterators size_t min_x() const { return x; } size_t max_x() const { return x + nx; } size_t min_y() const { return y; } size_t max_y() const { return y + ny; } container_type* array; // underlying container size_t x, y; // offset into array size_t nx, ny; // dimensions of subarray }; // generic read-only view into a rectangular subset of a 2D array template class const_view : public preview { public: typedef Container container_type; typedef typename container_type::value_type value_type; typedef typename zfp::internal::dim2::const_reference const_reference; typedef typename zfp::internal::dim2::const_pointer const_pointer; typedef typename zfp::internal::dim2::const_iterator const_iterator; // construction--perform shallow copy of (sub)array const_view(container_type* array) : preview(array) {} const_view(container_type* array, size_t x, size_t y, size_t nx, size_t ny) : preview(array, x, y, nx, ny) {} // dimensions of (sub)array size_t size_x() const { return nx; } size_t size_y() const { return ny; } // (i, j) inspector const_reference operator()(size_t i, size_t j) const { return const_reference(this, x + i, y + j); } // random access iterators const_iterator cbegin() const { return const_iterator(this, x, y); } const_iterator cend() const { return const_iterator(this, x, y + ny); } const_iterator begin() const { return cbegin(); } const_iterator end() const { return cend(); } protected: friend class zfp::internal::dim2::const_handle; friend class zfp::internal::dim2::const_pointer; friend class zfp::internal::dim2::const_iterator; using preview::min_x; using preview::max_x; using preview::min_y; using preview::max_y; using preview::array; using preview::x; using preview::y; using preview::nx; using preview::ny; // inspector value_type get(size_t x, size_t y) const { return array->get(x, y); } }; // generic read-write view into a rectangular subset of a 2D array template class view : public const_view { public: typedef Container container_type; typedef typename container_type::value_type value_type; typedef typename zfp::internal::dim2::const_reference const_reference; typedef typename zfp::internal::dim2::const_pointer const_pointer; typedef typename zfp::internal::dim2::const_iterator const_iterator; typedef typename zfp::internal::dim2::reference reference; typedef typename zfp::internal::dim2::pointer pointer; typedef typename zfp::internal::dim2::iterator iterator; // construction--perform shallow copy of (sub)array view(container_type* array) : const_view(array) {} view(container_type* array, size_t x, size_t y, size_t nx, size_t ny) : const_view(array, x, y, nx, ny) {} // (i, j) inspector const_reference operator()(size_t i, size_t j) const { return const_reference(this, x + i, y + j); } // (i, j) mutator reference operator()(size_t i, size_t j) { return reference(this, x + i, y + j); } // random access iterators const_iterator cbegin() const { return const_iterator(this, x, y); } const_iterator cend() const { return const_iterator(this, x, y + ny); } const_iterator begin() const { return cbegin(); } const_iterator end() const { return cend(); } iterator begin() { return iterator(this, x, y); } iterator end() { return iterator(this, x, y + ny); } protected: friend class zfp::internal::dim2::const_handle; friend class zfp::internal::dim2::const_pointer; friend class zfp::internal::dim2::const_iterator; friend class zfp::internal::dim2::reference; friend class zfp::internal::dim2::pointer; friend class zfp::internal::dim2::iterator; using const_view::min_x; using const_view::max_x; using const_view::min_y; using const_view::max_y; using const_view::get; using const_view::array; using const_view::x; using const_view::y; using const_view::nx; using const_view::ny; // mutator void set(size_t x, size_t y, value_type val) { array->set(x, y, val); } // in-place updates void add(size_t x, size_t y, value_type val) { array->add(x, y, val); } void sub(size_t x, size_t y, value_type val) { array->sub(x, y, val); } void mul(size_t x, size_t y, value_type val) { array->mul(x, y, val); } void div(size_t x, size_t y, value_type val) { array->div(x, y, val); } }; // flat view of 2D array (operator[] returns scalar) template class flat_view : public view { public: typedef Container container_type; typedef typename container_type::value_type value_type; typedef typename zfp::internal::dim2::const_reference const_reference; typedef typename zfp::internal::dim2::const_pointer const_pointer; typedef typename zfp::internal::dim2::reference reference; typedef typename zfp::internal::dim2::pointer pointer; // construction--perform shallow copy of (sub)array flat_view(container_type* array) : view(array) {} flat_view(container_type* array, size_t x, size_t y, size_t nx, size_t ny) : view(array, x, y, nx, ny) {} // convert (i, j) index to flat index size_t index(size_t i, size_t j) const { return i + nx * j; } // convert flat index to (i, j) index void ij(size_t& i, size_t& j, size_t index) const { i = index % nx; index /= nx; j = index; } // flat index [] inspector const_reference operator[](size_t index) const { size_t i, j; ij(i, j, index); return const_reference(this, x + i, y + j); } // flat index [] mutator reference operator[](size_t index) { size_t i, j; ij(i, j, index); return reference(this, x + i, y + j); } // (i, j) inspector const_reference operator()(size_t i, size_t j) const { return const_reference(this, x + i, y + j); } // (i, j) mutator reference operator()(size_t i, size_t j) { return reference(this, x + i, y + j); } protected: friend class zfp::internal::dim2::const_handle; friend class zfp::internal::dim2::const_pointer; friend class zfp::internal::dim2::reference; friend class zfp::internal::dim2::pointer; using view::array; using view::x; using view::y; using view::nx; using view::ny; // inspector value_type get(size_t x, size_t y) const { return array->get(x, y); } // mutator void set(size_t x, size_t y, value_type val) { array->set(x, y, val); } // in-place updates void add(size_t x, size_t y, value_type val) { array->add(x, y, val); } void sub(size_t x, size_t y, value_type val) { array->sub(x, y, val); } void mul(size_t x, size_t y, value_type val) { array->mul(x, y, val); } void div(size_t x, size_t y, value_type val) { array->div(x, y, val); } }; // forward declaration of friends template class nested_view1; template class nested_view2; // nested view into a 1D rectangular subset of a 2D array template class nested_view1 : public preview { public: typedef Container container_type; typedef typename container_type::value_type value_type; typedef typename zfp::internal::dim2::const_reference const_reference; typedef typename zfp::internal::dim2::const_pointer const_pointer; typedef typename zfp::internal::dim2::reference reference; typedef typename zfp::internal::dim2::pointer pointer; // dimensions of (sub)array size_t size_x() const { return nx; } // [i] inspector and mutator const_reference operator[](size_t index) const { return const_reference(this, x + index, y); } reference operator[](size_t index) { return reference(this, x + index, y); } // (i) inspector and mutator const_reference operator()(size_t i) const { return const_reference(this, x + i, y); } reference operator()(size_t i) { return reference(this, x + i, y); } protected: friend class zfp::internal::dim2::const_handle; friend class zfp::internal::dim2::const_pointer; friend class zfp::internal::dim2::reference; friend class zfp::internal::dim2::pointer; using preview::array; using preview::x; using preview::y; using preview::nx; using preview::ny; // construction--perform shallow copy of (sub)array friend class nested_view2; explicit nested_view1(container_type* array) : preview(array) {} explicit nested_view1(container_type* array, size_t x, size_t y, size_t nx, size_t ny) : preview(array, x, y, nx, ny) {} // inspector value_type get(size_t x, size_t y) const { return array->get(x, y); } // mutator void set(size_t x, size_t y, value_type val) { array->set(x, y, val); } // in-place updates void add(size_t x, size_t y, value_type val) { array->add(x, y, val); } void sub(size_t x, size_t y, value_type val) { array->sub(x, y, val); } void mul(size_t x, size_t y, value_type val) { array->mul(x, y, val); } void div(size_t x, size_t y, value_type val) { array->div(x, y, val); } }; // nested view into a 2D rectangular subset of a 2D array template class nested_view2 : public preview { public: typedef Container container_type; typedef typename container_type::value_type value_type; typedef typename zfp::internal::dim2::const_reference const_reference; typedef typename zfp::internal::dim2::const_pointer const_pointer; typedef typename zfp::internal::dim2::reference reference; typedef typename zfp::internal::dim2::pointer pointer; // construction--perform shallow copy of (sub)array nested_view2(container_type* array) : preview(array) {} nested_view2(container_type* array, size_t x, size_t y, size_t nx, size_t ny) : preview(array, x, y, nx, ny) {} // dimensions of (sub)array size_t size_x() const { return nx; } size_t size_y() const { return ny; } // 1D view nested_view1 operator[](size_t index) const { return nested_view1(array, x, y + index, nx, 1); } // (i, j) inspector and mutator const_reference operator()(size_t i, size_t j) const { return const_reference(this, x + i, y + j); } reference operator()(size_t i, size_t j) { return reference(this, x + i, y + j); } protected: friend class zfp::internal::dim2::const_handle; friend class zfp::internal::dim2::const_pointer; friend class zfp::internal::dim2::reference; friend class zfp::internal::dim2::pointer; using preview::array; using preview::x; using preview::y; using preview::nx; using preview::ny; // inspector value_type get(size_t x, size_t y) const { return array->get(x, y); } // mutator void set(size_t x, size_t y, value_type val) { array->set(x, y, val); } // in-place updates void add(size_t x, size_t y, value_type val) { array->add(x, y, val); } void sub(size_t x, size_t y, value_type val) { array->sub(x, y, val); } void mul(size_t x, size_t y, value_type val) { array->mul(x, y, val); } void div(size_t x, size_t y, value_type val) { array->div(x, y, val); } }; // thread-safe read-only view of 2D (sub)array with private cache template class private_const_view : public preview { public: typedef Container container_type; typedef typename container_type::value_type value_type; typedef typename container_type::store_type store_type; typedef typename zfp::internal::dim2::const_reference const_reference; typedef typename zfp::internal::dim2::const_pointer const_pointer; typedef typename zfp::internal::dim2::const_iterator const_iterator; // construction--perform shallow copy of (sub)array private_const_view(container_type* array, size_t cache_size = 0) : preview(array), cache(array->store, cache_size ? cache_size : array->cache.size()) { array->store.reference(); } private_const_view(container_type* array, size_t x, size_t y, size_t nx, size_t ny, size_t cache_size = 0) : preview(array, x, y, nx, ny), cache(array->store, cache_size ? cache_size : array->cache.size()) { array->store.reference(); } // destructor ~private_const_view() { array->store.unreference(); } // dimensions of (sub)array size_t size_x() const { return nx; } size_t size_y() const { return ny; } // cache size in number of bytes size_t cache_size() const { return cache.size(); } // set minimum cache size in bytes (array dimensions must be known) void set_cache_size(size_t bytes) { cache.resize(bytes); } // empty cache without compressing modified cached blocks void clear_cache() const { cache.clear(); } // (i, j) inspector const_reference operator()(size_t i, size_t j) const { return const_reference(this, x + i, y + j); } // random access iterators const_iterator cbegin() const { return const_iterator(this, x, y); } const_iterator cend() const { return const_iterator(this, x, y + ny); } const_iterator begin() const { return cbegin(); } const_iterator end() const { return cend(); } protected: friend class zfp::internal::dim2::const_handle; friend class zfp::internal::dim2::const_pointer; friend class zfp::internal::dim2::const_iterator; using preview::min_x; using preview::max_x; using preview::min_y; using preview::max_y; using preview::array; using preview::x; using preview::y; using preview::nx; using preview::ny; // inspector value_type get(size_t x, size_t y) const { return cache.get(x, y); } BlockCache2 cache; // cache of decompressed blocks }; // thread-safe read-write view of private 2D (sub)array template class private_view : public private_const_view { public: typedef Container container_type; typedef typename container_type::value_type value_type; typedef typename zfp::internal::dim2::const_reference const_reference; typedef typename zfp::internal::dim2::const_pointer const_pointer; typedef typename zfp::internal::dim2::const_iterator const_iterator; typedef typename zfp::internal::dim2::reference reference; typedef typename zfp::internal::dim2::pointer pointer; typedef typename zfp::internal::dim2::iterator iterator; // construction--perform shallow copy of (sub)array private_view(container_type* array, size_t cache_size = 0) : private_const_view(array, cache_size) {} private_view(container_type* array, size_t x, size_t y, size_t nx, size_t ny, size_t cache_size = 0) : private_const_view(array, x, y, nx, ny, cache_size) {} // partition view into count block-aligned pieces, with 0 <= index < count void partition(size_t index, size_t count) { if (nx > ny) partition(x, nx, index, count); else partition(y, ny, index, count); } // flush cache by compressing all modified cached blocks void flush_cache() const { cache.flush(); } // (i, j) inspector const_reference operator()(size_t i, size_t j) const { return const_reference(this, x + i, y + j); } // (i, j) mutator reference operator()(size_t i, size_t j) { return reference(this, x + i, y + j); } // random access iterators const_iterator cbegin() const { return const_iterator(this, x, y); } const_iterator cend() const { return const_iterator(this, x, y + ny); } const_iterator begin() const { return cbegin(); } const_iterator end() const { return cend(); } iterator begin() { return iterator(this, x, y); } iterator end() { return iterator(this, x, y + ny); } protected: friend class zfp::internal::dim2::const_handle; friend class zfp::internal::dim2::const_pointer; friend class zfp::internal::dim2::const_iterator; friend class zfp::internal::dim2::reference; friend class zfp::internal::dim2::pointer; friend class zfp::internal::dim2::iterator; using private_const_view::min_x; using private_const_view::max_x; using private_const_view::min_y; using private_const_view::max_y; using private_const_view::get; using private_const_view::array; using private_const_view::x; using private_const_view::y; using private_const_view::nx; using private_const_view::ny; using private_const_view::cache; // block-aligned partition of [offset, offset + size): index out of count static void partition(size_t& offset, size_t& size, size_t index, size_t count) { size_t bmin = offset / 4; size_t bmax = (offset + size + 3) / 4; size_t xmin = std::max(offset + 0, 4 * (bmin + (bmax - bmin) * (index + 0) / count)); size_t xmax = std::min(offset + size, 4 * (bmin + (bmax - bmin) * (index + 1) / count)); offset = xmin; size = xmax - xmin; } // mutator void set(size_t x, size_t y, value_type val) { cache.set(x, y, val); } // in-place updates void add(size_t x, size_t y, value_type val) { cache.ref(x, y) += val; } void sub(size_t x, size_t y, value_type val) { cache.ref(x, y) -= val; } void mul(size_t x, size_t y, value_type val) { cache.ref(x, y) *= val; } void div(size_t x, size_t y, value_type val) { cache.ref(x, y) /= val; } }; } // dim2 } // internal } // zfp #endif