constants.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. // Boost.Units - A C++ library for zero-overhead dimensional analysis and
  2. // unit/quantity manipulation and conversion
  3. //
  4. // Copyright (C) 2003-2008 Matthias Christian Schabel
  5. // Copyright (C) 2008 Steven Watanabe
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See
  8. // accompanying file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. #ifndef BOOST_UNITS_CONSTANTS_HPP
  11. #define BOOST_UNITS_CONSTANTS_HPP
  12. #include <boost/config/no_tr1/cmath.hpp>
  13. #include <iosfwd>
  14. #include <iomanip>
  15. #include <boost/io/ios_state.hpp>
  16. #include <boost/units/static_constant.hpp>
  17. #include <boost/units/units_fwd.hpp>
  18. #include <boost/units/operators.hpp>
  19. #include <boost/units/static_rational.hpp>
  20. #include <boost/units/detail/one.hpp>
  21. namespace boost {
  22. namespace units {
  23. template<class Base>
  24. struct constant
  25. {
  26. typedef typename Base::value_type value_type;
  27. BOOST_CONSTEXPR operator value_type() const { return Base().value(); }
  28. BOOST_CONSTEXPR value_type value() const { return Base().value(); }
  29. BOOST_CONSTEXPR value_type uncertainty() const { return Base().uncertainty(); }
  30. BOOST_CONSTEXPR value_type lower_bound() const { return Base().lower_bound(); }
  31. BOOST_CONSTEXPR value_type upper_bound() const { return Base().upper_bound(); }
  32. };
  33. template<class Base>
  34. struct physical_constant
  35. {
  36. typedef typename Base::value_type value_type;
  37. BOOST_CONSTEXPR operator value_type() const { return Base().value(); }
  38. BOOST_CONSTEXPR value_type value() const { return Base().value(); }
  39. BOOST_CONSTEXPR value_type uncertainty() const { return Base().uncertainty(); }
  40. BOOST_CONSTEXPR value_type lower_bound() const { return Base().lower_bound(); }
  41. BOOST_CONSTEXPR value_type upper_bound() const { return Base().upper_bound(); }
  42. };
  43. #define BOOST_UNITS_DEFINE_HELPER(name, symbol, template_name) \
  44. \
  45. template<class T, class Arg1, class Arg2> \
  46. struct name ## _typeof_helper<constant<T>, template_name<Arg1, Arg2> >\
  47. { \
  48. typedef typename name ## _typeof_helper<typename T::value_type, template_name<Arg1, Arg2> >::type type;\
  49. }; \
  50. \
  51. template<class T, class Arg1, class Arg2> \
  52. struct name ## _typeof_helper<template_name<Arg1, Arg2>, constant<T> >\
  53. { \
  54. typedef typename name ## _typeof_helper<template_name<Arg1, Arg2>, typename T::value_type>::type type;\
  55. }; \
  56. \
  57. template<class T, class Arg1, class Arg2> \
  58. BOOST_CONSTEXPR \
  59. typename name ## _typeof_helper<typename T::value_type, template_name<Arg1, Arg2> >::type \
  60. operator symbol(const constant<T>& t, const template_name<Arg1, Arg2>& u)\
  61. { \
  62. return(t.value() symbol u); \
  63. } \
  64. \
  65. template<class T, class Arg1, class Arg2> \
  66. BOOST_CONSTEXPR \
  67. typename name ## _typeof_helper<template_name<Arg1, Arg2>, typename T::value_type>::type \
  68. operator symbol(const template_name<Arg1, Arg2>& u, const constant<T>& t)\
  69. { \
  70. return(u symbol t.value()); \
  71. }
  72. BOOST_UNITS_DEFINE_HELPER(add, +, unit)
  73. BOOST_UNITS_DEFINE_HELPER(add, +, quantity)
  74. BOOST_UNITS_DEFINE_HELPER(subtract, -, unit)
  75. BOOST_UNITS_DEFINE_HELPER(subtract, -, quantity)
  76. BOOST_UNITS_DEFINE_HELPER(multiply, *, unit)
  77. BOOST_UNITS_DEFINE_HELPER(multiply, *, quantity)
  78. BOOST_UNITS_DEFINE_HELPER(divide, /, unit)
  79. BOOST_UNITS_DEFINE_HELPER(divide, /, quantity)
  80. #undef BOOST_UNITS_DEFINE_HELPER
  81. #define BOOST_UNITS_DEFINE_HELPER(name, symbol) \
  82. \
  83. template<class T1, class T2> \
  84. struct name ## _typeof_helper<constant<T1>, constant<T2> > \
  85. { \
  86. typedef typename name ## _typeof_helper<typename T1::value_type, typename T2::value_type>::type type;\
  87. }; \
  88. \
  89. template<class T1, class T2> \
  90. BOOST_CONSTEXPR \
  91. typename name ## _typeof_helper<typename T1::value_type, typename T2::value_type>::type \
  92. operator symbol(const constant<T1>& t, const constant<T2>& u) \
  93. { \
  94. return(t.value() symbol u.value()); \
  95. } \
  96. \
  97. template<class T1, class T2> \
  98. struct name ## _typeof_helper<constant<T1>, T2> \
  99. { \
  100. typedef typename name ## _typeof_helper<typename T1::value_type, T2>::type type;\
  101. }; \
  102. \
  103. template<class T1, class T2> \
  104. struct name ## _typeof_helper<T1, constant<T2> > \
  105. { \
  106. typedef typename name ## _typeof_helper<T1, typename T2::value_type>::type type;\
  107. }; \
  108. \
  109. template<class T1, class T2> \
  110. BOOST_CONSTEXPR \
  111. typename name ## _typeof_helper<typename T1::value_type, T2>::type \
  112. operator symbol(const constant<T1>& t, const T2& u) \
  113. { \
  114. return(t.value() symbol u); \
  115. } \
  116. \
  117. template<class T1, class T2> \
  118. BOOST_CONSTEXPR \
  119. typename name ## _typeof_helper<T1, typename T2::value_type>::type \
  120. operator symbol(const T1& t, const constant<T2>& u) \
  121. { \
  122. return(t symbol u.value()); \
  123. }
  124. BOOST_UNITS_DEFINE_HELPER(add, +)
  125. BOOST_UNITS_DEFINE_HELPER(subtract, -)
  126. BOOST_UNITS_DEFINE_HELPER(multiply, *)
  127. BOOST_UNITS_DEFINE_HELPER(divide, /)
  128. #undef BOOST_UNITS_DEFINE_HELPER
  129. #define BOOST_UNITS_DEFINE_HELPER(name, symbol) \
  130. \
  131. template<class T1> \
  132. struct name ## _typeof_helper<constant<T1>, one> \
  133. { \
  134. typedef typename name ## _typeof_helper<typename T1::value_type, one>::type type;\
  135. }; \
  136. \
  137. template<class T2> \
  138. struct name ## _typeof_helper<one, constant<T2> > \
  139. { \
  140. typedef typename name ## _typeof_helper<one, typename T2::value_type>::type type;\
  141. }; \
  142. \
  143. template<class T1> \
  144. BOOST_CONSTEXPR \
  145. typename name ## _typeof_helper<typename T1::value_type, one>::type \
  146. operator symbol(const constant<T1>& t, const one& u) \
  147. { \
  148. return(t.value() symbol u); \
  149. } \
  150. \
  151. template<class T2> \
  152. BOOST_CONSTEXPR \
  153. typename name ## _typeof_helper<one, typename T2::value_type>::type \
  154. operator symbol(const one& t, const constant<T2>& u) \
  155. { \
  156. return(t symbol u.value()); \
  157. }
  158. BOOST_UNITS_DEFINE_HELPER(multiply, *)
  159. BOOST_UNITS_DEFINE_HELPER(divide, /)
  160. #undef BOOST_UNITS_DEFINE_HELPER
  161. template<class T1, long N, long D>
  162. struct power_typeof_helper<constant<T1>, static_rational<N,D> >
  163. {
  164. typedef power_typeof_helper<typename T1::value_type, static_rational<N,D> > base;
  165. typedef typename base::type type;
  166. static BOOST_CONSTEXPR type value(const constant<T1>& arg)
  167. {
  168. return base::value(arg.value());
  169. }
  170. };
  171. #define BOOST_UNITS_DEFINE_HELPER(name, symbol) \
  172. \
  173. template<class T1, class E> \
  174. struct name ## _typeof_helper<constant<T1> > \
  175. { \
  176. typedef typename name ## _typeof_helper<typename T1::value_type, E>::type type;\
  177. }; \
  178. \
  179. template<class T1> \
  180. BOOST_CONSTEXPR \
  181. typename name ## _typeof_helper<typename T1::value_type, one>::type \
  182. operator symbol(const constant<T1>& t, const one& u) \
  183. { \
  184. return(t.value() symbol u); \
  185. } \
  186. \
  187. template<class T2> \
  188. BOOST_CONSTEXPR \
  189. typename name ## _typeof_helper<one, typename T2::value_type>::type \
  190. operator symbol(const one& t, const constant<T2>& u) \
  191. { \
  192. return(t symbol u.value()); \
  193. }
  194. #define BOOST_UNITS_PHYSICAL_CONSTANT(name, type, value_, uncertainty_) \
  195. struct name ## _t { \
  196. typedef type value_type; \
  197. BOOST_CONSTEXPR operator value_type() const { return value_; } \
  198. BOOST_CONSTEXPR value_type value() const { return value_; } \
  199. BOOST_CONSTEXPR value_type uncertainty() const { return uncertainty_; } \
  200. BOOST_CONSTEXPR value_type lower_bound() const { return value_-uncertainty_; } \
  201. BOOST_CONSTEXPR value_type upper_bound() const { return value_+uncertainty_; } \
  202. }; \
  203. BOOST_UNITS_STATIC_CONSTANT(name, boost::units::constant<boost::units::physical_constant<name ## _t> >) = { }
  204. // stream output
  205. template<class Char, class Traits, class Y>
  206. inline
  207. std::basic_ostream<Char,Traits>& operator<<(std::basic_ostream<Char,Traits>& os,const physical_constant<Y>& val)
  208. {
  209. boost::io::ios_precision_saver precision_saver(os);
  210. //boost::io::ios_width_saver width_saver(os);
  211. boost::io::ios_flags_saver flags_saver(os);
  212. //os << std::setw(21);
  213. typedef typename Y::value_type value_type;
  214. if (val.uncertainty() > value_type())
  215. {
  216. const double relative_uncertainty = std::abs(val.uncertainty()/val.value());
  217. const double exponent = std::log10(relative_uncertainty);
  218. const long digits_of_precision = static_cast<long>(std::ceil(std::abs(exponent)))+3;
  219. // should try to replicate NIST CODATA syntax
  220. os << std::setprecision(digits_of_precision)
  221. //<< std::setw(digits_of_precision+8)
  222. //<< std::scientific
  223. << val.value();
  224. // << long(10*(relative_uncertainty/std::pow(Y(10),Y(exponent))));
  225. os << " (rel. unc. = "
  226. << std::setprecision(1)
  227. //<< std::setw(7)
  228. << std::scientific
  229. << relative_uncertainty << ")";
  230. }
  231. else
  232. {
  233. os << val.value() << " (exact)";
  234. }
  235. return os;
  236. }
  237. // stream output
  238. template<class Char, class Traits, class Y>
  239. inline
  240. std::basic_ostream<Char,Traits>& operator<<(std::basic_ostream<Char,Traits>& os,const constant<Y>&)
  241. {
  242. os << Y();
  243. return os;
  244. }
  245. } // namespace units
  246. } // namespace boost
  247. #endif // BOOST_UNITS_CONSTANTS_HPP