From 0bb0bd514b235948c1a21c81ab0e8ab6223b1990 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Thu, 8 Nov 2012 23:42:18 -0800 Subject: SH-3499 WIP Ensure asset stats output is correct Finished making LLUnit implicitly convertible to/from scalar integer values cleaned up test code --- indra/llcommon/lldate.cpp | 4 +- indra/llcommon/lldate.h | 4 +- indra/llcommon/lldefs.h | 3 + indra/llcommon/llerrorlegacy.h | 7 + indra/llcommon/lltimer.cpp | 15 +- indra/llcommon/lltimer.h | 16 +- indra/llcommon/lltrace.h | 54 +++-- indra/llcommon/lltracerecording.h | 2 +- indra/llcommon/llunit.h | 404 +++++++++++++++++--------------------- 9 files changed, 239 insertions(+), 270 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp index d8b3dfe6c6..5569b4102d 100644 --- a/indra/llcommon/lldate.cpp +++ b/indra/llcommon/lldate.cpp @@ -54,8 +54,8 @@ LLDate::LLDate(const LLDate& date) : mSecondsSinceEpoch(date.mSecondsSinceEpoch) {} -LLDate::LLDate(LLUnit::Seconds seconds_since_epoch) : - mSecondsSinceEpoch(seconds_since_epoch) +LLDate::LLDate(LLUnit seconds_since_epoch) : + mSecondsSinceEpoch(seconds_since_epoch.value()) {} LLDate::LLDate(const std::string& iso8601_date) diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h index 0500b1dcd8..b62a846147 100644 --- a/indra/llcommon/lldate.h +++ b/indra/llcommon/lldate.h @@ -57,9 +57,9 @@ public: /** * @brief Construct a date from a seconds since epoch value. * - * @pararm seconds_since_epoch The number of seconds since UTC epoch. + * @param seconds_since_epoch The number of seconds since UTC epoch. */ - LLDate(LLUnit::Seconds seconds_since_epoch); + LLDate(LLUnit seconds_since_epoch); /** * @brief Construct a date from a string representation diff --git a/indra/llcommon/lldefs.h b/indra/llcommon/lldefs.h index 5a4b8325f4..d57b9dccff 100644 --- a/indra/llcommon/lldefs.h +++ b/indra/llcommon/lldefs.h @@ -244,5 +244,8 @@ inline void llswap(LLDATATYPE& lhs, LLDATATYPE& rhs) rhs = tmp; } +#define LL_GLUE_IMPL(x, y) x##y +#define LL_GLUE_TOKENS(x, y) LL_GLUE_IMPL(x, y) + #endif // LL_LLDEFS_H diff --git a/indra/llcommon/llerrorlegacy.h b/indra/llcommon/llerrorlegacy.h index 37cee579cd..58cc2899af 100644 --- a/indra/llcommon/llerrorlegacy.h +++ b/indra/llcommon/llerrorlegacy.h @@ -29,6 +29,7 @@ #define LL_LLERRORLEGACY_H #include "llpreprocessor.h" +#include /* LEGACY -- DO NOT USE THIS STUFF ANYMORE @@ -111,6 +112,12 @@ const int LL_ERR_PRICE_MISMATCH = -23018; #define llverify(func) do {if (func) {}} while(0) #endif +#ifdef LL_WINDOWS +#define llstatic_assert(func, msg) static_assert(func, msg) +#else +#define llstatic_assert(func, msg) BOOST_STATIC_ASSERT(func) +#endif + // handy compile-time assert - enforce those template parameters! #define cassert(expn) typedef char __C_ASSERT__[(expn)?1:-1] /* Flawfinder: ignore */ //XXX: used in two places in llcommon/llskipmap.h diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index 05f6b789e4..23cebf4336 100644 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -287,15 +287,14 @@ LLTimer::~LLTimer() } // static -LLUnit::Microseconds LLTimer::getTotalTime() +LLUnit LLTimer::getTotalTime() { - LLUnit::Seconds sec = LLUnit::Milliseconds(2000) + LLUnit::Hours(1.f / 360.f); // simply call into the implementation function. return totalTime(); } // static -LLUnit::Seconds LLTimer::getTotalSeconds() +LLUnit LLTimer::getTotalSeconds() { return U64_to_F64(getTotalTime()) * USEC_TO_SEC_F64; } @@ -344,23 +343,23 @@ U64 getElapsedTimeAndUpdate(U64& lastClockCount) } -LLUnit::Seconds LLTimer::getElapsedTimeF64() const +LLUnit LLTimer::getElapsedTimeF64() const { U64 last = mLastClockCount; return (F64)getElapsedTimeAndUpdate(last) * gClockFrequencyInv; } -LLUnit::Seconds LLTimer::getElapsedTimeF32() const +LLUnit LLTimer::getElapsedTimeF32() const { return (F32)getElapsedTimeF64(); } -LLUnit::Seconds LLTimer::getElapsedTimeAndResetF64() +LLUnit LLTimer::getElapsedTimeAndResetF64() { return (F64)getElapsedTimeAndUpdate(mLastClockCount) * gClockFrequencyInv; } -LLUnit::Seconds LLTimer::getElapsedTimeAndResetF32() +LLUnit LLTimer::getElapsedTimeAndResetF32() { return (F32)getElapsedTimeAndResetF64(); } @@ -373,7 +372,7 @@ void LLTimer::setTimerExpirySec(F32 expiration) + (U64)((F32)(expiration * gClockFrequency)); } -LLUnit::Seconds LLTimer::getRemainingTimeF32() const +LLUnit LLTimer::getRemainingTimeF32() const { U64 cur_ticks = get_clock_count(); if (cur_ticks > mExpirationTicks) diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h index e0a880a346..5cb2b18111 100644 --- a/indra/llcommon/lltimer.h +++ b/indra/llcommon/lltimer.h @@ -67,16 +67,16 @@ public: // Return a high precision number of seconds since the start of // this application instance. - static LLUnit::Seconds getElapsedSeconds() + static LLUnit getElapsedSeconds() { return sTimer->getElapsedTimeF64(); } // Return a high precision usec since epoch - static LLUnit::Microseconds getTotalTime(); + static LLUnit getTotalTime(); // Return a high precision seconds since epoch - static LLUnit::Seconds getTotalSeconds(); + static LLUnit getTotalSeconds(); // MANIPULATORS @@ -87,16 +87,16 @@ public: void setTimerExpirySec(F32 expiration); BOOL checkExpirationAndReset(F32 expiration); BOOL hasExpired() const; - LLUnit::Seconds getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset - LLUnit::Seconds getElapsedTimeAndResetF64(); + LLUnit getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset + LLUnit getElapsedTimeAndResetF64(); - LLUnit::Seconds getRemainingTimeF32() const; + LLUnit getRemainingTimeF32() const; static BOOL knownBadTimer(); // ACCESSORS - LLUnit::Seconds getElapsedTimeF32() const; // Returns elapsed time in seconds - LLUnit::Seconds getElapsedTimeF64() const; // Returns elapsed time in seconds + LLUnit getElapsedTimeF32() const; // Returns elapsed time in seconds + LLUnit getElapsedTimeF64() const; // Returns elapsed time in seconds bool getStarted() const { return mStarted; } diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h index e2530a8a24..d289ea9a88 100644 --- a/indra/llcommon/lltrace.h +++ b/indra/llcommon/lltrace.h @@ -38,37 +38,35 @@ #include -#define LL_TOKEN_PASTE_ACTUAL(x, y) x##y -#define LL_TOKEN_PASTE(x, y) LL_TOKEN_PASTE_ACTUAL(x, y) -#define LL_RECORD_BLOCK_TIME(block_timer) LLTrace::BlockTimer::Recorder LL_TOKEN_PASTE(block_time_recorder, __COUNTER__)(block_timer); +#define LL_RECORD_BLOCK_TIME(block_timer) LLTrace::BlockTimer::Recorder LL_GLUE_TOKENS(block_time_recorder, __COUNTER__)(block_timer); namespace LLTrace { class Recording; - typedef LLUnit::Bytes Bytes; - typedef LLUnit::Kilobytes Kilobytes; - typedef LLUnit::Megabytes Megabytes; - typedef LLUnit::Gigabytes Gigabytes; - typedef LLUnit::Bits Bits; - typedef LLUnit::Kilobits Kilobits; - typedef LLUnit::Megabits Megabits; - typedef LLUnit::Gigabits Gigabits; - - typedef LLUnit::Seconds Seconds; - typedef LLUnit::Milliseconds Milliseconds; - typedef LLUnit::Minutes Minutes; - typedef LLUnit::Hours Hours; - typedef LLUnit::Days Days; - typedef LLUnit::Weeks Weeks; - typedef LLUnit::Milliseconds Milliseconds; - typedef LLUnit::Microseconds Microseconds; - typedef LLUnit::Nanoseconds Nanoseconds; - - typedef LLUnit::Meters Meters; - typedef LLUnit::Kilometers Kilometers; - typedef LLUnit::Centimeters Centimeters; - typedef LLUnit::Millimeters Millimeters; + typedef LLUnit Bytes; + typedef LLUnit Kilobytes; + typedef LLUnit Megabytes; + typedef LLUnit Gigabytes; + typedef LLUnit Bits; + typedef LLUnit Kilobits; + typedef LLUnit Megabits; + typedef LLUnit Gigabits; + + typedef LLUnit Seconds; + typedef LLUnit Milliseconds; + typedef LLUnit Minutes; + typedef LLUnit Hours; + typedef LLUnit Days; + typedef LLUnit Weeks; + typedef LLUnit Milliseconds; + typedef LLUnit Microseconds; + typedef LLUnit Nanoseconds; + + typedef LLUnit Meters; + typedef LLUnit Kilometers; + typedef LLUnit Centimeters; + typedef LLUnit Millimeters; void init(); void cleanup(); @@ -438,7 +436,7 @@ namespace LLTrace void sample(UNIT_T value) { T converted_value; - converted_value.assignFrom(value); + converted_value = value; getPrimaryAccumulator().sample((storage_t)converted_value.value()); } }; @@ -478,7 +476,7 @@ namespace LLTrace void add(UNIT_T value) { T converted_value; - converted_value.assignFrom(value); + converted_value = value; getPrimaryAccumulator().add((storage_t)converted_value.value()); } }; diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h index fc96631ce0..ca9950b78d 100644 --- a/indra/llcommon/lltracerecording.h +++ b/indra/llcommon/lltracerecording.h @@ -197,7 +197,7 @@ namespace LLTrace U32 getSampleCount(const TraceType >& stat) const; U32 getSampleCount(const TraceType >& stat) const; - LLUnit::Seconds getDuration() const { return mElapsedSeconds; } + LLUnit getDuration() const { return mElapsedSeconds; } private: friend class ThreadRecorder; diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h index 4519905707..0dcafbe26e 100644 --- a/indra/llcommon/llunit.h +++ b/indra/llcommon/llunit.h @@ -30,326 +30,288 @@ #include "stdtypes.h" #include "llpreprocessor.h" -template -struct LLUnitType : public BASE_UNIT +namespace LLUnits { - typedef DERIVED_UNIT unit_t; - - typedef typename STORAGE_TYPE storage_t; - typedef void is_unit_tag_t; - - LLUnitType() - {} - - LLUnitType(storage_t value) - : BASE_UNIT(convertToBase(value)) - {} - - // implicit downcast - operator unit_t& () - { - return static_cast(*this); - } - - operator storage_t () const - { - return value(); - } - - storage_t value() const - { - return convertToDerived(mBaseValue); - } - - template - storage_t as() const - { - return CONVERTED_TYPE(*this).value(); - } - -protected: - static storage_t convertToBase(storage_t derived_value) - { - return (storage_t)((F32)derived_value * unit_t::conversionToBaseFactor()); - } - - static storage_t convertToDerived(storage_t base_value) +template +struct ConversionFactor +{ + static F64 get() { - return (storage_t)((F32)base_value / unit_t::conversionToBaseFactor()); + llstatic_assert(sizeof(DERIVED_UNITS_TAG) == 0, "Cannot convert between types."); } +}; +template +struct ConversionFactor +{ + static F64 get() { return 1.0; } }; +} -template -struct LLUnitType +template +struct LLUnit { - typedef T unit_t; - typedef STORAGE_TYPE storage_t; + typedef LLUnit self_t; + typedef typename STORAGE_TYPE storage_t; typedef void is_unit_tag_t; - LLUnitType() - : mBaseValue() + LLUnit(storage_t value = storage_t()) + : mValue(value) {} - LLUnitType(storage_t value) - : mBaseValue(value) + template + LLUnit(LLUnit other) + : mValue(convert(other)) {} - unit_t& operator=(storage_t value) + LLUnit(self_t& other) + : mValue(other.mValue) + {} + + self_t& operator = (storage_t value) { - setBaseValue(value); + mValue = value; return *this; } - //implicit downcast - operator unit_t& () + template + self_t& operator = (LLUnit other) { - return static_cast(*this); + mValue = convert(other); + return *this; } - operator storage_t () const + operator storage_t() const { return value(); } - storage_t value() const { return mBaseValue; } - - template - storage_t as() const + storage_t value() const { - return CONVERTED_TYPE(*this).value(); + return mValue; } - static storage_t convertToBase(storage_t derived_value) + void operator += (storage_t value) { - return (storage_t)derived_value; + mValue += value; } - static storage_t convertToDerived(storage_t base_value) + template + void operator += (LLUnit other) { - return (storage_t)base_value; + mValue += convert(other); } - void operator += (const unit_t other) + void operator -= (storage_t value) { - mBaseValue += other.mBaseValue; + mValue -= value; } - void operator -= (const unit_t other) + template + void operator -= (LLUnit other) { - mBaseValue -= other.mBaseValue; + mValue -= convert(other); } void operator *= (storage_t multiplicand) { - mBaseValue *= multiplicand; + mValue *= multiplicand; + } + + template + void operator *= (LLUnit multiplicand) + { + llstatic_assert(sizeof(OTHER_UNIT) == false, "Multiplication of unit types not supported."); } void operator /= (storage_t divisor) { - mBaseValue /= divisor; + mValue /= divisor; } -protected: - void setBaseValue(storage_t value) + template + void operator /= (LLUnit divisor) { - mBaseValue = value; + llstatic_assert(sizeof(OTHER_UNIT) == false, "Division of unit types not supported."); } - storage_t mBaseValue; -}; + template + static storage_t convert(LLUnit v) + { + return (storage_t)(v.value() + * LLUnits::ConversionFactor::get() + * LLUnits::ConversionFactor::get()); + } -template -struct LLUnitTypeWrapper -: public LLUnitType -{ - typedef LLUnitType unit_t; - LLUnitTypeWrapper(const unit_t& other) - : unit_t(other) - {} -}; +protected: + storage_t mValue; +}; // // operator + // -template -DERIVED_UNIT operator + (typename LLUnitType::storage_t first, LLUnitType second) +template +LLUnit operator + (LLUnit first, LLUnit second) { - return DERIVED_UNIT(first + LLUnitType(second).value()); + LLUnit result(first); + result += second; + return result; } +template +LLUnit operator + (LLUnit first, SCALAR_TYPE second) +{ + LLUnit result(first); + result += second; + return result; +} -// -// operator - -// -template -DERIVED_UNIT operator - (typename LLUnitType::storage_t first, LLUnitType second) +template +LLUnit operator + (SCALAR_TYPE first, LLUnit second) { - return DERIVED_UNIT(first - LLUnitType(second).value()); + LLUnit result(first); + result += second; + return result; } // -// operator * +// operator - // -template -DERIVED_UNIT operator * (STORAGE_TYPE first, LLUnitType second) +template +LLUnit operator - (LLUnit first, LLUnit second) { - return DERIVED_UNIT(first * second.value()); + LLUnit result(first); + result -= second; + return result; } -template -DERIVED_UNIT operator * (LLUnitType first, STORAGE_TYPE second) + +template +LLUnit operator - (LLUnit first, SCALAR_TYPE second) { - return DERIVED_UNIT(first.value() * second); + LLUnit result(first); + result -= second; + return result; } +template +LLUnit operator - (SCALAR_TYPE first, LLUnit second) +{ + LLUnit result(first); + result -= second; + return result; +} // -// operator / +// operator * // -template -DERIVED_UNIT operator / (STORAGE_TYPE first, LLUnitTypeWrapper second) +template +LLUnit operator * (SCALAR_TYPE first, LLUnit second) { - return DERIVED_UNIT(first / second.value()); + return LLUnit(first * second.value()); } -template -DERIVED_UNIT operator / (LLUnitTypeWrapper first, STORAGE_TYPE second) +template +LLUnit operator * (LLUnit first, SCALAR_TYPE second) { - return DERIVED_UNIT(first.value() / second); + return LLUnit(first.value() * second); } -// -// operator < -// -template - -bool operator < (typename LLUnitType::storage_t first, LLUnitType second) +template +void operator * (LLUnit, LLUnit) { - return first < second.value(); + llstatic_assert(sizeof(STORAGE_TYPE1) == false, "Multiplication of unit types results in new unit type - not supported."); } // -// operator <= +// operator / // -template -bool operator <= (typename LLUnitType::storage_t first, LLUnitType second) +template +SCALAR_TYPE operator / (SCALAR_TYPE first, LLUnit second) { - return first <= second.value(); + return SCALAR_TYPE(first / second.value()); } - -// -// operator > -// -template -bool operator > (typename LLUnitType::storage_t first, LLUnitType second) +template +LLUnit operator / (LLUnit first, SCALAR_TYPE second) { - return first > second.value(); + return LLUnit(first.value() / second); } -// -// operator >= -// -template -bool operator >= (typename LLUnitType::storage_t first, LLUnitType second) +template +void operator / (LLUnit, LLUnit) { - return first >= second.value(); + llstatic_assert(sizeof(STORAGE_TYPE1) == false, "Multiplication of unit types results in new unit type - not supported."); } -// -// operator == -// -template -bool operator == (typename LLUnitType::storage_t first, LLUnitType second) -{ - return first == second.value(); +#define COMPARISON_OPERATORS(op) \ +template \ +bool operator op (SCALAR_TYPE first, LLUnit second) \ +{ \ + return first op second.value(); \ +} \ + \ +template \ +bool operator op (LLUnit first, SCALAR_TYPE second) \ +{ \ + return first.value() op second; \ +} \ + \ +template \ +bool operator op (LLUnit first, LLUnit second) \ +{ \ + return first.value() op first.convert(second); \ } -// -// operator != -// -template -bool operator != (typename LLUnitType::storage_t first, LLUnitType second) +COMPARISON_OPERATORS(<) +COMPARISON_OPERATORS(<=) +COMPARISON_OPERATORS(>) +COMPARISON_OPERATORS(>=) +COMPARISON_OPERATORS(==) +COMPARISON_OPERATORS(!=) + +namespace LLUnits { - return first != second.value(); +#define LL_DECLARE_DERIVED_UNIT(base_unit_name, unit_name, conversion_factor)\ +struct unit_name \ +{ \ + typedef base_unit_name base_unit_t; \ +}; \ +template<> \ +struct ConversionFactor \ +{ \ + static F64 get() { return (conversion_factor); } \ +}; \ + \ +template<> \ +struct ConversionFactor \ +{ \ + static F64 get() { return 1.0 / (conversion_factor); } \ } -#define LL_DECLARE_BASE_UNIT(unit_name) \ - template \ - struct unit_name : public LLUnitType, unit_name > \ - { \ - typedef LLUnitType unit_t; \ - \ - unit_name(storage_t value = 0) \ - : LLUnitType(value) \ - {} \ - \ - template \ - unit_name(LLUnitType, SOURCE_TYPE> source) \ - { \ - assignFrom(source); \ - } \ - \ - template \ - void assignFrom(LLUnitType, SOURCE_TYPE> source) \ - { \ - setBaseValue((storage_t)source.unit_name::unit_t::value()); \ - } \ - \ - }; \ - -#define LL_DECLARE_DERIVED_UNIT(base_unit, derived_unit, conversion_factor) \ - template \ - struct derived_unit : public LLUnitType, derived_unit > \ - { \ - typedef LLUnitType, derived_unit > unit_t; \ - \ - derived_unit(storage_t value = 0) \ - : LLUnitType(value) \ - {} \ - \ - template \ - derived_unit(LLUnitType, SOURCE_TYPE> source) \ - { \ - assignFrom(source); \ - } \ - \ - template \ - void assignFrom(LLUnitType, SOURCE_TYPE> source) \ - { \ - setBaseValue((storage_t)source.base_unit::unit_t::value()); \ - } \ - \ - static F32 conversionToBaseFactor() { return (F32)(conversion_factor); } \ - \ - }; \ - -namespace LLUnit -{ - LL_DECLARE_BASE_UNIT(Bytes); - LL_DECLARE_DERIVED_UNIT(Bytes, Kilobytes, 1024); - LL_DECLARE_DERIVED_UNIT(Bytes, Megabytes, 1024 * 1024); - LL_DECLARE_DERIVED_UNIT(Bytes, Gigabytes, 1024 * 1024 * 1024); - LL_DECLARE_DERIVED_UNIT(Bytes, Bits, (1.f / 8.f)); - LL_DECLARE_DERIVED_UNIT(Bytes, Kilobits, (1024 / 8)); - LL_DECLARE_DERIVED_UNIT(Bytes, Megabits, (1024 / 8)); - LL_DECLARE_DERIVED_UNIT(Bytes, Gigabits, (1024 * 1024 * 1024 / 8)); - - LL_DECLARE_BASE_UNIT(Seconds); - LL_DECLARE_DERIVED_UNIT(Seconds, Minutes, 60); - LL_DECLARE_DERIVED_UNIT(Seconds, Hours, 60 * 60); - LL_DECLARE_DERIVED_UNIT(Seconds, Days, 60 * 60 * 24); - LL_DECLARE_DERIVED_UNIT(Seconds, Weeks, 60 * 60 * 24 * 7); - LL_DECLARE_DERIVED_UNIT(Seconds, Milliseconds, (1.f / 1000.f)); - LL_DECLARE_DERIVED_UNIT(Seconds, Microseconds, (1.f / (1000000.f))); - LL_DECLARE_DERIVED_UNIT(Seconds, Nanoseconds, (1.f / (1000000000.f))); - - LL_DECLARE_BASE_UNIT(Meters); - LL_DECLARE_DERIVED_UNIT(Meters, Kilometers, 1000); - LL_DECLARE_DERIVED_UNIT(Meters, Centimeters, 1 / 100); - LL_DECLARE_DERIVED_UNIT(Meters, Millimeters, 1 / 1000); +struct Bytes { typedef Bytes base_unit_t; }; +LL_DECLARE_DERIVED_UNIT(Bytes, Kilobytes, 1024); +LL_DECLARE_DERIVED_UNIT(Bytes, Megabytes, 1024 * 1024); +LL_DECLARE_DERIVED_UNIT(Bytes, Gigabytes, 1024 * 1024 * 1024); +LL_DECLARE_DERIVED_UNIT(Bytes, Bits, (1.0 / 8.0)); +LL_DECLARE_DERIVED_UNIT(Bytes, Kilobits, (1024 / 8)); +LL_DECLARE_DERIVED_UNIT(Bytes, Megabits, (1024 / 8)); +LL_DECLARE_DERIVED_UNIT(Bytes, Gigabits, (1024 * 1024 * 1024 / 8)); + +struct Seconds { typedef Seconds base_unit_t; }; +LL_DECLARE_DERIVED_UNIT(Seconds, Minutes, 60); +LL_DECLARE_DERIVED_UNIT(Seconds, Hours, 60 * 60); +LL_DECLARE_DERIVED_UNIT(Seconds, Days, 60 * 60 * 24); +LL_DECLARE_DERIVED_UNIT(Seconds, Weeks, 60 * 60 * 24 * 7); +LL_DECLARE_DERIVED_UNIT(Seconds, Milliseconds, (1.0 / 1000.0)); +LL_DECLARE_DERIVED_UNIT(Seconds, Microseconds, (1.0 / (1000000.0))); +LL_DECLARE_DERIVED_UNIT(Seconds, Nanoseconds, (1.0 / (1000000000.0))); + +struct Meters { typedef Meters base_unit_t; }; +LL_DECLARE_DERIVED_UNIT(Meters, Kilometers, 1000); +LL_DECLARE_DERIVED_UNIT(Meters, Centimeters, (1.0 / 100)); +LL_DECLARE_DERIVED_UNIT(Meters, Millimeters, (1.0 / 1000)); } #endif // LL_LLUNIT_H -- cgit v1.2.3