Skip to content
Snippets Groups Projects
basearray.hh 13.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • Ansgar Burchardt's avatar
    Ansgar Burchardt committed
    // SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root
    // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
    
    Peter Bastian's avatar
    Peter Bastian committed
    // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
    // vi: set et ts=4 sw=2 sts=2:
    
    #ifndef DUNE_ISTL_BASEARRAY_HH
    #define DUNE_ISTL_BASEARRAY_HH
    
    Peter Bastian's avatar
    Peter Bastian committed
    
    
    #include <cmath>
    #include <cstddef>
    
    #include <algorithm>
    
    #include <type_traits>
    
    Peter Bastian's avatar
    Peter Bastian committed
    
    #include "istlexception.hh"
    
    Markus Blatt's avatar
    Markus Blatt committed
    #include <dune/common/iteratorfacades.hh>
    
    Peter Bastian's avatar
    Peter Bastian committed
    
    
    Oliver Sander's avatar
    Oliver Sander committed
    /** \file
       \brief Implements several basic array containers.
    
    Peter Bastian's avatar
    Peter Bastian committed
     */
    
    namespace Dune {
    
    
    /** \brief Everything in this namespace is internal to dune-istl, and may change without warning */
    namespace Imp {
    
    
      /**  \brief A simple array container for objects of type B
    
         Implement.
    
    Peter Bastian's avatar
    Peter Bastian committed
    
           -  iterator access
           -  const_iterator access
           -  random access
    
               This container has *NO* memory management at all,
    
               copy constructor, assignment and destructor are all default.
    
    Peter Bastian's avatar
    Peter Bastian committed
    
               The constructor is made protected to emphasize that objects
    
    Oliver Sander's avatar
    Oliver Sander committed
           are only usable in derived classes.
    
    Peter Bastian's avatar
    Peter Bastian committed
    
               Error checking: no error checking is provided normally.
               Setting the compile time switch DUNE_ISTL_WITH_CHECKING
               enables error checking.
    
       \internal This class is an implementation detail, and should not be used outside of dune-istl.
    
    Peter Bastian's avatar
    Peter Bastian committed
       */
    
      template<class B, class ST=std::size_t >
    
    Peter Bastian's avatar
    Peter Bastian committed
      class base_array_unmanaged
      {
      public:
    
        //===== type definitions and constants
    
        //! export the type representing the components
        typedef B member_type;
    
    
        //! the type for the index access
    
        typedef ST size_type;
    
        //! the type used for references
        using reference = B&;
    
        //! the type used for const references
        using const_reference = const B&;
    
    Peter Bastian's avatar
    Peter Bastian committed
    
        //===== access to components
    
        //! random access to blocks
    
        reference operator[] (size_type i)
    
    Peter Bastian's avatar
    Peter Bastian committed
        {
    #ifdef DUNE_ISTL_WITH_CHECKING
    
          if (i>=n) DUNE_THROW(ISTLError,"index out of range");
    
    Peter Bastian's avatar
    Peter Bastian committed
    #endif
          return p[i];
        }
    
        //! same for read only access
    
        const_reference operator[] (size_type i) const
    
    Peter Bastian's avatar
    Peter Bastian committed
        {
    #ifdef DUNE_ISTL_WITH_CHECKING
    
          if (i>=n) DUNE_THROW(ISTLError,"index out of range");
    
    Peter Bastian's avatar
    Peter Bastian committed
    #endif
          return p[i];
        }
    
    
        /** \brief Iterator implementation class  */
    
    Markus Blatt's avatar
    Markus Blatt committed
        template<class T>
        class RealIterator
    
          :  public RandomAccessIteratorFacade<RealIterator<T>, T>
    
    Peter Bastian's avatar
    Peter Bastian committed
        {
        public:
    
    Markus Blatt's avatar
    Markus Blatt committed
          //! \brief The unqualified value type
    
          typedef typename std::remove_const<T>::type ValueType;
    
          friend class RandomAccessIteratorFacade<RealIterator<const ValueType>, const ValueType>;
          friend class RandomAccessIteratorFacade<RealIterator<ValueType>, ValueType>;
    
    Markus Blatt's avatar
    Markus Blatt committed
          friend class RealIterator<const ValueType>;
          friend class RealIterator<ValueType>;
    
    
    Peter Bastian's avatar
    Peter Bastian committed
          //! constructor
    
          RealIterator () = default;
    
    Peter Bastian's avatar
    Peter Bastian committed
    
    
          RealIterator (const B* _p, B* _i)
            : p(_p), i(_i)
          {}
    
    Peter Bastian's avatar
    Peter Bastian committed
    
    
          template <class T_,
            std::enable_if_t<std::is_same_v<std::remove_const_t<T>, std::remove_const_t<T_>>, int> = 0>
          RealIterator (const RealIterator<T_>& other)
            : p(other.p), i(other.i)
    
          template <class T_,
            std::enable_if_t<std::is_same_v<std::remove_const_t<T>, std::remove_const_t<T_>>, int> = 0>
          RealIterator& operator= (const RealIterator<T_>& other)
          {
            p = other.p;
            i = other.i;
            return *this;
          }
    
    
    Markus Blatt's avatar
    Markus Blatt committed
          //! return index
    
          size_type index () const
    
    Peter Bastian's avatar
    Peter Bastian committed
          {
    
    Markus Blatt's avatar
    Markus Blatt committed
            return i-p;
    
    Peter Bastian's avatar
    Peter Bastian committed
          }
    
          //! equality
    
    Markus Blatt's avatar
    Markus Blatt committed
          bool equals (const RealIterator<ValueType>& other) const
    
    Peter Bastian's avatar
    Peter Bastian committed
          {
    
    Markus Blatt's avatar
    Markus Blatt committed
            assert(other.p==p);
            return i==other.i;
    
    Peter Bastian's avatar
    Peter Bastian committed
          }
    
    
    Markus Blatt's avatar
    Markus Blatt committed
          //! equality
          bool equals (const RealIterator<const ValueType>& other) const
    
    Peter Bastian's avatar
    Peter Bastian committed
          {
    
    Markus Blatt's avatar
    Markus Blatt committed
            assert(other.p==p);
            return i==other.i;
    
    Peter Bastian's avatar
    Peter Bastian committed
          }
    
    
          std::ptrdiff_t distanceTo(const RealIterator& o) const
          {
            return o.i-i;
          }
    
    
    Markus Blatt's avatar
     
    Markus Blatt committed
        private:
    
    Markus Blatt's avatar
    Markus Blatt committed
          //! prefix increment
          void increment()
    
    Peter Bastian's avatar
    Peter Bastian committed
          {
    
    Markus Blatt's avatar
    Markus Blatt committed
            ++i;
    
    Peter Bastian's avatar
    Peter Bastian committed
          }
    
    
    Markus Blatt's avatar
    Markus Blatt committed
          //! prefix decrement
          void decrement()
    
    Peter Bastian's avatar
    Peter Bastian committed
          {
    
    Markus Blatt's avatar
    Markus Blatt committed
            --i;
    
    Peter Bastian's avatar
    Peter Bastian committed
          }
    
    
          // Needed for operator[] of the iterator
    
          reference elementAt (std::ptrdiff_t offset) const
    
          {
            return *(i+offset);
          }
    
    
    Peter Bastian's avatar
    Peter Bastian committed
          //! dereferencing
    
          reference dereference () const
    
    Peter Bastian's avatar
    Peter Bastian committed
          {
    
    Peter Bastian's avatar
    Peter Bastian committed
          }
    
    
          const B* p = nullptr;
          B* i = nullptr;
    
    Peter Bastian's avatar
    Peter Bastian committed
        };
    
    
    Markus Blatt's avatar
    Markus Blatt committed
        //! iterator type for sequential access
        typedef RealIterator<B> iterator;
    
    
    
    Peter Bastian's avatar
    Peter Bastian committed
        //! begin iterator
        iterator begin ()
        {
    
    Peter Bastian's avatar
    Peter Bastian committed
        }
    
        //! end iterator
        iterator end ()
        {
    
    Peter Bastian's avatar
    Peter Bastian committed
        }
    
    
    Markus Blatt's avatar
    Markus Blatt committed
        //! @returns an iterator that is positioned before
        //! the end iterator of the vector, i.e. at the last entry.
        iterator beforeEnd ()
    
    Peter Bastian's avatar
    Peter Bastian committed
        {
    
    Peter Bastian's avatar
    Peter Bastian committed
        }
    
    
    Markus Blatt's avatar
    Markus Blatt committed
        //! @returns an iterator that is positioned before
        //! the first entry of the vector.
        iterator beforeBegin ()
    
    Peter Bastian's avatar
    Peter Bastian committed
        {
    
    Peter Bastian's avatar
    Peter Bastian committed
        }
    
        //! random access returning iterator (end if not contained)
    
    Peter Bastian's avatar
    Peter Bastian committed
        {
    
          return iterator(p,p+std::min(i,n));
    
    Peter Bastian's avatar
    Peter Bastian committed
        }
    
    
    Markus Blatt's avatar
    Markus Blatt committed
        //! iterator class for sequential access
        typedef RealIterator<const B> const_iterator;
    
    Peter Bastian's avatar
    Peter Bastian committed
    
        //! begin const_iterator
        const_iterator begin () const
        {
    
    Peter Bastian's avatar
    Peter Bastian committed
        }
    
        //! end const_iterator
        const_iterator end () const
        {
    
    Peter Bastian's avatar
    Peter Bastian committed
        }
    
    
    Markus Blatt's avatar
    Markus Blatt committed
        //! @returns an iterator that is positioned before
        //! the end iterator of the vector. i.e. at the last element.
        const_iterator beforeEnd () const
    
    Peter Bastian's avatar
    Peter Bastian committed
        {
    
          return const_iterator(p,p+n-1);
    
    Peter Bastian's avatar
    Peter Bastian committed
        }
    
    
    Markus Blatt's avatar
    Markus Blatt committed
        //! @returns an iterator that is positioned before
        //! the first entry of the vector.
        const_iterator beforeBegin () const
    
    Peter Bastian's avatar
    Peter Bastian committed
        {
    
    Peter Bastian's avatar
    Peter Bastian committed
        }
    
    
        //! random access returning iterator (end if not contained)
    
        const_iterator find (size_type i) const
    
          return const_iterator(p,p+std::min(i,n));
    
    Peter Bastian's avatar
    Peter Bastian committed
    
        //===== sizes
    
        //! number of blocks in the array (are of size 1 here)
    
    Peter Bastian's avatar
    Peter Bastian committed
        {
          return n;
        }
    
    
        //! Returns pointer to the underlying array
        const B* data() const
        {
          return p;
        }
    
        //! Returns pointer to the underlying array
        B* data()
        {
          return p;
        }
    
    
    Peter Bastian's avatar
    Peter Bastian committed
      protected:
        //! makes empty array
        base_array_unmanaged ()
    
          : n(0), p(0)
        {}
        //! make an initialized array
        base_array_unmanaged (size_type n_, B* p_)
          : n(n_), p(p_)
        {}
    
        size_type n;     // number of elements in array
    
    Peter Bastian's avatar
    Peter Bastian committed
        B *p;      // pointer to dynamically allocated built-in array
      };
    
    
    
    
      /** \brief A simple array container with non-consecutive index set.
    
    
    Peter Bastian's avatar
    Peter Bastian committed
           Elements in the array are of type B. This class provides
    
           -  iterator access
           -  const_iterator access
           -  random access in log(n) steps using binary search
               -  find returning iterator
    
               This container has *NO* memory management at all,
    
               copy constructor, assignment and destructor are all default.
    
    Peter Bastian's avatar
    Peter Bastian committed
    
               The constructor is made protected to emphasize that objects
           are only usably in derived classes.
    
               Error checking: no error checking is provided normally.
               Setting the compile time switch DUNE_ISTL_WITH_CHECKING
               enables error checking.
    
    
        \internal This class is an implementation detail, and should not be used outside of dune-istl.
    
    Peter Bastian's avatar
    Peter Bastian committed
       */
    
      template<class B, class ST=std::size_t >
    
    Peter Bastian's avatar
    Peter Bastian committed
      class compressed_base_array_unmanaged
      {
      public:
    
        //===== type definitions and constants
    
        //! export the type representing the components
        typedef B member_type;
    
    
        //! The type used for the index access
    
        typedef ST size_type;
    
    Peter Bastian's avatar
    Peter Bastian committed
    
    
        //! the type used for references
        using reference = B&;
    
        //! the type used for const references
        using const_reference = const B&;
    
    
    Peter Bastian's avatar
    Peter Bastian committed
        //===== access to components
    
        //! random access to blocks, assumes ascending ordering
    
        reference operator[] (size_type i)
    
    Peter Bastian's avatar
    Peter Bastian committed
        {
    
          const size_type* lb = std::lower_bound(j, j+n, i);
    
          if (lb == j+n || *lb != i)
    
            DUNE_THROW(ISTLError,"index "<<i<<" not in compressed array");
    
    Peter Bastian's avatar
    Peter Bastian committed
        }
    
        //! same for read only access, assumes ascending ordering
    
        const_reference operator[] (size_type i) const
    
    Peter Bastian's avatar
    Peter Bastian committed
        {
    
          const size_type* lb = std::lower_bound(j, j+n, i);
    
          if (lb == j+n || *lb != i)
    
            DUNE_THROW(ISTLError,"index "<<i<<" not in compressed array");
    
    Peter Bastian's avatar
    Peter Bastian committed
        }
    
        //! iterator class for sequential access
    
    Markus Blatt's avatar
    Markus Blatt committed
        template<class T>
        class RealIterator
          : public BidirectionalIteratorFacade<RealIterator<T>, T>
    
    Peter Bastian's avatar
    Peter Bastian committed
        {
        public:
    
    Markus Blatt's avatar
    Markus Blatt committed
          //! \brief The unqualified value type
    
          typedef typename std::remove_const<T>::type ValueType;
    
    Markus Blatt's avatar
    Markus Blatt committed
    
          friend class BidirectionalIteratorFacade<RealIterator<const ValueType>, const ValueType>;
          friend class BidirectionalIteratorFacade<RealIterator<ValueType>, ValueType>;
          friend class RealIterator<const ValueType>;
          friend class RealIterator<ValueType>;
    
    
    Peter Bastian's avatar
    Peter Bastian committed
          //! constructor
    
          RealIterator () = default;
    
    Peter Bastian's avatar
    Peter Bastian committed
    
    
    Markus Blatt's avatar
    Markus Blatt committed
          //! constructor
          RealIterator (B* _p, size_type* _j, size_type _i)
            : p(_p), j(_j), i(_i)
    
    Peter Bastian's avatar
    Peter Bastian committed
    
    
          template <class T_,
            std::enable_if_t<std::is_same_v<std::remove_const_t<T>, std::remove_const_t<T_>>, int> = 0>
          RealIterator (const RealIterator<T_>& other)
            : p(other.p), j(other.j), i(other.i)
    
    Peter Bastian's avatar
    Peter Bastian committed
    
    
          template <class T_,
            std::enable_if_t<std::is_same_v<std::remove_const_t<T>, std::remove_const_t<T_>>, int> = 0>
          RealIterator& operator= (const RealIterator<T_>& other)
          {
            p = other.p;
            j = other.j;
            i = other.i;
            return *this;
          }
    
    
    Peter Bastian's avatar
    Peter Bastian committed
    
          //! equality
    
    Markus Blatt's avatar
    Markus Blatt committed
          bool equals (const RealIterator<ValueType>& it) const
    
    Peter Bastian's avatar
    Peter Bastian committed
          {
    
    Markus Blatt's avatar
    Markus Blatt committed
            assert(p==it.p);
    
    Peter Bastian's avatar
    Peter Bastian committed
            return (i)==(it.i);
          }
    
          //! equality
    
    Markus Blatt's avatar
    Markus Blatt committed
          bool equals (const RealIterator<const ValueType>& it) const
    
    Peter Bastian's avatar
    Peter Bastian committed
          {
    
    Markus Blatt's avatar
    Markus Blatt committed
            assert(p==it.p);
    
    Peter Bastian's avatar
    Peter Bastian committed
            return (i)==(it.i);
          }
    
    
    
          //! return index corresponding to pointer
    
    Peter Bastian's avatar
    Peter Bastian committed
          {
            return j[i];
          }
    
    
          //! Set index corresponding to pointer
    
    Peter Bastian's avatar
    Peter Bastian committed
          {
            return j[i] = k;
          }
    
    
           * @brief offset from the first entry.
    
           *
           * An iterator positioned at the beginning
           * has to be increment this amount of times to
           * the same position.
           */
    
    Markus Blatt's avatar
     
    Markus Blatt committed
        private:
    
    Markus Blatt's avatar
    Markus Blatt committed
          //! prefix increment
          void increment()
          {
            ++i;
          }
    
          //! prefix decrement
          void decrement()
          {
            --i;
          }
    
          //! dereferencing
    
          reference dereference () const
    
    Markus Blatt's avatar
    Markus Blatt committed
          {
            return p[i];
          }
    
    Peter Bastian's avatar
    Peter Bastian committed
    
    
          B* p = nullptr;
          size_type* j = nullptr;
          size_type i = 0;
    
    Peter Bastian's avatar
    Peter Bastian committed
        };
    
    
    Markus Blatt's avatar
    Markus Blatt committed
        /** @brief The iterator type. */
        typedef RealIterator<B> iterator;
    
    
    Peter Bastian's avatar
    Peter Bastian committed
        //! begin iterator
        iterator begin ()
        {
          return iterator(p,j,0);
        }
    
        //! end iterator
        iterator end ()
        {
          return iterator(p,j,n);
        }
    
    
    Markus Blatt's avatar
    Markus Blatt committed
        //! @returns an iterator that is positioned before
        //! the end iterator of the vector, i.e. at the last entry.
        iterator beforeEnd ()
    
    Peter Bastian's avatar
    Peter Bastian committed
        {
          return iterator(p,j,n-1);
        }
    
    
    Markus Blatt's avatar
    Markus Blatt committed
        //! @returns an iterator that is positioned before
        //! the first entry of the vector.
        iterator beforeBegin ()
    
    Peter Bastian's avatar
    Peter Bastian committed
        {
          return iterator(p,j,-1);
        }
    
    
        //! random access returning iterator (end if not contained)
    
          const size_type* lb = std::lower_bound(j, j+n, i);
    
          return (lb != j+n && *lb == i)
    
    Oliver Sander's avatar
    Oliver Sander committed
            : end();
    
    Peter Bastian's avatar
    Peter Bastian committed
        //! const_iterator class for sequential access
    
    Markus Blatt's avatar
    Markus Blatt committed
        typedef RealIterator<const B> const_iterator;
    
    Peter Bastian's avatar
    Peter Bastian committed
    
        //! begin const_iterator
        const_iterator begin () const
        {
          return const_iterator(p,j,0);
        }
    
        //! end const_iterator
        const_iterator end () const
        {
          return const_iterator(p,j,n);
        }
    
    
    Markus Blatt's avatar
    Markus Blatt committed
        //! @returns an iterator that is positioned before
        //! the end iterator of the vector. i.e. at the last element.
        const_iterator beforeEnd () const
    
    Peter Bastian's avatar
    Peter Bastian committed
        {
          return const_iterator(p,j,n-1);
        }
    
    
    Markus Blatt's avatar
    Markus Blatt committed
        //! @returns an iterator that is positioned before
        //! the first entry of the vector.
        const_iterator beforeBegin () const
    
    Peter Bastian's avatar
    Peter Bastian committed
        {
          return const_iterator(p,j,-1);
        }
    
        //! random access returning iterator (end if not contained)
    
        const_iterator find (size_type i) const
    
    Peter Bastian's avatar
    Peter Bastian committed
        {
    
          const size_type* lb = std::lower_bound(j, j+n, i);
    
          return (lb != j+n && *lb == i)
    
    Oliver Sander's avatar
    Oliver Sander committed
            : end();
    
    Peter Bastian's avatar
    Peter Bastian committed
        }
    
        //===== sizes
    
        //! number of blocks in the array (are of size 1 here)
    
    Peter Bastian's avatar
    Peter Bastian committed
        {
          return n;
        }
    
      protected:
        //! makes empty array
        compressed_base_array_unmanaged ()
    
          : n(0), p(0), j(0)
        {}
    
    Peter Bastian's avatar
    Peter Bastian committed
    
    
        size_type n;      // number of elements in array
    
    Peter Bastian's avatar
    Peter Bastian committed
        B *p;       // pointer to dynamically allocated built-in array
    
        size_type* j;     // the index set
    
    Peter Bastian's avatar
    Peter Bastian committed
      };
    
    
    Peter Bastian's avatar
    Peter Bastian committed
    } // end namespace
    
    #endif