void QLinearAllocator::Reallocate(const pointer_uint_q uNewSize, void* pNewLocation) { QE_ASSERT_ERROR(m_bUsesExternalBuffer, "This allocator uses an internal buffer so external reallocation is not possible"); QE_ASSERT_ERROR(pNewLocation != null_q, "The pointer to the new buffer cannot be null"); QE_ASSERT_WARNING(uNewSize > m_uSize, "The new size must be greater than the current size"); if(uNewSize > m_uSize) { pointer_uint_q uAdjustment = m_uAlignment - ((pointer_uint_q)pNewLocation & (m_uAlignment - 1U)); if(uAdjustment == m_uAlignment) uAdjustment = 0; const pointer_uint_q ADJUSTED_SIZE = uNewSize - uAdjustment; QE_ASSERT_WARNING(ADJUSTED_SIZE > m_uSize, "Due to the alignment adjustment, there is not enough space in the new buffer to allocate the data to be moved"); if(ADJUSTED_SIZE > m_uSize) { const pointer_uint_q BYTES_TO_COPY = this->GetAllocatedBytes(); void* pAdjustedLocation = (void*)((pointer_uint_q)pNewLocation + uAdjustment); memcpy(pAdjustedLocation, m_pBase, BYTES_TO_COPY); // Changes the base pointer to the first memory address that is aligned as intended m_pBase = pAdjustedLocation; m_pTop = (void*)((pointer_uint_q)m_pBase + BYTES_TO_COPY); m_uSize = ADJUSTED_SIZE; // Some free space may be lost } } }
QAlignment::QAlignment(const pointer_uint_q &uAlignment) { // Checking first if the alignment value is a power of 2. QE_ASSERT_WARNING( !(0 == uAlignment) && !(uAlignment & (uAlignment - 1)) , "The input alignment value must be a power of 2"); m_uAlignment = uAlignment; }
bool SQFloat::AreEqual(const float_q &fValueA, const float_q &fValueB, const float_q &fTolerance) { // The tolerance provided must be equal to or greater than the system tolerance. If the tolerance is too small it could become useless. QE_ASSERT_WARNING(fTolerance >= SQFloat::Epsilon, "The tolerance provided must be equal to or greater than the system tolerance. If the tolerance is too small it could become useless"); return SQFloat::Abs(fValueA - fValueB) <= fTolerance; }
void QLinearAllocator::CopyTo(QLinearAllocator &destination) const { QE_ASSERT_ERROR(destination.GetSize() >= this->GetAllocatedBytes(), "The input allocator's size must be greater than or equal to the size of the allocated bytes in the resident allocator."); QE_ASSERT_WARNING(destination.m_uAlignment == m_uAlignment, "The alignment of the input allocator is different from the resident allocator's."); const pointer_uint_q BYTES_TO_COPY = this->GetAllocatedBytes(); memcpy(destination.m_pBase, m_pBase, BYTES_TO_COPY); destination.m_pTop = (void*)((pointer_uint_q)destination.m_pBase + BYTES_TO_COPY); }
QMatrix2x2& QMatrix2x2::operator/=(const float_q &fScalar) { QE_ASSERT_WARNING(fScalar != SQFloat::_0, "Input value must not equal zero"); const float_q &DIVISOR = SQFloat::_1/fScalar; this->ij[0][0] *= DIVISOR; this->ij[0][1] *= DIVISOR; this->ij[1][0] *= DIVISOR; this->ij[1][1] *= DIVISOR; return *this; }
void QPoolAllocator::Reallocate(const pointer_uint_q uNewSize) { QE_ASSERT_WARNING(uNewSize > m_uPoolSize, "The new size must be greater than the current size of the pool."); if(uNewSize > m_uPoolSize) { void* pNewLocation = operator new(uNewSize, m_uAlignment); this->InternalReallocate(uNewSize, pNewLocation); m_bNeedDestroyMemoryChunk = true; } }
void* QLinearAllocator::Allocate(const pointer_uint_q uSize) { QE_ASSERT_ERROR(uSize > 0, "The size of the memory block to be allocated cannot be zero."); QE_ASSERT_WARNING(this->CanAllocate(uSize), "The size of the memory block to be allocated does not fit in the available free space."); void* pAllocatedMemory = null_q; if(this->CanAllocate(uSize)) { pAllocatedMemory = m_pTop; m_pTop = (void*)((pointer_uint_q)m_pTop + uSize); } return pAllocatedMemory; }
QMatrix2x2 QMatrix2x2::operator/(const float_q &fScalar) const { QE_ASSERT_WARNING(fScalar != SQFloat::_0, "Input value must not equal zero"); const float_q &DIVISOR = SQFloat::_1/fScalar; QMatrix2x2 aux; aux.ij[0][0] = this->ij[0][0] * DIVISOR; aux.ij[0][1] = this->ij[0][1] * DIVISOR; aux.ij[1][0] = this->ij[1][0] * DIVISOR; aux.ij[1][1] = this->ij[1][1] * DIVISOR; return aux; }
void QPoolAllocator::Reallocate(const pointer_uint_q uNewSize, const void* pNewLocation) { QE_ASSERT_WARNING(uNewSize > m_uPoolSize, "The new size must be greater than the current size of the pool."); QE_ASSERT_ERROR(pNewLocation != null_q, "The input new location cannot be null."); if(uNewSize > m_uPoolSize && pNewLocation != null_q) { pointer_uint_q uNewLocationAddress = (pointer_uint_q)pNewLocation; pointer_uint_q uAlignmentOffset = m_uAlignment - (uNewLocationAddress % m_uAlignment); void* pAdjustedNewLocation = (void*)((pointer_uint_q)pNewLocation + uAlignmentOffset); this->InternalReallocate(uNewSize, pAdjustedNewLocation); m_bNeedDestroyMemoryChunk = false; } }
QTimeSpan& QTimeSpan::operator+= (const QTimeSpan& timeSpan) { bool bNotGreaterThanMaxValue = ((QTimeSpan::MAXIMUM_VALUE - this->m_uTimeSpan) >= timeSpan.m_uTimeSpan); // Assertion to verify that we will not get overflow while calculating the time span QE_ASSERT_WARNING(bNotGreaterThanMaxValue == true, "The addition of the two timespan objects can not be higher than maximum value"); if (bNotGreaterThanMaxValue) { this->m_uTimeSpan += timeSpan.m_uTimeSpan; } else { this->m_uTimeSpan = QTimeSpan::MAXIMUM_VALUE; } return *this; }
void QLinearAllocator::Reallocate(const pointer_uint_q uNewSize) { QE_ASSERT_ERROR(!m_bUsesExternalBuffer, "This allocator uses an external buffer so internal reallocation is not possible"); QE_ASSERT_WARNING(uNewSize > m_uSize, "The new size must be greater than the current size"); if(uNewSize > m_uSize) { const pointer_uint_q BYTES_TO_COPY = this->GetAllocatedBytes(); void* pNewBuffer = ::operator new(uNewSize, QAlignment(m_uAlignment)); memcpy(pNewBuffer, m_pBase, BYTES_TO_COPY); ::operator delete(m_pBase, QAlignment(m_uAlignment)); m_pBase = pNewBuffer; m_pTop = (void*)((pointer_uint_q)m_pBase + BYTES_TO_COPY); m_uSize = uNewSize; } }
void* QLinearAllocator::Allocate(const pointer_uint_q uSize, const QAlignment &alignment) { QE_ASSERT_ERROR(uSize > 0, "The size of the memory block to be allocated cannot be zero."); QE_ASSERT_WARNING(this->CanAllocate(uSize, alignment), "The size of the memory block to be allocated (plus the alignment adjustment) does not fit in the available free space."); void* pAllocatedMemory = null_q; if(this->CanAllocate(uSize, alignment)) { pointer_uint_q uAdjustment = alignment - ((pointer_uint_q)m_pTop & (alignment - 1U)); if(uAdjustment == alignment) uAdjustment = 0; pAllocatedMemory = (void*)((pointer_uint_q)m_pTop + uAdjustment); m_pTop = (void*)((pointer_uint_q)m_pTop + uSize + uAdjustment); } return pAllocatedMemory; }
void QPoolAllocator::CopyTo(QPoolAllocator &poolAllocator) const { QE_ASSERT_ERROR(m_uBlocksCount <= poolAllocator.m_uBlocksCount, "Blocks count of destination pool allocator must be greater or equal than the source pool allocator" ); QE_ASSERT_ERROR(m_uPoolSize <= poolAllocator.m_uPoolSize, "Chunk size for allocations must be greater or equal in the destination pool allocator than in the source pool allocator" ); QE_ASSERT_ERROR(m_uBlockSize == poolAllocator.m_uBlockSize, "Block sizes of origin and destination pool allocators must be equal"); QE_ASSERT_WARNING(poolAllocator.m_uAlignment == m_uAlignment, "The alignment of the input allocator is different from the resident allocator's."); if(null_q == m_ppNextFreeBlock) { // No free blocks in source. Append extra destination free blocks pointers if it has more blocks count. if(m_uBlocksCount < poolAllocator.m_uBlocksCount) { // ppNext = first free block of remaining free blocks. void **ppNext = poolAllocator.m_ppFreeBlocks + m_uBlocksCount; // Assigns the next free block in the destination pool poolAllocator.m_ppNextFreeBlock = ppNext; // Frees remaining blocks from destination redoing the rest of the list. for( pointer_uint_q uIndex = m_uBlocksCount; uIndex < poolAllocator.m_uBlocksCount - 1; ++uIndex ) { *ppNext = (void*)((void**)ppNext + 1); ppNext = (void**)*ppNext; } *ppNext = null_q; } else { poolAllocator.m_ppNextFreeBlock = null_q; } } else { // Assigns the next free block in the destination pool (same block index as in origin). poolAllocator.m_ppNextFreeBlock = poolAllocator.m_ppFreeBlocks + (m_ppNextFreeBlock - m_ppFreeBlocks); // Copy free blocks pointers list from source to destination void **ppLastFreeBlock = m_ppNextFreeBlock; while( null_q != *ppLastFreeBlock ) { // Index of the next free block in the source = *ppLastFreeBlock - m_ppFreeBlocks *(poolAllocator.m_ppFreeBlocks + ((void**)ppLastFreeBlock - m_ppFreeBlocks)) = poolAllocator.m_ppFreeBlocks + ((void**)*ppLastFreeBlock - m_ppFreeBlocks); // ppLastFreeBlock will contain the pointer to last free block in the list or null if there are no free blocks // when exits from the while loop. if(null_q != *ppLastFreeBlock) ppLastFreeBlock = (void**)*ppLastFreeBlock; } if(m_uBlocksCount < poolAllocator.m_uBlocksCount) { // Appends extra free blocks pointers of destination // Links copied free blocks list from source to remaining free blocks from destination. // ppNext = first free block of remaining free blocks. void **ppNext = poolAllocator.m_ppFreeBlocks + m_uBlocksCount; // Links two lists. *(poolAllocator.m_ppFreeBlocks + (ppLastFreeBlock - m_ppFreeBlocks)) = ppNext; // Frees the rest of blocks from destination redoing the rest of the list. for( pointer_uint_q uIndex = m_uBlocksCount; uIndex < poolAllocator.m_uBlocksCount - 1; uIndex++ ) { *ppNext = (void*)((void**)ppNext + 1); ppNext = (void**)*ppNext; } *ppNext = null_q; } } // Copies all source blocks in destination memcpy(poolAllocator.m_pFirst, m_pFirst, m_uBlockSize * m_uBlocksCount); poolAllocator.m_uAllocatedBytes = m_uAllocatedBytes; }
QTimeSpan::QTimeSpan(const u64_q uDays, const u64_q uHours, const u64_q uMinutes, const u64_q uSeconds, const u64_q uMilliseconds, const u64_q uMicroseconds, const u64_q uHundredsNanoseconds) { // Constants containing the max value for each parameter. // Remember we have to convert them to hundreds of nanoseconds. const u64_q MAX_MICROSECONDS = MAXIMUM_VALUE / HUNDREDS_OF_NANOSECONDS_PER_MICROSECOND; const u64_q MAX_MILLISECONDS = MAXIMUM_VALUE / (HUNDREDS_OF_NANOSECONDS_PER_MICROSECOND * MICROSECONDS_PER_MILLISECOND ); const u64_q MAX_SECONDS = MAXIMUM_VALUE / (HUNDREDS_OF_NANOSECONDS_PER_MICROSECOND * MILLISECONDS_PER_SECOND * MICROSECONDS_PER_MILLISECOND); const u64_q MAX_MINUTES = MAXIMUM_VALUE / (HUNDREDS_OF_NANOSECONDS_PER_MICROSECOND * SECONDS_PER_MINUTE * MILLISECONDS_PER_SECOND * MICROSECONDS_PER_MILLISECOND); const u64_q MAX_HOURS = MAXIMUM_VALUE / (HUNDREDS_OF_NANOSECONDS_PER_MICROSECOND * MINUTES_PER_HOUR * SECONDS_PER_MINUTE * MILLISECONDS_PER_SECOND * MICROSECONDS_PER_MILLISECOND); const u64_q MAX_DAYS = MAXIMUM_VALUE / (HUNDREDS_OF_NANOSECONDS_PER_MICROSECOND * HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE * MILLISECONDS_PER_SECOND * MICROSECONDS_PER_MILLISECOND); bool bNotGreaterThanMaxValue = (uDays <= MAX_DAYS && uHours <= MAX_HOURS && uMinutes <= MAX_MINUTES && uSeconds <= MAX_SECONDS && uMilliseconds <= MAX_MILLISECONDS && uMicroseconds <= MAX_MICROSECONDS && uHundredsNanoseconds <= MAXIMUM_VALUE); // Assertion to verify that we will not get overflow while calculating the time span QE_ASSERT_WARNING(bNotGreaterThanMaxValue == true, "Parameters must be lower than maximum values"); // To avoid overflow if it happens return max value allowed if (!bNotGreaterThanMaxValue) { m_uTimeSpan = MAXIMUM_VALUE; } else { u64_q uMicrosecondsToHundreds = QTimeSpan::HUNDREDS_OF_NANOSECONDS_PER_MICROSECOND * uMicroseconds; u64_q uMillisecondsToHundreds = QTimeSpan::HUNDREDS_OF_NANOSECONDS_PER_MICROSECOND * QTimeSpan::MICROSECONDS_PER_MILLISECOND * uMilliseconds; u64_q uSecondsToHundreds = QTimeSpan::HUNDREDS_OF_NANOSECONDS_PER_MICROSECOND * QTimeSpan::MILLISECONDS_PER_SECOND * uSeconds * QTimeSpan::MICROSECONDS_PER_MILLISECOND; u64_q uMinutesToHundreds = QTimeSpan::HUNDREDS_OF_NANOSECONDS_PER_MICROSECOND * QTimeSpan::SECONDS_PER_MINUTE * uMinutes * QTimeSpan::MILLISECONDS_PER_SECOND * QTimeSpan::MICROSECONDS_PER_MILLISECOND; u64_q uHoursToHundreds = QTimeSpan::HUNDREDS_OF_NANOSECONDS_PER_MICROSECOND * QTimeSpan::MINUTES_PER_HOUR * uHours * QTimeSpan::SECONDS_PER_MINUTE * QTimeSpan::MILLISECONDS_PER_SECOND * QTimeSpan::MICROSECONDS_PER_MILLISECOND; u64_q uDaysToHundreds = QTimeSpan::HUNDREDS_OF_NANOSECONDS_PER_MICROSECOND * QTimeSpan::HOURS_PER_DAY * uDays * QTimeSpan::MINUTES_PER_HOUR * QTimeSpan::SECONDS_PER_MINUTE * QTimeSpan::MILLISECONDS_PER_SECOND * QTimeSpan::MICROSECONDS_PER_MILLISECOND; // Now check that we will not have overflow with the addition either bNotGreaterThanMaxValue = uMicrosecondsToHundreds <= (MAXIMUM_VALUE - uHundredsNanoseconds ) && uMillisecondsToHundreds <= (MAXIMUM_VALUE - (uHundredsNanoseconds + uMicrosecondsToHundreds)) && uSecondsToHundreds <= (MAXIMUM_VALUE - (uHundredsNanoseconds + uMicrosecondsToHundreds + uMillisecondsToHundreds)) && uMinutesToHundreds <= (MAXIMUM_VALUE - (uHundredsNanoseconds + uMicrosecondsToHundreds + uMillisecondsToHundreds + uSecondsToHundreds)) && uHoursToHundreds <= (MAXIMUM_VALUE - (uHundredsNanoseconds + uMicrosecondsToHundreds + uMillisecondsToHundreds + uSecondsToHundreds + uMinutesToHundreds)) && uDaysToHundreds <= (MAXIMUM_VALUE - (uHundredsNanoseconds + uMicrosecondsToHundreds + uMillisecondsToHundreds + uSecondsToHundreds + uMinutesToHundreds + uHoursToHundreds)); QE_ASSERT_WARNING(bNotGreaterThanMaxValue == true, "The converted values must be low enough to avoid overflow"); // To avoid overflow if it happens return max value allowed if (!bNotGreaterThanMaxValue) { m_uTimeSpan = MAXIMUM_VALUE; } else { // Add all the parameters m_uTimeSpan = uHundredsNanoseconds + uMicrosecondsToHundreds + uMillisecondsToHundreds + uSecondsToHundreds + uMinutesToHundreds + uHoursToHundreds + uDaysToHundreds; } } }