Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

more/phys/confidence_interval.h

Go to the documentation of this file.
00001 //  Copyright (C) 2001--2002  Petter Urkedal (petter.urkedal@matfys.lth.se)
00002 //
00003 //  This file is free software; you can redistribute it and/or modify
00004 //  it under the terms of the GNU General Public License as published by
00005 //  the Free Software Foundation; either version 2 of the License, or
00006 //  (at your option) any later version.
00007 //
00008 //  This file is distributed in the hope that it will be useful,
00009 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 //  GNU General Public License for more details.
00012 //
00013 //  You should have received a copy of the GNU General Public License
00014 //  along with this program; if not, write to the Free Software
00015 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00016 //
00017 //  As a special exception, you may use this file as part of a free
00018 //  software library without restriction.  Specifically, if other files
00019 //  instantiate templates or use macros or inline functions from this
00020 //  file, or you compile this file and link it with other files to
00021 //  produce an executable, this file does not by itself cause the
00022 //  resulting executable to be covered by the GNU General Public
00023 //  License.  This exception does not however invalidate any other
00024 //  reasons why the executable file might be covered by the GNU General
00025 //  Public License.
00026 //
00027 //  $Id: confidence_interval.h,v 1.1 2002/05/30 18:01:40 petter_urkedal Exp $
00028 
00029 
00030 #ifndef MORE_PHYS_CONFIDENCE_INTERVAL_H
00031 #define MORE_PHYS_CONFIDENCE_INTERVAL_H
00032 
00033 
00034 #include <iosfwd>
00035 #include <cmath>
00036 #include <cstdlib>
00037 #include <limits>
00038 #include <more/math/math.h>
00039 #include <more/io/syncstream.h>
00040 
00041 
00042 namespace more {
00043 namespace phys {
00044 
00045   /** Origin of a quantity.  Origins may be ored together, except for
00046    ** \c origin_theory which is 0 and \c origin_unknown which is the
00047    ** binary or of all the others.  */
00048   enum origin_t
00049   {
00050       /** Use for mathematical quantities or physical quantities which
00051        ** are exact by definition or known from a trusted theory (but
00052        ** not calculated from a model).  This origin is exclusive (can
00053        ** not be combined with the other origins). */
00054       origin_theory             = 0,
00055 
00056       /** The value is based on an experiment, and may usually
00057        ** be trusted within some small multiple of the given
00058        ** deviation. */
00059       origin_experiment         = 1,
00060 
00061       /** The value is based on a calculation and depends on
00062        ** the correctness of the model used. */
00063       origin_calculation        = 2,
00064 
00065       /** The value is based on systematics and may therefore
00066        ** have unexpected deviations. */
00067       origin_systematics        = 4,
00068 
00069       /** An origin different from the above.  This may have a
00070        ** specific meaning in client code or in parts of the code. */
00071       origin_other              = 8,
00072 
00073       /** Use if origin is unknown, uspecified, or other than
00074        ** the below.  This origin implies the other
00075        ** non-theoretic origins and is the least reliable. */
00076       origin_unknown            = 15
00077   };
00078 
00079   static unsigned int const origin_width = 4;
00080 
00081   inline origin_t operator|(origin_t x, origin_t y)
00082   { return origin_t(static_cast<int>(x) | static_cast<int>(y)); }
00083   inline origin_t operator&(origin_t x, origin_t y)
00084   { return origin_t(static_cast<int>(x) & static_cast<int>(y)); }
00085   inline origin_t operator^(origin_t x, origin_t y)
00086   { return origin_t(static_cast<int>(x) ^ static_cast<int>(y)); }
00087   inline origin_t operator~(origin_t x)
00088   { return origin_t(~ static_cast<int>(x)); }
00089 
00090   inline origin_t operator|=(origin_t& x, origin_t y) { return x = x | y; }
00091   inline origin_t operator&=(origin_t& x, origin_t y) { return x = x & y; }
00092   inline origin_t operator^=(origin_t& x, origin_t y) { return x = x ^ y; }
00093 
00094 
00095   /** \class confidence_interval confidence_interval.h \
00096    **     more/phys/confidence_interval.h
00097    **
00098    ** A type for storing a value and its deviation.
00099    ** \pre \c T is a floating point number. <tt>Moment > 0</tt>. */
00100   template<typename T>
00101     struct confidence_interval
00102     {
00103         typedef origin_t origin_type;
00104         static struct unknown_tag {} unknown;
00105         static struct infinite_tag {} infinite;
00106 
00107       private:
00108         enum pf_t
00109         {
00110             pf_unknown = 0,
00111             pf_finite = 1,
00112             pf_infinite = 2
00113         };
00114       public:
00115         /// Constuct an completely undefined value.
00116         confidence_interval()
00117             : m_origin(origin_unknown),
00118               m_pf_cent(pf_unknown),
00119               m_pf_s_mi(pf_unknown),
00120               m_pf_s_pl(pf_unknown),
00121               m_aux_flags(0),
00122               m_moment(0),
00123               m_cent(nan()),
00124               m_s_mi(nan()),
00125               m_s_pl(nan()) {}
00126 
00127         /// Construct an infinite value.
00128         confidence_interval(infinite_tag, origin_type origin = origin_unknown,
00129                             unsigned int moment = 2)
00130             : m_origin(origin),
00131               m_pf_cent(pf_infinite),
00132               m_pf_s_mi(pf_finite),
00133               m_pf_s_pl(pf_finite),
00134               m_aux_flags(0),
00135               m_moment(moment),
00136               m_cent(nan()),
00137               m_s_mi(0.0),
00138               m_s_pl(0.0) {}
00139 
00140         /** Construct an "approximately infinite" value.  Typically
00141          ** this may express a value which are unknown because it is
00142          ** too large too detect with present technology. */
00143         confidence_interval(infinite_tag, unknown_tag,
00144                             origin_type origin = origin_unknown,
00145                             unsigned int moment = 2)
00146             : m_origin(origin),
00147               m_pf_cent(pf_infinite),
00148               m_pf_s_mi(pf_unknown),
00149               m_pf_s_pl(pf_unknown),
00150               m_aux_flags(0),
00151               m_moment(moment),
00152               m_cent(nan()),
00153               m_s_mi(0.0),
00154               m_s_pl(0.0) {}
00155 
00156         /// Construct a symmetric confidence interval centered at \a x
00157         /// with standard deviation \a s.
00158         confidence_interval(T const& x, T const& s,
00159                             origin_type origin = origin_unknown,
00160                             unsigned int moment = 2)
00161             : m_origin(origin),
00162               m_pf_cent(pf_finite),
00163               m_pf_s_mi(pf_finite),
00164               m_pf_s_pl(pf_finite),
00165               m_aux_flags(0),
00166               m_moment(moment),
00167               m_cent(x),
00168               m_s_mi(s),
00169               m_s_pl(s) {}
00170 
00171         /// Construct an asymmetric confidence interval centered at \a
00172         /// x with deviations \a m_mi below and \a s_pl above.
00173         confidence_interval(T const& x, T const& s_mi, T const& s_pl,
00174                             origin_type origin = origin_unknown,
00175                             unsigned int moment = 2)
00176             : m_origin(origin),
00177               m_pf_cent(pf_finite),
00178               m_pf_s_mi(pf_finite),
00179               m_pf_s_pl(pf_finite),
00180               m_aux_flags(0),
00181               m_moment(moment),
00182               m_cent(x),
00183               m_s_mi(s_mi),
00184               m_s_pl(s_pl) {}
00185 
00186         /// Construct a lower bound \a x with deviation \a s_mi.
00187         confidence_interval(T const& x, T const& s_mi, infinite_tag,
00188                             origin_type origin = origin_unknown,
00189                             unsigned int moment = 2)
00190             : m_origin(origin),
00191               m_pf_cent(pf_finite),
00192               m_pf_s_mi(pf_finite),
00193               m_pf_s_pl(pf_infinite),
00194               m_aux_flags(0),
00195               m_moment(moment),
00196               m_cent(x),
00197               m_s_mi(s_mi),
00198               m_s_pl(inf()) {}
00199 
00200         /// Construct an upper bound \a x with deviation \a s_pl.
00201         confidence_interval(T const& x, infinite_tag, T const& s_pl,
00202                             origin_type origin = origin_unknown,
00203                             unsigned int moment = 2)
00204             : m_origin(origin),
00205               m_pf_cent(pf_finite),
00206               m_pf_s_mi(pf_infinite),
00207               m_pf_s_pl(pf_finite),
00208               m_aux_flags(0),
00209               m_moment(moment),
00210               m_cent(x),
00211               m_s_mi(nan()),
00212               m_s_pl(s_pl) {}
00213 
00214         /** Construct an approximate value \a x with unspecified
00215          ** deviation.  Approximate values are synced with 10 bits
00216          ** precition (œôøå 3 digits). */
00217         confidence_interval(T const& x, unknown_tag,
00218                             origin_type origin = origin_unknown)
00219             : m_origin(origin),
00220               m_pf_cent(pf_finite),
00221               m_pf_s_mi(pf_unknown),
00222               m_pf_s_pl(pf_unknown),
00223               m_aux_flags(0),
00224               m_moment(0),
00225               m_cent(x),
00226               m_s_mi(nan()),
00227               m_s_pl(nan()) {}
00228 
00229         /// Return generic information on the origin of the value.
00230         origin_type origin() const { return (origin_type)m_origin; }
00231 
00232         /// Set the generic origin of the value.
00233         void set_origin(origin_type o) { m_origin = o; }
00234 
00235         void be_uncertain() { m_aux_flags |= 1; }
00236         bool is_uncertain() const { return m_aux_flags & 1; }
00237         void be_signless() { m_aux_flags |= 2; }
00238         bool is_signless() const { return m_aux_flags & 2; }
00239 
00240 //      void set_systematic() { m_origin |= origin_systematics; }
00241 //      void set_calculated() { m_origin |= origin_calculation; }
00242 //      bool is_systematic() const { return m_origin & origin_systematics; }
00243 //      bool is_calculated() const { return m_origin & origin_calculation; }
00244 
00245         /// True if the value is defined is some way.
00246         bool is_known() const { return m_pf_cent != pf_unknown; }
00247 
00248         /// True if the valus is known and finite.
00249         bool is_finite() const { return m_pf_cent == pf_finite; }
00250 
00251         /// True if an infinite value.
00252         bool is_inf() const { return m_pf_cent == pf_infinite; }
00253 
00254         /// True if the lower deviation is given.
00255         bool dev_below_is_known() const { return m_pf_s_mi != pf_unknown; }
00256 
00257         /// True if the upper deviation is given.
00258         bool dev_above_is_known() const { return m_pf_s_pl != pf_unknown; }
00259 
00260         /// Deviation below is known and finite.
00261         bool dev_below_is_finite() const { return m_pf_s_mi == pf_finite; }
00262 
00263         /// Deviation above is known and finite.
00264         bool dev_above_is_finite() const { return m_pf_s_pl == pf_finite; }
00265 
00266         /// Deviation below is known and infinite.
00267         bool dev_below_is_inf() const { return m_pf_s_mi == pf_infinite; }
00268 
00269         /// Deviation above is known and infinite.
00270         bool dev_above_is_inf() const { return m_pf_s_pl == pf_infinite; }
00271 
00272         /// True if the deviation above and below are the same.
00273         bool is_symmetric() const
00274         {
00275             return m_pf_s_mi == m_pf_s_pl
00276                 && (m_pf_s_mi != pf_finite || m_s_pl == m_s_mi);
00277         }
00278 
00279         /// True if exact within the numeric precision.
00280         bool is_exact() const
00281         {
00282             return dev_below_is_finite()
00283                 && dev_above_is_finite()
00284                 && m_s_mi == 0.0 && m_s_pl == 0.0;
00285         }
00286 
00287         /// Center of the confidence interval.
00288         T cent() const { return m_cent; }
00289 
00290         /// Minimum value in the confidence interval.
00291         T min() const { return m_cent - m_s_mi; }
00292 
00293         /// Maximum value in the confidence interval.
00294         T max() const { return m_cent + m_s_pl; }
00295 
00296         /// Return <tt>max(dev_above(), dev_below())</tt>.
00297         T dev() const
00298         {
00299             return m_s_mi > m_s_pl? m_s_mi : m_s_pl;
00300         }
00301 
00302         /// Return \c abs(cent())/dev().
00303         T rdev() const { return dev()/std::fabs(m_cent); }
00304 
00305         /// The deviation below the central value.
00306         T dev_below() const { return m_s_mi; }
00307 
00308         /// The deviation above the central value.
00309         T dev_above() const { return m_s_pl; }
00310 
00311         confidence_interval&
00312         operator*=(T x)
00313         {
00314             if (x < 0) {
00315                 negate();
00316                 x = -x;
00317             }
00318             m_cent *= x;
00319             m_s_pl *= x;
00320             m_s_mi *= x;
00321             return *this;
00322         }
00323 
00324         confidence_interval&
00325         operator/=(T x) { return (*this) *= T(1)/x; }
00326 
00327         confidence_interval&
00328         operator+=(confidence_interval const& rhs)
00329         {
00330             m_cent += rhs.m_cent;
00331             add_deviation(rhs);
00332             return *this;
00333         }
00334 
00335         confidence_interval&
00336         operator-=(confidence_interval const& rhs)
00337         {
00338             m_cent -= rhs.m_cent;
00339             add_deviation(rhs);
00340             return *this;
00341         }
00342 
00343         void negate()
00344         {
00345             m_cent = -m_cent;
00346             T tmp = m_s_pl;
00347             m_s_pl = m_s_mi;
00348             m_s_mi = tmp;
00349         }
00350 
00351         void sync(io::syncstream&);
00352 
00353     private:
00354         static T nan() { return std::numeric_limits<T>::quiet_NaN(); }
00355         static T inf() { return std::numeric_limits<T>::infinity(); }
00356 
00357         void add_deviation(confidence_interval const& rhs);
00358 
00359         unsigned int m_origin : origin_width;
00360         unsigned int m_pf_cent : 2;
00361         unsigned int m_pf_s_mi : 2;
00362         unsigned int m_pf_s_pl : 2;
00363         unsigned int m_aux_flags : 4;
00364         unsigned char m_moment;
00365         T m_cent;
00366         T m_s_mi;
00367         T m_s_pl;
00368     };
00369 
00370 
00371   template<typename T>
00372     inline confidence_interval<T>
00373     operator-(confidence_interval<T> x)
00374     {
00375         x.negate();
00376         return x;
00377     }
00378   template<typename T>
00379     inline confidence_interval<T>
00380     operator+(confidence_interval<T> const& x) { return x; }
00381 
00382   template<typename T>
00383     inline confidence_interval<T>
00384     operator*(confidence_interval<T> x, T const& y)
00385     {
00386         return x *= y;
00387     }
00388   template<typename T>
00389     inline confidence_interval<T>
00390     operator*(T const& x, confidence_interval<T> y)
00391     {
00392         return y *= x;
00393     }
00394   template<typename T>
00395     inline confidence_interval<T>
00396     operator/(confidence_interval<T> x, T const& y)
00397     {
00398         return x /= y;
00399     }
00400   template<typename T>
00401     inline confidence_interval<T>
00402     operator+(confidence_interval<T> x,
00403               confidence_interval<T> y)
00404     {
00405         return x += y;
00406     }
00407   template<typename T>
00408     inline confidence_interval<T>
00409     operator-(confidence_interval<T> x,
00410               confidence_interval<T> y)
00411     {
00412         return x -= y;
00413     }
00414 
00415   template<typename T>
00416     inline bool
00417     better_precision(confidence_interval<T> const& x,
00418                      confidence_interval<T> const& y)
00419     {
00420         if (x.is_indet_below() || x.is_indet_above())
00421             return y.is_indet_below() && y.is_indet_above();
00422         else if (y.is_indet_below() || y.is_indet_above())
00423             return true;
00424         else
00425             return x.dev() < y.dev();
00426     }
00427 
00428   template<typename Char, typename Traits, typename T>
00429     std::basic_ostream<Char, Traits>&
00430     operator<<(std::basic_ostream<Char, Traits>&,
00431                confidence_interval<T> const&);
00432 
00433   void set_origin_indicator(std::ostream&, origin_t ogn, char const* ind);
00434 
00435   void set_origin_indicator(std::ostream&, char const* pfx, char const* sfx,
00436                             char const* sep);
00437 
00438 }}
00439 
00440 #endif

Generated on Sat Sep 7 19:11:21 2002 for more with Doxygen 1.2.13.1. Doxygen 1.2.13.1 is written and copyright 1997-2002 by Dimitri van Heesch.