summaryrefslogtreecommitdiff
path: root/indra/llcommon/llunit.h
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon/llunit.h')
-rw-r--r--indra/llcommon/llunit.h547
1 files changed, 378 insertions, 169 deletions
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 090e42607e..c600883607 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -29,238 +29,447 @@
#include "stdtypes.h"
#include "llpreprocessor.h"
+#include "llerrorlegacy.h"
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT = BASE_UNIT>
-struct LLUnitType : public BASE_UNIT
+namespace LLUnits
+{
+
+template<typename T>
+struct HighestPrecisionType
+{
+ typedef T type_t;
+};
+
+template<> struct HighestPrecisionType<F32> { typedef F64 type_t; };
+template<> struct HighestPrecisionType<S32> { typedef S64 type_t; };
+template<> struct HighestPrecisionType<U32> { typedef S64 type_t; };
+template<> struct HighestPrecisionType<S16> { typedef S64 type_t; };
+template<> struct HighestPrecisionType<U16> { typedef S64 type_t; };
+template<> struct HighestPrecisionType<S8> { typedef S64 type_t; };
+template<> struct HighestPrecisionType<U8> { typedef S64 type_t; };
+
+template<typename DERIVED_UNITS_TAG, typename BASE_UNITS_TAG, typename VALUE_TYPE>
+struct ConversionFactor
+{
+ static typename HighestPrecisionType<VALUE_TYPE>::type_t 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.");
+ }
+};
+
+template<typename BASE_UNITS_TAG, typename VALUE_TYPE>
+struct ConversionFactor<BASE_UNITS_TAG, BASE_UNITS_TAG, VALUE_TYPE>
{
- typedef DERIVED_UNIT unit_t;
- typedef typename BASE_UNIT::value_t value_t;
- typedef void is_unit_t;
+ static typename HighestPrecisionType<VALUE_TYPE>::type_t get()
+ {
+ return 1;
+ }
+};
+
+}
- LLUnitType()
+template<typename UNIT_TYPE, typename STORAGE_TYPE>
+struct LLUnit
+{
+ typedef LLUnit<UNIT_TYPE, STORAGE_TYPE> self_t;
+ typedef STORAGE_TYPE storage_t;
+
+ // value initialization
+ LLUnit(storage_t value = storage_t())
+ : mValue(value)
{}
- explicit LLUnitType(value_t value)
- : BASE_UNIT(convertToBase(value))
+ // unit initialization and conversion
+ template<typename OTHER_UNIT, typename OTHER_STORAGE>
+ LLUnit(LLUnit<OTHER_UNIT, OTHER_STORAGE> other)
+ : mValue(convert(other))
{}
+
+ // value assignment
+ self_t& operator = (storage_t value)
+ {
+ mValue = value;
+ return *this;
+ }
- operator unit_t& ()
+ // unit assignment
+ template<typename OTHER_UNIT, typename OTHER_STORAGE>
+ self_t& operator = (LLUnit<OTHER_UNIT, OTHER_STORAGE> other)
{
- return static_cast<unit_t&>(*this);
+ mValue = convert(other);
+ return *this;
}
- value_t value() const
+ storage_t value() const
{
- return convertToDerived(mBaseValue);
+ return mValue;
}
- template<typename CONVERTED_TYPE>
- value_t value() const
+ template<typename NEW_UNIT_TYPE, typename NEW_STORAGE_TYPE> LLUnit<NEW_UNIT_TYPE, NEW_STORAGE_TYPE> as()
{
- return CONVERTED_TYPE(*this).value();
+ return LLUnit<NEW_UNIT_TYPE, NEW_STORAGE_TYPE>(*this);
}
- static value_t convertToBase(value_t derived_value)
+ void operator += (storage_t value)
{
- return (value_t)((F32)derived_value * unit_t::conversionToBaseFactor());
+ mValue += value;
}
- static value_t convertToDerived(value_t base_value)
+ template<typename OTHER_UNIT, typename OTHER_STORAGE>
+ void operator += (LLUnit<OTHER_UNIT, OTHER_STORAGE> other)
{
- return (value_t)((F32)base_value / unit_t::conversionToBaseFactor());
+ mValue += convert(other);
}
- unit_t operator + (const unit_t other) const
+ void operator -= (storage_t value)
{
- return unit_t(mBaseValue + other.mBaseValue);
+ mValue -= value;
}
- unit_t operator - (const unit_t other) const
+ template<typename OTHER_UNIT, typename OTHER_STORAGE>
+ void operator -= (LLUnit<OTHER_UNIT, OTHER_STORAGE> other)
{
- return unit_t(mBaseValue - other.mBaseValue);
+ mValue -= convert(other);
}
- unit_t operator * (value_t multiplicand) const
+ void operator *= (storage_t multiplicand)
{
- return unit_t(mBaseValue * multiplicand);
+ mValue *= multiplicand;
}
- unit_t operator / (value_t divisor) const
+ template<typename OTHER_UNIT, typename OTHER_STORAGE>
+ void operator *= (LLUnit<OTHER_UNIT, OTHER_STORAGE> multiplicand)
{
- return unit_t(mBaseValue / divisor);
+ // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
+ llstatic_assert_template(OTHER_UNIT, 0, "Multiplication of unit types not supported.");
}
+ void operator /= (storage_t divisor)
+ {
+ mValue /= divisor;
+ }
+
+ template<typename OTHER_UNIT, typename OTHER_STORAGE>
+ void operator /= (LLUnit<OTHER_UNIT, OTHER_STORAGE> divisor)
+ {
+ // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
+ llstatic_assert_template(OTHER_UNIT, 0, "Illegal in-place division of unit types.");
+ }
+
+ template<typename SOURCE_UNITS, typename SOURCE_STORAGE>
+ static storage_t convert(LLUnit<SOURCE_UNITS, SOURCE_STORAGE> 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());
+ }
+
+protected:
+ storage_t mValue;
};
-template<typename STORAGE_TYPE, typename T>
-struct LLUnitType<STORAGE_TYPE, T, T>
+template<typename UNIT_TYPE, typename STORAGE_TYPE>
+struct LLUnitImplicit : public LLUnit<UNIT_TYPE, STORAGE_TYPE>
{
- typedef T unit_t;
- typedef typename STORAGE_TYPE value_t;
- typedef void is_unit_t;
+ 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;
- LLUnitType()
- : mBaseValue()
+ LLUnitImplicit(storage_t value = storage_t())
+ : base_t(value)
{}
- explicit LLUnitType(value_t value)
- : mBaseValue(value)
+ template<typename OTHER_UNIT, typename OTHER_STORAGE>
+ LLUnitImplicit(LLUnit<OTHER_UNIT, OTHER_STORAGE> other)
+ : base_t(convert(other))
{}
- unit_t& operator=(value_t value)
+ // unlike LLUnit, LLUnitImplicit is *implicitly* convertable to a POD scalar (F32, S32, etc)
+ // this allows for interoperability with legacy code
+ operator storage_t() const
{
- setBaseValue(value);
- return *this;
+ return base_t::value();
}
+};
- operator unit_t& ()
- {
- return static_cast<unit_t&>(*this);
- }
+//
+// 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)
+{
+ LLUnit<UNIT_TYPE1, STORAGE_TYPE1> result(first);
+ result += second;
+ return result;
+}
- value_t value() const { return mBaseValue; }
+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)
+{
+ LLUnit<UNIT_TYPE, STORAGE_TYPE> result(first);
+ result += second;
+ return result;
+}
- static value_t convertToBase(value_t derived_value)
- {
- return (value_t)derived_value;
- }
+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)
+{
+ LLUnit<UNIT_TYPE, STORAGE_TYPE> result(first);
+ result += second;
+ return result;
+}
- static value_t convertToDerived(value_t base_value)
- {
- return (value_t)base_value;
- }
+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)
+{
+ LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> result(first);
+ result += second;
+ return result;
+}
- unit_t operator + (const unit_t other) const
- {
- return unit_t(mBaseValue + other.mBaseValue);
- }
+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)
+{
+ LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> result(first);
+ result += second;
+ return result;
+}
- void operator += (const unit_t other)
- {
- mBaseValue += other.mBaseValue;
- }
+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)
+{
+ LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> result(first);
+ result += second;
+ return result;
+}
- unit_t operator - (const unit_t other) const
- {
- return unit_t(mBaseValue - other.mBaseValue);
- }
+//
+// 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)
+{
+ LLUnit<UNIT_TYPE1, STORAGE_TYPE1> result(first);
+ result -= second;
+ return result;
+}
- void operator -= (const unit_t other)
- {
- mBaseValue -= other.mBaseValue;
- }
+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)
+{
+ LLUnit<UNIT_TYPE, STORAGE_TYPE> result(first);
+ result -= second;
+ return result;
+}
- unit_t operator * (value_t multiplicand) const
- {
- return unit_t(mBaseValue * multiplicand);
- }
+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)
+{
+ LLUnit<UNIT_TYPE, STORAGE_TYPE> result(first);
+ result -= second;
+ return result;
+}
- void operator *= (value_t multiplicand)
- {
- mBaseValue *= multiplicand;
- }
+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)
+{
+ LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> result(first);
+ result -= second;
+ return result;
+}
- unit_t operator / (value_t divisor) const
- {
- return unit_t(mBaseValue / divisor);
- }
+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)
+{
+ LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> result(first);
+ result -= second;
+ return result;
+}
- void operator /= (value_t divisor)
- {
- mBaseValue /= divisor;
- }
+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)
+{
+ LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> result(first);
+ result -= second;
+ return result;
+}
-protected:
- void setBaseValue(value_t value)
- {
- mBaseValue = value;
- }
+//
+// 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)
+{
+ return LLUnit<UNIT_TYPE, STORAGE_TYPE>(first * second.value());
+}
- value_t mBaseValue;
-};
+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)
+{
+ return LLUnit<UNIT_TYPE, STORAGE_TYPE>(first.value() * second);
+}
-#define LL_DECLARE_BASE_UNIT(unit_name) \
- struct unit_name : public LLUnitType<F64, unit_name> \
- { \
- typedef unit_name base_unit_t; \
- typedef LLUnitType<F64, unit_name> unit_t; \
- typedef F64 storage_t; \
- \
- unit_name(F64 value) \
- : LLUnitType(value) \
- {} \
- \
- unit_name() \
- {} \
- \
- template <typename SOURCE_STORAGE_TYPE, typename SOURCE_TYPE> \
- unit_name(const LLUnitType<SOURCE_STORAGE_TYPE, unit_name, SOURCE_TYPE>& source) \
- { \
- setBaseValue((F64)source.unit_name::unit_t::value()); \
- } \
- \
- using LLUnitType::operator +; \
- using LLUnitType::operator +=; \
- using LLUnitType::operator -; \
- using LLUnitType::operator -=; \
- using LLUnitType::operator *; \
- using LLUnitType::operator *=; \
- using LLUnitType::operator /; \
- using LLUnitType::operator /=; \
- };
-
-#define LL_DECLARE_DERIVED_UNIT(base_unit, derived_unit, conversion_factor) \
- struct derived_unit : public LLUnitType<F64, base_unit, derived_unit> \
- { \
- typedef base_unit base_unit_t; \
- typedef LLUnitType<F64, base_unit, derived_unit> unit_t; \
- typedef F64 storage_t; \
- \
- derived_unit(value_t value) \
- : LLUnitType(value) \
- {} \
- \
- derived_unit() \
- {} \
- \
- template <typename SOURCE_STORAGE_TYPE, typename SOURCE_TYPE> \
- derived_unit(const LLUnitType<SOURCE_STORAGE_TYPE, base_unit, SOURCE_TYPE>& source) \
- { \
- setBaseValue((F64)source.base_unit::unit_t::value()); \
- } \
- \
- static F32 conversionToBaseFactor() { return (F32)(conversion_factor); } \
- \
- using LLUnitType::operator +; \
- using LLUnitType::operator +=; \
- using LLUnitType::operator -; \
- using LLUnitType::operator -=; \
- using LLUnitType::operator *; \
- using LLUnitType::operator *=; \
- using LLUnitType::operator /; \
- using LLUnitType::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>, LLUnit<UNIT_TYPE2, STORAGE_TYPE2>)
+{
+ // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
+ llstatic_assert_template(STORAGE_TYPE1, 0, "Multiplication of unit types results in new unit type - not supported.");
+ return LLUnit<UNIT_TYPE1, STORAGE_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)
+{
+ return LLUnitImplicit<UNIT_TYPE, STORAGE_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)
+{
+ return LLUnitImplicit<UNIT_TYPE, STORAGE_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>)
+{
+ // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
+ llstatic_assert_template(STORAGE_TYPE1, 0, "Multiplication of unit types results in new unit type - not supported.");
+ return LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1>();
+}
+
+//
+// operator /
+//
+template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE>
+SCALAR_TYPE operator / (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_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)
+{
+ return LLUnit<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)
+{
+ // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
+ return STORAGE_TYPE1(first.value() / 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)
+{
+ return LLUnitImplicit<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)
+{
+ // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
+ return STORAGE_TYPE1(first.value() / second.value());
+}
+
+#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) \
+{ \
+ 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) \
+{ \
+ 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) \
+{ \
+ 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) \
+{ \
+ return first.value() op first.convert(second); \
+}
+
+COMPARISON_OPERATORS(<)
+COMPARISON_OPERATORS(<=)
+COMPARISON_OPERATORS(>)
+COMPARISON_OPERATORS(>=)
+COMPARISON_OPERATORS(==)
+COMPARISON_OPERATORS(!=)
namespace LLUnits
{
- LL_DECLARE_BASE_UNIT(Bytes);
- LL_DECLARE_DERIVED_UNIT(Bytes, Kilobytes, 1024);
- LL_DECLARE_DERIVED_UNIT(Bytes, Megabytes, 1024 * 1024);
- LL_DECLARE_DERIVED_UNIT(Bytes, Gigabytes, 1024 * 1024 * 1024);
- LL_DECLARE_DERIVED_UNIT(Bytes, Bits, (1.f / 8.f));
- LL_DECLARE_DERIVED_UNIT(Bytes, Kilobits, (1024 / 8));
- LL_DECLARE_DERIVED_UNIT(Bytes, Megabits, (1024 / 8));
- LL_DECLARE_DERIVED_UNIT(Bytes, Gigabits, (1024 * 1024 * 1024 / 8));
-
- LL_DECLARE_BASE_UNIT(Seconds);
- LL_DECLARE_DERIVED_UNIT(Seconds, Minutes, 60);
- LL_DECLARE_DERIVED_UNIT(Seconds, Hours, 60 * 60);
- LL_DECLARE_DERIVED_UNIT(Seconds, Days, 60 * 60 * 24);
- LL_DECLARE_DERIVED_UNIT(Seconds, Weeks, 60 * 60 * 24 * 7);
- LL_DECLARE_DERIVED_UNIT(Seconds, Milliseconds, (1.f / 1000.f));
- LL_DECLARE_DERIVED_UNIT(Seconds, Microseconds, (1.f / (1000000.f)));
- LL_DECLARE_DERIVED_UNIT(Seconds, Nanoseconds, (1.f / (1000000000.f)));
+template<typename T>
+T rawValue(T val) { return val; }
+
+template<typename UNIT_TYPE, typename STORAGE_TYPE>
+STORAGE_TYPE rawValue(LLUnit<UNIT_TYPE, STORAGE_TYPE> val) { return val.value(); }
+template<typename UNIT_TYPE, typename STORAGE_TYPE>
+STORAGE_TYPE rawValue(LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> val) { return val.value(); }
+
+template<typename UNIT_TYPE, typename STORAGE_TYPE>
+struct HighestPrecisionType<LLUnit<UNIT_TYPE, STORAGE_TYPE> >
+{
+ typedef typename HighestPrecisionType<STORAGE_TYPE>::type_t type_t;
+};
+
+#define LL_DECLARE_DERIVED_UNIT(conversion_factor, base_unit_name, unit_name) \
+struct unit_name \
+{ \
+ typedef base_unit_name base_unit_t; \
+}; \
+template<typename STORAGE_TYPE> \
+struct ConversionFactor<unit_name, base_unit_name, STORAGE_TYPE> \
+{ \
+ static typename HighestPrecisionType<STORAGE_TYPE>::type_t get() \
+ { \
+ return typename HighestPrecisionType<STORAGE_TYPE>::type_t(conversion_factor); \
+ } \
+}; \
+ \
+template<typename STORAGE_TYPE> \
+struct ConversionFactor<base_unit_name, unit_name, STORAGE_TYPE> \
+{ \
+ static typename HighestPrecisionType<STORAGE_TYPE>::type_t get() \
+ { \
+ return typename HighestPrecisionType<STORAGE_TYPE>::type_t(1.0 / (conversion_factor)); \
+ } \
}
+struct Bytes { typedef Bytes base_unit_t; };
+LL_DECLARE_DERIVED_UNIT(1024, Bytes, Kilobytes);
+LL_DECLARE_DERIVED_UNIT(1024 * 1024, Bytes, Megabytes);
+LL_DECLARE_DERIVED_UNIT(1024 * 1024 * 1024, Bytes, Gigabytes);
+LL_DECLARE_DERIVED_UNIT(1.0 / 8.0, Bytes, Bits);
+LL_DECLARE_DERIVED_UNIT(1024 / 8, Bytes, Kilobits);
+LL_DECLARE_DERIVED_UNIT(1024 / 8, Bytes, Megabits);
+LL_DECLARE_DERIVED_UNIT(1024 * 1024 * 1024 / 8, Bytes, Gigabits);
+
+struct Seconds { typedef Seconds base_unit_t; };
+LL_DECLARE_DERIVED_UNIT(60, Seconds, Minutes);
+LL_DECLARE_DERIVED_UNIT(60 * 60, Seconds, Hours);
+LL_DECLARE_DERIVED_UNIT(1.0 / 1000.0, Seconds, Milliseconds);
+LL_DECLARE_DERIVED_UNIT(1.0 / 1000000.0, Seconds, Microseconds);
+LL_DECLARE_DERIVED_UNIT(1.0 / 1000000000.0, Seconds, Nanoseconds);
+
+struct Meters { typedef Meters base_unit_t; };
+LL_DECLARE_DERIVED_UNIT(1000, Meters, Kilometers);
+LL_DECLARE_DERIVED_UNIT(1.0 / 100.0, Meters, Centimeters);
+LL_DECLARE_DERIVED_UNIT(1.0 / 1000.0, Meters, Millimeters);
+
+struct Hertz { typedef Hertz base_unit_t; };
+LL_DECLARE_DERIVED_UNIT(1000, Hertz, Kilohertz);
+LL_DECLARE_DERIVED_UNIT(1000 * 1000, Hertz, Megahertz);
+LL_DECLARE_DERIVED_UNIT(1000 * 1000 * 1000, Hertz, Gigahertz);
+} // namespace LLUnits
+
#endif // LL_LLUNIT_H