blob: 217fac1b527ea5127c7a4962857dd0cf5cdef516 [file] [log] [blame]
// 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_MEASUREMENT_HPP
#define BOOST_UNITS_MEASUREMENT_HPP
#include <cmath>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <boost/io/ios_state.hpp>
#include <boost/units/static_rational.hpp>
namespace boost {
namespace units {
namespace sqr_namespace /**/ {
template<class Y>
Y sqr(Y val)
{ return val*val; }
} // namespace
using sqr_namespace::sqr;
template<class Y>
class measurement
{
public:
typedef measurement<Y> this_type;
typedef Y value_type;
measurement(const value_type& val = value_type(),
const value_type& err = value_type()) :
value_(val),
uncertainty_(std::abs(err))
{ }
measurement(const this_type& source) :
value_(source.value_),
uncertainty_(source.uncertainty_)
{ }
//~measurement() { }
this_type& operator=(const this_type& source)
{
if (this == &source) return *this;
value_ = source.value_;
uncertainty_ = source.uncertainty_;
return *this;
}
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_; }
this_type& operator+=(const value_type& val)
{
value_ += val;
return *this;
}
this_type& operator-=(const value_type& val)
{
value_ -= val;
return *this;
}
this_type& operator*=(const value_type& val)
{
value_ *= val;
uncertainty_ *= val;
return *this;
}
this_type& operator/=(const value_type& val)
{
value_ /= val;
uncertainty_ /= val;
return *this;
}
this_type& operator+=(const this_type& /*source*/);
this_type& operator-=(const this_type& /*source*/);
this_type& operator*=(const this_type& /*source*/);
this_type& operator/=(const this_type& /*source*/);
private:
value_type value_,
uncertainty_;
};
}
}
#if BOOST_UNITS_HAS_BOOST_TYPEOF
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::measurement, 1)
#endif
namespace boost {
namespace units {
template<class Y>
inline
measurement<Y>&
measurement<Y>::operator+=(const this_type& source)
{
uncertainty_ = std::sqrt(sqr(uncertainty_)+sqr(source.uncertainty_));
value_ += source.value_;
return *this;
}
template<class Y>
inline
measurement<Y>&
measurement<Y>::operator-=(const this_type& source)
{
uncertainty_ = std::sqrt(sqr(uncertainty_)+sqr(source.uncertainty_));
value_ -= source.value_;
return *this;
}
template<class Y>
inline
measurement<Y>&
measurement<Y>::operator*=(const this_type& source)
{
uncertainty_ = (value_*source.value_)*
std::sqrt(sqr(uncertainty_/value_)+
sqr(source.uncertainty_/source.value_));
value_ *= source.value_;
return *this;
}
template<class Y>
inline
measurement<Y>&
measurement<Y>::operator/=(const this_type& source)
{
uncertainty_ = (value_/source.value_)*
std::sqrt(sqr(uncertainty_/value_)+
sqr(source.uncertainty_/source.value_));
value_ /= source.value_;
return *this;
}
// value_type op measurement
template<class Y>
inline
measurement<Y>
operator+(Y lhs,const measurement<Y>& rhs)
{
return (measurement<Y>(lhs,Y(0))+=rhs);
}
template<class Y>
inline
measurement<Y>
operator-(Y lhs,const measurement<Y>& rhs)
{
return (measurement<Y>(lhs,Y(0))-=rhs);
}
template<class Y>
inline
measurement<Y>
operator*(Y lhs,const measurement<Y>& rhs)
{
return (measurement<Y>(lhs,Y(0))*=rhs);
}
template<class Y>
inline
measurement<Y>
operator/(Y lhs,const measurement<Y>& rhs)
{
return (measurement<Y>(lhs,Y(0))/=rhs);
}
// measurement op value_type
template<class Y>
inline
measurement<Y>
operator+(const measurement<Y>& lhs,Y rhs)
{
return (measurement<Y>(lhs)+=measurement<Y>(rhs,Y(0)));
}
template<class Y>
inline
measurement<Y>
operator-(const measurement<Y>& lhs,Y rhs)
{
return (measurement<Y>(lhs)-=measurement<Y>(rhs,Y(0)));
}
template<class Y>
inline
measurement<Y>
operator*(const measurement<Y>& lhs,Y rhs)
{
return (measurement<Y>(lhs)*=measurement<Y>(rhs,Y(0)));
}
template<class Y>
inline
measurement<Y>
operator/(const measurement<Y>& lhs,Y rhs)
{
return (measurement<Y>(lhs)/=measurement<Y>(rhs,Y(0)));
}
// measurement op measurement
template<class Y>
inline
measurement<Y>
operator+(const measurement<Y>& lhs,const measurement<Y>& rhs)
{
return (measurement<Y>(lhs)+=rhs);
}
template<class Y>
inline
measurement<Y>
operator-(const measurement<Y>& lhs,const measurement<Y>& rhs)
{
return (measurement<Y>(lhs)-=rhs);
}
template<class Y>
inline
measurement<Y>
operator*(const measurement<Y>& lhs,const measurement<Y>& rhs)
{
return (measurement<Y>(lhs)*=rhs);
}
template<class Y>
inline
measurement<Y>
operator/(const measurement<Y>& lhs,const measurement<Y>& rhs)
{
return (measurement<Y>(lhs)/=rhs);
}
/// specialize power typeof helper
template<class Y,long N,long D>
struct power_typeof_helper<measurement<Y>,static_rational<N,D> >
{
typedef measurement<
typename power_typeof_helper<Y,static_rational<N,D> >::type
> type;
static type value(const measurement<Y>& x)
{
const static_rational<N,D> rat;
const Y m = Y(rat.numerator())/Y(rat.denominator()),
newval = std::pow(x.value(),m),
err = newval*std::sqrt(std::pow(m*x.uncertainty()/x.value(),2));
return type(newval,err);
}
};
/// specialize root typeof helper
template<class Y,long N,long D>
struct root_typeof_helper<measurement<Y>,static_rational<N,D> >
{
typedef measurement<
typename root_typeof_helper<Y,static_rational<N,D> >::type
> type;
static type value(const measurement<Y>& x)
{
const static_rational<N,D> rat;
const Y m = Y(rat.denominator())/Y(rat.numerator()),
newval = std::pow(x.value(),m),
err = newval*std::sqrt(std::pow(m*x.uncertainty()/x.value(),2));
return type(newval,err);
}
};
// stream output
template<class Y>
inline
std::ostream& operator<<(std::ostream& os,const measurement<Y>& val)
{
boost::io::ios_precision_saver precision_saver(os);
boost::io::ios_flags_saver flags_saver(os);
os << val.value() << "(+/-" << val.uncertainty() << ")";
return os;
}
} // namespace units
} // namespace boost
#endif // BOOST_UNITS_MEASUREMENT_HPP