13#ifndef BELFEM_CL_SHIFTREGISTER_HPP
14#define BELFEM_CL_SHIFTREGISTER_HPP
17#include <initializer_list>
27 template<
typename T >
class Vector;
28 template<
typename T >
class Matrix;
55 template<
typename T >
58 template<
typename T >
61 template<
typename T >
72 template <
typename T >
76 "ShiftRegister<T> uses malloc/free — T must be trivially copyable, "
77 "or specialize belfem::is_shift_register_safe<T> for an owning type "
78 "that is default-constructible and has a well-behaved operator= "
79 "(see cl_ShiftRegister.hpp for details)" );
83 static_assert( std::is_trivially_copyable< T >::value
84 || std::is_default_constructible< T >::value,
85 "ShiftRegister<T>: an owning T must be default-constructible so its "
86 "slots can be default-constructed on reserve()" );
97 size_t mCapacity = 0 ;
99 enum class RevertState : uint8_t { None, CanRevert, CanRevertFull };
100 RevertState mCanRevert = RevertState::None;
112 if constexpr ( ! std::is_trivially_copyable< T >::value )
114 for (
size_t k = 0; k < mCapacity + 1; ++k )
116 ::new (
static_cast< void *
>( mData + k ) ) T();
130 if constexpr ( ! std::is_trivially_copyable< T >::value )
132 for (
size_t k = 0; k < mCapacity + 1; ++k )
153 std::fill( mData, mData + aCapacity, aInitValue );
161 this->
reserve( aInitList.size() );
164 for(
const T &
value : aInitList )
166 mData[ k++ ] =
value;
170 mSize = aInitList.size();
182 std::copy( aOther.
begin(), aOther.
end(), mData );
184 mCanRevert = RevertState::None ;
187 mSize = aOther.
size();
197 mData = aOther.data();
198 mSize = aOther.size();
199 mCapacity = aOther.capacity();
200 mCanRevert = aOther.mCanRevert;
203 aOther.mData =
nullptr;
204 aOther.mCapacity = 0;
206 aOther.mCanRevert = RevertState::None;
213 if(
this != &aOther )
217 mSize = aOther.
size();
219 std::copy( aOther.
begin(), aOther.
end(), mData );
220 mCanRevert = RevertState::None ;
232 if(
this != &aOther )
234 if ( mData !=
nullptr )
236 this->destroy_slots();
241 mData = aOther.data();
242 mSize = aOther.size();
243 mCapacity = aOther.capacity();
244 mCanRevert = aOther.mCanRevert;
247 aOther.mData =
nullptr;
248 aOther.mCapacity = 0;
250 aOther.mCanRevert = RevertState::None;
259 if ( mData !=
nullptr )
261 this->destroy_slots();
274 index_t tElementsToMove = std::min( mSize, mCapacity-1 );
277 if ( mSize == mCapacity ) ++tElementsToMove;
282 std::move_backward( mData, mData + tElementsToMove, mData + tElementsToMove + 1 );
288 mCanRevert = mSize == mCapacity ? RevertState::CanRevertFull : RevertState::CanRevert ;
291 mSize = std::min( mSize+1, mCapacity );
302 index_t tElementsToMove = std::min( mSize, mCapacity-1 );
305 if ( mSize == mCapacity ) ++tElementsToMove;
309 std::move_backward( mData, mData + tElementsToMove, mData + tElementsToMove + 1 );
315 mCanRevert = mSize == mCapacity ? RevertState::CanRevertFull : RevertState::CanRevert ;
318 mSize = std::min( mSize+1, mCapacity );
326 BELFEM_ERROR( mCanRevert != RevertState::None,
"Cannot revert" );
328 std::move( mData + 1, mData + mSize + ( mCanRevert == RevertState::CanRevertFull ? 1 : 0 ), mData );
330 if ( mCanRevert == RevertState::CanRevert ) --mSize;
332 mCanRevert = RevertState::None ;
343 "Index %u out of range (expect < %u)",
344 (
unsigned int) aIndex, (
unsigned int) mSize );
346 return mData[ aIndex ];
358 "Index %u out of range (expect < %u)",
359 (
unsigned int) aIndex, (
unsigned int) mSize );
361 return mData[ aIndex ];
370 size() const -> decltype( mSize )
405 return mSize == mCapacity ;
417 mCanRevert = RevertState::None ;
455 return mData + mSize;
471 return mData + mSize;
477 std::fill( mData, mData + mSize, aValue );
478 mCanRevert = RevertState::None ;
487 "ShiftRegister: capacity must be greater than zero" );
489 if ( mCapacity == aCapacity ) return ;
492 if ( mData !=
nullptr )
494 this->destroy_slots();
499 mCapacity = aCapacity ;
500 mData = ( T * ) std::malloc( ( aCapacity + 1 ) *
sizeof( T ) );
505 "ShiftRegister: failed to allocate %lu slots",
506 (
unsigned long ) ( aCapacity + 1 ) );
509 this->construct_slots();
512 mCanRevert = RevertState::None ;
518 if ( mData !=
nullptr )
520 this->destroy_slots();
525 mCanRevert = RevertState::None ;
#define BELFEM_ERROR(aCheck,...)
Definition assert.hpp:264
#define BELFEM_ASSERT(aCheck,...)
Definition assert.hpp:244
Dense column-major matrix.
Definition cl_BZ_Matrix.hpp:28
Fixed-capacity FIFO with history, for time-stepping.
Definition cl_ShiftRegister.hpp:74
void free()
Definition cl_ShiftRegister.hpp:516
bool full() const
Check if the register is full.
Definition cl_ShiftRegister.hpp:403
const T * end() const
Definition cl_ShiftRegister.hpp:469
void reserve(const index_t aCapacity)
Definition cl_ShiftRegister.hpp:482
ShiftRegister(const size_t aCapacity, const T &aInitValue)
Definition cl_ShiftRegister.hpp:150
void revert()
Definition cl_ShiftRegister.hpp:324
const T & operator()(const uint aIndex) const
Access element by index (const version).
Definition cl_ShiftRegister.hpp:355
void fill(const T aValue)
Definition cl_ShiftRegister.hpp:475
T * begin()
Definition cl_ShiftRegister.hpp:445
bool empty() const
Check if the register is empty.
Definition cl_ShiftRegister.hpp:392
auto size() const -> decltype(mSize)
Get current number of elements.
Definition cl_ShiftRegister.hpp:370
~ShiftRegister()
Definition cl_ShiftRegister.hpp:257
ShiftRegister(const size_t aCapacity)
Definition cl_ShiftRegister.hpp:144
ShiftRegister & operator=(const ShiftRegister &aOther)
Definition cl_ShiftRegister.hpp:211
T * end()
Definition cl_ShiftRegister.hpp:453
void push(T &aValue)
Definition cl_ShiftRegister.hpp:269
const T * data() const
Get raw pointer to data array (const version).
Definition cl_ShiftRegister.hpp:437
ShiftRegister(const std::initializer_list< T > &aInitList)
Definition cl_ShiftRegister.hpp:159
const T * begin() const
Definition cl_ShiftRegister.hpp:461
ShiftRegister(ShiftRegister &&aOther) noexcept
Definition cl_ShiftRegister.hpp:193
ShiftRegister(const ShiftRegister &aOther)
Definition cl_ShiftRegister.hpp:176
T * data()
Get raw pointer to data array.
Definition cl_ShiftRegister.hpp:426
auto capacity() const -> decltype(mCapacity)
Get maximum capacity.
Definition cl_ShiftRegister.hpp:381
void clear()
Clear all elements.
Definition cl_ShiftRegister.hpp:414
T & operator()(const uint aIndex)
Access element by index (0 = newest, N-1 = oldest).
Definition cl_ShiftRegister.hpp:340
void push(const T &aValue)
Definition cl_ShiftRegister.hpp:297
ShiftRegister & operator=(ShiftRegister &&aOther) noexcept
Definition cl_ShiftRegister.hpp:230
Column vector.
Definition cl_BZ_Vector.hpp:41
USER GUIDES:
Definition cl_Capacitor.cpp:16
std::pair< real, unit > value
Definition typedefs.hpp:74
unsigned int uint
Definition typedefs.hpp:30
uint32_t index_t
Definition typedefs.hpp:52
Type trait: may T be stored in a ShiftRegister?
Definition cl_ShiftRegister.hpp:56