You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/Framework/GridMate/GridMate/MathUtils.h

120 lines
3.4 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#ifndef GM_MATHUTILS_H
#define GM_MATHUTILS_H
#include <AzCore/base.h>
namespace GridMate
{
//-------------------------------------------------------------------------
// helper functions to encode float as int while preserving relative-order
// between +/- numbers and equality between +0.f and -0.f
// http://www.cygnus-software.com/papers/comparingfloats/Comparing%20floating%20point%20numbers.htm
//-------------------------------------------------------------------------
AZ_FORCE_INLINE int encode_float_as_int(float v)
{
union
{
int m_i;
float m_f;
};
m_f = v;
return m_i < 0 ? 0x80000000 - m_i : m_i;
}
//-------------------------------------------------------------------------
AZ_FORCE_INLINE float decode_float_as_int(int v)
{
union
{
int m_i;
float m_f;
};
m_i = v < 0 ? 0x80000000 - v : v;
return m_f;
}
//-------------------------------------------------------------------------
AZ_FORCE_INLINE AZ::u32 encode_int_as_uint(AZ::s32 val)
{
AZ::u64 val64 = (~static_cast<AZ::u32>(val)) + 0x80000000u; // packing signed int into unsigned: 0x00(127)..0x7F(0), 0x80(-1)..0xFE(-127)
return static_cast<AZ::u32>(val64);
}
//-------------------------------------------------------------------------
AZ_FORCE_INLINE AZ::s32 decode_int_as_uint(AZ::u32 val)
{
AZ::u64 val64 = val - 0x80000000u;
return static_cast<AZ::s32>(~val64);
}
//-------------------------------------------------------------------------
template<class T, unsigned int size>
class RollingSum
{
public:
AZ_FORCE_INLINE RollingSum()
: m_sum(T())
, m_pos(0)
, m_accumDt(0.f)
, m_accumValue(T())
{
for (T& val : m_history)
{
val = T();
}
}
AZ_FORCE_INLINE T GetSum() const
{
return m_sum;
}
AZ_FORCE_INLINE void Update(float dt, T value)
{
m_accumDt += dt;
m_accumValue += value;
const float thresholdDt = 1.f / size;
if (m_accumDt < thresholdDt)
{
return;
}
const float maxDt = size * thresholdDt; // clamping in case there was delay >1sec
m_accumValue = AZStd::GetMin(m_accumValue, m_accumValue * static_cast<T>(maxDt / m_accumDt));
m_accumDt = AZStd::GetMin(m_accumDt, maxDt);
unsigned int bytes = static_cast<unsigned int>(thresholdDt * m_accumValue / m_accumDt);
while (m_accumDt >= thresholdDt)
{
Add(bytes);
m_accumValue -= bytes;
m_accumDt -= thresholdDt;
}
}
private:
T m_sum;
T m_history[size];
size_t m_pos;
float m_accumDt;
T m_accumValue;
AZ_FORCE_INLINE void Add(T value)
{
m_sum -= m_history[m_pos];
m_history[m_pos] = value;
m_sum += value;
m_pos = (m_pos + 1) % size;
}
};
} // namespace GridMate
#endif // GM_MATHUTILS_H