CORSIKA8  0.0.0
The framework to simulate particle cascades for astroparticle physics
quantity_io.hpp
Go to the documentation of this file.
1 
22 #ifndef PHYS_UNITS_QUANTITY_IO_HPP_INCLUDED
23 #define PHYS_UNITS_QUANTITY_IO_HPP_INCLUDED
24 
26 
27 #include <algorithm>
28 #include <iosfwd>
29 #include <map>
30 #include <stdexcept>
31 #include <string>
32 #include <sstream>
33 
35 
36 namespace phys {
37 
39 
40 namespace units {
41 
43 
44 struct quantity_error : public std::runtime_error
45 {
46  quantity_error( std::string const text )
47  : std::runtime_error( text ) { }
48 };
49 
51 
53 {
54  prefix_error( std::string const text )
55  : quantity_error( text ) { }
56 };
57 
59 
60 inline Rep prefix( std::string const prefix_ )
61 {
62  std::map<std::string, Rep> table
63  {
64  { "m", milli },
65  { "k", kilo },
66  { "u", micro },
67  { "M", mega },
68  { "n", nano },
69  { "G", giga },
70  { "p", pico },
71  { "T", tera },
72  { "f", femto },
73  { "P", peta },
74  { "a", atto },
75  { "E", exa },
76  { "z", zepto },
77  { "Z", zetta },
78  { "y", yocto },
79  { "Y", yotta },
80  { "h", hecto },
81  { "da", deka },
82  { "d", deci },
83  { "c", centi },
84  };
85 
86  auto pos = table.find( prefix_ );
87 
88  if ( pos == table.end() )
89  {
90  throw prefix_error( "quantity: unrecognized prefix '" + prefix_ + "'" );
91  }
92 
93  return pos->second;
94 }
95 
102 template <typename Dims>
103 struct unit_info
104 {
106 
107  static bool single()
108  {
109  return Dims::is_base;
110  }
111 
113 
114  static std::string name()
115  {
116  return symbol();
117  }
118 
120 
121  static std::string symbol()
122  {
123  std::ostringstream os;
124 
125  bool first = true;
126 
127  emit_dim( os, "m", Dims::dim1, first );
128  emit_dim( os, "kg", Dims::dim2, first );
129  emit_dim( os, "s", Dims::dim3, first );
130  emit_dim( os, "A", Dims::dim4, first );
131  emit_dim( os, "K", Dims::dim5, first );
132  emit_dim( os, "mol", Dims::dim6, first );
133  emit_dim( os, "cd", Dims::dim7, first );
134  emit_dim( os, "eV", Dims::dim8, first );
135 
136  return os.str();
137  }
138 
140 
141  static void emit_dim( std::ostream & os, const char * label, int exp, bool & first )
142  {
143  if( exp == 0 )
144  return;
145 
146  if ( first )
147  first = false;
148  else
149  os << " ";
150 
151  os << label;
152 
153  if( exp > 1 )
154  os << "+";
155 
156  if( exp != 1 )
157  os << exp;
158  }
159 };
160 
161 }} // namespace phys::units
162 
163 #include "quantity_io_meter.hpp"
164 #include "quantity_io_kilogram.hpp"
165 #include "quantity_io_second.hpp"
166 #include "quantity_io_ampere.hpp"
167 #include "quantity_io_mole.hpp"
168 #include "quantity_io_candela.hpp"
169 
170 /*
171  * User must choose celsius or kelvin, either by defining
172  * QUANTITY_USE_CELSIUS or QUANTITY_USE_KELVIN, or by
173  * including the desired include file.
174  */
175 #if defined(QUANTITY_USE_CELSIUS) && defined(QUANTITY_USE_KELVIN)
176 # error At most define one of QUANTITY_USE_CELSIUS, QUANTITY_USE_KELVIN
177 #endif
178 #ifdef QUANTITY_USE_CELSIUS
179 # include "quantity_io_celsius.hpp"
180 #endif
181 #ifdef QUANTITY_USE_KELVIN
182 # include "quantity_io_kelvin.hpp"
183 #endif
184 
185 namespace phys { namespace units {
186 
188 
189 template< typename Dims, typename T >
190 std::string to_magnitude( quantity<Dims, T> const & q )
191 {
192  std::ostringstream os;
193  os << q.magnitude();
194  return os.str();
195 }
196 
198 
199 template< typename Dims, typename T >
200 std::string to_unit_name( quantity<Dims, T> const & /* q */)
201 {
202  return unit_info<Dims>::name();
203 }
204 
206 
207 template< typename Dims, typename T >
208 std::string to_unit_symbol( quantity<Dims, T> const & /* q */)
209 {
210  return unit_info<Dims>::symbol();
211 }
212 
214 
215 inline std::string to_string( long double const value )
216 {
217  std::ostringstream os;
218  os << value;
219  return os.str();
220 }
221 
223 
224 namespace io {
225 
227 
228 template< typename Dims, typename T >
229 std::ostream & operator<<( std::ostream & os, quantity<Dims, T> const & q )
230 {
231  return os << q.magnitude() << " " << to_unit_symbol( q );
232 }
233 
235 
236 template< typename Dims, typename T >
237 std::string to_string( quantity<Dims, T> const & q )
238 {
239  std::ostringstream os;
240  os << q;
241  return os.str();
242 }
243 
244 } // namespace io
245 
246 }} // namespace phys::units
247 
248 #endif // PHYS_UNITS_QUANTITY_IO_HPP_INCLUDED
249 
250 /*
251  * end of file
252  */
std::string to_magnitude(quantity< Dims, T > const &q)
magnitude as string.
quantity error base class (not used by quantity itself).
Definition: quantity_io.hpp:44
candela, fundamental dimension.
std::string to_unit_name(quantity< Dims, T > const &)
unit name.
std::string to_unit_symbol(quantity< Dims, T > const &)
unit symbol.
namespace phys.
Zero-overhead dimensional analysis and unit/quantity manipulation and conversion. ...
meter, fundamental dimension.
kilogram, fundamental dimension.
static std::string symbol()
provide unit&#39;s symbol.
std::string to_string(long double const value)
string representation of value.
Rep prefix(std::string const prefix_)
return factor for given prefix.
Definition: quantity_io.hpp:60
class "quantity" is the heart of the library.
Definition: quantity.hpp:54
constexpr value_type magnitude() const
the quantity&#39;s magnitude.
Definition: quantity.hpp:346
static bool single()
true if base dimension.
Provide SI units-and-exponents in as close to NIST-specified format as possible with plain ascii...
ampere, electrical current, a fundamental dimension.
celsius, thermodynamic temperature.
static void emit_dim(std::ostream &os, const char *label, int exp, bool &first)
emit a single dimension.
prefix error, e.g. when prefix is unrecognized.
Definition: quantity_io.hpp:52
second, fundamental dimension.
static std::string name()
provide unit&#39;s name.
kelvin, fundamental dimension.