diff options
author | Richard Linden <none@none> | 2013-06-18 23:42:59 -0700 |
---|---|---|
committer | Richard Linden <none@none> | 2013-06-18 23:42:59 -0700 |
commit | 8977f43230bda6d7f814e770ba574d016a3875fa (patch) | |
tree | 16b30705c490a250893699c486e63d4d97c0003f /indra/llcommon/llunit.h | |
parent | 1bc1d532cff1539bb5366f87b602970f1d2a8929 (diff) | |
parent | d136c4c29686c565b5a46503aa67a9c958b4145d (diff) |
Automated merge with bundle:d:\code\viewer-interesting+c:\users\richard\appdata\local\temp\thg.7jrj8n\https__bitbucket.org_lindenlab_viewer-interesting_jch9cd.hg
Diffstat (limited to 'indra/llcommon/llunit.h')
-rw-r--r-- | indra/llcommon/llunit.h | 442 |
1 files changed, 261 insertions, 181 deletions
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h index f48cbe0e11..5229fe69d7 100644 --- a/indra/llcommon/llunit.h +++ b/indra/llcommon/llunit.h @@ -30,36 +30,12 @@ #include "stdtypes.h" #include "llpreprocessor.h" #include "llerrorlegacy.h" +#include <boost/type_traits/is_same.hpp> -namespace LLUnits -{ - -template<typename DERIVED_UNITS_TAG, typename BASE_UNITS_TAG, typename VALUE_TYPE> -struct ConversionFactor -{ - static F64 get() - { - // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template - llstatic_assert_template(DERIVED_UNITS_TAG, false, "Cannot convert between types."); - return 0; - } -}; - -template<typename BASE_UNITS_TAG, typename VALUE_TYPE> -struct ConversionFactor<BASE_UNITS_TAG, BASE_UNITS_TAG, VALUE_TYPE> -{ - static F64 get() - { - return 1; - } -}; - -} - -template<typename UNIT_TYPE, typename STORAGE_TYPE> +template<typename STORAGE_TYPE, typename UNIT_TYPE> struct LLUnit { - typedef LLUnit<UNIT_TYPE, STORAGE_TYPE> self_t; + typedef LLUnit<STORAGE_TYPE, UNIT_TYPE> self_t; typedef STORAGE_TYPE storage_t; // value initialization @@ -68,11 +44,16 @@ struct LLUnit {} // unit initialization and conversion - template<typename OTHER_UNIT, typename OTHER_STORAGE> - LLUnit(LLUnit<OTHER_UNIT, OTHER_STORAGE> other) - : mValue(convert(other)) + template<typename OTHER_STORAGE, typename OTHER_UNIT> + LLUnit(LLUnit<OTHER_STORAGE, OTHER_UNIT> other) + : mValue(convert(other).mValue) {} + bool operator == (const self_t& other) + { + return mValue = other.mValue; + } + // value assignment self_t& operator = (storage_t value) { @@ -81,10 +62,10 @@ struct LLUnit } // unit assignment - template<typename OTHER_UNIT, typename OTHER_STORAGE> - self_t& operator = (LLUnit<OTHER_UNIT, OTHER_STORAGE> other) + template<typename OTHER_STORAGE, typename OTHER_UNIT> + self_t& operator = (LLUnit<OTHER_STORAGE, OTHER_UNIT> other) { - mValue = convert(other); + mValue = convert(other).mValue; return *this; } @@ -93,21 +74,27 @@ struct LLUnit return mValue; } - template<typename NEW_UNIT_TYPE> LLUnit<NEW_UNIT_TYPE, STORAGE_TYPE> as() + template<typename NEW_UNIT_TYPE> + STORAGE_TYPE getAs() { - return LLUnit<NEW_UNIT_TYPE, STORAGE_TYPE>(*this); + return LLUnit<STORAGE_TYPE, NEW_UNIT_TYPE>(*this).value(); } + template<typename NEW_UNIT_TYPE> + STORAGE_TYPE setAs(STORAGE_TYPE val) + { + *this = LLUnit<STORAGE_TYPE, NEW_UNIT_TYPE>(val); + } void operator += (storage_t value) { mValue += value; } - template<typename OTHER_UNIT, typename OTHER_STORAGE> - void operator += (LLUnit<OTHER_UNIT, OTHER_STORAGE> other) + template<typename OTHER_STORAGE, typename OTHER_UNIT> + void operator += (LLUnit<OTHER_STORAGE, OTHER_UNIT> other) { - mValue += convert(other); + mValue += convert(other).mValue; } void operator -= (storage_t value) @@ -115,10 +102,10 @@ struct LLUnit mValue -= value; } - template<typename OTHER_UNIT, typename OTHER_STORAGE> - void operator -= (LLUnit<OTHER_UNIT, OTHER_STORAGE> other) + template<typename OTHER_STORAGE, typename OTHER_UNIT> + void operator -= (LLUnit<OTHER_STORAGE, OTHER_UNIT> other) { - mValue -= convert(other); + mValue -= convert(other).mValue; } void operator *= (storage_t multiplicand) @@ -127,7 +114,7 @@ struct LLUnit } template<typename OTHER_UNIT, typename OTHER_STORAGE> - void operator *= (LLUnit<OTHER_UNIT, OTHER_STORAGE> multiplicand) + void operator *= (LLUnit<OTHER_STORAGE, OTHER_UNIT> multiplicand) { // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template llstatic_assert_template(OTHER_UNIT, false, "Multiplication of unit types not supported."); @@ -139,37 +126,37 @@ struct LLUnit } template<typename OTHER_UNIT, typename OTHER_STORAGE> - void operator /= (LLUnit<OTHER_UNIT, OTHER_STORAGE> divisor) + void operator /= (LLUnit<OTHER_STORAGE, OTHER_UNIT> divisor) { // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template llstatic_assert_template(OTHER_UNIT, false, "Illegal in-place division of unit types."); } - template<typename SOURCE_UNITS, typename SOURCE_STORAGE> - static storage_t convert(LLUnit<SOURCE_UNITS, SOURCE_STORAGE> v) + template<typename SOURCE_STORAGE, typename SOURCE_UNITS> + static self_t convert(LLUnit<SOURCE_STORAGE, SOURCE_UNITS> v) { - return (storage_t)(v.value() - * LLUnits::ConversionFactor<SOURCE_UNITS, typename UNIT_TYPE::base_unit_t, SOURCE_STORAGE>::get() - * LLUnits::ConversionFactor<typename UNIT_TYPE::base_unit_t, UNIT_TYPE, STORAGE_TYPE>::get()); + self_t result; + ll_convert_units(v, result); + return result; } protected: storage_t mValue; }; -template<typename UNIT_TYPE, typename STORAGE_TYPE> -struct LLUnitImplicit : public LLUnit<UNIT_TYPE, STORAGE_TYPE> +template<typename STORAGE_TYPE, typename UNIT_TYPE> +struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNIT_TYPE> { - typedef LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> self_t; - typedef typename LLUnit<UNIT_TYPE, STORAGE_TYPE>::storage_t storage_t; - typedef LLUnit<UNIT_TYPE, STORAGE_TYPE> base_t; + typedef LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> self_t; + typedef typename LLUnit<STORAGE_TYPE, UNIT_TYPE>::storage_t storage_t; + typedef LLUnit<STORAGE_TYPE, UNIT_TYPE> base_t; LLUnitImplicit(storage_t value = storage_t()) : base_t(value) {} - template<typename OTHER_UNIT, typename OTHER_STORAGE> - LLUnitImplicit(LLUnit<OTHER_UNIT, OTHER_STORAGE> other) + template<typename OTHER_STORAGE, typename OTHER_UNIT> + LLUnitImplicit(LLUnit<OTHER_STORAGE, OTHER_UNIT> other) : base_t(convert(other)) {} @@ -181,53 +168,86 @@ struct LLUnitImplicit : public LLUnit<UNIT_TYPE, STORAGE_TYPE> } }; + +template<typename S1, typename T1, typename S2, typename T2> +LL_FORCE_INLINE void ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out, ...) +{ + static_assert(boost::is_same<T1, T2>::value + || !boost::is_same<T1, typename T1::base_unit_t>::value + || !boost::is_same<T2, typename T2::base_unit_t>::value, + "invalid conversion"); + + if (boost::is_same<T1, typename T1::base_unit_t>::value) + { + if (boost::is_same<T2, typename T2::base_unit_t>::value) + { + // T1 and T2 fully reduced and equal...just copy + out = (S2)in.value(); + } + else + { + // reduce T2 + LLUnit<S2, typename T2::base_unit_t> new_out; + ll_convert_units(in, new_out); + ll_convert_units(new_out, out); + } + } + else + { + // reduce T1 + LLUnit<S1, typename T1::base_unit_t> new_in; + ll_convert_units(in, new_in); + ll_convert_units(new_in, out); + } +} + // // operator + // -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -LLUnit<UNIT_TYPE1, STORAGE_TYPE1> operator + (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +LLUnit<STORAGE_TYPE1, UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second) { - LLUnit<UNIT_TYPE1, STORAGE_TYPE1> result(first); + LLUnit<STORAGE_TYPE1, UNIT_TYPE1> result(first); result += second; return result; } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnit<UNIT_TYPE, STORAGE_TYPE> operator + (LLUnit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnit<STORAGE_TYPE, UNIT_TYPE> operator + (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) { - LLUnit<UNIT_TYPE, STORAGE_TYPE> result(first); + LLUnit<STORAGE_TYPE, UNIT_TYPE> result(first); result += second; return result; } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnit<UNIT_TYPE, STORAGE_TYPE> operator + (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_TYPE> second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnit<STORAGE_TYPE, UNIT_TYPE> operator + (SCALAR_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second) { - LLUnit<UNIT_TYPE, STORAGE_TYPE> result(first); + LLUnit<STORAGE_TYPE, UNIT_TYPE> result(first); result += second; return result; } -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> operator + (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second) { - LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> result(first); + LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> result(first); result += second; return result; } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator + (LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> operator + (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) { - LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> result(first); + LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> result(first); result += second; return result; } -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> operator + (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnitImplicit<UNIT_TYPE2, STORAGE_TYPE2> second) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second) { - LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> result(first); + LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> result(first); result += second; return result; } @@ -235,50 +255,50 @@ LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> operator + (LLUnitImplicit<UNIT_TYPE1, // // operator - // -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -LLUnit<UNIT_TYPE1, STORAGE_TYPE1> operator - (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +LLUnit<STORAGE_TYPE1, UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second) { - LLUnit<UNIT_TYPE1, STORAGE_TYPE1> result(first); + LLUnit<STORAGE_TYPE1, UNIT_TYPE1> result(first); result -= second; return result; } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnit<UNIT_TYPE, STORAGE_TYPE> operator - (LLUnit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnit<STORAGE_TYPE, UNIT_TYPE> operator - (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) { - LLUnit<UNIT_TYPE, STORAGE_TYPE> result(first); + LLUnit<STORAGE_TYPE, UNIT_TYPE> result(first); result -= second; return result; } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnit<UNIT_TYPE, STORAGE_TYPE> operator - (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_TYPE> second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnit<STORAGE_TYPE, UNIT_TYPE> operator - (SCALAR_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second) { - LLUnit<UNIT_TYPE, STORAGE_TYPE> result(first); + LLUnit<STORAGE_TYPE, UNIT_TYPE> result(first); result -= second; return result; } -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> operator - (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnitImplicit<UNIT_TYPE2, STORAGE_TYPE2> second) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second) { - LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> result(first); + LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> result(first); result -= second; return result; } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator - (LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> operator - (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) { - LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> result(first); + LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> result(first); result -= second; return result; } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator - (SCALAR_TYPE first, LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> operator - (SCALAR_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second) { - LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> result(first); + LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> result(first); result -= second; return result; } @@ -286,102 +306,100 @@ LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator - (SCALAR_TYPE first, LLUnitImp // // operator * // -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnit<UNIT_TYPE, STORAGE_TYPE> operator * (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_TYPE> second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnit<STORAGE_TYPE, UNIT_TYPE> operator * (SCALAR_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second) { - return LLUnit<UNIT_TYPE, STORAGE_TYPE>((STORAGE_TYPE)(first * second.value())); + return LLUnit<STORAGE_TYPE, UNIT_TYPE>((STORAGE_TYPE)(first * second.value())); } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnit<UNIT_TYPE, STORAGE_TYPE> operator * (LLUnit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnit<STORAGE_TYPE, UNIT_TYPE> operator * (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) { - return LLUnit<UNIT_TYPE, STORAGE_TYPE>((STORAGE_TYPE)(first.value() * second)); + return LLUnit<STORAGE_TYPE, UNIT_TYPE>((STORAGE_TYPE)(first.value() * second)); } -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -LLUnit<UNIT_TYPE1, STORAGE_TYPE1> operator * (LLUnit<UNIT_TYPE1, STORAGE_TYPE1>, LLUnit<UNIT_TYPE2, STORAGE_TYPE2>) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +LLUnit<STORAGE_TYPE1, UNIT_TYPE1> operator * (LLUnit<STORAGE_TYPE1, UNIT_TYPE1>, LLUnit<STORAGE_TYPE2, UNIT_TYPE2>) { // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template llstatic_assert_template(STORAGE_TYPE1, false, "Multiplication of unit types results in new unit type - not supported."); - return LLUnit<UNIT_TYPE1, STORAGE_TYPE1>(); + return LLUnit<STORAGE_TYPE1, UNIT_TYPE1>(); } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator * (SCALAR_TYPE first, LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> operator * (SCALAR_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second) { - return LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE>(first * second.value()); + return LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>(first * second.value()); } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator * (LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> operator * (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) { - return LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE>(first.value() * second); + return LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>(first.value() * second); } -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> operator * (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1>, LLUnitImplicit<UNIT_TYPE2, STORAGE_TYPE2>) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> operator * (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2>) { // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template llstatic_assert_template(STORAGE_TYPE1, false, "Multiplication of unit types results in new unit type - not supported."); - return LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1>(); + return LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>(); } // // operator / // -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -SCALAR_TYPE operator / (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_TYPE> second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +SCALAR_TYPE operator / (SCALAR_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second) { return SCALAR_TYPE(first / second.value()); } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnit<UNIT_TYPE, STORAGE_TYPE> operator / (LLUnit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnit<STORAGE_TYPE, UNIT_TYPE> operator / (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) { - return LLUnit<UNIT_TYPE, STORAGE_TYPE>((STORAGE_TYPE)(first.value() / second)); + return LLUnit<STORAGE_TYPE, UNIT_TYPE>((STORAGE_TYPE)(first.value() / second)); } -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -STORAGE_TYPE1 operator / (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +STORAGE_TYPE1 operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second) { - // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template - return STORAGE_TYPE1(first.value() / second.value()); + return STORAGE_TYPE1(first.value() / first.convert(second)); } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator / (LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> operator / (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) { - return LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE>((STORAGE_TYPE)(first.value() / second)); + return LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>((STORAGE_TYPE)(first.value() / second)); } -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -STORAGE_TYPE1 operator / (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnitImplicit<UNIT_TYPE2, STORAGE_TYPE2> second) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +STORAGE_TYPE1 operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second) { - // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template - return STORAGE_TYPE1(first.value() / second.value()); + return STORAGE_TYPE1(first.value() / first.convert(second)); } #define COMPARISON_OPERATORS(op) \ -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> \ -bool operator op (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_TYPE> second) \ +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> \ +bool operator op (SCALAR_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second) \ { \ return first op second.value(); \ } \ \ -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> \ -bool operator op (LLUnit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) \ +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> \ +bool operator op (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) \ { \ return first.value() op second; \ } \ \ -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> \ -bool operator op (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnitImplicit<UNIT_TYPE2, STORAGE_TYPE2> second) \ +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> \ +bool operator op (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second) \ { \ return first.value() op first.convert(second); \ } \ \ -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> \ - bool operator op (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second) \ +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> \ + bool operator op (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second) \ { \ return first.value() op first.convert(second); \ } @@ -401,80 +419,142 @@ struct LLGetUnitLabel }; template<typename T, typename STORAGE_T> -struct LLGetUnitLabel<LLUnit<T, STORAGE_T> > +struct LLGetUnitLabel<LLUnit<STORAGE_T, T> > { static const char* getUnitLabel() { return T::getUnitLabel(); } }; -// -// Unit declarations -// -namespace LLUnits +template<typename VALUE_TYPE> +struct LLUnitLinearOps { -template<typename T> -T rawValue(T val) { return val; } + typedef LLUnitLinearOps<VALUE_TYPE> self_t; + LLUnitLinearOps(VALUE_TYPE val) : mValue (val) {} -template<typename UNIT_TYPE, typename STORAGE_TYPE> -STORAGE_TYPE rawValue(LLUnit<UNIT_TYPE, STORAGE_TYPE> val) { return val.value(); } + operator VALUE_TYPE() const { return mValue; } + VALUE_TYPE mValue; -template<typename UNIT_TYPE, typename STORAGE_TYPE> -STORAGE_TYPE rawValue(LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> val) { return val.value(); } + template<typename T> + self_t operator * (T other) + { + return mValue * other; + } + + template<typename T> + self_t operator / (T other) + { + return mValue / other; + } + + template<typename T> + self_t operator + (T other) + { + return mValue + other; + } + + template<typename T> + self_t operator - (T other) + { + return mValue - other; + } +}; -#define LL_DECLARE_DERIVED_UNIT(conversion_factor, base_unit_name, unit_name, unit_label) \ +template<typename VALUE_TYPE> +struct LLUnitInverseLinearOps +{ + typedef LLUnitInverseLinearOps<VALUE_TYPE> self_t; + + LLUnitInverseLinearOps(VALUE_TYPE val) : mValue (val) {} + operator VALUE_TYPE() const { return mValue; } + VALUE_TYPE mValue; + + template<typename T> + self_t operator * (T other) + { + return mValue / other; + } + + template<typename T> + self_t operator / (T other) + { + return mValue * other; + } + + template<typename T> + self_t operator + (T other) + { + return mValue - other; + } + + template<typename T> + self_t operator - (T other) + { + return mValue + other; + } +}; + +#define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label) \ +struct base_unit_name { typedef base_unit_name base_unit_t; static const char* getUnitLabel() { return unit_label; }} + +#define LL_DECLARE_DERIVED_UNIT(unit_name, unit_label, base_unit_name, conversion_operation) \ struct unit_name \ { \ typedef base_unit_name base_unit_t; \ static const char* getUnitLabel() { return unit_label; } \ }; \ -template<typename STORAGE_TYPE> \ -struct ConversionFactor<unit_name, base_unit_name, STORAGE_TYPE> \ -{ \ - static F64 get() \ - { \ - return (F64)conversion_factor; \ - } \ -}; \ \ -template<typename STORAGE_TYPE> \ -struct ConversionFactor<base_unit_name, unit_name, STORAGE_TYPE> \ +template<typename S1, typename S2> \ +void ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out) \ { \ - static F64 get() \ - { \ - return (F64)(1.0 / (conversion_factor)); \ - } \ -} + out = (S2)(LLUnitLinearOps<S1>(in.value()) conversion_operation).mValue; \ +} \ + \ +template<typename S1, typename S2> \ +void ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out) \ +{ \ + out = (S2)(LLUnitInverseLinearOps<S1>(in.value()) conversion_operation).mValue; \ +} -#define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label) \ -struct base_unit_name { typedef base_unit_name base_unit_t; static const char* getUnitLabel() { return unit_label; }} +// +// Unit declarations +// +namespace LLUnits +{ LL_DECLARE_BASE_UNIT(Bytes, "B"); -LL_DECLARE_DERIVED_UNIT(1024, Bytes, Kibibytes, "KiB"); -LL_DECLARE_DERIVED_UNIT(1024 * 1024, Bytes, Mibibytes, "MiB"); -LL_DECLARE_DERIVED_UNIT(1024 * 1024 * 1024, Bytes, Gibibytes, "GiB"); -LL_DECLARE_DERIVED_UNIT(1.0 / 8.0, Bytes, Bits, "b"); -LL_DECLARE_DERIVED_UNIT(1024 / 8, Bytes, Kibibits, "Kib"); -LL_DECLARE_DERIVED_UNIT(1024 / 8, Bytes, Mibibits, "Mib"); -LL_DECLARE_DERIVED_UNIT(1024 * 1024 * 1024 / 8, Bytes, Gibibits, "Gib"); +LL_DECLARE_DERIVED_UNIT(Kilobytes, "KB", Bytes, * 1000); +LL_DECLARE_DERIVED_UNIT(Megabytes, "MB", Kilobytes, * 1000); +LL_DECLARE_DERIVED_UNIT(Gigabytes, "GB", Megabytes, * 1000); +LL_DECLARE_DERIVED_UNIT(Kibibytes, "KiB", Bytes, * 1024); +LL_DECLARE_DERIVED_UNIT(Mibibytes, "MiB", Kibibytes, * 1024); +LL_DECLARE_DERIVED_UNIT(Gibibytes, "GiB", Mibibytes, * 1024); + +LL_DECLARE_DERIVED_UNIT(Bits, "b", Bytes, / 8); +LL_DECLARE_DERIVED_UNIT(Kilobits, "Kb", Bytes, * 1000 / 8); +LL_DECLARE_DERIVED_UNIT(Megabits, "Mb", Kilobits, * 1000 / 8); +LL_DECLARE_DERIVED_UNIT(Gigabits, "Gb", Megabits, * 1000 / 8); +LL_DECLARE_DERIVED_UNIT(Kibibits, "Kib", Bytes, * 1024 / 8); +LL_DECLARE_DERIVED_UNIT(Mibibits, "Mib", Kibibits, * 1024 / 8); +LL_DECLARE_DERIVED_UNIT(Gibibits, "Gib", Mibibits, * 1024 / 8); LL_DECLARE_BASE_UNIT(Seconds, "s"); -LL_DECLARE_DERIVED_UNIT(60, Seconds, Minutes, "min"); -LL_DECLARE_DERIVED_UNIT(60 * 60, Seconds, Hours, "h"); -LL_DECLARE_DERIVED_UNIT(1.0 / 1000.0, Seconds, Milliseconds, "ms"); -LL_DECLARE_DERIVED_UNIT(1.0 / 1000000.0, Seconds, Microseconds, "\x09\x3cs"); -LL_DECLARE_DERIVED_UNIT(1.0 / 1000000000.0, Seconds, Nanoseconds, "ns"); +LL_DECLARE_DERIVED_UNIT(Minutes, "min", Seconds, * 60); +LL_DECLARE_DERIVED_UNIT(Hours, "h", Seconds, * 60 * 60); +LL_DECLARE_DERIVED_UNIT(Milliseconds, "ms", Seconds, / 1000); +LL_DECLARE_DERIVED_UNIT(Microseconds, "\x09\x3cs", Milliseconds, / 1000); +LL_DECLARE_DERIVED_UNIT(Nanoseconds, "ns", Microseconds, / 1000); LL_DECLARE_BASE_UNIT(Meters, "m"); -LL_DECLARE_DERIVED_UNIT(1000, Meters, Kilometers, "km"); -LL_DECLARE_DERIVED_UNIT(1.0 / 100.0, Meters, Centimeters, "cm"); -LL_DECLARE_DERIVED_UNIT(1.0 / 1000.0, Meters, Millimeters, "mm"); +LL_DECLARE_DERIVED_UNIT(Kilometers, "km", Meters, * 1000); +LL_DECLARE_DERIVED_UNIT(Centimeters, "cm", Meters, / 100); +LL_DECLARE_DERIVED_UNIT(Millimeters, "mm", Meters, / 1000); LL_DECLARE_BASE_UNIT(Hertz, "Hz"); -LL_DECLARE_DERIVED_UNIT(1000, Hertz, Kilohertz, "KHz"); -LL_DECLARE_DERIVED_UNIT(1000 * 1000, Hertz, Megahertz, "MHz"); -LL_DECLARE_DERIVED_UNIT(1000 * 1000 * 1000, Hertz, Gigahertz, "GHz"); +LL_DECLARE_DERIVED_UNIT(Kilohertz, "KHz", Hertz, * 1000); +LL_DECLARE_DERIVED_UNIT(Megahertz, "MHz", Kilohertz, * 1000); +LL_DECLARE_DERIVED_UNIT(Gigahertz, "GHz", Megahertz, * 1000); LL_DECLARE_BASE_UNIT(Radians, "rad"); -LL_DECLARE_DERIVED_UNIT(0.01745329251994, Radians, Degrees, "deg"); +LL_DECLARE_DERIVED_UNIT(Degrees, "deg", Radians, * 0.01745329251994); } // namespace LLUnits |