summaryrefslogtreecommitdiff
path: root/indra/llcommon/llunit.h
diff options
context:
space:
mode:
authorRichard Linden <none@none>2013-06-18 23:42:59 -0700
committerRichard Linden <none@none>2013-06-18 23:42:59 -0700
commit8977f43230bda6d7f814e770ba574d016a3875fa (patch)
tree16b30705c490a250893699c486e63d4d97c0003f /indra/llcommon/llunit.h
parent1bc1d532cff1539bb5366f87b602970f1d2a8929 (diff)
parentd136c4c29686c565b5a46503aa67a9c958b4145d (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.h442
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