diff options
author | Richard Linden <none@none> | 2013-08-27 16:36:36 -0700 |
---|---|---|
committer | Richard Linden <none@none> | 2013-08-27 16:36:36 -0700 |
commit | 00bd492b30f0dcb49d354be74e6e9a312a84863f (patch) | |
tree | 4d0e24dc57090948d7c03d5550a9cf54a00f0bbb | |
parent | 014969690bed06d77cc2e08efbd2dc9b71fb0cd2 (diff) |
got linear unit conversions (like fahrenheit <-> celsius) working correctly
further optimizations for codegen
-rw-r--r-- | indra/llcommon/llunittype.h | 74 | ||||
-rw-r--r-- | indra/llcommon/tests/llunits_test.cpp | 40 |
2 files changed, 79 insertions, 35 deletions
diff --git a/indra/llcommon/llunittype.h b/indra/llcommon/llunittype.h index a5e99070b6..50037ccade 100644 --- a/indra/llcommon/llunittype.h +++ b/indra/llcommon/llunittype.h @@ -147,35 +147,35 @@ struct LLUnit } template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> - LL_FORCE_INLINE bool operator == (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) + LL_FORCE_INLINE bool operator == (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const { return mValue == convert(other).value(); } template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> - LL_FORCE_INLINE bool operator != (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) + LL_FORCE_INLINE bool operator != (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const { return mValue != convert(other).value(); } template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> - LL_FORCE_INLINE bool operator < (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) + LL_FORCE_INLINE bool operator < (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const { return mValue < convert(other).value(); } template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> - LL_FORCE_INLINE bool operator <= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) + LL_FORCE_INLINE bool operator <= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const { return mValue <= convert(other).value(); } template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> - LL_FORCE_INLINE bool operator > (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) + LL_FORCE_INLINE bool operator > (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const { return mValue > convert(other).value(); } template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> - LL_FORCE_INLINE bool operator >= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) + LL_FORCE_INLINE bool operator >= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const { return mValue >= convert(other).value(); } @@ -193,6 +193,15 @@ struct LLUnit return result; } + template<typename FROM_UNITS> + LL_FORCE_INLINE static self_t convert(LLUnit<STORAGE_TYPE, FROM_UNITS> v) + { + self_t result; + STORAGE_TYPE divisor = ll_convert_units(v, result); + result.mValue /= divisor; + return result; + } + template<typename FROM_STORAGE_TYPE, typename FROM_UNITS> LL_FORCE_INLINE static self_t convert(LLUnit<FROM_STORAGE_TYPE, FROM_UNITS> v) { @@ -276,78 +285,78 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNITS> using base_t::operator ==; template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> - LL_FORCE_INLINE bool operator == (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) + LL_FORCE_INLINE bool operator == (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const { return mValue == convert(other).value(); } template<typename STORAGE_T> - LL_FORCE_INLINE bool operator == (STORAGE_T other) + LL_FORCE_INLINE bool operator == (STORAGE_T other) const { return mValue == other; } using base_t::operator !=; template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> - LL_FORCE_INLINE bool operator != (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) + LL_FORCE_INLINE bool operator != (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const { return mValue != convert(other).value(); } template<typename STORAGE_T> - LL_FORCE_INLINE bool operator != (STORAGE_T other) + LL_FORCE_INLINE bool operator != (STORAGE_T other) const { return mValue != other; } using base_t::operator <; template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> - LL_FORCE_INLINE bool operator < (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) + LL_FORCE_INLINE bool operator < (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const { return mValue < convert(other).value(); } template<typename STORAGE_T> - LL_FORCE_INLINE bool operator < (STORAGE_T other) + LL_FORCE_INLINE bool operator < (STORAGE_T other) const { return mValue < other; } using base_t::operator <=; template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> - LL_FORCE_INLINE bool operator <= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) + LL_FORCE_INLINE bool operator <= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const { return mValue <= convert(other).value(); } template<typename STORAGE_T> - LL_FORCE_INLINE bool operator <= (STORAGE_T other) + LL_FORCE_INLINE bool operator <= (STORAGE_T other) const { return mValue <= other; } using base_t::operator >; template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> - LL_FORCE_INLINE bool operator > (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) + LL_FORCE_INLINE bool operator > (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const { return mValue > convert(other).value(); } template<typename STORAGE_T> - LL_FORCE_INLINE bool operator > (STORAGE_T other) + LL_FORCE_INLINE bool operator > (STORAGE_T other) const { return mValue > other; } using base_t::operator >=; template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> - LL_FORCE_INLINE bool operator >= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) + LL_FORCE_INLINE bool operator >= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const { return mValue >= convert(other).value(); } template<typename STORAGE_T> - LL_FORCE_INLINE bool operator >= (STORAGE_T other) + LL_FORCE_INLINE bool operator >= (STORAGE_T other) const { return mValue >= other; } @@ -670,16 +679,14 @@ struct LLUnitLinearOps template<typename OTHER_T> self_t operator + (OTHER_T other) { - mValue /= mDivisor; - mValue += other; + mValue += other * mDivisor; return *this; } template<typename OTHER_T> self_t operator - (OTHER_T other) { - mValue /= mDivisor; - mValue -= other; + mValue -= other * mDivisor; return *this; } @@ -694,7 +701,8 @@ struct LLUnitInverseLinearOps LLUnitInverseLinearOps(T val) : mValue(val), - mDivisor(1) + mDivisor(1), + mMultiplicand(1) {} template<typename OTHER_T> @@ -708,27 +716,27 @@ struct LLUnitInverseLinearOps self_t operator / (OTHER_T other) { mValue *= other; + mMultiplicand *= other; return *this; } template<typename OTHER_T> self_t operator + (OTHER_T other) { - mValue /= mDivisor; - mValue -= other; + mValue -= other * mMultiplicand; return *this; } template<typename OTHER_T> self_t operator - (OTHER_T other) { - mValue /= mDivisor; - mValue += other; + mValue += other * mMultiplicand; return *this; } T mValue; T mDivisor; + T mMultiplicand; }; #define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label) \ @@ -762,20 +770,20 @@ template<typename S1, typename S2> LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out) \ { \ typedef typename LLResultTypePromote<S1, S2>::type_t result_storage_t; \ - LLUnitInverseLinearOps<result_storage_t> op = \ + LLUnitInverseLinearOps<result_storage_t> result = \ LLUnitInverseLinearOps<result_storage_t>(in.value()) conversion_operation; \ - out = LLUnit<S2, base_unit_name>((S2)op.mValue); \ - return op.mDivisor; \ + out = LLUnit<S2, base_unit_name>((S2)result.mValue); \ + return result.mDivisor; \ } \ \ template<typename S1, typename S2> \ LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out) \ { \ typedef typename LLResultTypePromote<S1, S2>::type_t result_storage_t; \ - LLUnitLinearOps<result_storage_t> op = \ + LLUnitLinearOps<result_storage_t> result = \ LLUnitLinearOps<result_storage_t>(in.value()) conversion_operation; \ - out = LLUnit<S2, unit_name>((S2)op.mValue); \ - return op.mDivisor; \ + out = LLUnit<S2, unit_name>((S2)result.mValue); \ + return result.mDivisor; \ } #define LL_DECLARE_UNIT_TYPEDEFS(ns, unit_name) \ diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp index 5a18603e4e..59876ce3b4 100644 --- a/indra/llcommon/tests/llunits_test.cpp +++ b/indra/llcommon/tests/llunits_test.cpp @@ -42,6 +42,18 @@ LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Quatloos); LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Latinum); LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Solari); +namespace LLUnits +{ + LL_DECLARE_BASE_UNIT(Celcius, "c"); + LL_DECLARE_DERIVED_UNIT(Fahrenheit, "f", Celcius, * 9 / 5 + 32); + LL_DECLARE_DERIVED_UNIT(Kelvin, "k", Celcius, + 273.15f); +} + +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Celcius); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Fahrenheit); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kelvin); + + namespace tut { using namespace LLUnits; @@ -328,8 +340,8 @@ namespace tut ensure("GHz -> Hz conversion", Hz.value() == 1000 * 1000 * 1000); F32Radians rad(6.2831853071795f); - F32Degrees deg(rad); - ensure("radians -> degrees conversion", deg.value() > 359 && deg.value() < 361); + S32Degrees deg(rad); + ensure("radians -> degrees conversion", deg.value() == 360); F32Percent percent(50); F32Ratio ratio(percent); @@ -339,4 +351,28 @@ namespace tut U32Triangles tris(ktris); ensure("kilotriangles -> triangles conversion", tris.value() == 1000); } + + bool value_near(F32 value, F32 target, F32 threshold) + { + return fabsf(value - target) < threshold; + } + + // linear transforms + template<> template<> + void units_object_t::test<10>() + { + F32Celcius float_celcius(100); + F32Fahrenheit float_fahrenheit(float_celcius); + ensure("floating point celcius -> fahrenheit conversion using linear transform", value_near(float_fahrenheit.value(), 212, 0.1f) ); + + float_celcius = float_fahrenheit; + ensure("floating point fahrenheit -> celcius conversion using linear transform (round trip)", value_near(float_celcius.value(), 100.f, 0.1f) ); + + S32Celcius int_celcius(100); + S32Fahrenheit int_fahrenheit(int_celcius); + ensure("integer celcius -> fahrenheit conversion using linear transform", int_fahrenheit.value() == 212); + + int_celcius = int_fahrenheit; + ensure("integer fahrenheit -> celcius conversion using linear transform (round trip)", int_celcius.value() == 100); + } } |