summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon')
-rwxr-xr-xindra/llcommon/CMakeLists.txt3
-rwxr-xr-xindra/llcommon/llcriticaldamp.h2
-rwxr-xr-xindra/llcommon/lldate.h2
-rwxr-xr-xindra/llcommon/llerror.cpp18
-rwxr-xr-xindra/llcommon/llerror.h14
-rwxr-xr-xindra/llcommon/llfasttimer.cpp2
-rwxr-xr-xindra/llcommon/llmemory.cpp4
-rwxr-xr-xindra/llcommon/llmemory.h2
-rwxr-xr-xindra/llcommon/llpreprocessor.h11
-rwxr-xr-xindra/llcommon/llprocessor.h2
-rwxr-xr-xindra/llcommon/lltimer.h2
-rw-r--r--indra/llcommon/lltraceaccumulators.h2
-rw-r--r--indra/llcommon/llunit.h836
-rw-r--r--indra/llcommon/llunits.h129
-rw-r--r--indra/llcommon/llunittype.h835
-rwxr-xr-xindra/llcommon/tests/llprocess_test.cpp3
-rw-r--r--indra/llcommon/tests/lltrace_test.cpp8
-rw-r--r--indra/llcommon/tests/llunits_test.cpp118
18 files changed, 1120 insertions, 873 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);
}
}