00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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
00046
00047
00048 enum origin_t
00049 {
00050
00051
00052
00053
00054 origin_theory = 0,
00055
00056
00057
00058
00059 origin_experiment = 1,
00060
00061
00062
00063 origin_calculation = 2,
00064
00065
00066
00067 origin_systematics = 4,
00068
00069
00070
00071 origin_other = 8,
00072
00073
00074
00075
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
00096
00097
00098
00099
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
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
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
00141
00142
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
00157
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
00172
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
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
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
00215
00216
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
00230 origin_type origin() const { return (origin_type)m_origin; }
00231
00232
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
00241
00242
00243
00244
00245
00246 bool is_known() const { return m_pf_cent != pf_unknown; }
00247
00248
00249 bool is_finite() const { return m_pf_cent == pf_finite; }
00250
00251
00252 bool is_inf() const { return m_pf_cent == pf_infinite; }
00253
00254
00255 bool dev_below_is_known() const { return m_pf_s_mi != pf_unknown; }
00256
00257
00258 bool dev_above_is_known() const { return m_pf_s_pl != pf_unknown; }
00259
00260
00261 bool dev_below_is_finite() const { return m_pf_s_mi == pf_finite; }
00262
00263
00264 bool dev_above_is_finite() const { return m_pf_s_pl == pf_finite; }
00265
00266
00267 bool dev_below_is_inf() const { return m_pf_s_mi == pf_infinite; }
00268
00269
00270 bool dev_above_is_inf() const { return m_pf_s_pl == pf_infinite; }
00271
00272
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
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
00288 T cent() const { return m_cent; }
00289
00290
00291 T min() const { return m_cent - m_s_mi; }
00292
00293
00294 T max() const { return m_cent + m_s_pl; }
00295
00296
00297 T dev() const
00298 {
00299 return m_s_mi > m_s_pl? m_s_mi : m_s_pl;
00300 }
00301
00302
00303 T rdev() const { return dev()/std::fabs(m_cent); }
00304
00305
00306 T dev_below() const { return m_s_mi; }
00307
00308
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