You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
201 lines
9.0 KiB
201 lines
9.0 KiB
// Boost.Units - A C++ library for zero-overhead dimensional analysis and |
|
// unit/quantity manipulation and conversion |
|
// |
|
// Copyright (C) 2003-2008 Matthias Christian Schabel |
|
// Copyright (C) 2008 Steven Watanabe |
|
// |
|
// Distributed under the Boost Software License, Version 1.0. (See |
|
// accompanying file LICENSE_1_0.txt or copy at |
|
// http://www.boost.org/LICENSE_1_0.txt) |
|
|
|
#ifndef BOOST_UNITS_CONSTANTS_HPP |
|
#define BOOST_UNITS_CONSTANTS_HPP |
|
|
|
#include <boost/config/no_tr1/cmath.hpp> |
|
#include <iosfwd> |
|
#include <iomanip> |
|
|
|
#include <boost/io/ios_state.hpp> |
|
|
|
#include <boost/units/static_constant.hpp> |
|
#include <boost/units/units_fwd.hpp> |
|
#include <boost/units/operators.hpp> |
|
|
|
namespace boost { |
|
|
|
namespace units { |
|
|
|
template<class Base> |
|
struct constant |
|
{ |
|
typedef typename Base::value_type value_type; |
|
operator value_type() const { return Base().value(); } |
|
value_type value() const { return Base().value(); } |
|
value_type uncertainty() const { return Base().uncertainty(); } |
|
value_type lower_bound() const { return Base().lower_bound(); } |
|
value_type upper_bound() const { return Base().upper_bound(); } |
|
}; |
|
|
|
template<class Base> |
|
struct physical_constant |
|
{ |
|
typedef typename Base::value_type value_type; |
|
operator value_type() const { return Base().value(); } |
|
value_type value() const { return Base().value(); } |
|
value_type uncertainty() const { return Base().uncertainty(); } |
|
value_type lower_bound() const { return Base().lower_bound(); } |
|
value_type upper_bound() const { return Base().upper_bound(); } |
|
}; |
|
|
|
#define BOOST_UNITS_DEFINE_HELPER(name, symbol, template_name) \ |
|
\ |
|
template<class T, class Arg1, class Arg2> \ |
|
struct name ## _typeof_helper<constant<T>, template_name<Arg1, Arg2> >\ |
|
{ \ |
|
typedef typename name ## _typeof_helper<typename T::value_type, template_name<Arg1, Arg2> >::type type;\ |
|
}; \ |
|
\ |
|
template<class T, class Arg1, class Arg2> \ |
|
struct name ## _typeof_helper<template_name<Arg1, Arg2>, constant<T> >\ |
|
{ \ |
|
typedef typename name ## _typeof_helper<template_name<Arg1, Arg2>, typename T::value_type>::type type;\ |
|
}; \ |
|
\ |
|
template<class T, class Arg1, class Arg2> \ |
|
typename name ## _typeof_helper<typename T::value_type, template_name<Arg1, Arg2> >::type \ |
|
operator symbol(const constant<T>& t, const template_name<Arg1, Arg2>& u)\ |
|
{ \ |
|
return(t.value() symbol u); \ |
|
} \ |
|
\ |
|
template<class T, class Arg1, class Arg2> \ |
|
typename name ## _typeof_helper<template_name<Arg1, Arg2>, typename T::value_type>::type \ |
|
operator symbol(const template_name<Arg1, Arg2>& u, const constant<T>& t)\ |
|
{ \ |
|
return(u symbol t.value()); \ |
|
} |
|
|
|
BOOST_UNITS_DEFINE_HELPER(add, +, unit) |
|
BOOST_UNITS_DEFINE_HELPER(add, +, quantity) |
|
BOOST_UNITS_DEFINE_HELPER(subtract, -, unit) |
|
BOOST_UNITS_DEFINE_HELPER(subtract, -, quantity) |
|
BOOST_UNITS_DEFINE_HELPER(multiply, *, unit) |
|
BOOST_UNITS_DEFINE_HELPER(multiply, *, quantity) |
|
BOOST_UNITS_DEFINE_HELPER(divide, /, unit) |
|
BOOST_UNITS_DEFINE_HELPER(divide, /, quantity) |
|
|
|
#undef BOOST_UNITS_DEFINE_HELPER |
|
|
|
#define BOOST_UNITS_DEFINE_HELPER(name, symbol) \ |
|
\ |
|
template<class T1, class T2> \ |
|
struct name ## _typeof_helper<constant<T1>, constant<T2> > \ |
|
{ \ |
|
typedef typename name ## _typeof_helper<typename T1::value_type, typename T2::value_type>::type type;\ |
|
}; \ |
|
\ |
|
template<class T1, class T2> \ |
|
typename name ## _typeof_helper<typename T1::value_type, typename T2::value_type>::type \ |
|
operator symbol(const constant<T1>& t, const constant<T2>& u) \ |
|
{ \ |
|
return(t.value() symbol u.value()); \ |
|
} \ |
|
\ |
|
template<class T1, class T2> \ |
|
struct name ## _typeof_helper<constant<T1>, T2> \ |
|
{ \ |
|
typedef typename name ## _typeof_helper<typename T1::value_type, T2>::type type;\ |
|
}; \ |
|
\ |
|
template<class T1, class T2> \ |
|
struct name ## _typeof_helper<T1, constant<T2> > \ |
|
{ \ |
|
typedef typename name ## _typeof_helper<T1, typename T2::value_type>::type type;\ |
|
}; \ |
|
\ |
|
template<class T1, class T2> \ |
|
typename name ## _typeof_helper<typename T1::value_type, T2>::type \ |
|
operator symbol(const constant<T1>& t, const T2& u) \ |
|
{ \ |
|
return(t.value() symbol u); \ |
|
} \ |
|
\ |
|
template<class T1, class T2> \ |
|
typename name ## _typeof_helper<T1, typename T2::value_type>::type \ |
|
operator symbol(const T1& t, const constant<T2>& u) \ |
|
{ \ |
|
return(t symbol u.value()); \ |
|
} |
|
|
|
BOOST_UNITS_DEFINE_HELPER(add, +) |
|
BOOST_UNITS_DEFINE_HELPER(subtract, -) |
|
BOOST_UNITS_DEFINE_HELPER(multiply, *) |
|
BOOST_UNITS_DEFINE_HELPER(divide, /) |
|
|
|
#undef BOOST_UNITS_DEFINE_HELPER |
|
|
|
#define BOOST_UNITS_PHYSICAL_CONSTANT(name, type, value_, uncertainty_) \ |
|
struct name ## _t { \ |
|
typedef type value_type; \ |
|
operator value_type() const { return value_; } \ |
|
value_type value() const { return value_; } \ |
|
value_type uncertainty() const { return uncertainty_; } \ |
|
value_type lower_bound() const { return value_-uncertainty_; } \ |
|
value_type upper_bound() const { return value_+uncertainty_; } \ |
|
}; \ |
|
BOOST_UNITS_STATIC_CONSTANT(name, boost::units::constant<boost::units::physical_constant<name ## _t> >) = { } |
|
|
|
// stream output |
|
template<class Char, class Traits, class Y> |
|
inline |
|
std::basic_ostream<Char,Traits>& operator<<(std::basic_ostream<Char,Traits>& os,const physical_constant<Y>& val) |
|
{ |
|
boost::io::ios_precision_saver precision_saver(os); |
|
//boost::io::ios_width_saver width_saver(os); |
|
boost::io::ios_flags_saver flags_saver(os); |
|
|
|
//os << std::setw(21); |
|
typedef typename Y::value_type value_type; |
|
|
|
if (val.uncertainty() > value_type()) |
|
{ |
|
const double relative_uncertainty = std::abs(val.uncertainty()/val.value()); |
|
|
|
const double exponent = std::log10(relative_uncertainty); |
|
const long digits_of_precision = static_cast<long>(std::ceil(std::abs(exponent)))+3; |
|
|
|
// should try to replicate NIST CODATA syntax |
|
os << std::setprecision(digits_of_precision) |
|
//<< std::setw(digits_of_precision+8) |
|
//<< std::scientific |
|
<< val.value(); |
|
// << long(10*(relative_uncertainty/std::pow(Y(10),Y(exponent)))); |
|
|
|
os << " (rel. unc. = " |
|
<< std::setprecision(1) |
|
//<< std::setw(7) |
|
<< std::scientific |
|
<< relative_uncertainty << ")"; |
|
} |
|
else |
|
{ |
|
os << val.value() << " (exact)"; |
|
} |
|
|
|
return os; |
|
} |
|
|
|
// stream output |
|
template<class Char, class Traits, class Y> |
|
inline |
|
std::basic_ostream<Char,Traits>& operator<<(std::basic_ostream<Char,Traits>& os,const constant<Y>&) |
|
{ |
|
os << Y(); |
|
return os; |
|
} |
|
|
|
} // namespace units |
|
|
|
} // namespace boost |
|
|
|
#endif // BOOST_UNITS_CONSTANTS_HPP
|
|
|