21#include "ns3/length.h"
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);
238std::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);
437 return Length ( value, Length::Unit::Meter );
444 return Length ( value, Length::Unit::Meter );
450 double value = left.
GetDouble () * scalar;
451 return Length ( value, Length::Unit::Meter );
457 return right * scalar;
468 return left * (1.0 / scalar);
476 return std::numeric_limits<double>::quiet_NaN ();
485 double value = numerator / denominator;
487 if (std::isnan (value))
495 *remainder =
Length (rem, Length::Unit::Meter);
498 return static_cast<int64_t
> (std::trunc (value));
506 if (std::isnan (rem))
511 return Length (rem, Length::Unit::Meter);
517 using StringTable = std::unordered_map<Length::Unit, std::string, EnumHash>;
519 static const StringTable STRINGS {
520 {Length::Unit::Nanometer,
"nm"},
521 {Length::Unit::Micrometer,
"um"},
522 {Length::Unit::Millimeter,
"mm"},
523 {Length::Unit::Centimeter,
"cm"},
524 {Length::Unit::Meter,
"m"},
525 {Length::Unit::Kilometer,
"km"},
526 {Length::Unit::NauticalMile,
"nmi"},
527 {Length::Unit::Inch,
"in"},
528 {Length::Unit::Foot,
"ft"},
529 {Length::Unit::Yard,
"yd"},
530 {Length::Unit::Mile,
"mi"}
533 auto iter = STRINGS.find (unit);
535 if (iter == STRINGS.end ())
537 NS_FATAL_ERROR (
"A symbol could not be found for Length::Unit with value "
538 << EnumHash ()(unit));
547 using Entry = std::tuple<std::string, std::string>;
548 using StringTable = std::unordered_map<Length::Unit, Entry, EnumHash>;
550 static const StringTable STRINGS {
551 {Length::Unit::Nanometer, Entry{
"nanometer",
"nanometers"}},
552 {Length::Unit::Micrometer, Entry{
"micrometer",
"micrometer"}},
553 {Length::Unit::Millimeter, Entry{
"millimeter",
"millimeters"}},
554 {Length::Unit::Centimeter, Entry{
"centimeter",
"centimeters"}},
555 {Length::Unit::Meter, Entry{
"meter",
"meters"}},
556 {Length::Unit::Kilometer, Entry{
"kilometer",
"kilometers"}},
557 {Length::Unit::NauticalMile, Entry{
"nautical mile",
"nautical miles"}},
558 {Length::Unit::Inch, Entry{
"inch",
"inches"}},
559 {Length::Unit::Foot, Entry{
"foot",
"feet"}},
560 {Length::Unit::Yard, Entry{
"yard",
"yards"}},
561 {Length::Unit::Mile, Entry{
"mile",
"miles"}}
564 auto iter = STRINGS.find (unit);
566 if (iter == STRINGS.end ())
568 NS_FATAL_ERROR (
"A symbol could not be found for Length::Unit with value "
569 << EnumHash ()(unit));
574 return std::get<1> (iter->second);
577 return std::get<0> (iter->second);
580std::tuple<bool, Length::Unit>
583 using UnitTable = std::unordered_map<std::string, Length::Unit>;
585 static const UnitTable UNITS {
586 {
"nm", Length::Unit::Nanometer },
587 {
"nanometer", Length::Unit::Nanometer },
588 {
"nanometers", Length::Unit::Nanometer },
589 {
"nanometre", Length::Unit::Nanometer },
590 {
"nanometres", Length::Unit::Nanometer },
591 {
"um", Length::Unit::Micrometer },
592 {
"micrometer", Length::Unit::Micrometer },
593 {
"micrometers", Length::Unit::Micrometer },
594 {
"micrometre", Length::Unit::Micrometer },
595 {
"micrometres", Length::Unit::Micrometer },
596 {
"mm", Length::Unit::Millimeter },
597 {
"millimeter", Length::Unit::Millimeter },
598 {
"millimeters", Length::Unit::Millimeter },
599 {
"millimetre", Length::Unit::Millimeter },
600 {
"millimetres", Length::Unit::Millimeter },
601 {
"cm", Length::Unit::Centimeter },
602 {
"centimeter", Length::Unit::Centimeter },
603 {
"centimeters", Length::Unit::Centimeter },
604 {
"centimetre", Length::Unit::Centimeter },
605 {
"centimetres", Length::Unit::Centimeter },
606 {
"m", Length::Unit::Meter },
607 {
"meter", Length::Unit::Meter },
608 {
"metre", Length::Unit::Meter },
609 {
"meters", Length::Unit::Meter },
610 {
"metres", Length::Unit::Meter },
611 {
"km", Length::Unit::Kilometer },
612 {
"kilometer", Length::Unit::Kilometer },
613 {
"kilometers", Length::Unit::Kilometer },
614 {
"kilometre", Length::Unit::Kilometer },
615 {
"kilometres", Length::Unit::Kilometer },
616 {
"nmi", Length::Unit::NauticalMile },
617 {
"nauticalmile", Length::Unit::NauticalMile },
618 {
"nauticalmiles", Length::Unit::NauticalMile },
619 {
"in", Length::Unit::Inch },
620 {
"inch", Length::Unit::Inch },
621 {
"inches", Length::Unit::Inch },
622 {
"ft", Length::Unit::Foot },
623 {
"foot", Length::Unit::Foot },
624 {
"feet", Length::Unit::Foot },
625 {
"yd", Length::Unit::Yard },
626 {
"yard", Length::Unit::Yard },
627 {
"yards", Length::Unit::Yard },
628 {
"mi", Length::Unit::Mile },
629 {
"mile", Length::Unit::Mile },
630 {
"miles", Length::Unit::Mile }
634 static auto Normalize = [] (
const std::string& str)
637 output.reserve (str.size ());
639 for (
unsigned char c : str)
642 if (std::isspace (c) )
647 output.push_back (std::tolower (c));
653 unitString = Normalize (unitString);
655 auto iter = UNITS.find (unitString);
660 if (iter != UNITS.end ())
666 return std::make_tuple (valid, unit);
672 stream << l.
As (Length::Unit::Meter);
709std::tuple<bool, double, std::string>
720 value = std::stod(input, &pos);
722 catch (
const std::exception& e)
724 NS_LOG_ERROR (
"Caught exception while parsing double: " << e.what());
726 return std::make_tuple(
false, 0,
"");
730 while (pos < input.size () && std::isspace(input[pos]))
733 if (pos < input.size ())
735 NS_LOG_LOGIC (
"String has value and symbol, extracting symbol");
738 symbol = input.substr(pos);
741 return std::make_tuple(
true, value, symbol);
747 bool success =
false;
753 auto origFlags = stream.flags ();
754 std::skipws (stream);
761 if (success && symbol.empty ())
763 NS_LOG_LOGIC (
"Temp string only contained value, extracting unit symbol from stream");
771 if (symbol ==
"nautical")
777 symbol.push_back (
' ');
778 symbol.append (temp);
785 stream.flags (origFlags);
793 return Length (value, Length::Unit::Nanometer);
799 return Length (value, Length::Unit::Micrometer);
805 return Length (value, Length::Unit::Millimeter);
811 return Length (value, Length::Unit::Centimeter);
817 return Length (value, Length::Unit::Meter);
823 return Length (value, Length::Unit::Kilometer);
829 return Length (value, Length::Unit::NauticalMile);
835 return Length (value, Length::Unit::Inch);
841 return Length (value, Length::Unit::Foot);
847 return Length (value, Length::Unit::Yard);
853 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.
Length & operator=(const Length &other)=default
Copy Assignment operator.
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.
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()
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 NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
int64x64_t operator/(const int64x64_t &lhs, const int64x64_t &rhs)
Division 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)
Subtraction operator.
int64x64_t operator+(const int64x64_t &lhs, const int64x64_t &rhs)
Addition operator.
int64x64_t operator*(const int64x64_t &lhs, const int64x64_t &rhs)
Multiplication operator.
Length KiloMeters(double value)
Construct a length from a value in the indicated unit.
Length MilliMeters(double value)
Construct a length from a value in the indicated unit.
Length NauticalMiles(double value)
Construct a length from a value in the indicated unit.
std::string ToName(Length::Unit unit, bool plural)
Return the name of the supplied unit.
bool operator>(const Length &left, const Length &right)
Check if left has a value greater than right.
Length Yards(double value)
Construct a length from a value in the indicated unit.
Length Feet(double value)
Construct a length from a value in the indicated unit.
Length Mod(const Length &numerator, const Length &denominator)
Calculate the amount remaining after dividing two lengths.
Length MicroMeters(double value)
Construct a length from a value in the indicated unit.
Length Miles(double value)
Construct a length from a value in the indicated unit.
std::tuple< bool, Length::Unit > FromString(std::string unitString)
Find the equivalent Length::Unit for a unit string.
Length Meters(double value)
Construct a length from a value in the indicated unit.
std::string ToSymbol(Length::Unit unit)
Return the symbol of the supplied unit.
Length CentiMeters(double value)
Construct a length from a value in the indicated unit.
int64_t Div(const Length &numerator, const Length &denominator, Length *remainder)
Calculate how many times numerator can be split into denominator sized pieces.
Length NanoMeters(double value)
Construct a length from a value in the indicated unit.
Length Inches(double value)
Construct a length from a value in the indicated unit.
#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 ",...
Length::Unit Unit
Save some typing by defining a short alias for Length::Unit.
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)
std::ostream & operator<<(std::ostream &os, const Angles &a)
ATTRIBUTE_HELPER_CPP(Length)
std::istream & operator>>(std::istream &is, Angles &a)
bool operator<(const EventId &a, const EventId &b)
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...
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.