openfoam/src/OpenFOAM/containers/Lists/List/UList.H
Mark Olesen d9f0587416 ENH: promote ListOps::identity to Foam::identity
- becoming more frequently used and there is no ambiguity in calling
  parameters either - identity(label) vs identity(labelUList&).

  Provide both int32 and int64 versions.
2023-10-26 11:24:57 +02:00

777 lines
24 KiB
C++

/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM 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 General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::UList
Description
A 1D vector of objects of type \<T\>, where the size of the vector is
known and can be used for subscript bounds checking, etc.
Storage is not allocated during construction or use but is supplied to
the constructor as an argument. This type of list is particularly useful
for lists that refer to parts of existing lists such as SubList.
SourceFiles
UList.C
UListI.H
UListIO.C
\*---------------------------------------------------------------------------*/
#ifndef Foam_UList_H
#define Foam_UList_H
#include "bool.H"
#include "label.H"
#include "uLabel.H"
#include "zero.H"
#include "one.H"
#include "contiguous.H"
#include "stdFoam.H"
#include "nullObject.H"
#include "Hash.H"
#include "ListPolicy.H"
#include <iterator>
#include <vector> // i.e, std::vector
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward Declarations
class labelRange;
template<class T> class List;
template<class T> class SubList;
template<class T> class UList;
template<class T> class IndirectList;
template<class T> class UIndirectList;
template<class T, class Addr> class IndirectListBase;
template<class T> Istream& operator>>(Istream&, UList<T>&);
template<class T> Ostream& operator<<(Ostream&, const UList<T>&);
// Common list types
typedef UList<bool> boolUList; //!< A UList of bools
typedef UList<char> charUList; //!< A UList of chars
typedef UList<label> labelUList; //!< A UList of labels
/*---------------------------------------------------------------------------*\
Class UList Declaration
\*---------------------------------------------------------------------------*/
template<class T>
class UList
{
// Private Data
//- Number of elements in UList
label size_;
//- Vector of values of type T
T* __restrict__ v_;
protected:
// Protected Member Functions
//- Set addressed size to be inconsistent with allocated storage.
// Use with care
inline void setAddressableSize(const label n) noexcept;
//- Older name for setAddressableSize
FOAM_DEPRECATED_FOR(2021-01, "setAddressableSize(label) method")
void size(const label n) { this->setAddressableSize(n); }
//- Write the UList with its compound type
void writeEntry(Ostream& os) const;
//- Return a validated (start,size) subset range, which means that it
//- always addresses a valid section of the list.
labelRange validateRange(const labelRange& requestedRange) const;
//- Assign all entries to the given value
// Caution: method name subject to change
inline void fill_uniform(const T& val);
//- Assign all entries to zero
// Caution: method name subject to change
inline void fill_uniform(const Foam::zero);
//- No copy assignment (default: shallow copy)
//
// Assignment may need to be shallow (copy pointer)
// or deep (copy elements) depending on context or type of list.
// Disallow default assignment and provide separate 'shallowCopy' and
// 'deepCopy' member functions.
UList<T>& operator=(const UList<T>&) = delete;
public:
// STL type definitions
//- The value type the list contains
typedef T value_type;
//- The pointer type for non-const access to value_type items
typedef T* pointer;
//- The pointer type for const access to value_type items
typedef const T* const_pointer;
//- The type used for storing into value_type objects
typedef T& reference;
//- The type used for reading from constant value_type objects.
typedef const T& const_reference;
//- Random access iterator for traversing a UList
typedef T* iterator;
//- Random access iterator for traversing a UList
typedef const T* const_iterator;
//- The type to represent the size of a UList
typedef label size_type;
//- The difference between iterator objects
typedef label difference_type;
//- Reverse iterator (non-const access)
typedef std::reverse_iterator<iterator> reverse_iterator;
//- Reverse iterator (const access)
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
// Related types
//- Declare friendship with the List class
friend class List<T>;
//- Declare friendship with the SubList class
friend class SubList<T>;
// Static Functions
//- Return a UList reference to a nullObject
inline static const UList<T>& null();
// Public Classes
//- A list compare binary predicate for normal sort
struct less
{
const UList<T>& values;
less(const UList<T>& list)
:
values(list)
{}
bool operator()(const label a, const label b) const
{
return (values[a] < values[b]);
}
};
//- A list compare binary predicate for reverse sort
struct greater
{
const UList<T>& values;
greater(const UList<T>& list)
:
values(list)
{}
bool operator()(const label a, const label b) const
{
return (values[b] < values[a]);
}
};
// Generated Methods
//- Copy construct
UList(const UList<T>&) = default;
// Constructors
//- Default construct, zero-sized and nullptr
inline constexpr UList() noexcept;
//- Construct from components
inline UList(T* __restrict__ v, const label len) noexcept;
// Member Functions
// Access
//- The forward circular index. The next index in the list
//- which returns to the first at the end of the list
inline label fcIndex(const label i) const noexcept;
//- The reverse circular index. The previous index in the list
//- which returns to the last at the beginning of the list
inline label rcIndex(const label i) const noexcept;
//- Return forward circular value (ie, next value in the list)
inline const T& fcValue(const label i) const;
//- Return forward circular value (ie, next value in the list)
inline T& fcValue(const label i);
//- Return reverse circular value (ie, previous value in the list)
inline const T& rcValue(const label i) const;
//- Return reverse circular value (ie, previous value in the list)
inline T& rcValue(const label i);
//- Return pointer to the underlying array serving as data storage.
inline const T* cdata() const noexcept;
//- Return pointer to the underlying array serving as data storage.
inline T* data() noexcept;
//- Return pointer to the underlying array serving as data storage,
// reinterpreted as byte data
// \note Only meaningful for contiguous data
inline const char* cdata_bytes() const noexcept;
//- Return pointer to the underlying array serving as data storage,
// reinterpreted as byte data
// \note Only meaningful for contiguous data
inline char* data_bytes() noexcept;
//- Access first element of the list, position [0]
inline T& front();
//- Access first element of the list
inline const T& front() const;
//- Access last element of the list, position [size()-1]
inline T& back();
//- Access last element of the list, position [size()-1]
inline const T& back() const;
//- Number of contiguous bytes for the List data.
// \note Only meaningful for contiguous data
inline std::streamsize size_bytes() const noexcept;
//- Number of contiguous bytes for the List data,
//- runtime FatalError if type is not contiguous
std::streamsize byteSize() const;
// Check
//- Check start is within valid range [0,size)
inline void checkStart(const label start) const;
//- Check size is within valid range [0,size]
inline void checkSize(const label size) const;
//- Check that start and length define a valid range
inline void checkRange(const label start, const label len) const;
//- Check index is within valid range [0,size)
inline void checkIndex(const label i) const;
//- True if all entries have identical values, and list is non-empty
inline bool uniform() const;
// Search
//- True if the value is contained in the list.
inline bool contains(const T& val) const;
//- Is the value contained in the list?
// \param val The value to search for
// \param pos The first position to examine (no-op if -ve)
// \param len The length of the search region (-ve until the end)
// \return true if found.
inline bool contains(const T& val, label pos, label len = -1) const;
//- Find index of the first occurrence of the value.
// \param val The value to search for
// \return position in list or -1 if not found.
label find(const T& val) const;
//- Find index of the first occurrence of the value.
// \param val The value to search for
// \param pos The first position to examine (no-op if -ve)
// \param len The length of the search region (-ve until the end)
// \return position in list or -1 if not found.
label find(const T& val, label pos, label len = -1) const;
//- Find index of the last occurrence of the value.
// Any occurrences after the end pos are ignored.
// Linear search.
// \return position in list or -1 if not found.
label rfind(const T& val, label pos = -1) const;
// Edit
//- Move element to the first position.
void moveFirst(const label i);
//- Move element to the last position.
void moveLast(const label i);
//- Swap element with the first element. Fatal on an empty list.
void swapFirst(const label i);
//- Swap element with the last element. Fatal on an empty list.
void swapLast(const label i);
// Copy
//- Copy the pointer and size
inline void shallowCopy(T* __restrict__ ptr, const label len) noexcept;
//- Copy the pointer and size held by the given UList
inline void shallowCopy(const UList<T>& list) noexcept;
//- Copy elements of the given UList. Sizes must match!
void deepCopy(const UList<T>& list);
//- Copy elements of the given indirect list. Sizes must match!
template<class Addr>
void deepCopy(const IndirectListBase<T, Addr>& list);
// Other Access
//- Return SubList slice (non-const access) - no range checking
SubList<T> slice(const label pos, label len = -1);
//- Return SubList slice (const access) - no range checking
const SubList<T> slice(const label pos, label len = -1) const;
//- Return SubList slice (non-const access) - with range checking.
// The range is subsetted with the list size itself to ensure that the
// result always addresses a valid section of the list.
SubList<T> slice(const labelRange& range);
//- Return SubList slice (const access) - with range checking.
// The range is subsetted with the list size itself to ensure that the
// result always addresses a valid section of the list.
const SubList<T> slice(const labelRange& range) const;
// Member Operators
//- Return element of UList
inline T& operator[](const label i);
//- Return element of constant UList
// \note bool specialization adds lazy evaluation so reading an
// out-of-range element returns false without ill-effects
inline const T& operator[](const label i) const;
//- Allow cast to a const List<T>&
inline operator const Foam::List<T>&() const;
//- Assignment of all entries to the given value
inline void operator=(const T& val);
//- Assignment of all entries to zero
void operator=(const Foam::zero);
// Random access iterator (non-const)
//- Return an iterator to begin traversing the UList
inline iterator begin() noexcept;
//- Return an iterator to end traversing the UList
inline iterator end() noexcept;
//- Return iterator at offset i from begin,
//- clamped to [0,size] range
inline iterator begin(const label i) noexcept;
// Random access iterator (const)
//- Return const_iterator to begin traversing the constant UList
inline const_iterator cbegin() const noexcept;
//- Return const_iterator to end traversing the constant UList
inline const_iterator cend() const noexcept;
//- Return const_iterator to begin traversing the constant UList
inline const_iterator begin() const noexcept;
//- Return const_iterator to end traversing the constant UList
inline const_iterator end() const noexcept;
//- Return const_iterator at offset i from begin,
//- clamped to [0,size] range
inline const_iterator cbegin(const label i) const noexcept;
//- Return const_iterator at offset i from begin,
//- clamped to [0,size] range
inline const_iterator begin(const label i) const noexcept;
// Reverse iterators (non-const)
//- Return reverse_iterator to begin reverse traversing the UList
inline reverse_iterator rbegin();
//- Return reverse_iterator to end reverse traversing the UList
inline reverse_iterator rend();
// Reverse iterators (const)
//- Return const_reverse_iterator to begin reverse traversing the UList
inline const_reverse_iterator crbegin() const;
//- Return const_reverse_iterator to end reverse traversing the UList
inline const_reverse_iterator crend() const;
//- Return const_reverse_iterator to begin reverse traversing the UList
inline const_reverse_iterator rbegin() const;
//- Return const_reverse_iterator to end reverse traversing the UList
inline const_reverse_iterator rend() const;
// STL member functions
//- True if List is empty (ie, size() is zero)
bool empty() const noexcept { return !size_; }
//- The number of elements in the container
label size() const noexcept { return size_; }
//- Size of the underlying storage.
label capacity() const noexcept { return size_; }
//- The size of the largest possible UList
static constexpr label max_size() noexcept { return labelMax; }
//- Swap content with another UList of the same type in constant time
inline void swap(UList<T>& list) noexcept;
// STL member operators
//- Equality operation on ULists of the same type.
// Returns true when the ULists are element-wise equal
// (using UList::value_type::operator==). Takes linear time
bool operator==(const UList<T>& list) const;
//- The opposite of the equality operation. Takes linear time
bool operator!=(const UList<T>& list) const;
//- Compare two ULists lexicographically. Takes linear time
bool operator<(const UList<T>& list) const;
//- Compare two ULists lexicographically. Takes linear time
bool operator>(const UList<T>& list) const;
//- Return true if !(a > b). Takes linear time
bool operator<=(const UList<T>& list) const;
//- Return true if !(a < b). Takes linear time
bool operator>=(const UList<T>& list) const;
// Reading/writing
//- Read List contents from Istream.
// The List must have the proper size before calling
Istream& readList(Istream& is);
//- Write the List as a dictionary entry with keyword
void writeEntry(const word& keyword, Ostream& os) const;
//- Write List, with line-breaks in ASCII when length exceeds shortLen.
// Using '0' suppresses line-breaks entirely.
Ostream& writeList(Ostream& os, const label shortLen=0) const;
// IOstream Operators
//- Use the readList() method to read contents from Istream.
friend Istream& operator>> <T>
(
Istream& os,
UList<T>& list
);
// Special Methods
//- Test \c bool value at specified position,
//- always false for out-of-range access.
// \note Method name compatibility with bitSet, HashSet
template<class TypeT = T>
typename std::enable_if<std::is_same<bool, TypeT>::value, bool>::type
inline test(const label i) const
{
return (i >= 0 && i < size_ && v_[i]);
}
//- Return \c bool value at specified position,
//- always false for out-of-range access.
// \note Method name compatibility with bitSet
template<class TypeT = T>
typename std::enable_if<std::is_same<bool, TypeT>::value, bool>::type
inline get(const label i) const
{
return (i >= 0 && i < size_ && v_[i]);
}
//- Unset the \c bool entry at specified position,
//- always false for out-of-range access.
// \return True if value changed and was not out-of-range
// \note Method name compatibility with bitSet
template<class TypeT = T>
typename std::enable_if<std::is_same<bool, TypeT>::value, bool>::type
inline unset(const label i)
{
if (i >= 0 && i < size_ && v_[i])
{
v_[i] = false;
return true;
}
return false;
}
// Hashing
//- Hashing functor for UList
struct hasher
{
inline unsigned operator()
(
const UList<T>& obj,
unsigned seed=0
) const
{
if (is_contiguous<T>::value)
{
return Foam::Hasher(obj.cdata(), obj.size_bytes(), seed);
}
Foam::Hash<T> op;
for (const T& val : obj)
{
seed = op(val, seed);
}
return seed;
}
};
//- Deprecated(2021-04) hashing functor. Use hasher()
// \deprecated(2021-04) - use hasher() functor
template<class Unused=bool>
struct Hash : UList<T>::hasher
{
FOAM_DEPRECATED_FOR(2021-04, "hasher()") Hash() {}
};
// Housekeeping
//- Access first element of the list, position [0]
//FOAM_DEPRECATED_FOR(2022-10, "front()")
T& first() { return front(); }
//- Access first element of the list
//FOAM_DEPRECATED_FOR(2022-10, "front()")
const T& first() const { return front(); };
//- Access last element of the list, position [size()-1]
//FOAM_DEPRECATED_FOR(2022-10, "back()")
T& last() { return back(); }
//- Access last element of the list, position [size()-1]
//FOAM_DEPRECATED_FOR(2022-10, "back()")
const T& last() const { return back(); };
//- Same as contains()
bool found(const T& val, label pos = 0) const
{
return this->contains(val, pos);
}
};
// * * * * * * * * * * * * Template Specializations * * * * * * * * * * * * //
//- Character list writeEntry
template<>
void UList<char>::writeEntry(Ostream& os) const;
//- Character list assign zero - avoids Foam::zero casting ambiguities
template<>
void UList<char>::operator=(const Foam::zero);
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
//- Read List contents from Istream, list must have the proper size!
template<class T>
Istream& operator>>(Istream& is, UList<T>& list)
{
return list.readList(is);
}
//- Write List to Ostream, as per UList::writeList() with default length.
// The default short-length is given by Detail::ListPolicy::short_length
template<class T>
Ostream& operator<<(Ostream& os, const UList<T>& list)
{
return list.writeList(os, Detail::ListPolicy::short_length<T>::value);
}
//- Write std::vector to Ostream. ASCII only, no line-breaks
template<class T>
Ostream& operator<<(Ostream& os, const std::vector<T>& list);
// * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * * //
//- Fill an identity map with (map[i] == i), works like std::iota().
// Optionally with an alternative start index, so that (map[i] == i+start)
void identity(UList<int32_t>& map, int32_t start = 0);
//- Fill an identity map with (map[i] == i), works like std::iota().
// Optionally with an alternative start index, so that (map[i] == i+start)
void identity(UList<int64_t>& map, int64_t start = 0);
//- Sort the list
template<class T>
void sort(UList<T>& list);
//- Sort the list with the specified comparator
template<class T, class Compare>
void sort(UList<T>& list, const Compare& comp);
//- Stable sort the list
template<class T>
void stableSort(UList<T>& list);
//- Stable sort the list with the specified comparator
template<class T, class Compare>
void stableSort(UList<T>& list, const Compare& comp);
//- Randomise the list order
template<class T>
void shuffle(UList<T>& list);
//- Reverse the first n elements of the list
template<class T>
inline void reverse(UList<T>& list, const label n);
//- Reverse all elements of the list
template<class T>
inline void reverse(UList<T>& list);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Hashing for List data
template<class T>
struct Hash<UList<T>> : UList<T>::hasher {};
//- Object access operator or list access operator (default is pass-through)
//- \sa ListListOps::combine()
template<class T>
struct accessOp
{
const T& operator()(const T& obj) const { return obj; }
};
//- Test if object is empty, typically using its empty() method.
template<class T>
struct emptyOp
{
bool operator()(const T& obj) const { return obj.empty(); }
};
//- Extract size (as label) from an object, typically using its size() method.
template<class T>
struct sizeOp
{
label operator()(const T& obj) const { return obj.size(); }
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
// Does not need std::swap or Foam::Swap() specialization
// since UList is MoveConstructible and MoveAssignable
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "UListI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "UList.C"
#include "UListIO.C"
#include "stdVectorIO.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //