// Copyright (C) 2026 Kiyotsugu Arai // SPDX-License-Identifier: LGPL-3.0-or-later // vector_view.hpp // // Definitions of the vector view classes // // This file defines the vector view classes of the MKL algebra library. // View classes provide references to part or all of an existing vector, // allowing access to data without copying. // // Main features: // - Reference view onto an existing vector // - Partial view (subvector) of a vector // - Read-only view // - Mutable view #ifndef SANGI_VECTOR_VIEW_HPP #define SANGI_VECTOR_VIEW_HPP #include "../common.hpp" #include #include #include #include namespace sangi { namespace detail { //----------------------------------------------------------------------------- // Vector view class //----------------------------------------------------------------------------- template class VectorView { public: // Borrow type definitions from the host type using value_type = typename std::remove_reference_t::value_type; using size_type = std::size_t; using difference_type = std::ptrdiff_t; using reference = value_type&; using const_reference = const value_type&; using pointer = value_type*; using const_pointer = const value_type*; using iterator = value_type*; using const_iterator = const value_type*; // Reference type to the underlying vector using vector_reference = VectorType&; // Create a view over the entire vector explicit VectorView(vector_reference vector) : vector_(vector), offset_(0), size_(vector.size()) {} // Create a partial view of the vector VectorView(vector_reference vector, size_type offset, size_type size) : vector_(vector), offset_(offset), size_(size) { // Range check if (offset + size > vector.size()) { throw IndexError("VectorView: view range exceeds vector bounds"); } } // Copy constructor VectorView(const VectorView&) = default; // Copy assignment operator VectorView& operator=(const VectorView&) = delete; // Copying the view itself is forbidden // Assignment that copies the contents of another view template VectorView& operator=(const VectorView& other) { assign(other.begin(), other.end()); return *this; } // Assignment that copies the contents of a vector template VectorView& operator=(const OtherVectorType& other) { assign(other.begin(), other.end()); return *this; } // Assignment from an initializer list VectorView& operator=(std::initializer_list ilist) { assign(ilist.begin(), ilist.end()); return *this; } // Element access // Subscript access (non-const) reference operator[](size_type pos) { assert(pos < size_ && "VectorView::operator[]: index out of range"); return vector_[offset_ + pos]; } // Subscript access (const) const_reference operator[](size_type pos) const { assert(pos < size_ && "VectorView::operator[]: index out of range"); return vector_[offset_ + pos]; } // Range-checked subscript access (non-const) reference at(size_type pos) { if (pos >= size_) { throw IndexError("VectorView::at: index out of range"); } return vector_[offset_ + pos]; } // Range-checked subscript access (const) const_reference at(size_type pos) const { if (pos >= size_) { throw IndexError("VectorView::at: index out of range"); } return vector_[offset_ + pos]; } // Front element access (non-const) reference front() { if (empty()) { throw IndexError("VectorView::front: empty view"); } return vector_[offset_]; } // Front element access (const) const_reference front() const { if (empty()) { throw IndexError("VectorView::front: empty view"); } return vector_[offset_]; } // Back element access (non-const) reference back() { if (empty()) { throw IndexError("VectorView::back: empty view"); } return vector_[offset_ + size_ - 1]; } // Back element access (const) const_reference back() const { if (empty()) { throw IndexError("VectorView::back: empty view"); } return vector_[offset_ + size_ - 1]; } // Data pointer access (non-const) pointer data() noexcept { return &vector_[offset_]; } // Data pointer access (const) const_pointer data() const noexcept { return &vector_[offset_]; } // Iterators // Begin iterator (non-const) iterator begin() noexcept { return &vector_[offset_]; } // Begin iterator (const) const_iterator begin() const noexcept { return &vector_[offset_]; } // Begin iterator (always const) const_iterator cbegin() const noexcept { return &vector_[offset_]; } // End iterator (non-const) iterator end() noexcept { return &vector_[offset_ + size_]; } // End iterator (const) const_iterator end() const noexcept { return &vector_[offset_ + size_]; } // End iterator (always const) const_iterator cend() const noexcept { return &vector_[offset_ + size_]; } // Capacity // Check whether the view is empty bool empty() const noexcept { return size_ == 0; } // Get the size size_type size() const noexcept { return size_; } // Size of the underlying vector size_type parent_size() const noexcept { return vector_.size(); } // Get the offset size_type offset() const noexcept { return offset_; } // Create a subview VectorView subview(size_type sub_offset, size_type sub_size) const { if (sub_offset + sub_size > size_) { throw IndexError("VectorView::subview: subview range exceeds view bounds"); } return VectorView(vector_, offset_ + sub_offset, sub_size); } // Set every element to a scalar value void fill(const value_type& value) { std::fill(begin(), end(), value); } // Zero-clear void zero() { fill(numeric_traits::zero()); } // Assign from an iterator range template void assign(InputIt first, InputIt last) { const auto count = std::distance(first, last); if (count > static_cast(size_)) { throw DimensionError("VectorView::assign: source range too large for view"); } std::copy(first, last, begin()); } // Get a reference to the underlying vector vector_reference parent() noexcept { return vector_; } const vector_reference parent() const noexcept { return vector_; } private: vector_reference vector_; // Reference to the underlying vector size_type offset_; // Offset into the underlying vector size_type size_; // Size of the view }; //----------------------------------------------------------------------------- // Read-only vector view class //----------------------------------------------------------------------------- template class ConstVectorView { public: // Borrow type definitions from the host type using value_type = typename std::remove_reference_t::value_type; using size_type = std::size_t; using difference_type = std::ptrdiff_t; using reference = const value_type&; // const reference using const_reference = const value_type&; using pointer = const value_type*; // const pointer using const_pointer = const value_type*; using iterator = const value_type*; // const iterator using const_iterator = const value_type*; // Reference type to the underlying vector (always const) using vector_reference = const VectorType&; // Create a view over the entire vector explicit ConstVectorView(vector_reference vector) : vector_(vector), offset_(0), size_(vector.size()) {} // Create a partial view of the vector ConstVectorView(vector_reference vector, size_type offset, size_type size) : vector_(vector), offset_(offset), size_(size) { // Range check if (offset + size > vector.size()) { throw IndexError("ConstVectorView: view range exceeds vector bounds"); } } // Converting constructor from VectorView explicit ConstVectorView(const VectorView& view) : vector_(view.parent()), offset_(view.offset()), size_(view.size()) {} // Copy constructor ConstVectorView(const ConstVectorView&) = default; // Copy assignment operator ConstVectorView& operator=(const ConstVectorView&) = delete; // Copying the view itself is forbidden // Element access // Subscript access (always const) const_reference operator[](size_type pos) const { assert(pos < size_ && "ConstVectorView::operator[]: index out of range"); return vector_[offset_ + pos]; } // Range-checked subscript access (always const) const_reference at(size_type pos) const { if (pos >= size_) { throw IndexError("ConstVectorView::at: index out of range"); } return vector_[offset_ + pos]; } // Front element access (always const) const_reference front() const { if (empty()) { throw IndexError("ConstVectorView::front: empty view"); } return vector_[offset_]; } // Back element access (always const) const_reference back() const { if (empty()) { throw IndexError("ConstVectorView::back: empty view"); } return vector_[offset_ + size_ - 1]; } // Data pointer access (always const) const_pointer data() const noexcept { return &vector_[offset_]; } // Iterators (all const) // Begin iterator const_iterator begin() const noexcept { return &vector_[offset_]; } const_iterator cbegin() const noexcept { return &vector_[offset_]; } // End iterator const_iterator end() const noexcept { return &vector_[offset_ + size_]; } const_iterator cend() const noexcept { return &vector_[offset_ + size_]; } // Capacity // Check whether the view is empty bool empty() const noexcept { return size_ == 0; } // Get the size size_type size() const noexcept { return size_; } // Size of the underlying vector size_type parent_size() const noexcept { return vector_.size(); } // Get the offset size_type offset() const noexcept { return offset_; } // Create a subview ConstVectorView subview(size_type sub_offset, size_type sub_size) const { if (sub_offset + sub_size > size_) { throw IndexError("ConstVectorView::subview: subview range exceeds view bounds"); } return ConstVectorView(vector_, offset_ + sub_offset, sub_size); } // Get a reference to the underlying vector vector_reference parent() const noexcept { return vector_; } private: vector_reference vector_; // Reference to the underlying vector (const) size_type offset_; // Offset into the underlying vector size_type size_; // Size of the view }; // Helper functions to create views // Create a view over the entire vector template VectorView make_vector_view(VectorType& vector) { return VectorView(vector); } // Create a partial view of the vector template VectorView make_vector_view(VectorType& vector, std::size_t offset, std::size_t size) { return VectorView(vector, offset, size); } // Create a read-only view over the entire vector template ConstVectorView make_const_vector_view(const VectorType& vector) { return ConstVectorView(vector); } // Create a partial read-only view of the vector template ConstVectorView make_const_vector_view(const VectorType& vector, std::size_t offset, std::size_t size) { return ConstVectorView(vector, offset, size); } } // namespace detail } // namespace sangi #endif // SANGI_VECTOR_VIEW_HPP