diff options
Diffstat (limited to 'indra')
27 files changed, 1157 insertions, 891 deletions
| diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 62880b07f6..e138a54d29 100755 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -209,7 +209,8 @@ set(llcommon_HEADER_FILES      lltracerecording.h      lltracethreadrecorder.h      lltreeiterators.h -    llunit.h +    llunits.h +    llunittype.h      lluri.h      lluuid.h  	llwin32headers.h diff --git a/indra/llcommon/llcriticaldamp.h b/indra/llcommon/llcriticaldamp.h index a02a2a0dcf..1fb6a1af29 100755 --- a/indra/llcommon/llcriticaldamp.h +++ b/indra/llcommon/llcriticaldamp.h @@ -31,7 +31,7 @@  #include <vector>  #include "llframetimer.h" -#include "llunit.h" +#include "llunits.h"  class LL_COMMON_API LLSmoothInterpolation   { diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h index aecf3b765e..be2cd2d051 100755 --- a/indra/llcommon/lldate.h +++ b/indra/llcommon/lldate.h @@ -33,7 +33,7 @@  #include <string>  #include "stdtypes.h" -#include "llunit.h" +#include "llunits.h"  /**    * @class LLDate diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index a51f8f216a..96dbaa572a 100755 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -926,7 +926,6 @@ namespace  			std::ostringstream message_stream; -            const_cast<LLError::CallSite&>(site).mTagString += " ";  			if (show_location && (r->wantsLocation() || level == LLError::LEVEL_ERROR || s.mPrintLocation))  			{  				message_stream << site.mLocationString << " "; @@ -937,16 +936,16 @@ namespace  				message_stream << s.mTimeFunction() << " ";  			} -			if (show_tags && r->wantsTags()) +			if (show_level && r->wantsLevel())  			{ -				message_stream << site.mTagString << " "; +				message_stream << site.mLevelString << " ";  			} -			if (show_level && r->wantsLevel()) +			if (show_tags && r->wantsTags())  			{ -				message_stream << site.mLevelString << " "; +				message_stream << site.mTagString << " ";  			} -			 +  			if (show_function && r->wantsFunctionName())  			{  				message_stream << site.mFunctionString << " "; @@ -954,8 +953,7 @@ namespace  			message_stream << message; -            std::string final_message = message_stream.str(); -			r->recordMessage(level, final_message); +			r->recordMessage(level, message_stream.str());  		}  	}  } @@ -1159,10 +1157,6 @@ namespace LLError  		Globals& g = Globals::get();  		Settings& s = Settings::get(); -        //const_cast<CallSite&>(site).mTagString += " "; -        std::string tag_string = site.mTagString; -        tag_string += " "; -          		std::string message = out->str();  		if (out == &g.messageStream)  		{ diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index 6cac952b7e..1ddb4874a0 100755 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -356,13 +356,13 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;  #define LL_INFOS_ONCE(...)	lllog(LLError::LEVEL_INFO, true, ##__VA_ARGS__)  #define LL_WARNS_ONCE(...)	lllog(LLError::LEVEL_WARN, true, ##__VA_ARGS__) -  // DEPRECATED: Use the new macros that allow tags and *look* like macros. -//#define lldebugs	LL_DEBUGS() -#define llinfos		LL_INFOS() -//#define llwarns		LL_WARNS() -//#define llerrs		LL_ERRS() -//#define llcont		LL_CONT -#define llendl		LL_ENDL  +#define lldebugs	LL_COMPILE_TIME_MESSAGE("Warning: lldebugs deprecated, use LL_DEBUGS() instead"); LL_DEBUGS() +#define llinfos		LL_COMPILE_TIME_MESSAGE("Warning: llinfos deprecated, use LL_INFOS() instead"); LL_INFOS() +#define llwarns		LL_COMPILE_TIME_MESSAGE("Warning: llwarns deprecated, use LL_WARNS() instead"); LL_WARNS() +#define llerrs		LL_COMPILE_TIME_MESSAGE("Warning: llerrs deprecated, use LL_ERRS() instead"); LL_ERRS() +#define llcont		LL_COMPILE_TIME_MESSAGE("Warning: llcont deprecated, use LL_CONT instead"); LL_CONT +#define llendl		LL_COMPILE_TIME_MESSAGE("Warning: llendl deprecated, use LL_ENDL instead"); LL_ENDL +  #endif // LL_LLERROR_H diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp index ae3234a87a..2235eb1a08 100755 --- a/indra/llcommon/llfasttimer.cpp +++ b/indra/llcommon/llfasttimer.cpp @@ -32,7 +32,7 @@  #include "llsingleton.h"  #include "lltreeiterators.h"  #include "llsdserialize.h" -#include "llunit.h" +#include "llunits.h"  #include "llsd.h"  #include "lltracerecording.h"  #include "lltracethreadrecorder.h" diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index 06334c012a..cb2f853070 100755 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -206,8 +206,8 @@ bool LLMemory::isMemoryPoolLow()  		return true ;  	} -	bool is_low = (S32)(sAvailPhysicalMemInKB < LOW_MEMORY_POOL_THRESHOLD ||  -		sAllocatedPageSizeInKB + LOW_MEMORY_POOL_THRESHOLD > sMaxHeapSizeInKB) ; +	bool is_low = (S32)(sAvailPhysicalMemInKB < LOW_MEMORY_POOL_THRESHOLD  +						|| sAllocatedPageSizeInKB + LOW_MEMORY_POOL_THRESHOLD > sMaxHeapSizeInKB) ;  	//check the virtual address space fragmentation  	if(!is_low) diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index 23be1e5b2d..d3c5e5235d 100755 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -27,7 +27,7 @@  #define LLMEMORY_H  #include "linden_common.h" -#include "llunit.h" +#include "llunits.h"  #if !LL_WINDOWS  #include <stdint.h>  #endif diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h index e5c8482ed1..0fcc872690 100755 --- a/indra/llcommon/llpreprocessor.h +++ b/indra/llcommon/llpreprocessor.h @@ -188,4 +188,15 @@  #elif LL_DARWIN  #define LL_TYPEOF(exp) typeof(exp)  #endif + +#define LL_TO_STRING_HELPER(x) #x +#define LL_TO_STRING(x) LL_TO_STRING_HELPER(x) +#define LL_FILE_LINENO(msg) __FILE__ "(" LL_TO_STRING(__LINE__) ") : " msg +#if LL_WINDOWS +#define LL_COMPILE_TIME_MESSAGE(msg) __pragma(message(LL_FILE_LINENO(msg))) +#else +// no way to get gcc 4.2 to print a user-defined diagnostic message only when a macro is used +#define LL_COMPILE_TIME_MESSAGE(msg) +#endif +  #endif	//	not LL_LINDEN_PREPROCESSOR_H diff --git a/indra/llcommon/llprocessor.h b/indra/llcommon/llprocessor.h index 4956a39700..90e5bc59ee 100755 --- a/indra/llcommon/llprocessor.h +++ b/indra/llcommon/llprocessor.h @@ -27,7 +27,7 @@  #ifndef LLPROCESSOR_H  #define LLPROCESSOR_H -#include "llunit.h" +#include "llunits.h"  class LLProcessorInfoImpl; diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h index 8b3930e2fa..4e58102094 100755 --- a/indra/llcommon/lltimer.h +++ b/indra/llcommon/lltimer.h @@ -37,7 +37,7 @@  #include <string>  #include <list>  // units conversions -#include "llunit.h" +#include "llunits.h"  #ifndef USEC_PER_SEC      const U32	USEC_PER_SEC	= 1000000;  #endif diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h index bf195f72b1..e0f60800e3 100644 --- a/indra/llcommon/lltraceaccumulators.h +++ b/indra/llcommon/lltraceaccumulators.h @@ -31,7 +31,7 @@  #include "stdtypes.h"  #include "llpreprocessor.h" -#include "llunit.h" +#include "llunits.h"  #include "lltimer.h"  #include "llrefcount.h"  #include "llthreadlocalstorage.h" diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h deleted file mode 100644 index de9cee33fd..0000000000 --- a/indra/llcommon/llunit.h +++ /dev/null @@ -1,836 +0,0 @@ -/**  - * @file llunit.h - * @brief Unit conversion classes - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2012, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLUNIT_H -#define LL_LLUNIT_H - -#include "stdtypes.h" -#include "llpreprocessor.h" -#include "llerror.h" - -//lightweight replacement of type traits for simple type equality check -template<typename S, typename T>  -struct LLIsSameType -{ -	static const bool value = false; -}; - -template<typename T> -struct LLIsSameType<T, T> -{ -	static const bool value = true; -}; - -// workaround for decltype() not existing and typeof() not working inline in gcc 4.2 -template<typename S, typename T> -struct LLResultTypeAdd -{ -	typedef LL_TYPEOF(S() + T()) type_t; -}; - -template<typename S, typename T> -struct LLResultTypeSubtract -{ -	typedef LL_TYPEOF(S() - T()) type_t; -}; - -template<typename S, typename T> -struct LLResultTypeMultiply -{ -	typedef LL_TYPEOF(S() * T()) type_t; -}; - -template<typename S, typename T> -struct LLResultTypeDivide -{ -	typedef LL_TYPEOF(S() / T(1)) type_t; -}; - -template<typename S, typename T> -struct LLResultTypePromote -{ -	typedef LL_TYPEOF((true) ? S() : T()) type_t; -}; - -template<typename STORAGE_TYPE, typename UNIT_TYPE> -struct LLUnit -{ -	typedef LLUnit<STORAGE_TYPE, UNIT_TYPE> self_t; -	typedef STORAGE_TYPE storage_t; - -	// value initialization -	explicit LLUnit(storage_t value = storage_t()) -	:	mValue(value) -	{} - -	// unit initialization and conversion -	template<typename OTHER_STORAGE, typename OTHER_UNIT> -	LLUnit(LLUnit<OTHER_STORAGE, OTHER_UNIT> other) -	:	mValue(convert(other).mValue) -	{} -	 -	// unit assignment -	template<typename OTHER_STORAGE, typename OTHER_UNIT> -	self_t& operator = (LLUnit<OTHER_STORAGE, OTHER_UNIT> other) -	{ -		mValue = convert(other).mValue; -		return *this; -	} - -	storage_t value() const -	{ -		return mValue; -	} - -	void value(storage_t value) -	{ -		mValue = value; -	} - -	template<typename NEW_UNIT_TYPE>  -	storage_t valueInUnits() -	{ -		return LLUnit<storage_t, NEW_UNIT_TYPE>(*this).value(); -	} - -	template<typename NEW_UNIT_TYPE>  -	void valueInUnits(storage_t value) -	{ -		*this = LLUnit<storage_t, NEW_UNIT_TYPE>(value); -	} - -	template<typename OTHER_STORAGE, typename OTHER_UNIT> -	void operator += (LLUnit<OTHER_STORAGE, OTHER_UNIT> other) -	{ -		mValue += convert(other).mValue; -	} - -	template<typename OTHER_STORAGE, typename OTHER_UNIT> -	void operator -= (LLUnit<OTHER_STORAGE, OTHER_UNIT> other) -	{ -		mValue -= convert(other).mValue; -	} - -	void operator *= (storage_t multiplicand) -	{ -		mValue *= multiplicand; -	} - -	template<typename OTHER_UNIT, typename OTHER_STORAGE> -	void operator *= (LLUnit<OTHER_STORAGE, OTHER_UNIT> multiplicand) -	{ -		// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template -		LL_BAD_TEMPLATE_INSTANTIATION(OTHER_UNIT, "Multiplication of unit types not supported."); -	} - -	void operator /= (storage_t divisor) -	{ -		mValue /= divisor; -	} - -	template<typename OTHER_UNIT, typename OTHER_STORAGE> -	void operator /= (LLUnit<OTHER_STORAGE, OTHER_UNIT> divisor) -	{ -		// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template -		LL_BAD_TEMPLATE_INSTANTIATION(OTHER_UNIT, "Illegal in-place division of unit types."); -	} - -	template<typename SOURCE_STORAGE, typename SOURCE_UNITS> -	static self_t convert(LLUnit<SOURCE_STORAGE, SOURCE_UNITS> v)  -	{  -		typedef typename LLResultTypePromote<STORAGE_TYPE, SOURCE_STORAGE>::type_t result_storage_t; -		LLUnit<result_storage_t, UNIT_TYPE> result; -		result_storage_t divisor = ll_convert_units(v, result); -		result.value(result.value() / divisor); -		return self_t(result.value()); -	} - -protected: -	storage_t mValue; -}; - -template<typename STORAGE_TYPE, typename UNIT_TYPE> -std::ostream& operator <<(std::ostream& s, const LLUnit<STORAGE_TYPE, UNIT_TYPE>& unit) -{ -        s << unit.value() << UNIT_TYPE::getUnitLabel(); -        return s; -} - -template<typename STORAGE_TYPE, typename UNIT_TYPE> -std::istream& operator >>(std::istream& s, LLUnit<STORAGE_TYPE, UNIT_TYPE>& unit) -{ -        STORAGE_TYPE val; -        s >> val; -        unit.value(val); -        return s; -} - -template<typename STORAGE_TYPE, typename UNIT_TYPE> -struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNIT_TYPE> -{ -	typedef LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> self_t; -	typedef typename LLUnit<STORAGE_TYPE, UNIT_TYPE>::storage_t storage_t; -	typedef LLUnit<STORAGE_TYPE, UNIT_TYPE> base_t; - -	LLUnitImplicit(storage_t value = storage_t()) -	:	base_t(value) -	{} - -	template<typename OTHER_STORAGE, typename OTHER_UNIT> -	LLUnitImplicit(LLUnit<OTHER_STORAGE, OTHER_UNIT> other) -	:	base_t(other) -	{} - -	// unlike LLUnit, LLUnitImplicit is *implicitly* convertable to a POD value (F32, S32, etc) -	// this allows for interoperability with legacy code -	operator storage_t() const -	{ -		return base_t::value(); -	} - -	using base_t::operator +=; -	void operator += (storage_t value) -	{ -        base_t::mValue += value; -	} - -	// this overload exists to explicitly catch use of another implicit unit -	// without ambiguity between conversion to storage_t vs conversion to base_t -	template<typename OTHER_STORAGE, typename OTHER_UNIT> -	void operator += (LLUnitImplicit<OTHER_STORAGE, OTHER_UNIT> other) -	{ -        base_t::mValue += convert(other).value(); -	} - -	using base_t::operator -=; -	void operator -= (storage_t value) -	{ -        base_t::mValue -= value; -	} - -	// this overload exists to explicitly catch use of another implicit unit -	// without ambiguity between conversion to storage_t vs conversion to base_t -	template<typename OTHER_STORAGE, typename OTHER_UNIT> -	void operator -= (LLUnitImplicit<OTHER_STORAGE, OTHER_UNIT> other) -	{ -        base_t::mValue -= convert(other).value(); -	} - -}; - -template<typename STORAGE_TYPE, typename UNIT_TYPE> -std::ostream& operator <<(std::ostream& s, const LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>& unit) -{ -        s << unit.value() << UNIT_TYPE::getUnitLabel(); -        return s; -} - -template<typename STORAGE_TYPE, typename UNIT_TYPE> -std::istream& operator >>(std::istream& s, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>& unit) -{ -        STORAGE_TYPE val; -        s >> val; -        unit = val; -        return s; -} - -template<typename S1, typename T1, typename S2, typename T2> -LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out, ...) -{ -	S2 divisor(1); - -	LL_STATIC_ASSERT((LLIsSameType<T1, T2>::value  -						|| !LLIsSameType<T1, typename T1::base_unit_t>::value  -						|| !LLIsSameType<T2, typename T2::base_unit_t>::value),  -						"conversion requires compatible units"); - -	if (LLIsSameType<T1, T2>::value) -	{ -		// T1 and T2 same type, just assign -		out.value((S2)in.value()); -	} -	else if (LLIsSameType<T2, typename T2::base_unit_t>::value) -	{ -		// reduce T1 -		LLUnit<S2, typename T1::base_unit_t> new_in; -		divisor *= (S2)ll_convert_units(in, new_in); -		divisor *= (S2)ll_convert_units(new_in, out); -	} -	else -	{ -		// reduce T2 -		LLUnit<S2, typename T2::base_unit_t> new_out; -		divisor *= (S2)ll_convert_units(in, new_out); -		divisor *= (S2)ll_convert_units(new_out, out); -	} -	return divisor; -} - -template<typename T> -struct LLStorageType -{ -	typedef T type_t; -}; - -template<typename STORAGE_TYPE, typename UNIT_TYPE> -struct LLStorageType<LLUnit<STORAGE_TYPE, UNIT_TYPE> > -{ -	typedef STORAGE_TYPE type_t; -}; - -// -// operator + -// -template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> -LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second) -{ -	LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first); -	result += second; -	return result; -} - -template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS> -LLUnit<STORAGE_TYPE, UNIT_TYPE> operator + (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS second) -{ -	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types"); -	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0); -} - -template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS> -LLUnit<STORAGE_TYPE, UNIT_TYPE> operator + (UNITLESS first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second) -{ -	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types"); -	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0); -} - -template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> -LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second) -{ -	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first); -	result += second; -	return result; -} - -template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> -LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second) -{ -	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first); -	result += second; -	return result; -} - -template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> -LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second) -{ -	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first); -	result += LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>(second); -	return result; -} - -template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE> -LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator + (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second) -{ -	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> result(first); -	result += second; -	return result; -} - -template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE> -LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>:: -	type_t, UNIT_TYPE> operator + (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second) -{ -	LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> result(first); -	result += second; -	return result; -} - -// -// operator - -// -template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> -LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second) -{ -	LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first); -	result -= second; -	return result; -} - -template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS> -LLUnit<STORAGE_TYPE, UNIT_TYPE> operator - (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS second) -{ -	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types"); -	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0); -} - -template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS> -LLUnit<STORAGE_TYPE, UNIT_TYPE> operator - (UNITLESS first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second) -{ -	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types"); -	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0); -} - -template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> -LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second) -{ -	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first); -	result -= second; -	return result; -} - -template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> -LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second) -{ -	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first); -	result -= second; -	return result; -} - -template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> -LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second) -{ -	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first); -	result -= LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>(second); -	return result; -} - -template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE> -LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator - (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second) -{ -	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> result(first); -	result -= second; -	return result; -} - -template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE> -LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> operator - (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second) -{ -	LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> result(first); -	result -= second; -	return result; -} - -// -// operator * -// -template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> -LLUnit<STORAGE_TYPE1, UNIT_TYPE1> operator * (LLUnit<STORAGE_TYPE1, UNIT_TYPE1>, LLUnit<STORAGE_TYPE2, UNIT_TYPE2>) -{ -	// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template -	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported."); -	return LLUnit<STORAGE_TYPE1, UNIT_TYPE1>(); -} - -template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE> -LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator * (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second) -{ -	return LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE>(first.value() * second); -} - -template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE> -LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> operator * (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second) -{ -	return LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE>(first * second.value()); -} - -template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> -LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> operator * (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2>) -{ -	// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template -	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported."); -	return LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>(); -} - -template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE> -LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator * (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second) -{ -	return LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, UNITLESS_TYPE>::type_t, UNIT_TYPE>(first.value() * second); -} - -template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE> -LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> operator * (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second) -{ -	return LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE>(first * second.value()); -} - - -// -// operator / -// - -template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE> -LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator / (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second) -{ -	return LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE>(first.value() / second); -} - -template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> -typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second) -{ -	return first.value() / first.convert(second).value(); -} - -template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE> -LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator / (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second) -{ -	return LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE>(first.value() / second); -} - -template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> -typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second) -{ -	return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value()); -} - -template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> -typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second) -{ -	return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value()); -} - -template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> -typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second) -{ -	return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value()); -} - -// -// comparison operators -// - -#define LL_UNIT_DECLARE_COMPARISON_OPERATOR(op)                                                                            \ -template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>                         \ -bool operator op (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)       \ -{                                                                                                                          \ -	return first.value() op first.convert(second).value();                                                                 \ -}                                                                                                                          \ -	                                                                                                                       \ -template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>                                                \ -bool operator op (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)                                     \ -{                                                                                                                          \ -	return first.value() op second;                                                                                        \ -}                                                                                                                          \ -                                                                                                                           \ -template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>                                                \ -bool operator op (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)                                     \ -{                                                                                                                          \ -	return first op second.value();                                                                                        \ -}                                                                                                                          \ -                                                                                                                           \ -template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>                         \ -bool operator op (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)                       \ -{                                                                                                                          \ -	return first.value() op first.convert(second).value();                                                                 \ -}                                                                                                                          \ -                                                                                                                           \ -template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>                                                \ -bool operator op (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)                                             \ -{                                                                                                                          \ -	LL_BAD_TEMPLATE_INSTANTIATION(UNITLESS_TYPE, "operator " #op " requires compatible unit types");                       \ -	return false;                                                                                                          \ -}                                                                                                                          \ -                                                                                                                           \ -template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>                                                \ -bool operator op (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)                                             \ -{                                                                                                                          \ -	LL_BAD_TEMPLATE_INSTANTIATION(UNITLESS_TYPE, "operator " #op " requires compatible unit types");                       \ -	return false;                                                                                                          \ -}                                                                                                                          \ -	                                                                                                                       \ -template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>                         \ -bool operator op (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)               \ -{                                                                                                                          \ -	return first.value() op first.convert(second).value();                                                                 \ -}                                                                                                                          \ -                                                                                                                           \ -template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>                         \ -bool operator op (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)               \ -{                                                                                                                          \ -	return first.value() op first.convert(second).value();                                                                 \ -} - -LL_UNIT_DECLARE_COMPARISON_OPERATOR(<); -LL_UNIT_DECLARE_COMPARISON_OPERATOR(<=); -LL_UNIT_DECLARE_COMPARISON_OPERATOR(>); -LL_UNIT_DECLARE_COMPARISON_OPERATOR(>=); -LL_UNIT_DECLARE_COMPARISON_OPERATOR(==); -LL_UNIT_DECLARE_COMPARISON_OPERATOR(!=); - - -template<typename T>  -struct LLGetUnitLabel -{ -	static const char* getUnitLabel() { return ""; } -}; - -template<typename T, typename STORAGE_T> -struct LLGetUnitLabel<LLUnit<STORAGE_T, T> > -{ -	static const char* getUnitLabel() { return T::getUnitLabel(); } -}; - -template<typename T> -struct LLUnitLinearOps -{ -	typedef LLUnitLinearOps<T> self_t; - -	LLUnitLinearOps(T val)  -	:	mValue(val), -		mDivisor(1) -	{} - -	template<typename OTHER_T> -	self_t operator * (OTHER_T other) -	{ -		return mValue * other; -	} - -	template<typename OTHER_T> -	self_t operator / (OTHER_T other) -	{ -		mDivisor *= other; -		return *this; -	} - -	template<typename OTHER_T> -	self_t operator + (OTHER_T other) -	{ -		mValue /= mDivisor; -		mValue += other; -		return *this; -	} - -	template<typename OTHER_T> -	self_t operator - (OTHER_T other) -	{ -		mValue /= mDivisor; -		mValue -= other; -		return *this; -	} - -	T mValue; -	T mDivisor; -}; - -template<typename T> -struct LLUnitInverseLinearOps -{ -	typedef LLUnitInverseLinearOps<T> self_t; - -	LLUnitInverseLinearOps(T val)  -	:	mValue(val), -		mDivisor(1) -	{} - -	template<typename OTHER_T> -	self_t operator * (OTHER_T other) -	{ -		mDivisor *= other; -		return *this; -	} - -	template<typename OTHER_T> -	self_t operator / (OTHER_T other) -	{ -		mValue *= other; -		return *this; -	} - -	template<typename OTHER_T> -	self_t operator + (OTHER_T other) -	{ -		mValue /= mDivisor; -		mValue -= other; -		return *this; -	} - -	template<typename OTHER_T> -	self_t operator - (OTHER_T other) -	{ -		mValue /= mDivisor; -		mValue += other; -		return *this; -	} - -	T mValue; -	T mDivisor; -}; - -#define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label)                                             \ -struct base_unit_name                                                                                \ -{                                                                                                    \ -	typedef base_unit_name base_unit_t;                                                              \ -	static const char* getUnitLabel() { return unit_label; }                                         \ -	template<typename T>                                                                             \ -	static LLUnit<T, base_unit_name> fromValue(T value) { return LLUnit<T, base_unit_name>(value); } \ -	template<typename STORAGE_T, typename UNIT_T>                                                    \ -	static LLUnit<STORAGE_T, base_unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value)              \ -	{ return LLUnit<STORAGE_T, base_unit_name>(value); }                                             \ -} - - -#define LL_DECLARE_DERIVED_UNIT(base_unit_name, conversion_operation, unit_name, unit_label)	 \ -struct unit_name                                                                                 \ -{                                                                                                \ -	typedef base_unit_name base_unit_t;                                                          \ -	static const char* getUnitLabel() { return unit_label; }									 \ -	template<typename T>                                                                         \ -	static LLUnit<T, unit_name> fromValue(T value) { return LLUnit<T, unit_name>(value); }		 \ -	template<typename STORAGE_T, typename UNIT_T>                                                \ -	static LLUnit<STORAGE_T, unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value)				 \ -	{ return LLUnit<STORAGE_T, unit_name>(value); }												 \ -};                                                                                               \ -	                                                                                             \ -template<typename S1, typename S2>                                                               \ -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;                       \ -	LLUnitLinearOps<result_storage_t> op =                                                       \ -		LLUnitLinearOps<result_storage_t>(in.value()) conversion_operation;                      \ -	out = LLUnit<S2, base_unit_name>((S2)op.mValue);	                                         \ -	return op.mDivisor;                                                                          \ -}                                                                                                \ -                                                                                                 \ -template<typename S1, typename S2>                                                               \ -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;                       \ -	LLUnitInverseLinearOps<result_storage_t> op =                                                \ -		LLUnitInverseLinearOps<result_storage_t>(in.value()) conversion_operation;               \ -	out = LLUnit<S2, unit_name>((S2)op.mValue);                                                  \ -	return op.mDivisor;                                                                          \ -}                                                                                                - -#define LL_DECLARE_UNIT_TYPEDEFS(ns, unit_name)                         \ -	typedef LLUnit<F32, ns::unit_name> F32##unit_name;                  \ -	typedef LLUnitImplicit<F32, ns::unit_name> F32##unit_name##Implicit;\ -	typedef LLUnit<F64, ns::unit_name> F64##unit_name;                  \ -	typedef LLUnitImplicit<F64, ns::unit_name> F64##unit_name##Implicit;\ -	typedef LLUnit<S32, ns::unit_name> S32##unit_name;                  \ -	typedef LLUnitImplicit<S32, ns::unit_name> S32##unit_name##Implicit;\ -	typedef LLUnit<S64, ns::unit_name> S64##unit_name;                  \ -	typedef LLUnitImplicit<S64, ns::unit_name> S64##unit_name##Implicit;\ -	typedef LLUnit<U32, ns::unit_name> U32##unit_name;                  \ -	typedef LLUnitImplicit<U32, ns::unit_name> U32##unit_name##Implicit;\ -	typedef LLUnit<U64, ns::unit_name> U64##unit_name;                  \ -	typedef LLUnitImplicit<U64, ns::unit_name> U64##unit_name##Implicit - -// -// Unit declarations -// - -namespace LLUnits -{ -LL_DECLARE_BASE_UNIT(Bytes, "B"); -// technically, these are kibibytes, mibibytes, etc. but we should stick with commonly accepted terminology -LL_DECLARE_DERIVED_UNIT(Bytes, * 1024,			Kilobytes, "KB"); -LL_DECLARE_DERIVED_UNIT(Kilobytes, * 1024,		Megabytes, "MB"); -LL_DECLARE_DERIVED_UNIT(Megabytes, * 1024,		Gigabytes, "GB"); -} - -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Bytes); -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilobytes); -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megabytes); -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigabytes); - -namespace LLUnits -{ -// technically, these are kibibits, mibibits, etc. but we should stick with commonly accepted terminology -LL_DECLARE_DERIVED_UNIT(Bytes, / 8,				Bits, "b"); -LL_DECLARE_DERIVED_UNIT(Bits, * 1024,			Kilobits, "Kb"); -LL_DECLARE_DERIVED_UNIT(Kilobits, * 1024,		Megabits, "Mb");   -LL_DECLARE_DERIVED_UNIT(Megabits, * 1024,		Gigabits, "Gb"); -} - -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Bits); -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilobits); -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megabits); -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigabits); - -namespace LLUnits -{ -LL_DECLARE_BASE_UNIT(Seconds, "s"); -LL_DECLARE_DERIVED_UNIT(Seconds, * 60,			Minutes, "min"); -LL_DECLARE_DERIVED_UNIT(Minutes, * 60,			Hours, "h"); -LL_DECLARE_DERIVED_UNIT(Hours, * 24,			Days, "d"); -LL_DECLARE_DERIVED_UNIT(Seconds, / 1000,		Milliseconds, "ms"); -LL_DECLARE_DERIVED_UNIT(Milliseconds, / 1000,	Microseconds, "\x09\x3cs"); -LL_DECLARE_DERIVED_UNIT(Microseconds, / 1000,	Nanoseconds, "ns"); -} - -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Seconds); -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Minutes); -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Hours); -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Days); -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Milliseconds); -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Microseconds); -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Nanoseconds); - -namespace LLUnits -{ -LL_DECLARE_BASE_UNIT(Meters, "m"); -LL_DECLARE_DERIVED_UNIT(Meters, * 1000,			Kilometers, "km"); -LL_DECLARE_DERIVED_UNIT(Meters, / 100,			Centimeters, "cm"); -LL_DECLARE_DERIVED_UNIT(Meters, / 1000,			Millimeters, "mm"); -} - -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Meters); -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilometers); -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Centimeters); -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Millimeters); - -namespace LLUnits -{ -// rare units -LL_DECLARE_BASE_UNIT(Hertz, "Hz"); -LL_DECLARE_DERIVED_UNIT(Hertz, * 1000,			Kilohertz, "KHz"); -LL_DECLARE_DERIVED_UNIT(Kilohertz, * 1000,		Megahertz, "MHz"); -LL_DECLARE_DERIVED_UNIT(Megahertz, * 1000,		Gigahertz, "GHz"); - -LL_DECLARE_BASE_UNIT(Radians, "rad"); -LL_DECLARE_DERIVED_UNIT(Radians, / 57.29578f,	Degrees, "deg"); - -LL_DECLARE_BASE_UNIT(Percent, "%"); -LL_DECLARE_DERIVED_UNIT(Percent, * 100,			Ratio, "x"); - -LL_DECLARE_BASE_UNIT(Triangles, "tris"); -LL_DECLARE_DERIVED_UNIT(Triangles, * 1000,		Kilotriangles, "ktris"); - -} // namespace LLUnits - -// rare units -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Hertz); -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilohertz); -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megahertz); -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigahertz); -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Radians); -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Degrees); -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Percent); -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Ratio); -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Triangles); -LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilotriangles); - - -#endif // LL_LLUNIT_H diff --git a/indra/llcommon/llunits.h b/indra/llcommon/llunits.h new file mode 100644 index 0000000000..0fcb8281a0 --- /dev/null +++ b/indra/llcommon/llunits.h @@ -0,0 +1,129 @@ +/**  + * @file llunits.h + * @brief Unit definitions + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLUNITTYPE_H +#define LL_LLUNITTYPE_H + +#include "stdtypes.h" +#include "llunittype.h" + +// +// Unit declarations +// + +namespace LLUnits +{ +LL_DECLARE_BASE_UNIT(Bytes, "B"); +// technically, these are kibibytes, mibibytes, etc. but we should stick with commonly accepted terminology +LL_DECLARE_DERIVED_UNIT(Kilobytes, "KB", Bytes, / 1024); +LL_DECLARE_DERIVED_UNIT(Megabytes, "MB", Kilobytes, / 1024); +LL_DECLARE_DERIVED_UNIT(Gigabytes, "GB", Megabytes, / 1024); +} + +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Bytes); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilobytes); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megabytes); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigabytes); + +namespace LLUnits +{ +// technically, these are kibibits, mibibits, etc. but we should stick with commonly accepted terminology +LL_DECLARE_DERIVED_UNIT(Bits,		"b", 	Bytes, * 8	); +LL_DECLARE_DERIVED_UNIT(Kilobits,	"Kb",	Bits, / 1024); +LL_DECLARE_DERIVED_UNIT(Megabits,	"Mb",	Kilobits, / 1024);   +LL_DECLARE_DERIVED_UNIT(Gigabits,	"Gb",	Megabits, / 1024); +} + +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Bits); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilobits); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megabits); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigabits); + +namespace LLUnits +{ +LL_DECLARE_BASE_UNIT(Seconds, "s"); +LL_DECLARE_DERIVED_UNIT(Minutes,		"min",			Seconds, / 60); +LL_DECLARE_DERIVED_UNIT(Hours,			"h",			Minutes, / 60); +LL_DECLARE_DERIVED_UNIT(Days,			"d",			Hours, / 24); +LL_DECLARE_DERIVED_UNIT(Milliseconds,	"ms",			Seconds, * 1000); +LL_DECLARE_DERIVED_UNIT(Microseconds,	"\x09\x3cs",	Milliseconds, * 1000); +LL_DECLARE_DERIVED_UNIT(Nanoseconds,	"ns",			Microseconds, * 1000); +} + +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Seconds); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Minutes); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Hours); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Days); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Milliseconds); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Microseconds); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Nanoseconds); + +namespace LLUnits +{ +LL_DECLARE_BASE_UNIT(Meters, "m"); +LL_DECLARE_DERIVED_UNIT(Kilometers,		"km",	Meters, / 1000); +LL_DECLARE_DERIVED_UNIT(Centimeters,	"cm",	Meters, * 100); +LL_DECLARE_DERIVED_UNIT(Millimeters,	"mm",	Meters, * 1000); +} + +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Meters); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilometers); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Centimeters); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Millimeters); + +namespace LLUnits +{ +// rare units +LL_DECLARE_BASE_UNIT(Hertz, "Hz"); +LL_DECLARE_DERIVED_UNIT(Kilohertz, "KHz", Hertz, / 1000); +LL_DECLARE_DERIVED_UNIT(Megahertz, "MHz", Kilohertz, / 1000); +LL_DECLARE_DERIVED_UNIT(Gigahertz, "GHz", Megahertz, / 1000); + +LL_DECLARE_BASE_UNIT(Radians, "rad"); +LL_DECLARE_DERIVED_UNIT(Degrees, "deg", Radians, * 57.29578f); + +LL_DECLARE_BASE_UNIT(Percent, "%"); +LL_DECLARE_DERIVED_UNIT(Ratio, "x", Percent, / 100); + +LL_DECLARE_BASE_UNIT(Triangles, "tris"); +LL_DECLARE_DERIVED_UNIT(Kilotriangles, "ktris", Triangles, / 1000); + +} // namespace LLUnits + +// rare units +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Hertz); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilohertz); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megahertz); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigahertz); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Radians); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Degrees); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Percent); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Ratio); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Triangles); +LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilotriangles); + + +#endif // LL_LLUNITTYPE_H diff --git a/indra/llcommon/llunittype.h b/indra/llcommon/llunittype.h new file mode 100644 index 0000000000..fb72d6d8a9 --- /dev/null +++ b/indra/llcommon/llunittype.h @@ -0,0 +1,835 @@ +/**  + * @file llunit.h + * @brief Unit conversion classes + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_UNITTYPE_H +#define LL_UNITTYPE_H + +#include "stdtypes.h" +#include "llpreprocessor.h" +#include "llerror.h" + +//lightweight replacement of type traits for simple type equality check +template<typename S, typename T>  +struct LLIsSameType +{ +	static const bool value = false; +}; + +template<typename T> +struct LLIsSameType<T, T> +{ +	static const bool value = true; +}; + +// workaround for decltype() not existing and typeof() not working inline in gcc 4.2 +template<typename S, typename T> +struct LLResultTypeAdd +{ +	typedef LL_TYPEOF(S() + T()) type_t; +}; + +template<typename S, typename T> +struct LLResultTypeSubtract +{ +	typedef LL_TYPEOF(S() - T()) type_t; +}; + +template<typename S, typename T> +struct LLResultTypeMultiply +{ +	typedef LL_TYPEOF(S() * T()) type_t; +}; + +template<typename S, typename T> +struct LLResultTypeDivide +{ +	typedef LL_TYPEOF(S() / T(1)) type_t; +}; + +template<typename S, typename T> +struct LLResultTypePromote +{ +	typedef LL_TYPEOF((true) ? S() : T()) type_t; +}; + +template<typename STORAGE_TYPE, typename UNITS> +struct LLUnit +{ +	typedef LLUnit<STORAGE_TYPE, UNITS> self_t; +	typedef STORAGE_TYPE storage_t; + +	// value initialization +	LL_FORCE_INLINE explicit LLUnit(storage_t value = storage_t()) +	:	mValue(value) +	{} + +	// unit initialization and conversion +	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> +	LL_FORCE_INLINE LLUnit(LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) +	:	mValue(convert(other).mValue) +	{} +	 +	LL_FORCE_INLINE storage_t value() const +	{ +		return mValue; +	} + +	LL_FORCE_INLINE void value(storage_t value) +	{ +		mValue = value; +	} + +	template<typename NEW_UNITS>  +	storage_t valueInUnits() +	{ +		return LLUnit<storage_t, NEW_UNITS>(*this).value(); +	} + +	template<typename NEW_UNITS>  +	void valueInUnits(storage_t value) +	{ +		*this = LLUnit<storage_t, NEW_UNITS>(value); +	} + +	LL_FORCE_INLINE void operator += (self_t other) +	{ +		mValue += convert(other).mValue; +	} + +	LL_FORCE_INLINE void operator -= (self_t other) +	{ +		mValue -= convert(other).mValue; +	} + +	LL_FORCE_INLINE void operator *= (storage_t multiplicand) +	{ +		mValue *= multiplicand; +	} + +	LL_FORCE_INLINE void operator *= (self_t multiplicand) +	{ +		// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template +		LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Multiplication of unit types not supported."); +	} + +	LL_FORCE_INLINE void operator /= (storage_t divisor) +	{ +		mValue /= divisor; +	} + +	void operator /= (self_t divisor) +	{ +		// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template +		LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Illegal in-place division of unit types."); +	} + +	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> +	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) 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) 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) 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) 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) const +	{ +		return mValue >= convert(other).value(); +	} + +	LL_FORCE_INLINE static self_t convert(self_t v)  +	{  +		return v; +	} + +	template<typename FROM_STORAGE_TYPE> +	LL_FORCE_INLINE static self_t convert(LLUnit<FROM_STORAGE_TYPE, UNITS> v)  +	{ +		self_t result; +		result.mValue = (STORAGE_TYPE)v.value(); +		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)  +	{  +		typedef typename LLResultTypePromote<FROM_STORAGE_TYPE, STORAGE_TYPE>::type_t result_storage_t; +		LLUnit<result_storage_t, UNITS> result; +		result_storage_t divisor = ll_convert_units(v, result); +		result.value(result.value() / divisor); +		return self_t(result.value()); +	} + +protected: +	storage_t mValue; +}; + +template<typename STORAGE_TYPE, typename UNITS> +std::ostream& operator <<(std::ostream& s, const LLUnit<STORAGE_TYPE, UNITS>& unit) +{ +        s << unit.value() << UNITS::getUnitLabel(); +        return s; +} + +template<typename STORAGE_TYPE, typename UNITS> +std::istream& operator >>(std::istream& s, LLUnit<STORAGE_TYPE, UNITS>& unit) +{ +        STORAGE_TYPE val; +        s >> val; +        unit.value(val); +        return s; +} + +template<typename STORAGE_TYPE, typename UNITS> +struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNITS> +{ +	typedef LLUnitImplicit<STORAGE_TYPE, UNITS> self_t; +	typedef typename LLUnit<STORAGE_TYPE, UNITS>::storage_t storage_t; +	typedef LLUnit<STORAGE_TYPE, UNITS> base_t; + +	LL_FORCE_INLINE LLUnitImplicit(storage_t value = storage_t()) +	:	base_t(value) +	{} + +	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> +	LL_FORCE_INLINE LLUnitImplicit(LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) +	:	base_t(other) +	{} + +	// unlike LLUnit, LLUnitImplicit is *implicitly* convertable to a POD value (F32, S32, etc) +	// this allows for interoperability with legacy code +	LL_FORCE_INLINE operator storage_t() const +	{ +		return base_t::value(); +	} + +	using base_t::operator +=; +	LL_FORCE_INLINE void operator += (storage_t value) +	{ +        base_t::mValue += value; +	} + +	// this overload exists to explicitly catch use of another implicit unit +	// without ambiguity between conversion to storage_t vs conversion to base_t +	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> +	LL_FORCE_INLINE void operator += (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) +	{ +        base_t::mValue += convert(other).value(); +	} + +	using base_t::operator -=; +	LL_FORCE_INLINE void operator -= (storage_t value) +	{ +        base_t::mValue -= value; +	} + +	// this overload exists to explicitly catch use of another implicit unit +	// without ambiguity between conversion to storage_t vs conversion to base_t +	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> +	LL_FORCE_INLINE void operator -= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) +	{ +        base_t::mValue -= convert(other).value(); +	} + +	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> +	LL_FORCE_INLINE bool operator == (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const +	{ +		return base_t::mValue == convert(other).value(); +	} + +	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> +	LL_FORCE_INLINE bool operator == (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const +	{ +		return base_t::mValue == convert(other).value(); +	} + +	template<typename STORAGE_T> +	LL_FORCE_INLINE bool operator == (STORAGE_T other) const +	{ +		return base_t::mValue == other; +	} + +	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> +	LL_FORCE_INLINE bool operator != (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const +	{ +		return base_t::mValue != convert(other).value(); +	} + +	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> +	LL_FORCE_INLINE bool operator != (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const +	{ +		return base_t::mValue != convert(other).value(); +	} + +	template<typename STORAGE_T> +	LL_FORCE_INLINE bool operator != (STORAGE_T other) const +	{ +		return base_t::mValue != other; +	} +	 +	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> +	LL_FORCE_INLINE bool operator < (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const +	{ +		return base_t::mValue < convert(other).value(); +	} + +	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> +	LL_FORCE_INLINE bool operator < (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const +	{ +		return base_t::mValue < convert(other).value(); +	} + +	template<typename STORAGE_T> +	LL_FORCE_INLINE bool operator < (STORAGE_T other) const +	{ +		return base_t::mValue < other; +	} + +	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> +	LL_FORCE_INLINE bool operator <= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const +	{ +		return base_t::mValue <= convert(other).value(); +	} + +	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> +	LL_FORCE_INLINE bool operator <= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const +	{ +		return base_t::mValue <= convert(other).value(); +	} + +	template<typename STORAGE_T> +	LL_FORCE_INLINE bool operator <= (STORAGE_T other) const +	{ +		return base_t::mValue <= other; +	} + +	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> +	LL_FORCE_INLINE bool operator > (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const +	{ +		return base_t::mValue > convert(other).value(); +	} + +	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> +	LL_FORCE_INLINE bool operator > (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const +	{ +		return base_t::mValue > convert(other).value(); +	} + +	template<typename STORAGE_T> +	LL_FORCE_INLINE bool operator > (STORAGE_T other) const +	{ +		return base_t::mValue > other; +	} + +	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> +	LL_FORCE_INLINE bool operator >= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const +	{ +		return base_t::mValue >= convert(other).value(); +	} + +	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> +	LL_FORCE_INLINE bool operator >= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const +	{ +		return base_t::mValue >= convert(other).value(); +	} + +	template<typename STORAGE_T> +	LL_FORCE_INLINE bool operator >= (STORAGE_T other) const +	{ +		return base_t::mValue >= other; +	} +}; + +template<typename STORAGE_TYPE, typename UNITS> +std::ostream& operator <<(std::ostream& s, const LLUnitImplicit<STORAGE_TYPE, UNITS>& unit) +{ +        s << unit.value() << UNITS::getUnitLabel(); +        return s; +} + +template<typename STORAGE_TYPE, typename UNITS> +std::istream& operator >>(std::istream& s, LLUnitImplicit<STORAGE_TYPE, UNITS>& unit) +{ +        STORAGE_TYPE val; +        s >> val; +        unit = val; +        return s; +} + +template<typename S1, typename T1, typename S2, typename T2> +LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out) +{ +	S2 divisor(1); + +	LL_STATIC_ASSERT((LLIsSameType<T1, T2>::value  +						|| !LLIsSameType<T1, typename T1::base_unit_t>::value  +						|| !LLIsSameType<T2, typename T2::base_unit_t>::value),  +						"conversion requires compatible units"); + +	if (LLIsSameType<T1, T2>::value) +	{ +		// T1 and T2 same type, just assign +		out.value((S2)in.value()); +	} +	else if (T1::sLevel > T2::sLevel) +	{ +		// reduce T1 +		LLUnit<S2, typename T1::base_unit_t> new_in; +		divisor *= (S2)ll_convert_units(in, new_in); +		divisor *= (S2)ll_convert_units(new_in, out); +	} +	else +	{ +		// reduce T2 +		LLUnit<S2, typename T2::base_unit_t> new_out; +		divisor *= (S2)ll_convert_units(in, new_out); +		divisor *= (S2)ll_convert_units(new_out, out); +	} +	return divisor; +} + +template<typename T> +struct LLStorageType +{ +	typedef T type_t; +}; + +template<typename STORAGE_TYPE, typename UNITS> +struct LLStorageType<LLUnit<STORAGE_TYPE, UNITS> > +{ +	typedef STORAGE_TYPE type_t; +}; + +// all of these operators need to perform type promotion on the storage type of the units, so they  +// cannot be expressed as operations on identical types with implicit unit conversion  +// e.g. typeof(S32Bytes(x) + F32Megabytes(y)) <==> F32Bytes + +// +// operator + +// +template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2> +LL_FORCE_INLINE LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second) +{ +	LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first); +	result += second; +	return result; +} + +template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS> +LLUnit<STORAGE_TYPE, UNITS> operator + (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS second) +{ +	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types"); +	return LLUnit<STORAGE_TYPE, UNITS>(0); +} + +template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS> +LLUnit<STORAGE_TYPE, UNITS> operator + (UNITLESS first, LLUnit<STORAGE_TYPE, UNITS> second) +{ +	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types"); +	return LLUnit<STORAGE_TYPE, UNITS>(0); +} + +template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2> +LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second) +{ +	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first); +	result += second; +	return result; +} + +template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2> +LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second) +{ +	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first); +	result += second; +	return result; +} + +template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2> +LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second) +{ +	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first); +	result += LLUnitImplicit<STORAGE_TYPE1, UNITS1>(second); +	return result; +} + +template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE> +LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator + (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second) +{ +	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> result(first); +	result += second; +	return result; +} + +template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE> +LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>:: +	type_t, UNITS> operator + (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNITS> second) +{ +	LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> result(first); +	result += second; +	return result; +} + +// +// operator - +// +template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2> +LL_FORCE_INLINE LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second) +{ +	LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first); +	result -= second; +	return result; +} + +template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS> +LLUnit<STORAGE_TYPE, UNITS> operator - (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS second) +{ +	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types"); +	return LLUnit<STORAGE_TYPE, UNITS>(0); +} + +template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS> +LLUnit<STORAGE_TYPE, UNITS> operator - (UNITLESS first, LLUnit<STORAGE_TYPE, UNITS> second) +{ +	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types"); +	return LLUnit<STORAGE_TYPE, UNITS>(0); +} + +template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2> +LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second) +{ +	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first); +	result -= second; +	return result; +} + +template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2> +LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second) +{ +	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first); +	result -= second; +	return result; +} + +template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2> +LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second) +{ +	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first); +	result -= LLUnitImplicit<STORAGE_TYPE1, UNITS1>(second); +	return result; +} + +template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE> +LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator - (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second) +{ +	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> result(first); +	result -= second; +	return result; +} + +template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE> +LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> operator - (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNITS> second) +{ +	LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> result(first); +	result -= second; +	return result; +} + +// +// operator * +// +template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2> +LLUnit<STORAGE_TYPE1, UNITS1> operator * (LLUnit<STORAGE_TYPE1, UNITS1>, LLUnit<STORAGE_TYPE2, UNITS2>) +{ +	// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template +	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported."); +	return LLUnit<STORAGE_TYPE1, UNITS1>(); +} + +template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE> +LL_FORCE_INLINE LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator * (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second) +{ +	return LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() * second); +} + +template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE> +LL_FORCE_INLINE LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> operator * (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNITS> second) +{ +	return LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS>(first * second.value()); +} + +template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2> +LLUnitImplicit<STORAGE_TYPE1, UNITS1> operator * (LLUnitImplicit<STORAGE_TYPE1, UNITS1>, LLUnitImplicit<STORAGE_TYPE2, UNITS2>) +{ +	// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template +	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported."); +	return LLUnitImplicit<STORAGE_TYPE1, UNITS1>(); +} + +template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE> +LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator * (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second) +{ +	return LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, UNITLESS_TYPE>::type_t, UNITS>(first.value() * second); +} + +template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE> +LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> operator * (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNITS> second) +{ +	return LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS>(first * second.value()); +} + + +// +// operator / +// + +template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE> +LL_FORCE_INLINE LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator / (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second) +{ +	return LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() / second); +} + +template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2> +LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second) +{ +	return first.value() / first.convert(second).value(); +} + +template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE> +LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator / (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second) +{ +	return LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() / second); +} + +template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2> +LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second) +{ +	return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value()); +} + +template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2> +LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second) +{ +	return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value()); +} + +template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2> +LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second) +{ +	return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value()); +} + +template<typename T>  +struct LLGetUnitLabel +{ +	static const char* getUnitLabel() { return ""; } +}; + +template<typename T, typename STORAGE_T> +struct LLGetUnitLabel<LLUnit<STORAGE_T, T> > +{ +	static const char* getUnitLabel() { return T::getUnitLabel(); } +}; + +template<typename T> +struct LLUnitLinearOps +{ +	typedef LLUnitLinearOps<T> self_t; + +	LLUnitLinearOps(T val)  +	:	mValue(val), +		mDivisor(1) +	{} + +	template<typename OTHER_T> +	self_t operator * (OTHER_T other) +	{ +		return mValue * other; +	} + +	template<typename OTHER_T> +	self_t operator / (OTHER_T other) +	{ +		mDivisor *= other; +		return *this; +	} + +	template<typename OTHER_T> +	self_t operator + (OTHER_T other) +	{ +		mValue += other * mDivisor; +		return *this; +	} + +	template<typename OTHER_T> +	self_t operator - (OTHER_T other) +	{ +		mValue -= other * mDivisor; +		return *this; +	} + +	T mValue; +	T mDivisor; +}; + +template<typename T> +struct LLUnitInverseLinearOps +{ +	typedef LLUnitInverseLinearOps<T> self_t; + +	LLUnitInverseLinearOps(T val)  +	:	mValue(val), +		mDivisor(1), +		mMultiplicand(1) +	{} + +	template<typename OTHER_T> +	self_t operator * (OTHER_T other) +	{ +		mDivisor *= other; +		return *this; +	} + +	template<typename OTHER_T> +	self_t operator / (OTHER_T other) +	{ +		mValue *= other; +		mMultiplicand *= other; +		return *this; +	} + +	template<typename OTHER_T> +	self_t operator + (OTHER_T other) +	{ +		mValue -= other * mMultiplicand; +		return *this; +	} + +	template<typename OTHER_T> +	self_t operator - (OTHER_T other) +	{ +		mValue += other * mMultiplicand; +		return *this; +	} + +	T mValue; +	T mDivisor; +	T mMultiplicand; +}; + +#define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label)                                             \ +struct base_unit_name                                                                                \ +{                                                                                                    \ +	static const int sLevel = 0;                                                                     \ +	typedef base_unit_name base_unit_t;                                                              \ +	static const char* getUnitLabel() { return unit_label; }                                         \ +	template<typename T>                                                                             \ +	static LLUnit<T, base_unit_name> fromValue(T value) { return LLUnit<T, base_unit_name>(value); } \ +	template<typename STORAGE_T, typename UNIT_T>                                                    \ +	static LLUnit<STORAGE_T, base_unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value)              \ +	{ return LLUnit<STORAGE_T, base_unit_name>(value); }                                             \ +} + + +#define LL_DECLARE_DERIVED_UNIT(unit_name, unit_label, base_unit_name, conversion_operation)	 \ +struct unit_name                                                                                 \ +{                                                                                                \ +	static const int sLevel = base_unit_name::sLevel + 1;                                        \ +	typedef base_unit_name base_unit_t;                                                          \ +	static const char* getUnitLabel() { return unit_label; }									 \ +	template<typename T>                                                                         \ +	static LLUnit<T, unit_name> fromValue(T value) { return LLUnit<T, unit_name>(value); }		 \ +	template<typename STORAGE_T, typename UNIT_T>                                                \ +	static LLUnit<STORAGE_T, unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value)				 \ +	{ return LLUnit<STORAGE_T, unit_name>(value); }												 \ +};                                                                                               \ +	                                                                                             \ +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> result =                                            \ +		LLUnitInverseLinearOps<result_storage_t>(in.value()) conversion_operation;               \ +	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> result =                                                   \ +		LLUnitLinearOps<result_storage_t>(in.value()) conversion_operation;				         \ +	out = LLUnit<S2, unit_name>((S2)result.mValue);                                              \ +	return result.mDivisor;                                                                      \ +}                                                                                                + +#define LL_DECLARE_UNIT_TYPEDEFS(ns, unit_name)                         \ +	typedef LLUnit<F32, ns::unit_name> F32##unit_name;                  \ +	typedef LLUnitImplicit<F32, ns::unit_name> F32##unit_name##Implicit;\ +	typedef LLUnit<F64, ns::unit_name> F64##unit_name;                  \ +	typedef LLUnitImplicit<F64, ns::unit_name> F64##unit_name##Implicit;\ +	typedef LLUnit<S32, ns::unit_name> S32##unit_name;                  \ +	typedef LLUnitImplicit<S32, ns::unit_name> S32##unit_name##Implicit;\ +	typedef LLUnit<S64, ns::unit_name> S64##unit_name;                  \ +	typedef LLUnitImplicit<S64, ns::unit_name> S64##unit_name##Implicit;\ +	typedef LLUnit<U32, ns::unit_name> U32##unit_name;                  \ +	typedef LLUnitImplicit<U32, ns::unit_name> U32##unit_name##Implicit;\ +	typedef LLUnit<U64, ns::unit_name> U64##unit_name;                  \ +	typedef LLUnitImplicit<U64, ns::unit_name> U64##unit_name##Implicit + +#endif //LL_UNITTYPE_H diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp index 709a095105..e09692c82d 100755 --- a/indra/llcommon/tests/llprocess_test.cpp +++ b/indra/llcommon/tests/llprocess_test.cpp @@ -62,7 +62,8 @@  #define aprchk(expr) aprchk_(#expr, (expr))  static void aprchk_(const char* call, apr_status_t rv, apr_status_t expected=APR_SUCCESS)  { -    tut::ensure_equals(STRINGIZE(call << " => " << rv << ": " << apr_strerror_helper(rv)), +    tut::ensure_equals(STRINGIZE(call << " => " << rv << ": " << apr_strerror_helper +                                 (rv)),                         rv, expected);  } diff --git a/indra/llcommon/tests/lltrace_test.cpp b/indra/llcommon/tests/lltrace_test.cpp index 1c2a4528ae..8ce509699d 100644 --- a/indra/llcommon/tests/lltrace_test.cpp +++ b/indra/llcommon/tests/lltrace_test.cpp @@ -36,12 +36,12 @@ namespace LLUnits  {  	// using powers of 2 to allow strict floating point equality  	LL_DECLARE_BASE_UNIT(Ounces, "oz"); -	LL_DECLARE_DERIVED_UNIT(Ounces, * 12, TallCup, ""); -	LL_DECLARE_DERIVED_UNIT(Ounces, * 16, GrandeCup, ""); -	LL_DECLARE_DERIVED_UNIT(Ounces, * 20, VentiCup, ""); +	LL_DECLARE_DERIVED_UNIT(TallCup, "", Ounces, / 12); +	LL_DECLARE_DERIVED_UNIT(GrandeCup, "", Ounces, / 16); +	LL_DECLARE_DERIVED_UNIT(VentiCup, "", Ounces, / 20);  	LL_DECLARE_BASE_UNIT(Grams, "g"); -	LL_DECLARE_DERIVED_UNIT(Grams, / 1000, Milligrams, "mg"); +	LL_DECLARE_DERIVED_UNIT(Milligrams, "mg", Grams, * 1000);  }  LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Ounces); diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp index 292c6122af..57cf9810af 100644 --- a/indra/llcommon/tests/llunits_test.cpp +++ b/indra/llcommon/tests/llunits_test.cpp @@ -27,21 +27,33 @@  #include "linden_common.h" -#include "llunit.h" +#include "llunits.h"  #include "../test/lltut.h"  namespace LLUnits  {  	// using powers of 2 to allow strict floating point equality  	LL_DECLARE_BASE_UNIT(Quatloos, "Quat"); -	LL_DECLARE_DERIVED_UNIT(Quatloos, * 4, Latinum, "Lat"); -	LL_DECLARE_DERIVED_UNIT(Latinum, / 16, Solari, "Sol"); +	LL_DECLARE_DERIVED_UNIT(Latinum, "Lat", Quatloos, / 4); +	LL_DECLARE_DERIVED_UNIT(Solari, "Sol", Latinum, * 16);  }  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; @@ -256,6 +268,22 @@ namespace tut  		// conversion of implicits  		LLUnitImplicit<F32, Latinum> latinum_implicit(2);  		ensure("implicit units of different types are comparable", latinum_implicit * 2 == quatloos_implicit); + +		quatloos_implicit += F32Quatloos(10); +		ensure("can add-assign explicit units", quatloos_implicit == 26); + +		quatloos_implicit -= F32Quatloos(10); +		ensure("can subtract-assign explicit units", quatloos_implicit == 16); + +		// comparisons +		ensure("can compare greater than implicit unit", quatloos_implicit > F32QuatloosImplicit(0.f)); +		ensure("can compare greater than non-implicit unit", quatloos_implicit > F32Quatloos(0.f)); +		ensure("can compare greater than or equal to implicit unit", quatloos_implicit >= F32QuatloosImplicit(0.f)); +		ensure("can compare greater than or equal to non-implicit unit", quatloos_implicit >= F32Quatloos(0.f)); +		ensure("can compare less than implicit unit", quatloos_implicit < F32QuatloosImplicit(20.f)); +		ensure("can compare less than non-implicit unit", quatloos_implicit < F32Quatloos(20.f)); +		ensure("can compare less than or equal to implicit unit", quatloos_implicit <= F32QuatloosImplicit(20.f)); +		ensure("can compare less than or equal to non-implicit unit", quatloos_implicit <= F32Quatloos(20.f));  	}  	// precision tests @@ -271,6 +299,90 @@ namespace tut  		mega_bytes = (U32Megabytes)5 + (S32Megabytes)-1;  		ensure("can mix unsigned and signed in units addition", mega_bytes == (S32Megabytes)4); +	} + +	// default units +	template<> template<> +	void units_object_t::test<9>() +	{ +		U32Gigabytes GB(1); +		U32Megabytes MB(GB); +		U32Kilobytes KB(GB); +		U32Bytes B(GB); + +		ensure("GB -> MB conversion", MB.value() == 1024); +		ensure("GB -> KB conversion", KB.value() == 1024 * 1024); +		ensure("GB -> B conversion", B.value() == 1024 * 1024 * 1024); + +		KB = U32Kilobytes(1); +		U32Kilobits Kb(KB); +		U32Bits b(KB); +		ensure("KB -> Kb conversion", Kb.value() == 8); +		ensure("KB -> b conversion", b.value() == 8 * 1024); + +		U32Days days(1); +		U32Hours hours(days); +		U32Minutes minutes(days); +		U32Seconds seconds(days); +		U32Milliseconds ms(days); +		 +		ensure("days -> hours conversion", hours.value() == 24); +		ensure("days -> minutes conversion", minutes.value() == 24 * 60); +		ensure("days -> seconds conversion", seconds.value() == 24 * 60 * 60); +		ensure("days -> ms conversion", ms.value() == 24 * 60 * 60 * 1000); + +		U32Kilometers km(1); +		U32Meters m(km); +		U32Centimeters cm(km); +		U32Millimeters mm(km); + +		ensure("km -> m conversion", m.value() == 1000); +		ensure("km -> cm conversion", cm.value() == 1000 * 100); +		ensure("km -> mm conversion", mm.value() == 1000 * 1000); +		 +		U32Gigahertz GHz(1); +		U32Megahertz MHz(GHz); +		U32Kilohertz KHz(GHz); +		U32Hertz	 Hz(GHz); + +		ensure("GHz -> MHz conversion", MHz.value() == 1000); +		ensure("GHz -> KHz conversion", KHz.value() == 1000 * 1000); +		ensure("GHz -> Hz conversion", Hz.value() == 1000 * 1000 * 1000); + +		F32Radians rad(6.2831853071795f); +		S32Degrees deg(rad); +		ensure("radians -> degrees conversion", deg.value() == 360); + +		F32Percent percent(50); +		F32Ratio ratio(percent); +		ensure("percent -> ratio conversion", ratio.value() == 0.5f); + +		U32Kilotriangles ktris(1); +		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);  	}  } diff --git a/indra/llmessage/llpacketack.h b/indra/llmessage/llpacketack.h index f55d5246f6..f0ed923f19 100755 --- a/indra/llmessage/llpacketack.h +++ b/indra/llmessage/llpacketack.h @@ -28,7 +28,7 @@  #define LL_LLPACKETACK_H  #include "llhost.h" -#include "llunit.h" +#include "llunits.h"  class LLReliablePacketParams  { diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 5e027851f3..09ea8a1124 100755 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -34,7 +34,7 @@  #include "llpointer.h"  #include "llrefcount.h"  #include "v2math.h" -#include "llunit.h" +#include "llunits.h"  #include "llrender.h"  class LLTextureAtlas ; diff --git a/indra/llui/llstatbar.cpp b/indra/llui/llstatbar.cpp index 3cd2e53001..725a835f7f 100755 --- a/indra/llui/llstatbar.cpp +++ b/indra/llui/llstatbar.cpp @@ -325,7 +325,7 @@ void LLStatBar::draw()  	{  		const LLTrace::TraceType<LLTrace::CountAccumulator>& count_stat = *mCountFloatp; -		unit_label    = mUnitLabel.empty() ? (std::string(count_stat.getUnitLabel()) + "/s") : mUnitLabel; +		unit_label    = std::string(count_stat.getUnitLabel()) + "/s";  		current       = last_frame_recording.getPerSec(count_stat);  		min           = frame_recording.getPeriodMinPerSec(count_stat, num_frames);  		max           = frame_recording.getPeriodMaxPerSec(count_stat, num_frames); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 015c307afc..b2e3c8b683 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9846,7 +9846,7 @@        <key>Comment</key>        <string>Enabled scene loading monitor if set</string>        <key>Persist</key> -      <integer>1</integer> +      <integer>0</integer>        <key>Type</key>        <string>Boolean</string>        <key>Value</key> diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 6b16a96c11..d642d55b14 100755 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -32,7 +32,7 @@  #include "llsys.h"			// for LLOSInfo  #include "lltimer.h"  #include "llappcorehttp.h" -#include "llunit.h" +#include "llunits.h"  class LLCommandLineParser;  class LLFrameTimer; diff --git a/indra/newview/llfasttimerview.h b/indra/newview/llfasttimerview.h index 8c2c939c5e..8c8eb99b59 100755 --- a/indra/newview/llfasttimerview.h +++ b/indra/newview/llfasttimerview.h @@ -29,7 +29,7 @@  #include "llfloater.h"  #include "llfasttimer.h" -#include "llunit.h" +#include "llunits.h"  #include "lltracerecording.h"  #include <deque> diff --git a/indra/newview/llscenemonitor.cpp b/indra/newview/llscenemonitor.cpp index 7fafabb493..ecffc67993 100644 --- a/indra/newview/llscenemonitor.cpp +++ b/indra/newview/llscenemonitor.cpp @@ -274,17 +274,17 @@ void LLSceneMonitor::capture()  	if(mEnabled != enabled)  	{  		if(mEnabled) -		{ +		{			 +			mEnabled = enabled;  			unfreezeScene();  			reset();  			force_capture = true;  		}  		else  		{ +			mEnabled = enabled;  			freezeScene();  		} - -		mEnabled = enabled;  	}  	if (mEnabled  @@ -565,8 +565,9 @@ void LLSceneMonitor::dumpToFile(std::string file_name)  		for (S32 frame = 1; frame <= frame_count; frame++)  		{ -			samples += scene_load_recording.getPrevRecording(frame_count - frame).getSampleCount(*it); -			row << ", " << scene_load_recording.getPrevRecording(frame_count - frame).getSum(*it); +			Recording& recording = scene_load_recording.getPrevRecording(frame_count - frame); +			samples += recording.getSampleCount(*it); +			row << ", " << recording.getSum(*it);  		}  		row << '\n'; @@ -597,8 +598,17 @@ void LLSceneMonitor::dumpToFile(std::string file_name)  		for (S32 frame = 1; frame <= frame_count; frame++)  		{ -			samples += scene_load_recording.getPrevRecording(frame_count - frame).getSampleCount(*it); -			row << ", " << scene_load_recording.getPrevRecording(frame_count - frame).getMean(*it); +			Recording& recording = scene_load_recording.getPrevRecording(frame_count - frame); +			samples += recording.getSampleCount(*it); +			F64 mean = recording.getMean(*it); +			if (llisnan(mean)) +			{ +				row << ", n/a"; +			} +			else +			{ +				row << ", " << mean; +			}  		}  		row << '\n'; @@ -629,8 +639,17 @@ void LLSceneMonitor::dumpToFile(std::string file_name)  		for (S32 frame = 1; frame <= frame_count; frame++)  		{ -			samples += scene_load_recording.getPrevRecording(frame_count - frame).getSampleCount(*it); -			row << ", " << scene_load_recording.getPrevRecording(frame_count - frame).getMean(*it); +			Recording& recording = scene_load_recording.getPrevRecording(frame_count - frame); +			samples += recording.getSampleCount(*it); +			F64 mean = recording.getMean(*it); +			if (llisnan(mean)) +			{ +				row << ", n/a"; +			} +			else +			{ +				row << ", " << mean; +			}  		}  		row << '\n';  diff --git a/indra/newview/lltextureinfodetails.h b/indra/newview/lltextureinfodetails.h index 7cba87e5a8..a42c335035 100755 --- a/indra/newview/lltextureinfodetails.h +++ b/indra/newview/lltextureinfodetails.h @@ -28,7 +28,7 @@  #define LL_LLTEXTUREINFODETAILS_H  #include "lluuid.h" -#include "llunit.h" +#include "llunits.h"  struct LLTextureInfoDetails  { diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index b4ed2adb07..7de8e1ff12 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -7219,10 +7219,10 @@ void process_script_teleport_request(LLMessageSystem* msg, void**)  	LLFloaterWorldMap* instance = LLFloaterWorldMap::getInstance();  	if(instance)  	{ -		llinfos << "Object named " << object_name  +		LL_INFOS() << "Object named " << object_name   			<< " is offering TP to region "  			<< sim_name << " position " << pos -			<< llendl; +			<< LL_ENDL;  		instance->trackURL(sim_name, (S32)pos.mV[VX], (S32)pos.mV[VY], (S32)pos.mV[VZ]);  		LLFloaterReg::showInstance("world_map", "center"); | 
