constants.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  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. operator value_type() const { return Base().value(); }
  28. value_type value() const { return Base().value(); }
  29. value_type uncertainty() const { return Base().uncertainty(); }
  30. value_type lower_bound() const { return Base().lower_bound(); }
  31. 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. operator value_type() const { return Base().value(); }
  38. value_type value() const { return Base().value(); }
  39. value_type uncertainty() const { return Base().uncertainty(); }
  40. value_type lower_bound() const { return Base().lower_bound(); }
  41. 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. typename name ## _typeof_helper<typename T::value_type, template_name<Arg1, Arg2> >::type \
  59. operator symbol(const constant<T>& t, const template_name<Arg1, Arg2>& u)\
  60. { \
  61. return(t.value() symbol u); \
  62. } \
  63. \
  64. template<class T, class Arg1, class Arg2> \
  65. typename name ## _typeof_helper<template_name<Arg1, Arg2>, typename T::value_type>::type \
  66. operator symbol(const template_name<Arg1, Arg2>& u, const constant<T>& t)\
  67. { \
  68. return(u symbol t.value()); \
  69. }
  70. BOOST_UNITS_DEFINE_HELPER(add, +, unit)
  71. BOOST_UNITS_DEFINE_HELPER(add, +, quantity)
  72. BOOST_UNITS_DEFINE_HELPER(subtract, -, unit)
  73. BOOST_UNITS_DEFINE_HELPER(subtract, -, quantity)
  74. BOOST_UNITS_DEFINE_HELPER(multiply, *, unit)
  75. BOOST_UNITS_DEFINE_HELPER(multiply, *, quantity)
  76. BOOST_UNITS_DEFINE_HELPER(divide, /, unit)
  77. BOOST_UNITS_DEFINE_HELPER(divide, /, quantity)
  78. #undef BOOST_UNITS_DEFINE_HELPER
  79. #define BOOST_UNITS_DEFINE_HELPER(name, symbol) \
  80. \
  81. template<class T1, class T2> \
  82. struct name ## _typeof_helper<constant<T1>, constant<T2> > \
  83. { \
  84. typedef typename name ## _typeof_helper<typename T1::value_type, typename T2::value_type>::type type;\
  85. }; \
  86. \
  87. template<class T1, class T2> \
  88. typename name ## _typeof_helper<typename T1::value_type, typename T2::value_type>::type \
  89. operator symbol(const constant<T1>& t, const constant<T2>& u) \
  90. { \
  91. return(t.value() symbol u.value()); \
  92. } \
  93. \
  94. template<class T1, class T2> \
  95. struct name ## _typeof_helper<constant<T1>, T2> \
  96. { \
  97. typedef typename name ## _typeof_helper<typename T1::value_type, T2>::type type;\
  98. }; \
  99. \
  100. template<class T1, class T2> \
  101. struct name ## _typeof_helper<T1, constant<T2> > \
  102. { \
  103. typedef typename name ## _typeof_helper<T1, typename T2::value_type>::type type;\
  104. }; \
  105. \
  106. template<class T1, class T2> \
  107. typename name ## _typeof_helper<typename T1::value_type, T2>::type \
  108. operator symbol(const constant<T1>& t, const T2& u) \
  109. { \
  110. return(t.value() symbol u); \
  111. } \
  112. \
  113. template<class T1, class T2> \
  114. typename name ## _typeof_helper<T1, typename T2::value_type>::type \
  115. operator symbol(const T1& t, const constant<T2>& u) \
  116. { \
  117. return(t symbol u.value()); \
  118. }
  119. BOOST_UNITS_DEFINE_HELPER(add, +)
  120. BOOST_UNITS_DEFINE_HELPER(subtract, -)
  121. BOOST_UNITS_DEFINE_HELPER(multiply, *)
  122. BOOST_UNITS_DEFINE_HELPER(divide, /)
  123. #undef BOOST_UNITS_DEFINE_HELPER
  124. #define BOOST_UNITS_DEFINE_HELPER(name, symbol) \
  125. \
  126. template<class T1> \
  127. struct name ## _typeof_helper<constant<T1>, one> \
  128. { \
  129. typedef typename name ## _typeof_helper<typename T1::value_type, one>::type type;\
  130. }; \
  131. \
  132. template<class T2> \
  133. struct name ## _typeof_helper<one, constant<T2> > \
  134. { \
  135. typedef typename name ## _typeof_helper<one, typename T2::value_type>::type type;\
  136. }; \
  137. \
  138. template<class T1> \
  139. typename name ## _typeof_helper<typename T1::value_type, one>::type \
  140. operator symbol(const constant<T1>& t, const one& u) \
  141. { \
  142. return(t.value() symbol u); \
  143. } \
  144. \
  145. template<class T2> \
  146. typename name ## _typeof_helper<one, typename T2::value_type>::type \
  147. operator symbol(const one& t, const constant<T2>& u) \
  148. { \
  149. return(t symbol u.value()); \
  150. }
  151. BOOST_UNITS_DEFINE_HELPER(multiply, *)
  152. BOOST_UNITS_DEFINE_HELPER(divide, /)
  153. #undef BOOST_UNITS_DEFINE_HELPER
  154. template<class T1, long N, long D>
  155. struct power_typeof_helper<constant<T1>, static_rational<N,D> >
  156. {
  157. typedef power_typeof_helper<typename T1::value_type, static_rational<N,D> > base;
  158. typedef typename base::type type;
  159. static type value(const constant<T1>& arg)
  160. {
  161. return base::value(arg.value());
  162. }
  163. };
  164. #define BOOST_UNITS_DEFINE_HELPER(name, symbol) \
  165. \
  166. template<class T1, class E> \
  167. struct name ## _typeof_helper<constant<T1> > \
  168. { \
  169. typedef typename name ## _typeof_helper<typename T1::value_type, E>::type type;\
  170. }; \
  171. \
  172. template<class T1> \
  173. typename name ## _typeof_helper<typename T1::value_type, one>::type \
  174. operator symbol(const constant<T1>& t, const one& u) \
  175. { \
  176. return(t.value() symbol u); \
  177. } \
  178. \
  179. template<class T2> \
  180. typename name ## _typeof_helper<one, typename T2::value_type>::type \
  181. operator symbol(const one& t, const constant<T2>& u) \
  182. { \
  183. return(t symbol u.value()); \
  184. }
  185. #define BOOST_UNITS_PHYSICAL_CONSTANT(name, type, value_, uncertainty_) \
  186. struct name ## _t { \
  187. typedef type value_type; \
  188. operator value_type() const { return value_; } \
  189. value_type value() const { return value_; } \
  190. value_type uncertainty() const { return uncertainty_; } \
  191. value_type lower_bound() const { return value_-uncertainty_; } \
  192. value_type upper_bound() const { return value_+uncertainty_; } \
  193. }; \
  194. BOOST_UNITS_STATIC_CONSTANT(name, boost::units::constant<boost::units::physical_constant<name ## _t> >) = { }
  195. // stream output
  196. template<class Char, class Traits, class Y>
  197. inline
  198. std::basic_ostream<Char,Traits>& operator<<(std::basic_ostream<Char,Traits>& os,const physical_constant<Y>& val)
  199. {
  200. boost::io::ios_precision_saver precision_saver(os);
  201. //boost::io::ios_width_saver width_saver(os);
  202. boost::io::ios_flags_saver flags_saver(os);
  203. //os << std::setw(21);
  204. typedef typename Y::value_type value_type;
  205. if (val.uncertainty() > value_type())
  206. {
  207. const double relative_uncertainty = std::abs(val.uncertainty()/val.value());
  208. const double exponent = std::log10(relative_uncertainty);
  209. const long digits_of_precision = static_cast<long>(std::ceil(std::abs(exponent)))+3;
  210. // should try to replicate NIST CODATA syntax
  211. os << std::setprecision(digits_of_precision)
  212. //<< std::setw(digits_of_precision+8)
  213. //<< std::scientific
  214. << val.value();
  215. // << long(10*(relative_uncertainty/std::pow(Y(10),Y(exponent))));
  216. os << " (rel. unc. = "
  217. << std::setprecision(1)
  218. //<< std::setw(7)
  219. << std::scientific
  220. << relative_uncertainty << ")";
  221. }
  222. else
  223. {
  224. os << val.value() << " (exact)";
  225. }
  226. return os;
  227. }
  228. // stream output
  229. template<class Char, class Traits, class Y>
  230. inline
  231. std::basic_ostream<Char,Traits>& operator<<(std::basic_ostream<Char,Traits>& os,const constant<Y>&)
  232. {
  233. os << Y();
  234. return os;
  235. }
  236. } // namespace units
  237. } // namespace boost
  238. #endif // BOOST_UNITS_CONSTANTS_HPP