36 #include <type_traits>
37 #include <unordered_map>
63 return (value * R::num) /
static_cast<double> (R::den);
75 return value * 0.3048;
87 return value * 3.28084;
136 using Key = std::pair<Unit, Unit>;
137 using Conversion = std::function<double (
double)>;
144 std::size_t operator () (
const Key& key)
const noexcept
146 static_assert (
sizeof(
Unit) <
sizeof(std::size_t),
147 "sizeof(Length::Unit) changed, it must be less than "
148 "sizeof(std::size_t)");
150 int shift =
sizeof(
Unit) * 8;
151 return static_cast<std::size_t
> (key.first) << shift |
152 static_cast<std::size_t
> (key.second);
157 using ConversionTable = std::unordered_map<Key, Conversion, KeyHash>;
159 static ConversionTable CONVERSIONS {
160 { {Unit::Nanometer, Unit::Meter}, ScaleValue<std::nano> },
161 { {Unit::Meter, Unit::Nanometer}, ScaleValue<std::giga> },
162 { {Unit::Micrometer, Unit::Meter}, ScaleValue<std::micro> },
163 { {Unit::Meter, Unit::Micrometer}, ScaleValue<std::mega> },
164 { {Unit::Millimeter, Unit::Meter}, ScaleValue<std::milli> },
165 { {Unit::Meter, Unit::Millimeter}, ScaleValue<std::kilo> },
166 { {Unit::Centimeter, Unit::Meter}, ScaleValue<std::centi> },
167 { {Unit::Meter, Unit::Centimeter}, ScaleValue<std::hecto> },
168 { {Unit::Meter, Unit::Meter}, ScaleValue<std::ratio<1,1> > },
169 { {Unit::Kilometer, Unit::Meter}, ScaleValue<std::kilo> },
170 { {Unit::Meter, Unit::Kilometer}, ScaleValue<std::milli> },
171 { {Unit::NauticalMile, Unit::Meter}, ScaleValue<std::ratio<1852, 1> > },
172 { {Unit::Meter, Unit::NauticalMile}, ScaleValue<std::ratio<1, 1852> > },
173 { {Unit::Inch, Unit::Meter}, USToMeter<std::ratio<1, 12> > },
174 { {Unit::Meter, Unit::Inch}, MeterToUS<std::ratio<12, 1> > },
177 { {Unit::Yard, Unit::Meter}, USToMeter<std::ratio<3, 1> > },
178 { {Unit::Meter, Unit::Yard}, MeterToUS<std::ratio<1, 3> > },
179 { {Unit::Mile, Unit::Meter}, USToMeter<std::ratio<5280, 1> > },
180 { {Unit::Meter, Unit::Mile}, MeterToUS<std::ratio<1, 5280> > }
183 auto iter = CONVERSIONS.find ( Key {fromUnit, toUnit} );
185 if (iter == CONVERSIONS.end ())
188 <<
" -> " << toUnit);
191 return iter->second (value);
225 return static_cast<std::size_t
> (u);
238 std::tuple<bool, Length>
243 bool validUnit =
false;
246 std::tie (validUnit, unit) =
FromString (unitString);
252 length =
Length (value, unit);
255 return std::make_tuple (validUnit, length);
269 std::istringstream stream (input);
282 std::tie (validUnit, unit) =
FromString (unitString);
286 NS_FATAL_ERROR (
"A Length object could not be constructed from the unit "
287 "string '" << unitString <<
"', because the string is not associated "
288 "with a Length::Unit entry");
303 :
Length (quantity.Value (), quantity.
Unit ())
330 return diff <= tolerance;
338 return !
IsEqual (other, tolerance);
370 return !
IsLess (other, tolerance);
442 return Length ( value, Length::Unit::Meter );
449 return Length ( value, Length::Unit::Meter );
455 double value = left.
GetDouble () * scalar;
456 return Length ( value, Length::Unit::Meter );
462 return right * scalar;
473 return left * (1.0 / scalar);
481 return std::numeric_limits<double>::quiet_NaN ();
490 double value = numerator / denominator;
492 if (std::isnan (value))
500 *remainder =
Length (rem, Length::Unit::Meter);
503 return static_cast<int64_t
> (std::trunc (value));
511 if (std::isnan (rem))
516 return Length (rem, Length::Unit::Meter);
522 using StringTable = std::unordered_map<Length::Unit, std::string, EnumHash>;
524 static const StringTable STRINGS {
525 {Length::Unit::Nanometer,
"nm"},
526 {Length::Unit::Micrometer,
"um"},
527 {Length::Unit::Millimeter,
"mm"},
528 {Length::Unit::Centimeter,
"cm"},
529 {Length::Unit::Meter,
"m"},
530 {Length::Unit::Kilometer,
"km"},
531 {Length::Unit::NauticalMile,
"nmi"},
532 {Length::Unit::Inch,
"in"},
533 {Length::Unit::Foot,
"ft"},
534 {Length::Unit::Yard,
"yd"},
535 {Length::Unit::Mile,
"mi"}
538 auto iter = STRINGS.find (unit);
540 if (iter == STRINGS.end ())
542 NS_FATAL_ERROR (
"A symbol could not be found for Length::Unit with value "
543 << EnumHash ()(unit));
552 using Entry = std::tuple<std::string, std::string>;
553 using StringTable = std::unordered_map<Length::Unit, Entry, EnumHash>;
555 static const StringTable STRINGS {
556 {Length::Unit::Nanometer, Entry{
"nanometer",
"nanometers"}},
557 {Length::Unit::Micrometer, Entry{
"micrometer",
"micrometer"}},
558 {Length::Unit::Millimeter, Entry{
"millimeter",
"millimeters"}},
559 {Length::Unit::Centimeter, Entry{
"centimeter",
"centimeters"}},
560 {Length::Unit::Meter, Entry{
"meter",
"meters"}},
561 {Length::Unit::Kilometer, Entry{
"kilometer",
"kilometers"}},
562 {Length::Unit::NauticalMile, Entry{
"nautical mile",
"nautical miles"}},
563 {Length::Unit::Inch, Entry{
"inch",
"inches"}},
564 {Length::Unit::Foot, Entry{
"foot",
"feet"}},
565 {Length::Unit::Yard, Entry{
"yard",
"yards"}},
566 {Length::Unit::Mile, Entry{
"mile",
"miles"}}
569 auto iter = STRINGS.find (unit);
571 if (iter == STRINGS.end ())
573 NS_FATAL_ERROR (
"A symbol could not be found for Length::Unit with value "
574 << EnumHash ()(unit));
579 return std::get<1> (iter->second);
582 return std::get<0> (iter->second);
585 std::tuple<bool, Length::Unit>
588 using UnitTable = std::unordered_map<std::string, Length::Unit>;
590 static const UnitTable UNITS {
591 {
"nm", Length::Unit::Nanometer },
592 {
"nanometer", Length::Unit::Nanometer },
593 {
"nanometers", Length::Unit::Nanometer },
594 {
"nanometre", Length::Unit::Nanometer },
595 {
"nanometres", Length::Unit::Nanometer },
596 {
"um", Length::Unit::Micrometer },
597 {
"micrometer", Length::Unit::Micrometer },
598 {
"micrometers", Length::Unit::Micrometer },
599 {
"micrometre", Length::Unit::Micrometer },
600 {
"micrometres", Length::Unit::Micrometer },
601 {
"mm", Length::Unit::Millimeter },
602 {
"millimeter", Length::Unit::Millimeter },
603 {
"millimeters", Length::Unit::Millimeter },
604 {
"millimetre", Length::Unit::Millimeter },
605 {
"millimetres", Length::Unit::Millimeter },
606 {
"cm", Length::Unit::Centimeter },
607 {
"centimeter", Length::Unit::Centimeter },
608 {
"centimeters", Length::Unit::Centimeter },
609 {
"centimetre", Length::Unit::Centimeter },
610 {
"centimetres", Length::Unit::Centimeter },
611 {
"m", Length::Unit::Meter },
612 {
"meter", Length::Unit::Meter },
613 {
"metre", Length::Unit::Meter },
614 {
"meters", Length::Unit::Meter },
615 {
"metres", Length::Unit::Meter },
616 {
"km", Length::Unit::Kilometer },
617 {
"kilometer", Length::Unit::Kilometer },
618 {
"kilometers", Length::Unit::Kilometer },
619 {
"kilometre", Length::Unit::Kilometer },
620 {
"kilometres", Length::Unit::Kilometer },
621 {
"nmi", Length::Unit::NauticalMile },
622 {
"nauticalmile", Length::Unit::NauticalMile },
623 {
"nauticalmiles", Length::Unit::NauticalMile },
624 {
"in", Length::Unit::Inch },
625 {
"inch", Length::Unit::Inch },
626 {
"inches", Length::Unit::Inch },
627 {
"ft", Length::Unit::Foot },
628 {
"foot", Length::Unit::Foot },
629 {
"feet", Length::Unit::Foot },
630 {
"yd", Length::Unit::Yard },
631 {
"yard", Length::Unit::Yard },
632 {
"yards", Length::Unit::Yard },
633 {
"mi", Length::Unit::Mile },
634 {
"mile", Length::Unit::Mile },
635 {
"miles", Length::Unit::Mile }
639 static auto Normalize = [] (
const std::string& str)
642 output.reserve (str.size ());
644 for (
unsigned char c : str)
647 if (std::isspace (c) )
652 output.push_back (std::tolower (c));
658 unitString = Normalize (unitString);
660 auto iter = UNITS.find (unitString);
665 if (iter != UNITS.end ())
671 return std::make_tuple (valid, unit);
677 stream << l.
As (Length::Unit::Meter);
714 std::tuple<bool, double, std::string>
725 value = std::stod(input, &pos);
727 catch (
const std::exception& e)
729 NS_LOG_ERROR (
"Caught exception while parsing double: " << e.what());
731 return std::make_tuple(
false, 0,
"");
735 while (pos < input.size () && std::isspace(input[pos]))
738 if (pos < input.size ())
740 NS_LOG_LOGIC (
"String has value and symbol, extracting symbol");
743 symbol = input.substr(pos);
746 return std::make_tuple(
true, value, symbol);
752 bool success =
false;
758 auto origFlags = stream.flags ();
759 std::skipws (stream);
766 if (success && symbol.empty ())
768 NS_LOG_LOGIC (
"Temp string only contained value, extracting unit symbol from stream");
776 if (symbol ==
"nautical")
782 symbol.push_back (
' ');
783 symbol.append (temp);
790 stream.flags (origFlags);
798 return Length (value, Length::Unit::Nanometer);
804 return Length (value, Length::Unit::Micrometer);
810 return Length (value, Length::Unit::Millimeter);
816 return Length (value, Length::Unit::Centimeter);
822 return Length (value, Length::Unit::Meter);
828 return Length (value, Length::Unit::Kilometer);
834 return Length (value, Length::Unit::NauticalMile);
840 return Length (value, Length::Unit::Inch);
846 return Length (value, Length::Unit::Foot);
852 return Length (value, Length::Unit::Yard);
858 return Length (value, Length::Unit::Mile);
Functor for hashing Length::Unit values.
An immutable class which represents a value in a specific length unit.
double Value() const
The value of the quantity.
Length::Unit Unit() const
The unit of the quantity.
Represents a length in meters.
void swap(Length &other)
Swap values with another object.
bool IsGreaterOrEqual(const Length &other, double tolerance=DEFAULT_TOLERANCE) const
Check if other is equal or less in value than this instance.
double GetDouble() const
Current length value.
bool IsGreater(const Length &other, double tolerance=DEFAULT_TOLERANCE) const
Check if other is less in value than this instance.
double m_value
Length in meters.
std::tuple< bool, Length::Unit > FromString(std::string unitString)
Find the equivalent Length::Unit for a unit string.
bool IsEqual(const Length &other, double tolerance=DEFAULT_TOLERANCE) const
Check if other is equal in value to this instance.
Quantity As(Unit unit) const
Create a Quantity in a specific unit from a Length.
bool IsLessOrEqual(const Length &other, double tolerance=DEFAULT_TOLERANCE) const
Check if other is greater or equal in value than this instance.
Unit
Units of length in various measurement systems that are supported by the Length class.
Length & operator=(const Length &other)=default
Copy Assignment operator.
Length()
Default Constructor.
bool IsLess(const Length &other, double tolerance=DEFAULT_TOLERANCE) const
Check if other is greater in value than this instance.
static std::tuple< bool, Length > TryParse(double value, const std::string &unit)
Attempt to construct a Length object from a value and a unit string.
bool IsNotEqual(const Length &other, double tolerance=DEFAULT_TOLERANCE) const
Check if other is not equal in value to this instance.
#define ATTRIBUTE_HELPER_CPP(type)
Define the attribute value, accessor and checkers for class type
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
bool operator>(const int64x64_t &lhs, const int64x64_t &rhs)
Greater operator.
int64x64_t operator+(const int64x64_t &lhs)
Unary plus operator.
int64x64_t operator/(const int64x64_t &lhs, const int64x64_t &rhs)
Division operator.
int64x64_t operator-(const int64x64_t &lhs)
Unary negation operator (change sign operator).
bool operator>=(const int64x64_t &lhs, const int64x64_t &rhs)
Greater or equal operator.
bool operator<=(const int64x64_t &lhs, const int64x64_t &rhs)
Less or equal operator.
int64x64_t operator*(const int64x64_t &lhs, const int64x64_t &rhs)
Multiplication operator.
Length KiloMeters(double value)
This function provides a string parsing method that does not rely on istream, which has been found to...
Length MilliMeters(double value)
This function provides a string parsing method that does not rely on istream, which has been found to...
std::tuple< bool, double, std::string > ParseLengthString(const std::string &input)
This function provides a string parsing method that does not rely on istream, which has been found to...
Length NauticalMiles(double value)
This function provides a string parsing method that does not rely on istream, which has been found to...
Length Yards(double value)
This function provides a string parsing method that does not rely on istream, which has been found to...
Length Feet(double value)
This function provides a string parsing method that does not rely on istream, which has been found to...
int64_t Div(const Length &numerator, const Length &denominator, Length *remainder)
This function provides a string parsing method that does not rely on istream, which has been found to...
Length Mod(const Length &numerator, const Length &denominator)
This function provides a string parsing method that does not rely on istream, which has been found to...
Length MicroMeters(double value)
This function provides a string parsing method that does not rely on istream, which has been found to...
Length Miles(double value)
This function provides a string parsing method that does not rely on istream, which has been found to...
std::tuple< bool, Length::Unit > FromString(std::string unitString)
This function provides a string parsing method that does not rely on istream, which has been found to...
Length Meters(double value)
This function provides a string parsing method that does not rely on istream, which has been found to...
std::string ToSymbol(Length::Unit unit)
This function provides a string parsing method that does not rely on istream, which has been found to...
Length CentiMeters(double value)
This function provides a string parsing method that does not rely on istream, which has been found to...
std::string ToName(Length::Unit unit, bool plural)
This function provides a string parsing method that does not rely on istream, which has been found to...
Length NanoMeters(double value)
This function provides a string parsing method that does not rely on istream, which has been found to...
Length Inches(double value)
This function provides a string parsing method that does not rely on istream, which has been found to...
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Declaration of ns3::Length class.
double Convert(const ns3::Length::Quantity &from, ns3::Length::Unit toUnit)
Convert a Length::Quantity to the equivalent value in another unit.
double USToMeter(double value)
Convert a value from a US Customary unit (inches, feet, yards etc.) to meters.
double MeterToFoot(double value)
Convert a value in meters to the equivalent value in feet.
double MeterToUS(double value)
Convert a value from meters to a US Customary unit (inches, feet, yards etc.)
double FootToMeter(double value)
Convert a value in feet to the equivalent value in meters.
double ScaleValue(double value)
Helper function to scale an input value by a given ratio.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
bool operator==(const EventId &a, const EventId &b)
bool operator<(const EventId &a, const EventId &b)
bool operator!=(Callback< R, T1, T2, T3, T4, T5, T6, T7, T8, T9 > a, Callback< R, T1, T2, T3, T4, T5, T6, T7, T8, T9 > b)
Inequality test.
std::istream & operator>>(std::istream &is, Angles &a)
std::ostream & operator<<(std::ostream &os, const Angles &a)