|
|
/* $Id$ */
|
|
|
|
|
|
/** @file overflowsafe_type.hpp An overflow safe integer-like type. */
|
|
|
|
|
|
#ifndef OVERFLOWSAFE_TYPE_HPP
|
|
|
#define OVERFLOWSAFE_TYPE_HPP
|
|
|
|
|
|
#include "math_func.hpp"
|
|
|
|
|
|
/**
|
|
|
* Overflow safe template for integers, i.e. integers that will never overflow
|
|
|
* you multiply the maximum value with 2, or add 2, or substract somethng from
|
|
|
* the minimum value, etc.
|
|
|
* @param T the type these integers are stored with.
|
|
|
* @param T_MAX the maximum value for the integers.
|
|
|
* @param T_MIN the minimum value for the integers.
|
|
|
*/
|
|
|
template <class T, T T_MAX, T T_MIN>
|
|
|
class OverflowSafeInt
|
|
|
{
|
|
|
private:
|
|
|
/** The non-overflow safe backend to store the value in. */
|
|
|
T m_value;
|
|
|
public:
|
|
|
OverflowSafeInt() : m_value(0) { }
|
|
|
|
|
|
OverflowSafeInt(const OverflowSafeInt& other) { this->m_value = other.m_value; }
|
|
|
OverflowSafeInt(const int64 int_) { this->m_value = int_; }
|
|
|
|
|
|
FORCEINLINE OverflowSafeInt& operator = (const OverflowSafeInt& other) { this->m_value = other.m_value; return *this; }
|
|
|
|
|
|
FORCEINLINE OverflowSafeInt operator - () const { return OverflowSafeInt(-this->m_value); }
|
|
|
|
|
|
/**
|
|
|
* Safe implementation of addition.
|
|
|
* @param other the amount to add
|
|
|
* @note when the addition would yield more than T_MAX (or less than T_MIN),
|
|
|
* it will be T_MAX (respectively T_MIN).
|
|
|
*/
|
|
|
FORCEINLINE OverflowSafeInt& operator += (const OverflowSafeInt& other)
|
|
|
{
|
|
|
if ((T_MAX - abs(other.m_value)) < abs(this->m_value) &&
|
|
|
(this->m_value < 0) == (other.m_value < 0)) {
|
|
|
this->m_value = (this->m_value < 0) ? T_MIN : T_MAX ;
|
|
|
} else {
|
|
|
this->m_value += other.m_value;
|
|
|
}
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
|
/* Operators for addition and substraction */
|
|
|
FORCEINLINE OverflowSafeInt operator + (const OverflowSafeInt& other) const { OverflowSafeInt result = *this; result += other; return result; }
|
|
|
FORCEINLINE OverflowSafeInt operator + (const int other) const { OverflowSafeInt result = *this; result += (int64)other; return result; }
|
|
|
FORCEINLINE OverflowSafeInt operator + (const uint other) const { OverflowSafeInt result = *this; result += (int64)other; return result; }
|
|
|
FORCEINLINE OverflowSafeInt& operator -= (const OverflowSafeInt& other) { return *this += (-other); }
|
|
|
FORCEINLINE OverflowSafeInt operator - (const OverflowSafeInt& other) const { OverflowSafeInt result = *this; result -= other; return result; }
|
|
|
FORCEINLINE OverflowSafeInt operator - (const int other) const { OverflowSafeInt result = *this; result -= (int64)other; return result; }
|