diff options
| -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); +	}  } | 
