static T clip(const T& a, const T& _min, const T& _max)
{ return max(_min, min(_max, a)); }
+
+ /// Add two (integer) values taking care of overflows.
+ static T addClipOverflow(T a, T b)
+ {
+ if( b > 0 )
+ {
+ if( SGLimits<T>::max() - b < a )
+ return SGLimits<T>::max();
+ }
+ else
+ {
+ if( SGLimits<T>::min() - b > a )
+ return SGLimits<T>::min();
+ }
+
+ return a + b;
+ }
+
+ /// Add two (integer) values in place, taking care of overflows.
+ static T& addClipOverflowInplace(T& a, T b)
+ {
+ return a = addClipOverflow(a, b);
+ }
+
+ /**
+ * Seek a variable towards a target value with given rate and timestep
+ *
+ * @param var Variable or eg. SGPropObj
+ * @param target Target value
+ * @param rate Max. change rate/sec
+ * @param dt Time step (sec)
+ */
+ template<class Var>
+ static T seek(Var& var, T target, T rate, T dt)
+ {
+ if( var < target )
+ return var = min(var + rate * dt, target);
+ else
+ return var = max(var - rate * dt, target);
+ }
+
+ /**
+ * Get @c base raised to the power of @c N
+ *
+ * @tparam N Exponent
+ * @param base Base
+ */
+ template<int N>
+ static T pow(T base)
+ {
+ return (N < 0)
+ ? (1. / pow<-N>(base))
+ : ( ((N & 1) ? base : 1)
+ * ((N > 1) ? pow<N / 2>(base * base) : 1)
+ );
+ }
+
static int sign(const T& a)
{
if (a < -SGLimits<T>::min())
return min;
T normalized = value - range*floor((value - min)/range);
// two security checks that can only happen due to roundoff
- if (value <= min)
+ if (normalized <= min)
return min;
if (max <= normalized)
return min;
static int roundToInt(const T& v)
{ return int(round(v)); }
-#ifndef NDEBUG
+ // Linear interpolation between two arbitrary typed values
+ template<typename S>
+ static S lerp(const S& val0, const S& val1, const T& t)
+ { return val0*(T(1) - t) + val1*t; }
+
/// Returns true if v is a NaN value
/// Use with care: allways code that you do not need to use that!
static bool isNaN(const T& v)
return !(v == v);
#endif
}
-#endif
};
#endif