annotate DEPENDENCIES/generic/include/boost/units/io.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 // Boost.Units - A C++ library for zero-overhead dimensional analysis and
Chris@16 2 // unit/quantity manipulation and conversion
Chris@16 3 //
Chris@16 4 // Copyright (C) 2003-2008 Matthias Christian Schabel
Chris@16 5 // Copyright (C) 2007-2010 Steven Watanabe
Chris@16 6 //
Chris@16 7 // Distributed under the Boost Software License, Version 1.0. (See
Chris@16 8 // accompanying file LICENSE_1_0.txt or copy at
Chris@16 9 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 10
Chris@16 11 #ifndef BOOST_UNITS_IO_HPP
Chris@16 12 #define BOOST_UNITS_IO_HPP
Chris@16 13
Chris@16 14 /// \file
Chris@16 15 /// \brief Stream input and output for rationals, units and quantities.
Chris@16 16 /// \details Functions and manipulators for output and input of units and quantities.
Chris@16 17 /// symbol and name format, and engineering and binary autoprefix.
Chris@16 18 /// Serialization output is also supported.
Chris@16 19
Chris@16 20 #include <cassert>
Chris@16 21 #include <cmath>
Chris@16 22 #include <string>
Chris@16 23 #include <iosfwd>
Chris@16 24 #include <ios>
Chris@16 25 #include <sstream>
Chris@16 26
Chris@16 27 #include <boost/serialization/nvp.hpp>
Chris@16 28
Chris@16 29 #include <boost/units/units_fwd.hpp>
Chris@16 30 #include <boost/units/heterogeneous_system.hpp>
Chris@16 31 #include <boost/units/make_scaled_unit.hpp>
Chris@16 32 #include <boost/units/quantity.hpp>
Chris@16 33 #include <boost/units/scale.hpp>
Chris@16 34 #include <boost/units/static_rational.hpp>
Chris@16 35 #include <boost/units/unit.hpp>
Chris@16 36 #include <boost/units/detail/utility.hpp>
Chris@16 37
Chris@16 38 namespace boost {
Chris@16 39
Chris@16 40 namespace serialization {
Chris@16 41
Chris@16 42 /// Boost Serialization library support for units.
Chris@16 43 template<class Archive,class System,class Dim>
Chris@16 44 inline void serialize(Archive& ar,boost::units::unit<Dim,System>&,const unsigned int /*version*/)
Chris@16 45 { }
Chris@16 46
Chris@16 47 /// Boost Serialization library support for quantities.
Chris@16 48 template<class Archive,class Unit,class Y>
Chris@16 49 inline void serialize(Archive& ar,boost::units::quantity<Unit,Y>& q,const unsigned int /*version*/)
Chris@16 50 {
Chris@16 51 ar & boost::serialization::make_nvp("value", units::quantity_cast<Y&>(q));
Chris@16 52 }
Chris@16 53
Chris@16 54 } // namespace serialization
Chris@16 55
Chris@16 56 namespace units {
Chris@16 57
Chris@16 58 // get string representation of arbitrary type.
Chris@16 59 template<class T> std::string to_string(const T& t)
Chris@16 60 {
Chris@16 61 std::stringstream sstr;
Chris@16 62
Chris@16 63 sstr << t;
Chris@16 64
Chris@16 65 return sstr.str();
Chris@16 66 }
Chris@16 67
Chris@16 68 /// get string representation of integral-valued @c static_rational.
Chris@16 69 template<integer_type N> std::string to_string(const static_rational<N>&)
Chris@16 70 {
Chris@16 71 return to_string(N);
Chris@16 72 }
Chris@16 73
Chris@16 74 /// get string representation of @c static_rational.
Chris@16 75 template<integer_type N, integer_type D> std::string to_string(const static_rational<N,D>&)
Chris@16 76 {
Chris@16 77 return '(' + to_string(N) + '/' + to_string(D) + ')';
Chris@16 78 }
Chris@16 79
Chris@16 80 /// Write @c static_rational to @c std::basic_ostream.
Chris@16 81 template<class Char, class Traits, integer_type N, integer_type D>
Chris@16 82 inline std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& os,const static_rational<N,D>& r)
Chris@16 83 {
Chris@16 84 os << to_string(r);
Chris@16 85 return os;
Chris@16 86 }
Chris@16 87
Chris@16 88 /// traits template for unit names.
Chris@16 89 template<class BaseUnit>
Chris@16 90 struct base_unit_info
Chris@16 91 {
Chris@16 92 /// INTERNAL ONLY
Chris@16 93 typedef void base_unit_info_primary_template;
Chris@16 94 /// The full name of the unit (returns BaseUnit::name() by default)
Chris@16 95 static std::string name()
Chris@16 96 {
Chris@16 97 return(BaseUnit::name());
Chris@16 98 }
Chris@16 99 /// The symbol for the base unit (Returns BaseUnit::symbol() by default)
Chris@16 100 static std::string symbol()
Chris@16 101 {
Chris@16 102 return(BaseUnit::symbol()); /// \returns BaseUnit::symbol(), for example "m"
Chris@16 103 }
Chris@16 104 };
Chris@16 105
Chris@16 106 /// \enum format_mode format of output of units, for example "m" or "meter".
Chris@16 107 enum format_mode
Chris@16 108 {
Chris@16 109 symbol_fmt = 0, /// default - reduces unit names to known symbols for both base and derived units.
Chris@16 110 name_fmt = 1, /// output full unit names for base and derived units, for example "meter".
Chris@16 111 raw_fmt = 2, /// output only symbols for base units (but not derived units), for example "m".
Chris@16 112 typename_fmt = 3, /// output demangled typenames (useful only for diagnosis).
Chris@16 113 fmt_mask = 3 /// Bits used for format.
Chris@16 114 };
Chris@16 115
Chris@16 116 /// \enum autoprefix_mode automatic scaling and prefix (controlled by value of quantity) a, if any,
Chris@16 117 enum autoprefix_mode
Chris@16 118 {
Chris@16 119 autoprefix_none = 0, /// No automatic prefix.
Chris@16 120 autoprefix_engineering = 4, /// Scale and prefix with 10^3 multiples, 1234.5 m output as 1.2345 km.
Chris@16 121 autoprefix_binary = 8, /// Scale and prefix with 2^10 (1024) multiples, 1024 as 1 kb.
Chris@16 122 autoprefix_mask = 12 /// Bits used for autoprefix.
Chris@16 123 };
Chris@16 124
Chris@16 125 namespace detail {
Chris@16 126
Chris@16 127 template<bool>
Chris@16 128 struct xalloc_key_holder
Chris@16 129 {
Chris@16 130 static int value;
Chris@16 131 static bool initialized;
Chris@16 132 };
Chris@16 133
Chris@16 134 template<bool b>
Chris@16 135 int xalloc_key_holder<b>::value = 0;
Chris@16 136
Chris@16 137 template<bool b>
Chris@16 138 bool xalloc_key_holder<b>::initialized = 0;
Chris@16 139
Chris@16 140 struct xalloc_key_initializer_t
Chris@16 141 {
Chris@16 142 xalloc_key_initializer_t()
Chris@16 143 {
Chris@16 144 if (!xalloc_key_holder<true>::initialized)
Chris@16 145 {
Chris@16 146 xalloc_key_holder<true>::value = std::ios_base::xalloc();
Chris@16 147 xalloc_key_holder<true>::initialized = true;
Chris@16 148 }
Chris@16 149 }
Chris@16 150 };
Chris@16 151
Chris@16 152 namespace /**/ {
Chris@16 153
Chris@16 154 xalloc_key_initializer_t xalloc_key_initializer;
Chris@16 155
Chris@16 156 } // namespace
Chris@16 157
Chris@16 158 } // namespace detail
Chris@16 159
Chris@16 160 /// returns flags controlling output.
Chris@16 161 inline long get_flags(std::ios_base& ios, long mask)
Chris@16 162 {
Chris@16 163 return(ios.iword(detail::xalloc_key_holder<true>::value) & mask);
Chris@16 164 }
Chris@16 165
Chris@16 166 /// Set new flags controlling output format.
Chris@16 167 inline void set_flags(std::ios_base& ios, long new_flags, long mask)
Chris@16 168 {
Chris@16 169 assert((~mask & new_flags) == 0);
Chris@16 170 long& flags = ios.iword(detail::xalloc_key_holder<true>::value);
Chris@16 171 flags = (flags & ~mask) | new_flags;
Chris@16 172 }
Chris@16 173
Chris@16 174 /// returns flags controlling output format.
Chris@16 175 inline format_mode get_format(std::ios_base& ios)
Chris@16 176 {
Chris@16 177 return(static_cast<format_mode>((get_flags)(ios, fmt_mask)));
Chris@16 178 }
Chris@16 179
Chris@16 180 /// Set new flags controlling output format.
Chris@16 181 inline void set_format(std::ios_base& ios, format_mode new_mode)
Chris@16 182 {
Chris@16 183 (set_flags)(ios, new_mode, fmt_mask);
Chris@16 184 }
Chris@16 185
Chris@16 186 /// Set new flags for type_name output format.
Chris@16 187 inline std::ios_base& typename_format(std::ios_base& ios)
Chris@16 188 {
Chris@16 189 (set_format)(ios, typename_fmt);
Chris@16 190 return(ios);
Chris@16 191 }
Chris@16 192
Chris@16 193 /// set new flag for raw format output, for example "m".
Chris@16 194 inline std::ios_base& raw_format(std::ios_base& ios)
Chris@16 195 {
Chris@16 196 (set_format)(ios, raw_fmt);
Chris@16 197 return(ios);
Chris@16 198 }
Chris@16 199
Chris@16 200 /// set new format flag for symbol output, for example "m".
Chris@16 201 inline std::ios_base& symbol_format(std::ios_base& ios)
Chris@16 202 {
Chris@16 203 (set_format)(ios, symbol_fmt);
Chris@16 204 return(ios);
Chris@16 205 }
Chris@16 206
Chris@16 207 /// set new format for name output, for example "meter".
Chris@16 208 inline std::ios_base& name_format(std::ios_base& ios)
Chris@16 209 {
Chris@16 210 (set_format)(ios, name_fmt);
Chris@16 211 return(ios);
Chris@16 212 }
Chris@16 213
Chris@16 214 /// get autoprefix flags for output.
Chris@16 215 inline autoprefix_mode get_autoprefix(std::ios_base& ios)
Chris@16 216 {
Chris@16 217 return static_cast<autoprefix_mode>((get_flags)(ios, autoprefix_mask));
Chris@16 218 }
Chris@16 219
Chris@16 220 /// Get format for output.
Chris@16 221 inline void set_autoprefix(std::ios_base& ios, autoprefix_mode new_mode)
Chris@16 222 {
Chris@16 223 (set_flags)(ios, new_mode, autoprefix_mask);
Chris@16 224 }
Chris@16 225
Chris@16 226 /// Clear autoprefix flags.
Chris@16 227 inline std::ios_base& no_prefix(std::ios_base& ios)
Chris@16 228 {
Chris@16 229 (set_autoprefix)(ios, autoprefix_none);
Chris@16 230 return ios;
Chris@16 231 }
Chris@16 232
Chris@16 233 /// Set flag for engineering prefix, so 1234.5 m displays as "1.2345 km".
Chris@16 234 inline std::ios_base& engineering_prefix(std::ios_base& ios)
Chris@16 235 {
Chris@16 236 (set_autoprefix)(ios, autoprefix_engineering);
Chris@16 237 return ios;
Chris@16 238 }
Chris@16 239
Chris@16 240 /// Set flag for binary prefix, so 1024 byte displays as "1 Kib".
Chris@16 241 inline std::ios_base& binary_prefix(std::ios_base& ios)
Chris@16 242 {
Chris@16 243 (set_autoprefix)(ios, autoprefix_binary);
Chris@16 244 return ios;
Chris@16 245 }
Chris@16 246
Chris@16 247 namespace detail {
Chris@16 248
Chris@16 249 /// \return exponent string like "^1/2".
Chris@16 250 template<integer_type N, integer_type D>
Chris@16 251 inline std::string exponent_string(const static_rational<N,D>& r)
Chris@16 252 {
Chris@16 253 return '^' + to_string(r);
Chris@16 254 }
Chris@16 255
Chris@16 256 /// \return empty exponent string for integer rational like 2.
Chris@16 257 template<>
Chris@16 258 inline std::string exponent_string(const static_rational<1>&)
Chris@16 259 {
Chris@16 260 return "";
Chris@16 261 }
Chris@16 262
Chris@16 263 template<class T>
Chris@16 264 inline std::string base_unit_symbol_string(const T&)
Chris@16 265 {
Chris@16 266 return base_unit_info<typename T::tag_type>::symbol() + exponent_string(typename T::value_type());
Chris@16 267 }
Chris@16 268
Chris@16 269 template<class T>
Chris@16 270 inline std::string base_unit_name_string(const T&)
Chris@16 271 {
Chris@16 272 return base_unit_info<typename T::tag_type>::name() + exponent_string(typename T::value_type());
Chris@16 273 }
Chris@16 274
Chris@16 275 // stringify with symbols.
Chris@16 276 template<int N>
Chris@16 277 struct symbol_string_impl
Chris@16 278 {
Chris@16 279 template<class Begin>
Chris@16 280 struct apply
Chris@16 281 {
Chris@16 282 typedef typename symbol_string_impl<N-1>::template apply<typename Begin::next> next;
Chris@16 283 static void value(std::string& str)
Chris@16 284 {
Chris@16 285 str += base_unit_symbol_string(typename Begin::item()) + ' ';
Chris@16 286 next::value(str);
Chris@16 287 }
Chris@16 288 };
Chris@16 289 };
Chris@16 290
Chris@16 291 template<>
Chris@16 292 struct symbol_string_impl<1>
Chris@16 293 {
Chris@16 294 template<class Begin>
Chris@16 295 struct apply
Chris@16 296 {
Chris@16 297 static void value(std::string& str)
Chris@16 298 {
Chris@16 299 str += base_unit_symbol_string(typename Begin::item());
Chris@16 300 };
Chris@16 301 };
Chris@16 302 };
Chris@16 303
Chris@16 304 template<>
Chris@16 305 struct symbol_string_impl<0>
Chris@16 306 {
Chris@16 307 template<class Begin>
Chris@16 308 struct apply
Chris@16 309 {
Chris@16 310 static void value(std::string& str)
Chris@16 311 {
Chris@16 312 // better shorthand for dimensionless?
Chris@16 313 str += "dimensionless";
Chris@16 314 }
Chris@16 315 };
Chris@16 316 };
Chris@16 317
Chris@16 318 template<int N>
Chris@16 319 struct scale_symbol_string_impl
Chris@16 320 {
Chris@16 321 template<class Begin>
Chris@16 322 struct apply
Chris@16 323 {
Chris@16 324 static void value(std::string& str)
Chris@16 325 {
Chris@16 326 str += Begin::item::symbol();
Chris@16 327 scale_symbol_string_impl<N - 1>::template apply<typename Begin::next>::value(str);
Chris@16 328 }
Chris@16 329 };
Chris@16 330 };
Chris@16 331
Chris@16 332 template<>
Chris@16 333 struct scale_symbol_string_impl<0>
Chris@16 334 {
Chris@16 335 template<class Begin>
Chris@16 336 struct apply
Chris@16 337 {
Chris@16 338 static void value(std::string&) { }
Chris@16 339 };
Chris@16 340 };
Chris@16 341
Chris@16 342 // stringify with names.
Chris@16 343 template<int N>
Chris@16 344 struct name_string_impl
Chris@16 345 {
Chris@16 346 template<class Begin>
Chris@16 347 struct apply
Chris@16 348 {
Chris@16 349 typedef typename name_string_impl<N-1>::template apply<typename Begin::next> next;
Chris@16 350 static void value(std::string& str)
Chris@16 351 {
Chris@16 352 str += base_unit_name_string(typename Begin::item()) + ' ';
Chris@16 353 next::value(str);
Chris@16 354 }
Chris@16 355 };
Chris@16 356 };
Chris@16 357
Chris@16 358 template<>
Chris@16 359 struct name_string_impl<1>
Chris@16 360 {
Chris@16 361 template<class Begin>
Chris@16 362 struct apply
Chris@16 363 {
Chris@16 364 static void value(std::string& str)
Chris@16 365 {
Chris@16 366 str += base_unit_name_string(typename Begin::item());
Chris@16 367 };
Chris@16 368 };
Chris@16 369 };
Chris@16 370
Chris@16 371 template<>
Chris@16 372 struct name_string_impl<0>
Chris@16 373 {
Chris@16 374 template<class Begin>
Chris@16 375 struct apply
Chris@16 376 {
Chris@16 377 static void value(std::string& str)
Chris@16 378 {
Chris@16 379 str += "dimensionless";
Chris@16 380 }
Chris@16 381 };
Chris@16 382 };
Chris@16 383
Chris@16 384 template<int N>
Chris@16 385 struct scale_name_string_impl
Chris@16 386 {
Chris@16 387 template<class Begin>
Chris@16 388 struct apply
Chris@16 389 {
Chris@16 390 static void value(std::string& str)
Chris@16 391 {
Chris@16 392 str += Begin::item::name();
Chris@16 393 scale_name_string_impl<N - 1>::template apply<typename Begin::next>::value(str);
Chris@16 394 }
Chris@16 395 };
Chris@16 396 };
Chris@16 397
Chris@16 398 template<>
Chris@16 399 struct scale_name_string_impl<0>
Chris@16 400 {
Chris@16 401 template<class Begin>
Chris@16 402 struct apply
Chris@16 403 {
Chris@16 404 static void value(std::string&) { }
Chris@16 405 };
Chris@16 406 };
Chris@16 407
Chris@16 408 } // namespace detail
Chris@16 409
Chris@16 410 namespace detail {
Chris@16 411
Chris@16 412 // These two overloads of symbol_string and name_string will
Chris@16 413 // will pick up homogeneous_systems. They simply call the
Chris@16 414 // appropriate function with a heterogeneous_system.
Chris@16 415 template<class Dimension,class System, class SubFormatter>
Chris@16 416 inline std::string
Chris@16 417 to_string_impl(const unit<Dimension,System>&, SubFormatter f)
Chris@16 418 {
Chris@16 419 return f(typename reduce_unit<unit<Dimension, System> >::type());
Chris@16 420 }
Chris@16 421
Chris@16 422 /// INTERNAL ONLY
Chris@16 423 // this overload picks up heterogeneous units that are not scaled.
Chris@16 424 template<class Dimension,class Units, class Subformatter>
Chris@16 425 inline std::string
Chris@16 426 to_string_impl(const unit<Dimension, heterogeneous_system<heterogeneous_system_impl<Units, Dimension, dimensionless_type> > >&, Subformatter f)
Chris@16 427 {
Chris@16 428 std::string str;
Chris@16 429 f.template append_units_to<Units>(str);
Chris@16 430 return(str);
Chris@16 431 }
Chris@16 432
Chris@16 433 // This overload is a special case for heterogeneous_system which
Chris@16 434 // is really unitless
Chris@16 435 /// INTERNAL ONLY
Chris@16 436 template<class Subformatter>
Chris@16 437 inline std::string
Chris@16 438 to_string_impl(const unit<dimensionless_type, heterogeneous_system<heterogeneous_system_impl<dimensionless_type, dimensionless_type, dimensionless_type> > >&, Subformatter)
Chris@16 439 {
Chris@16 440 return("dimensionless");
Chris@16 441 }
Chris@16 442
Chris@16 443 // this overload deals with heterogeneous_systems which are unitless
Chris@16 444 // but scaled.
Chris@16 445 /// INTERNAL ONLY
Chris@16 446 template<class Scale, class Subformatter>
Chris@16 447 inline std::string
Chris@16 448 to_string_impl(const unit<dimensionless_type, heterogeneous_system<heterogeneous_system_impl<dimensionless_type, dimensionless_type, Scale> > >&, Subformatter f)
Chris@16 449 {
Chris@16 450 std::string str;
Chris@16 451 f.template append_scale_to<Scale>(str);
Chris@16 452 return(str);
Chris@16 453 }
Chris@16 454
Chris@16 455 // this overload deals with scaled units.
Chris@16 456 /// INTERNAL ONLY
Chris@16 457 template<class Dimension,class Units,class Scale, class Subformatter>
Chris@16 458 inline std::string
Chris@16 459 to_string_impl(const unit<Dimension, heterogeneous_system<heterogeneous_system_impl<Units, Dimension, Scale> > >&, Subformatter f)
Chris@16 460 {
Chris@16 461 std::string str;
Chris@16 462
Chris@16 463 f.template append_scale_to<Scale>(str);
Chris@16 464
Chris@16 465 std::string without_scale = f(unit<Dimension, heterogeneous_system<heterogeneous_system_impl<Units, Dimension, dimensionless_type> > >());
Chris@16 466
Chris@16 467 if (f.is_default_string(without_scale, unit<Dimension, heterogeneous_system<heterogeneous_system_impl<Units, Dimension, dimensionless_type> > >()))
Chris@16 468 {
Chris@16 469 str += "(";
Chris@16 470 str += without_scale;
Chris@16 471 str += ")";
Chris@16 472 }
Chris@16 473 else
Chris@16 474 {
Chris@16 475 str += without_scale;
Chris@16 476 }
Chris@16 477
Chris@16 478 return(str);
Chris@16 479 }
Chris@16 480
Chris@16 481 // This overload catches scaled units that have a single base unit
Chris@16 482 // raised to the first power. It causes si::nano * si::meters to not
Chris@16 483 // put parentheses around the meters. i.e. nm rather than n(m)
Chris@16 484 /// INTERNAL ONLY
Chris@16 485 template<class Dimension,class Unit,class Scale, class Subformatter>
Chris@16 486 inline std::string
Chris@16 487 to_string_impl(const unit<Dimension, heterogeneous_system<heterogeneous_system_impl<list<heterogeneous_system_dim<Unit, static_rational<1> >,dimensionless_type>, Dimension, Scale> > >&, Subformatter f)
Chris@16 488 {
Chris@16 489 std::string str;
Chris@16 490
Chris@16 491 f.template append_scale_to<Scale>(str);
Chris@16 492 str += f(unit<Dimension, heterogeneous_system<heterogeneous_system_impl<list<heterogeneous_system_dim<Unit, static_rational<1> >, dimensionless_type>, Dimension, dimensionless_type> > >());
Chris@16 493
Chris@16 494 return(str);
Chris@16 495 }
Chris@16 496
Chris@16 497 // This overload is necessary to disambiguate.
Chris@16 498 // it catches units that are unscaled and have a single
Chris@16 499 // base unit raised to the first power. It is treated the
Chris@16 500 // same as any other unscaled unit.
Chris@16 501 /// INTERNAL ONLY
Chris@16 502 template<class Dimension,class Unit,class Subformatter>
Chris@16 503 inline std::string
Chris@16 504 to_string_impl(const unit<Dimension, heterogeneous_system<heterogeneous_system_impl<list<heterogeneous_system_dim<Unit, static_rational<1> >,dimensionless_type>, Dimension, dimensionless_type> > >&, Subformatter f)
Chris@16 505 {
Chris@16 506 std::string str;
Chris@16 507 f.template append_units_to<list<heterogeneous_system_dim<Unit, static_rational<1> >,dimensionless_type> >(str);
Chris@16 508 return(str);
Chris@16 509 }
Chris@16 510
Chris@16 511 // This overload catches scaled units that have a single scaled base unit
Chris@16 512 // raised to the first power. It moves that scaling on the base unit
Chris@16 513 // to the unit level scaling and recurses. By doing this we make sure that
Chris@16 514 // si::milli * si::kilograms will print g rather than mkg.
Chris@16 515 //
Chris@16 516 // This transformation will not be applied if base_unit_info is specialized
Chris@16 517 // for the scaled base unit.
Chris@16 518 //
Chris@16 519 /// INTERNAL ONLY
Chris@16 520 template<class Dimension,class Unit,class UnitScale, class Scale, class Subformatter>
Chris@16 521 inline std::string
Chris@16 522 to_string_impl(
Chris@16 523 const unit<
Chris@16 524 Dimension,
Chris@16 525 heterogeneous_system<
Chris@16 526 heterogeneous_system_impl<
Chris@16 527 list<heterogeneous_system_dim<scaled_base_unit<Unit, UnitScale>, static_rational<1> >, dimensionless_type>,
Chris@16 528 Dimension,
Chris@16 529 Scale
Chris@16 530 >
Chris@16 531 >
Chris@16 532 >&,
Chris@16 533 Subformatter f,
Chris@16 534 typename base_unit_info<scaled_base_unit<Unit, UnitScale> >::base_unit_info_primary_template* = 0)
Chris@16 535 {
Chris@16 536 return(f(
Chris@16 537 unit<
Chris@16 538 Dimension,
Chris@16 539 heterogeneous_system<
Chris@16 540 heterogeneous_system_impl<
Chris@16 541 list<heterogeneous_system_dim<Unit, static_rational<1> >, dimensionless_type>,
Chris@16 542 Dimension,
Chris@16 543 typename mpl::times<Scale, list<scale_list_dim<UnitScale>, dimensionless_type> >::type
Chris@16 544 >
Chris@16 545 >
Chris@16 546 >()));
Chris@16 547 }
Chris@16 548
Chris@16 549 // this overload disambuguates between the overload for an unscaled unit
Chris@16 550 // and the overload for a scaled base unit raised to the first power.
Chris@16 551 /// INTERNAL ONLY
Chris@16 552 template<class Dimension,class Unit,class UnitScale,class Subformatter>
Chris@16 553 inline std::string
Chris@16 554 to_string_impl(
Chris@16 555 const unit<
Chris@16 556 Dimension,
Chris@16 557 heterogeneous_system<
Chris@16 558 heterogeneous_system_impl<
Chris@16 559 list<heterogeneous_system_dim<scaled_base_unit<Unit, UnitScale>, static_rational<1> >, dimensionless_type>,
Chris@16 560 Dimension,
Chris@16 561 dimensionless_type
Chris@16 562 >
Chris@16 563 >
Chris@16 564 >&,
Chris@16 565 Subformatter f,
Chris@16 566 typename base_unit_info<scaled_base_unit<Unit, UnitScale> >::base_unit_info_primary_template* = 0)
Chris@16 567 {
Chris@16 568 std::string str;
Chris@16 569 f.template append_units_to<list<heterogeneous_system_dim<scaled_base_unit<Unit, UnitScale>, static_rational<1> >, dimensionless_type> >(str);
Chris@16 570 return(str);
Chris@16 571 }
Chris@16 572
Chris@16 573 struct format_raw_symbol_impl {
Chris@16 574 template<class Units>
Chris@16 575 void append_units_to(std::string& str) {
Chris@16 576 detail::symbol_string_impl<Units::size::value>::template apply<Units>::value(str);
Chris@16 577 }
Chris@16 578 template<class Scale>
Chris@16 579 void append_scale_to(std::string& str) {
Chris@16 580 detail::scale_symbol_string_impl<Scale::size::value>::template apply<Scale>::value(str);
Chris@16 581 }
Chris@16 582 template<class Unit>
Chris@16 583 std::string operator()(const Unit& u) {
Chris@16 584 return(to_string_impl(u, *this));
Chris@16 585 }
Chris@16 586 template<class Unit>
Chris@16 587 bool is_default_string(const std::string&, const Unit&) {
Chris@16 588 return(true);
Chris@16 589 }
Chris@16 590 };
Chris@16 591
Chris@16 592 struct format_symbol_impl : format_raw_symbol_impl {
Chris@16 593 template<class Unit>
Chris@16 594 std::string operator()(const Unit& u) {
Chris@16 595 return(symbol_string(u));
Chris@16 596 }
Chris@16 597 template<class Unit>
Chris@16 598 bool is_default_string(const std::string& str, const Unit& u) {
Chris@16 599 return(str == to_string_impl(u, format_raw_symbol_impl()));
Chris@16 600 }
Chris@16 601 };
Chris@16 602
Chris@16 603 struct format_raw_name_impl {
Chris@16 604 template<class Units>
Chris@16 605 void append_units_to(std::string& str) {
Chris@16 606 detail::name_string_impl<(Units::size::value)>::template apply<Units>::value(str);
Chris@16 607 }
Chris@16 608 template<class Scale>
Chris@16 609 void append_scale_to(std::string& str) {
Chris@16 610 detail::scale_name_string_impl<Scale::size::value>::template apply<Scale>::value(str);
Chris@16 611 }
Chris@16 612 template<class Unit>
Chris@16 613 std::string operator()(const Unit& u) {
Chris@16 614 return(to_string_impl(u, *this));
Chris@16 615 }
Chris@16 616 template<class Unit>
Chris@16 617 bool is_default_string(const std::string&, const Unit&) {
Chris@16 618 return(true);
Chris@16 619 }
Chris@16 620 };
Chris@16 621
Chris@16 622 struct format_name_impl : format_raw_name_impl {
Chris@16 623 template<class Unit>
Chris@16 624 std::string operator()(const Unit& u) {
Chris@16 625 return(name_string(u));
Chris@16 626 }
Chris@16 627 template<class Unit>
Chris@16 628 bool is_default_string(const std::string& str, const Unit& u) {
Chris@16 629 return(str == to_string_impl(u, format_raw_name_impl()));
Chris@16 630 }
Chris@16 631 };
Chris@16 632
Chris@16 633 template<class Char, class Traits>
Chris@16 634 inline void do_print(std::basic_ostream<Char, Traits>& os, const std::string& s)
Chris@16 635 {
Chris@16 636 os << s.c_str();
Chris@16 637 }
Chris@16 638
Chris@16 639 inline void do_print(std::ostream& os, const std::string& s)
Chris@16 640 {
Chris@16 641 os << s;
Chris@16 642 }
Chris@16 643
Chris@16 644 template<class Char, class Traits>
Chris@16 645 inline void do_print(std::basic_ostream<Char, Traits>& os, const char* s)
Chris@16 646 {
Chris@16 647 os << s;
Chris@16 648 }
Chris@16 649
Chris@16 650 // For automatically applying the appropriate prefixes.
Chris@16 651
Chris@16 652 }
Chris@16 653
Chris@16 654 #ifdef BOOST_UNITS_DOXYGEN
Chris@16 655
Chris@16 656 /// ADL customization point for automatic prefixing.
Chris@16 657 /// Returns a non-negative value. Implemented as std::abs
Chris@16 658 /// for built-in types.
Chris@16 659 template<class T>
Chris@16 660 double autoprefix_norm(const T& arg);
Chris@16 661
Chris@16 662 #else
Chris@16 663
Chris@16 664 template<class T, bool C = boost::is_arithmetic<T>::value>
Chris@16 665 struct autoprefix_norm_impl;
Chris@16 666
Chris@16 667 template<class T>
Chris@16 668 struct autoprefix_norm_impl<T, true>
Chris@16 669 {
Chris@16 670 typedef double type;
Chris@16 671 static double call(const T& arg) { return std::abs(arg); }
Chris@16 672 };
Chris@16 673
Chris@16 674 template<class T>
Chris@16 675 struct autoprefix_norm_impl<T, false>
Chris@16 676 {
Chris@16 677 typedef one type;
Chris@16 678 static one call(const T&) { return one(); }
Chris@16 679 };
Chris@16 680
Chris@16 681 template<class T>
Chris@16 682 typename autoprefix_norm_impl<T>::type autoprefix_norm(const T& arg)
Chris@16 683 {
Chris@16 684 return autoprefix_norm_impl<T>::call(arg);
Chris@16 685 }
Chris@16 686
Chris@16 687 #endif
Chris@16 688
Chris@16 689 namespace detail {
Chris@16 690
Chris@16 691 template<class End, class Prev, class T, class F>
Chris@16 692 bool find_matching_scale_impl(End, End, Prev, T, double, F)
Chris@16 693 {
Chris@16 694 return false;
Chris@16 695 }
Chris@16 696
Chris@16 697 template<class Begin, class End, class Prev, class T, class F>
Chris@16 698 bool find_matching_scale_impl(Begin, End end, Prev prev, T t, double x, F f)
Chris@16 699 {
Chris@16 700 if(Begin::item::value() > x) {
Chris@16 701 f(prev, t);
Chris@16 702 return true;
Chris@16 703 } else {
Chris@16 704 return detail::find_matching_scale_impl(
Chris@16 705 typename Begin::next(),
Chris@16 706 end,
Chris@16 707 typename Begin::item(),
Chris@16 708 t,
Chris@16 709 x,
Chris@16 710 f
Chris@16 711 );
Chris@16 712 }
Chris@16 713 }
Chris@16 714
Chris@16 715 template<class End, class T, class F>
Chris@16 716 bool find_matching_scale_i(End, End, T, double, F)
Chris@16 717 {
Chris@16 718 return false;
Chris@16 719 }
Chris@16 720
Chris@16 721 template<class Begin, class End, class T, class F>
Chris@16 722 bool find_matching_scale_i(Begin, End end, T t, double x, F f)
Chris@16 723 {
Chris@16 724 if(Begin::item::value() > x) {
Chris@16 725 return false;
Chris@16 726 } else {
Chris@16 727 return detail::find_matching_scale_impl(typename Begin::next(), end, typename Begin::item(), t, x, f);
Chris@16 728 }
Chris@16 729 }
Chris@16 730
Chris@16 731 template<class Scales, class T, class F>
Chris@16 732 bool find_matching_scale(T t, double x, F f)
Chris@16 733 {
Chris@16 734 return detail::find_matching_scale_i(Scales(), dimensionless_type(), t, x, f);
Chris@16 735 }
Chris@16 736
Chris@16 737 typedef list<scale<10, static_rational<-24> >,
Chris@16 738 list<scale<10, static_rational<-21> >,
Chris@16 739 list<scale<10, static_rational<-18> >,
Chris@16 740 list<scale<10, static_rational<-15> >,
Chris@16 741 list<scale<10, static_rational<-12> >,
Chris@16 742 list<scale<10, static_rational<-9> >,
Chris@16 743 list<scale<10, static_rational<-6> >,
Chris@16 744 list<scale<10, static_rational<-3> >,
Chris@16 745 list<scale<10, static_rational<0> >,
Chris@16 746 list<scale<10, static_rational<3> >,
Chris@16 747 list<scale<10, static_rational<6> >,
Chris@16 748 list<scale<10, static_rational<9> >,
Chris@16 749 list<scale<10, static_rational<12> >,
Chris@16 750 list<scale<10, static_rational<15> >,
Chris@16 751 list<scale<10, static_rational<18> >,
Chris@16 752 list<scale<10, static_rational<21> >,
Chris@16 753 list<scale<10, static_rational<24> >,
Chris@16 754 list<scale<10, static_rational<27> >,
Chris@16 755 dimensionless_type> > > > > > > > > > > > > > > > > > engineering_prefixes;
Chris@16 756
Chris@16 757 typedef list<scale<2, static_rational<10> >,
Chris@16 758 list<scale<2, static_rational<20> >,
Chris@16 759 list<scale<2, static_rational<30> >,
Chris@16 760 list<scale<2, static_rational<40> >,
Chris@16 761 list<scale<2, static_rational<50> >,
Chris@16 762 list<scale<2, static_rational<60> >,
Chris@16 763 list<scale<2, static_rational<70> >,
Chris@101 764 list<scale<2, static_rational<80> >,
Chris@101 765 list<scale<2, static_rational<90> >,
Chris@101 766 dimensionless_type> > > > > > > > > binary_prefixes;
Chris@16 767
Chris@16 768 template<class Os, class Quantity>
Chris@16 769 struct print_default_t {
Chris@16 770 typedef void result_type;
Chris@16 771 void operator()() const
Chris@16 772 {
Chris@16 773 *os << q->value() << ' ' << typename Quantity::unit_type();
Chris@16 774 }
Chris@16 775 Os* os;
Chris@16 776 const Quantity* q;
Chris@16 777 };
Chris@16 778
Chris@16 779 template<class Os, class Quantity>
Chris@16 780 print_default_t<Os, Quantity> print_default(Os& os, const Quantity& q)
Chris@16 781 {
Chris@16 782 print_default_t<Os, Quantity> result = { &os, &q };
Chris@16 783 return result;
Chris@16 784 }
Chris@16 785
Chris@16 786 template<class Os>
Chris@16 787 struct print_scale_t {
Chris@16 788 typedef void result_type;
Chris@16 789 template<class Prefix, class T>
Chris@16 790 void operator()(Prefix, const T& t) const
Chris@16 791 {
Chris@16 792 *prefixed = true;
Chris@16 793 *os << t / Prefix::value() << ' ';
Chris@16 794 switch(units::get_format(*os)) {
Chris@16 795 case name_fmt: do_print(*os, Prefix::name()); break;
Chris@16 796 case raw_fmt:
Chris@16 797 case symbol_fmt: do_print(*os, Prefix::symbol()); break;
Chris@16 798 case typename_fmt: do_print(*os, units::simplify_typename(Prefix())); *os << ' '; break;
Chris@16 799 }
Chris@16 800 }
Chris@16 801 template<long N, class T>
Chris@16 802 void operator()(scale<N, static_rational<0> >, const T& t) const
Chris@16 803 {
Chris@16 804 *prefixed = false;
Chris@16 805 *os << t << ' ';
Chris@16 806 }
Chris@16 807 Os* os;
Chris@16 808 bool* prefixed;
Chris@16 809 };
Chris@16 810
Chris@16 811 template<class Os>
Chris@16 812 print_scale_t<Os> print_scale(Os& os, bool& prefixed)
Chris@16 813 {
Chris@16 814 print_scale_t<Os> result = { &os, &prefixed };
Chris@16 815 return result;
Chris@16 816 }
Chris@16 817
Chris@16 818 // puts parentheses around a unit
Chris@16 819 /// INTERNAL ONLY
Chris@16 820 template<class Dimension,class Units,class Scale, class Subformatter>
Chris@16 821 inline std::string
Chris@16 822 maybe_parenthesize(const unit<Dimension, heterogeneous_system<heterogeneous_system_impl<Units, Dimension, Scale> > >&, Subformatter f)
Chris@16 823 {
Chris@16 824 std::string str;
Chris@16 825
Chris@16 826 std::string without_scale = f(unit<Dimension, heterogeneous_system<heterogeneous_system_impl<Units, Dimension, dimensionless_type> > >());
Chris@16 827
Chris@16 828 if (f.is_default_string(without_scale, unit<Dimension, heterogeneous_system<heterogeneous_system_impl<Units, Dimension, dimensionless_type> > >()))
Chris@16 829 {
Chris@16 830 str += "(";
Chris@16 831 str += without_scale;
Chris@16 832 str += ")";
Chris@16 833 }
Chris@16 834 else
Chris@16 835 {
Chris@16 836 str += without_scale;
Chris@16 837 }
Chris@16 838
Chris@16 839 return(str);
Chris@16 840 }
Chris@16 841
Chris@16 842 // This overload catches scaled units that have a single base unit
Chris@16 843 // raised to the first power. It causes si::nano * si::meters to not
Chris@16 844 // put parentheses around the meters. i.e. nm rather than n(m)
Chris@16 845 /// INTERNAL ONLY
Chris@16 846 template<class Dimension,class Unit,class Scale, class Subformatter>
Chris@16 847 inline std::string
Chris@16 848 maybe_parenthesize(const unit<Dimension, heterogeneous_system<heterogeneous_system_impl<list<heterogeneous_system_dim<Unit, static_rational<1> >,dimensionless_type>, Dimension, Scale> > >&, Subformatter f)
Chris@16 849 {
Chris@16 850 return f(unit<Dimension, heterogeneous_system<heterogeneous_system_impl<list<heterogeneous_system_dim<Unit, static_rational<1> >, dimensionless_type>, Dimension, dimensionless_type> > >());
Chris@16 851 }
Chris@16 852
Chris@16 853 template<class Prefixes, class CharT, class Traits, class Unit, class T, class F>
Chris@16 854 void do_print_prefixed_impl(std::basic_ostream<CharT, Traits>& os, const quantity<Unit, T>& q, F default_)
Chris@16 855 {
Chris@16 856 bool prefixed;
Chris@16 857 if(detail::find_matching_scale<Prefixes>(q.value(), autoprefix_norm(q.value()), detail::print_scale(os, prefixed))) {
Chris@16 858 if(prefixed) {
Chris@16 859 switch(units::get_format(os)) {
Chris@16 860 case symbol_fmt: do_print(os, maybe_parenthesize(Unit(), format_symbol_impl())); break;
Chris@16 861 case raw_fmt: do_print(os, maybe_parenthesize(Unit(), format_raw_symbol_impl())); break;
Chris@16 862 case name_fmt: do_print(os, maybe_parenthesize(Unit(), format_name_impl())); break;
Chris@16 863 case typename_fmt: do_print(os, simplify_typename(Unit())); break;
Chris@16 864 }
Chris@16 865 } else {
Chris@16 866 os << Unit();
Chris@16 867 }
Chris@16 868 } else {
Chris@16 869 default_();
Chris@16 870 }
Chris@16 871 }
Chris@16 872
Chris@16 873 // Handle units like si::kilograms that have a scale embedded in the
Chris@16 874 // base unit. This overload is disabled if the scaled base unit has
Chris@16 875 // a user-defined string representation.
Chris@16 876 template<class Prefixes, class CharT, class Traits, class Dimension, class BaseUnit, class BaseScale, class Scale, class T>
Chris@16 877 typename base_unit_info<
Chris@16 878 scaled_base_unit<BaseUnit, Scale>
Chris@16 879 >::base_unit_info_primary_template
Chris@16 880 do_print_prefixed(
Chris@16 881 std::basic_ostream<CharT, Traits>& os,
Chris@16 882 const quantity<
Chris@16 883 unit<
Chris@16 884 Dimension,
Chris@16 885 heterogeneous_system<
Chris@16 886 heterogeneous_system_impl<
Chris@16 887 list<
Chris@16 888 heterogeneous_system_dim<
Chris@16 889 scaled_base_unit<BaseUnit, BaseScale>,
Chris@16 890 static_rational<1>
Chris@16 891 >,
Chris@16 892 dimensionless_type
Chris@16 893 >,
Chris@16 894 Dimension,
Chris@16 895 Scale
Chris@16 896 >
Chris@16 897 >
Chris@16 898 >,
Chris@16 899 T
Chris@16 900 >& q)
Chris@16 901 {
Chris@16 902 quantity<
Chris@16 903 unit<
Chris@16 904 Dimension,
Chris@16 905 heterogeneous_system<
Chris@16 906 heterogeneous_system_impl<
Chris@16 907 list<
Chris@16 908 heterogeneous_system_dim<BaseUnit, static_rational<1> >,
Chris@16 909 dimensionless_type
Chris@16 910 >,
Chris@16 911 Dimension,
Chris@16 912 dimensionless_type
Chris@16 913 >
Chris@16 914 >
Chris@16 915 >,
Chris@16 916 T
Chris@16 917 > unscaled(q);
Chris@16 918 detail::do_print_prefixed_impl<Prefixes>(os, unscaled, detail::print_default(os, q));
Chris@16 919 }
Chris@16 920
Chris@16 921 template<class Prefixes, class CharT, class Traits, class Dimension, class L, class Scale, class T>
Chris@16 922 void do_print_prefixed(
Chris@16 923 std::basic_ostream<CharT, Traits>& os,
Chris@16 924 const quantity<
Chris@16 925 unit<
Chris@16 926 Dimension,
Chris@16 927 heterogeneous_system<
Chris@16 928 heterogeneous_system_impl<
Chris@16 929 L,
Chris@16 930 Dimension,
Chris@16 931 Scale
Chris@16 932 >
Chris@16 933 >
Chris@16 934 >,
Chris@16 935 T
Chris@16 936 >& q)
Chris@16 937 {
Chris@16 938 quantity<
Chris@16 939 unit<
Chris@16 940 Dimension,
Chris@16 941 heterogeneous_system<
Chris@16 942 heterogeneous_system_impl<
Chris@16 943 L,
Chris@16 944 Dimension,
Chris@16 945 dimensionless_type
Chris@16 946 >
Chris@16 947 >
Chris@16 948 >,
Chris@16 949 T
Chris@16 950 > unscaled(q);
Chris@16 951 detail::do_print_prefixed_impl<Prefixes>(os, unscaled, detail::print_default(os, q));
Chris@16 952 }
Chris@16 953
Chris@16 954 template<class Prefixes, class CharT, class Traits, class Dimension, class System, class T>
Chris@16 955 void do_print_prefixed(std::basic_ostream<CharT, Traits>& os, const quantity<unit<Dimension, System>, T>& q)
Chris@16 956 {
Chris@16 957 detail::do_print_prefixed<Prefixes>(os, quantity<unit<Dimension, typename make_heterogeneous_system<Dimension, System>::type>, T>(q));
Chris@16 958 }
Chris@16 959
Chris@16 960 template<class Prefixes, class CharT, class Traits, class Unit, class T>
Chris@16 961 void do_print_prefixed(std::basic_ostream<CharT, Traits>& os, const quantity<Unit, T>& q)
Chris@16 962 {
Chris@16 963 detail::print_default(os, q)();
Chris@16 964 }
Chris@16 965
Chris@16 966 template<class Prefixes, class CharT, class Traits, class Unit, class T>
Chris@16 967 void maybe_print_prefixed(std::basic_ostream<CharT, Traits>& os, const quantity<Unit, T>& q, mpl::true_)
Chris@16 968 {
Chris@16 969 detail::do_print_prefixed<Prefixes>(os, q);
Chris@16 970 }
Chris@16 971
Chris@16 972 template<class Prefixes, class CharT, class Traits, class Unit, class T>
Chris@16 973 void maybe_print_prefixed(std::basic_ostream<CharT, Traits>& os, const quantity<Unit, T>& q, mpl::false_)
Chris@16 974 {
Chris@16 975 detail::print_default(os, q)();
Chris@16 976 }
Chris@16 977
Chris@16 978 inline mpl::true_ test_norm(double) { return mpl::true_(); }
Chris@16 979 inline mpl::false_ test_norm(one) { return mpl::false_(); }
Chris@16 980
Chris@16 981 } // namespace detail
Chris@16 982
Chris@16 983 template<class Dimension,class System>
Chris@16 984 inline std::string
Chris@16 985 typename_string(const unit<Dimension, System>&)
Chris@16 986 {
Chris@16 987 return simplify_typename(typename reduce_unit< unit<Dimension,System> >::type());
Chris@16 988 }
Chris@16 989
Chris@16 990 template<class Dimension,class System>
Chris@16 991 inline std::string
Chris@16 992 symbol_string(const unit<Dimension, System>&)
Chris@16 993 {
Chris@16 994 return detail::to_string_impl(unit<Dimension,System>(), detail::format_symbol_impl());
Chris@16 995 }
Chris@16 996
Chris@16 997 template<class Dimension,class System>
Chris@16 998 inline std::string
Chris@16 999 name_string(const unit<Dimension, System>&)
Chris@16 1000 {
Chris@16 1001 return detail::to_string_impl(unit<Dimension,System>(), detail::format_name_impl());
Chris@16 1002 }
Chris@16 1003
Chris@16 1004 /// Print a @c unit as a list of base units and their exponents.
Chris@16 1005 ///
Chris@16 1006 /// for @c symbol_format outputs e.g. "m s^-1" or "J".
Chris@16 1007 /// for @c name_format outputs e.g. "meter second^-1" or "joule".
Chris@16 1008 /// for @c raw_format outputs e.g. "m s^-1" or "meter kilogram^2 second^-2".
Chris@16 1009 /// for @c typename_format outputs the typename itself (currently demangled only on GCC).
Chris@16 1010 template<class Char, class Traits, class Dimension, class System>
Chris@16 1011 inline std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& os, const unit<Dimension, System>& u)
Chris@16 1012 {
Chris@16 1013 if (units::get_format(os) == typename_fmt)
Chris@16 1014 {
Chris@16 1015 detail::do_print(os, typename_string(u));
Chris@16 1016 }
Chris@16 1017 else if (units::get_format(os) == raw_fmt)
Chris@16 1018 {
Chris@16 1019 detail::do_print(os, detail::to_string_impl(u, detail::format_raw_symbol_impl()));
Chris@16 1020 }
Chris@16 1021 else if (units::get_format(os) == symbol_fmt)
Chris@16 1022 {
Chris@16 1023 detail::do_print(os, symbol_string(u));
Chris@16 1024 }
Chris@16 1025 else if (units::get_format(os) == name_fmt)
Chris@16 1026 {
Chris@16 1027 detail::do_print(os, name_string(u));
Chris@16 1028 }
Chris@16 1029 else
Chris@16 1030 {
Chris@16 1031 assert(!"The format mode must be one of: typename_format, raw_format, name_format, symbol_format");
Chris@16 1032 }
Chris@16 1033
Chris@16 1034 return(os);
Chris@16 1035 }
Chris@16 1036
Chris@16 1037 /// \brief Print a @c quantity.
Chris@16 1038 /// \details Prints the value followed by the unit.
Chris@16 1039 /// If the engineering_prefix, or binary_prefix is set,
Chris@16 1040 /// tries to scale the value appropriately.
Chris@16 1041 /// For example, it might print 12.345 km instead of 12345 m.
Chris@16 1042 /// (Note does @b not attempt to automatically scale scalars like double, float...)
Chris@16 1043 template<class Char, class Traits, class Unit, class T>
Chris@16 1044 inline std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& os, const quantity<Unit, T>& q)
Chris@16 1045 {
Chris@16 1046 if (units::get_autoprefix(os) == autoprefix_none)
Chris@16 1047 {
Chris@16 1048 os << q.value() << ' ' << Unit();
Chris@16 1049 }
Chris@16 1050 else if (units::get_autoprefix(os) == autoprefix_engineering)
Chris@16 1051 {
Chris@16 1052 detail::maybe_print_prefixed<detail::engineering_prefixes>(os, q, detail::test_norm(autoprefix_norm(q.value())));
Chris@16 1053 }
Chris@16 1054 else if (units::get_autoprefix(os) == autoprefix_binary)
Chris@16 1055 {
Chris@16 1056 detail::maybe_print_prefixed<detail::binary_prefixes>(os, q, detail::test_norm(autoprefix_norm(q.value())));
Chris@16 1057 }
Chris@16 1058 else
Chris@16 1059 {
Chris@16 1060 assert(!"Autoprefixing must be one of: no_prefix, engineering_prefix, binary_prefix");
Chris@16 1061 }
Chris@16 1062 return(os);
Chris@16 1063 }
Chris@16 1064
Chris@16 1065 } // namespace units
Chris@16 1066
Chris@16 1067 } // namespace boost
Chris@16 1068
Chris@16 1069 #endif