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
|