From 00bd492b30f0dcb49d354be74e6e9a312a84863f Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Tue, 27 Aug 2013 16:36:36 -0700 Subject: got linear unit conversions (like fahrenheit <-> celsius) working correctly further optimizations for codegen --- indra/llcommon/llunittype.h | 74 +++++++++++++++++++---------------- 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 - LL_FORCE_INLINE bool operator == (LLUnit other) + LL_FORCE_INLINE bool operator == (LLUnit other) const { return mValue == convert(other).value(); } template - LL_FORCE_INLINE bool operator != (LLUnit other) + LL_FORCE_INLINE bool operator != (LLUnit other) const { return mValue != convert(other).value(); } template - LL_FORCE_INLINE bool operator < (LLUnit other) + LL_FORCE_INLINE bool operator < (LLUnit other) const { return mValue < convert(other).value(); } template - LL_FORCE_INLINE bool operator <= (LLUnit other) + LL_FORCE_INLINE bool operator <= (LLUnit other) const { return mValue <= convert(other).value(); } template - LL_FORCE_INLINE bool operator > (LLUnit other) + LL_FORCE_INLINE bool operator > (LLUnit other) const { return mValue > convert(other).value(); } template - LL_FORCE_INLINE bool operator >= (LLUnit other) + LL_FORCE_INLINE bool operator >= (LLUnit other) const { return mValue >= convert(other).value(); } @@ -193,6 +193,15 @@ struct LLUnit return result; } + template + LL_FORCE_INLINE static self_t convert(LLUnit v) + { + self_t result; + STORAGE_TYPE divisor = ll_convert_units(v, result); + result.mValue /= divisor; + return result; + } + template LL_FORCE_INLINE static self_t convert(LLUnit v) { @@ -276,78 +285,78 @@ struct LLUnitImplicit : public LLUnit using base_t::operator ==; template - LL_FORCE_INLINE bool operator == (LLUnitImplicit other) + LL_FORCE_INLINE bool operator == (LLUnitImplicit other) const { return mValue == convert(other).value(); } template - 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 - LL_FORCE_INLINE bool operator != (LLUnitImplicit other) + LL_FORCE_INLINE bool operator != (LLUnitImplicit other) const { return mValue != convert(other).value(); } template - 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 - LL_FORCE_INLINE bool operator < (LLUnitImplicit other) + LL_FORCE_INLINE bool operator < (LLUnitImplicit other) const { return mValue < convert(other).value(); } template - 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 - LL_FORCE_INLINE bool operator <= (LLUnitImplicit other) + LL_FORCE_INLINE bool operator <= (LLUnitImplicit other) const { return mValue <= convert(other).value(); } template - 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 - LL_FORCE_INLINE bool operator > (LLUnitImplicit other) + LL_FORCE_INLINE bool operator > (LLUnitImplicit other) const { return mValue > convert(other).value(); } template - 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 - LL_FORCE_INLINE bool operator >= (LLUnitImplicit other) + LL_FORCE_INLINE bool operator >= (LLUnitImplicit other) const { return mValue >= convert(other).value(); } template - 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 self_t operator + (OTHER_T other) { - mValue /= mDivisor; - mValue += other; + mValue += other * mDivisor; return *this; } template 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 @@ -708,27 +716,27 @@ struct LLUnitInverseLinearOps self_t operator / (OTHER_T other) { mValue *= other; + mMultiplicand *= other; return *this; } template self_t operator + (OTHER_T other) { - mValue /= mDivisor; - mValue -= other; + mValue -= other * mMultiplicand; return *this; } template 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 LL_FORCE_INLINE S2 ll_convert_units(LLUnit in, LLUnit& out) \ { \ typedef typename LLResultTypePromote::type_t result_storage_t; \ - LLUnitInverseLinearOps op = \ + LLUnitInverseLinearOps result = \ LLUnitInverseLinearOps(in.value()) conversion_operation; \ - out = LLUnit((S2)op.mValue); \ - return op.mDivisor; \ + out = LLUnit((S2)result.mValue); \ + return result.mDivisor; \ } \ \ template \ LL_FORCE_INLINE S2 ll_convert_units(LLUnit in, LLUnit& out) \ { \ typedef typename LLResultTypePromote::type_t result_storage_t; \ - LLUnitLinearOps op = \ + LLUnitLinearOps result = \ LLUnitLinearOps(in.value()) conversion_operation; \ - out = LLUnit((S2)op.mValue); \ - return op.mDivisor; \ + out = LLUnit((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); + } } -- cgit v1.2.3