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.h193
1 files changed, 140 insertions, 53 deletions
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 1f3ed0237c..6b023f8287 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -65,6 +65,7 @@ struct ConversionFactor<BASE_UNITS_TAG, BASE_UNITS_TAG, VALUE_TYPE>
return 1;
}
};
+
}
template<typename UNIT_TYPE, typename STORAGE_TYPE>
@@ -73,25 +74,25 @@ 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)
{}
+ // unit initialization and conversion
template<typename OTHER_UNIT, typename OTHER_STORAGE>
LLUnit(LLUnit<OTHER_UNIT, OTHER_STORAGE> other)
: mValue(convert(other))
{}
-
- LLUnit(self_t& other)
- : mValue(other.mValue)
- {}
-
+
+ // value assignment
self_t& operator = (storage_t value)
{
mValue = value;
return *this;
}
+ // unit assignment
template<typename OTHER_UNIT, typename OTHER_STORAGE>
self_t& operator = (LLUnit<OTHER_UNIT, OTHER_STORAGE> other)
{
@@ -99,11 +100,6 @@ struct LLUnit
return *this;
}
- operator storage_t() const
- {
- return value();
- }
-
storage_t value() const
{
return mValue;
@@ -157,7 +153,7 @@ struct LLUnit
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(sizeof(OTHER_UNIT) == 0, "Division of unit types not supported.");
+ llstatic_assert(sizeof(OTHER_UNIT) == 0, "Illegal in-place division of unit types.");
}
template<typename SOURCE_UNITS, typename SOURCE_STORAGE>
@@ -169,34 +165,30 @@ struct LLUnit
}
protected:
-
storage_t mValue;
};
template<typename UNIT_TYPE, typename STORAGE_TYPE>
-struct LLUnitStrict : public LLUnit<UNIT_TYPE, STORAGE_TYPE>
+struct LLUnitImplicit : public LLUnit<UNIT_TYPE, STORAGE_TYPE>
{
- typedef LLUnitStrict<UNIT_TYPE, STORAGE_TYPE> self_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;
- explicit LLUnitStrict(storage_t value = storage_t())
- : LLUnit<UNIT_TYPE, STORAGE_TYPE>(value)
+ LLUnitImplicit(storage_t value = storage_t())
+ : base_t(value)
{}
template<typename OTHER_UNIT, typename OTHER_STORAGE>
- LLUnitStrict(LLUnit<OTHER_UNIT, OTHER_STORAGE> other)
- : LLUnit<UNIT_TYPE, STORAGE_TYPE>(convert(other))
+ LLUnitImplicit(LLUnit<OTHER_UNIT, OTHER_STORAGE> other)
+ : base_t(convert(other))
{}
- LLUnitStrict(self_t& other)
- : LLUnit<UNIT_TYPE, STORAGE_TYPE>(other)
- {}
-
-
-private:
+ // unlike LLUnit, LLUnitImplicit is *implicitly* convertable to a POD scalar (F32, S32, etc)
+ // this allows for interoperability with legacy code
operator storage_t() const
{
- return LLUnit<UNIT_TYPE, STORAGE_TYPE>::value();
+ return value();
}
};
@@ -204,7 +196,7 @@ private:
// operator +
//
template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2>
-LLUnit<STORAGE_TYPE1, UNIT_TYPE1> operator + (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second)
+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;
@@ -227,6 +219,30 @@ LLUnit<UNIT_TYPE, STORAGE_TYPE> operator + (SCALAR_TYPE first, LLUnit<UNIT_TYPE,
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)
+{
+ LLUnitImplicit<UNIT_TYPE1, STORAGE_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)
+{
+ LLUnitImplicit<UNIT_TYPE, STORAGE_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)
+{
+ LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> result(first);
+ result += second;
+ return result;
+}
+
//
// operator -
//
@@ -238,7 +254,6 @@ LLUnit<UNIT_TYPE1, STORAGE_TYPE1> operator - (LLUnit<UNIT_TYPE1, STORAGE_TYPE1>
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)
{
@@ -255,6 +270,30 @@ LLUnit<UNIT_TYPE, STORAGE_TYPE> operator - (SCALAR_TYPE first, LLUnit<UNIT_TYPE,
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)
+{
+ LLUnitImplicit<UNIT_TYPE1, STORAGE_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)
+{
+ LLUnitImplicit<UNIT_TYPE, STORAGE_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)
+{
+ LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> result(first);
+ result -= second;
+ return result;
+}
+
//
// operator *
//
@@ -278,6 +317,26 @@ LLUnit<UNIT_TYPE1, STORAGE_TYPE1> operator * (LLUnit<UNIT_TYPE1, STORAGE_TYPE1>,
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(sizeof(STORAGE_TYPE1) == 0, "Multiplication of unit types results in new unit type - not supported.");
+ return LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1>();
+}
+
//
// operator /
//
@@ -300,23 +359,42 @@ STORAGE_TYPE1 operator / (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_T
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 (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second) \
-{ \
- return first.value() op 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)
+{
+ 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(<)
@@ -328,6 +406,15 @@ COMPARISON_OPERATORS(!=)
namespace LLUnits
{
+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> >
{
@@ -361,22 +448,22 @@ 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);
+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);
+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);
+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);