Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r80870 - in sandbox/SOC/2007/quan: . boost boost/quan boost/quan/impl libs libs/quan libs/quan/doc libs/quan/doc/doxygen libs/quan/example libs/quan/example/quan_simple libs/quan/test
From: pbristow_at_[hidden]
Date: 2012-10-05 10:48:19


Author: pbristow
Date: 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
New Revision: 80870
URL: http://svn.boost.org/trac/boost/changeset/80870

Log:
New quan package for type unc encoding uncertainty requires by visualization SVG_plot package.
Added:
   sandbox/SOC/2007/quan/
   sandbox/SOC/2007/quan/boost/
   sandbox/SOC/2007/quan/boost/quan/
   sandbox/SOC/2007/quan/boost/quan/impl/
   sandbox/SOC/2007/quan/boost/quan/impl/meas.ipp (contents, props changed)
   sandbox/SOC/2007/quan/boost/quan/impl/unc.ipp (contents, props changed)
   sandbox/SOC/2007/quan/boost/quan/impl/unc_input.ipp (contents, props changed)
   sandbox/SOC/2007/quan/boost/quan/impl/unc_output.ipp (contents, props changed)
   sandbox/SOC/2007/quan/boost/quan/impl/xiostream.ipp (contents, props changed)
   sandbox/SOC/2007/quan/boost/quan/meas.hpp (contents, props changed)
   sandbox/SOC/2007/quan/boost/quan/meas2.hpp (contents, props changed)
   sandbox/SOC/2007/quan/boost/quan/pair_io.hpp (contents, props changed)
   sandbox/SOC/2007/quan/boost/quan/rounding.hpp (contents, props changed)
   sandbox/SOC/2007/quan/boost/quan/si_units.hpp (contents, props changed)
   sandbox/SOC/2007/quan/boost/quan/type_erasure_printer.hpp (contents, props changed)
   sandbox/SOC/2007/quan/boost/quan/unc.hpp (contents, props changed)
   sandbox/SOC/2007/quan/boost/quan/unc_init.hpp (contents, props changed)
   sandbox/SOC/2007/quan/boost/quan/uncbools.hpp (contents, props changed)
   sandbox/SOC/2007/quan/boost/quan/uncdata.hpp (contents, props changed)
   sandbox/SOC/2007/quan/boost/quan/uncs.hpp (contents, props changed)
   sandbox/SOC/2007/quan/boost/quan/xiostream.hpp (contents, props changed)
   sandbox/SOC/2007/quan/libs/
   sandbox/SOC/2007/quan/libs/quan/
   sandbox/SOC/2007/quan/libs/quan/doc/
   sandbox/SOC/2007/quan/libs/quan/doc/doxygen/
   sandbox/SOC/2007/quan/libs/quan/doc/doxygen/draft.png (contents, props changed)
   sandbox/SOC/2007/quan/libs/quan/doc/doxygen/draft.svg (contents, props changed)
   sandbox/SOC/2007/quan/libs/quan/doc/doxygen/important.png (contents, props changed)
   sandbox/SOC/2007/quan/libs/quan/doc/doxygen/proposed_for_boost.png (contents, props changed)
   sandbox/SOC/2007/quan/libs/quan/doc/doxygen/quan_doxyfile.txt (contents, props changed)
   sandbox/SOC/2007/quan/libs/quan/doc/doxygen/quan_doxygen.css (contents, props changed)
   sandbox/SOC/2007/quan/libs/quan/doc/doxygen/quan_doxygen_footer.html (contents, props changed)
   sandbox/SOC/2007/quan/libs/quan/doc/doxygen/quan_doxygen_header.html (contents, props changed)
   sandbox/SOC/2007/quan/libs/quan/example/
   sandbox/SOC/2007/quan/libs/quan/example/quan_simple/
   sandbox/SOC/2007/quan/libs/quan/example/quan_simple/quan_simple.cpp (contents, props changed)
   sandbox/SOC/2007/quan/libs/quan/test/
   sandbox/SOC/2007/quan/libs/quan/test/Quan1In.txt (contents, props changed)
   sandbox/SOC/2007/quan/libs/quan/test/TestQuan1.cpp (contents, props changed)
   sandbox/SOC/2007/quan/libs/quan/test/test_rounding.cpp (contents, props changed)
   sandbox/SOC/2007/quan/libs/quan/test/unc_tests.cpp (contents, props changed)

Added: sandbox/SOC/2007/quan/boost/quan/impl/meas.ipp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/boost/quan/impl/meas.ipp 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,485 @@
+/*! \file
+ \brief Class for measurement using uncertain class - definitions.
+ \details class meas with UReal and measurement ID, order & time.
+*/
+
+// meas.ipp
+// Copyright Paul A. Bristow 2003, 2012
+
+#ifndef MEAS_IPP
+#define MEAS_IPP
+
+#ifdef _MSC_VER
+# pragma warning (push)
+#pragma warning (disable : 4189) // local variable is initialized but not referenced TODO!
+# pragma warning (disable : 4146) // unary minus operator applied to unsigned type, result still unsigned
+# pragma warning (disable : 4305) //C4305: 'initializing' : truncation from 'unsigned int' to 'short'.
+# pragma warning (disable : 4309) // C4309: 'initializing' : truncation of constant value.
+#endif
+
+#include <boost/date_time/gregorian/gregorian.hpp> //include all types plus i/o
+#include <boost/date_time/posix_time/posix_time.hpp> //include all types plus i/o
+
+//using namespace boost::gregorian;
+//using namespace boost::posix_time;
+
+#include <iostream>
+#include <cmath> // for fabs
+#include <functional> // for binary_function min
+
+#include <boost/quan/unc.hpp> // Declarations of class unc.
+#include <boost/quan/meas.hpp> // Declarations of class Meas, which calls this file.
+
+class Meas; // Measured uncertain value AND its id and order and/or time-date stamp.
+
+//using std::cout;
+//using std::cerr;
+//using std::endl;
+//using std::istream;
+//using std::ostream;
+//using std::min;
+//using std::binary_function; // <functional>
+
+// Global control of format output by class Meas.
+
+//const char timeFormatString[] = "%H:%M:%S"; // 12:20:55 time HH:MM:SS == "%X"
+ // "%H:%M"; // time as 12:26 HH:MM only, no seconds.
+ // "%X"; // 12:20:55 time HH:MM:SS
+ // "%d %b %y %H:%M:%S"; // 20 Apr 01 12:16:17
+ // "%d %b %y %H:%M"; // 20 Apr 01 12:16 // no seconds.
+ // "%a %b %d %m %Y %H:%M:%S %p"; // Fri Apr 20 04 2001 12:18:48 PM
+ // "%x"; // 04/20/01 US style MM/DD/YY.
+ // "%d %b %y"; // date as 20 Apr 01
+ // "%H:%M"; // time as 12:26 HH:MM only, no seconds.
+
+typedef double real_type; // or
+// typedef float real_type;
+
+// class Meas definitions
+// Measured value, id and its order and/or time-date.
+
+std::ostream& operator<< (std::ostream& os, const unc<false>& ud);
+// Need to instantiate for UReal<false> (might need for UReal<true> too).
+
+/*
+Meas::Meas()
+{ // Default constructor Usage: Meas z; (not Meas z()!) is exact zero.
+ value_ = 0.;
+ uncertainty_ = 0.F;
+ degFree_ = 0;
+ unctypes_ = UNC_KNOWN | UNC_EXPLICIT| DEG_FREE_EXACT | DEG_FREE_KNOWN;
+ time_ = ptime(not_a_date_time); // Time not known, and cannot be calculated from order.
+ order_ = -1; // Order not known, and cannot be calculated from time.
+ id_ = "";
+} // Meas::Meas()
+*/
+
+Meas::Meas(double d)
+{ // Constructor from double - needed by Meas(0.) lessAbs.
+ value_ = d;
+ uncertainty_ = 0.F;
+ degFree_ = 0;
+ unctypes_ = UNC_KNOWN | UNC_EXPLICIT| DEG_FREE_EXACT | DEG_FREE_KNOWN;
+ time_ = boost::gregorian::not_a_date_time; // Time not known, and cannot be calculated from order.
+ order_ = -1; // Order not known, and cannot be calculated from time.
+ id_ = "";
+#ifdef CD_TRACE
+ cerr << "Construct Meas from just double value " << value_ << "." << endl;
+#endif
+}
+/*
+Meas::Meas(uncun u)
+{ // Constructor from uncertain.
+ value_ = u.value_;
+ uncertainty_ = u.uncertainty_;
+ degFree_ = u.degFree_;
+ unctypes_ = u.unctypes_;
+ time_ = not_a_date_time; // Time not known, and cannot be calculated from order.
+ order_ = -1; // Order not known, and cannot be calculated from time.
+ id_ = "";
+#ifdef CD_TRACE
+ {
+ cerr << "Construct Meas from uncertain uncun " << value_ << "." << endl;
+ }
+#endif
+}
+
+Meas::Meas(uncun u, string id, ptime ti)
+: id_(id), time_(ti)
+{ // Constructor value, id & time (but NOT order) with default values.
+ order_ = -1; // order not known.
+ // (but may be calculated from time if in a sequence).
+ value_ = u.value_;
+ degFree_ =u.degFree_;
+ unctypes_ =u.unctypes_;
+ uncertainty_ = u.uncertainty_;
+#ifdef CD_TRACE
+ {
+ cerr << "Construct Meas using known time " << time_ << "." << endl;
+ }
+#endif
+}
+*/
+
+Meas::Meas(uncun u, string id, boost::posix_time::ptime ti /* = (boost::gregorian_time::not_a_date_time)*/, int order)
+: id_(id), time_(ti), order_(order)
+{ // Constructor value, id & order (but NOT time) with default values.
+ time_ = ti; // time not known, & cannot be calculated from order.
+ value_ = u.value_;
+ degFree_ =u.degFree_;
+ unctypes_ =u.unctypes_;
+ uncertainty_ = u.uncertainty_;
+#ifdef CD_TRACE
+ cerr << "Construct Meas using time AND known order " << time_ << ", " << order_ << "." << endl;
+#endif
+}
+
+/*
+Meas::Meas(uncun u, string id, int o)
+: id_(id), order_(o)
+{ // Constructor value, id & order (but NOT time) with default values.
+ time_ = boost::posix_time::not_a_date_time; // time not known, & cannot be calculated from order.
+ value_ = u.value_;
+ degFree_ =u.degFree_;
+ unctypes_ =u.unctypes_;
+ uncertainty_ = u.uncertainty_;
+ if(cdtrace)
+ {
+ cerr << "Construct Meas using known order " << time_ << "." << endl;
+ }
+}
+*/
+
+Meas::Meas(const Meas& rhs)
+{ // Copy constructor.
+ value_ = rhs.value_;
+ uncertainty_ = rhs.uncertainty_;
+ degFree_ = rhs.degFree_;
+ unctypes_ = rhs.unctypes_;
+ id_ = rhs.id_;
+ order_ = rhs.order_;
+ time_ = rhs.time_;
+ id_ = rhs.id_;
+}
+
+Meas::~Meas()
+{ // Default destructor used.
+}
+
+// Operators.
+
+// Meas& operator= (Meas&); // Assignment operator.
+Meas& Meas::operator= (const Meas& rhs) // Assignment operator.
+{ // Deep copy.
+ if (this == &rhs) return *this; // Assign to self, so do nothing.
+ value_ = rhs.value_;
+ uncertainty_ = rhs.uncertainty_;
+ degFree_ = rhs.degFree_;
+ unctypes_ = rhs.unctypes_;
+ order_ = rhs.order_;
+ time_ = rhs.time_;
+ id_ = rhs.id_;
+ return *this;
+}
+
+// Meas& abs (Meas&); // abs Assignment operator.
+Meas& Meas::abs(const Meas& rhs) // abs Assignment operator.
+{
+ value_ = fabs(rhs.value_);
+ uncertainty_ = rhs.uncertainty_;
+ degFree_ = rhs.degFree_;
+ unctypes_ = rhs.unctypes_;
+ order_ = rhs.order_;
+ time_ = rhs.time_;
+ id_ = rhs.id_;
+ return *this;
+}
+
+// Meas& abs (Meas&); // abs operator.
+Meas& Meas::abs(Meas& rhs) // abs Assignment operator.
+{
+ double d = rhs.value_;
+ //rhs.value_ = abs(d); // Not OK for reasons unclear - trying to use std::abs?
+ rhs.value_ = fabs(rhs.value_); // OK
+ return rhs;
+}
+
+bool Meas::operator== (const Meas& p) const
+{ // Exact Meas value Equality Comparison.
+ return (p.value_ == value_);
+ // What about checking if time the same too?
+} // Meas::operator==
+
+bool Meas::operator!= (const Meas& p) const
+{ // Comparison.
+ return (p.value_ != value_); // meas value differ (order && (p.order_ != order_).
+} // Meas::operator!=
+
+bool Meas::operator< (const Meas& rhs) const
+{// less uses operator< the most probable central value.
+ // member function so *this.value_ < *this.rhs.value_;
+ return (value_ < rhs.value_); // Comparison criterion.
+ // Only uses the measured value, not order.
+} // Meas::operator<
+
+bool Meas::operator> (const Meas& rhs) const
+{// greater uses operator> using the most probable value.
+ // member function so *this.value_ < rhs.value_;
+ return (value_ > rhs.value_);
+ // Comparison only uses the measured value (not order, nor time).
+} // Meas::operator>
+
+/*
+// What is meaning of adding measurements?
+// Has no meaning - can only add the values and uncertainty to get a new uncertain.
+// And time and order number can't be added, so
+// doubtful if operator+ and operator- are wise for Meas.
+bool Meas::operator- (const Meas& rhs) const
+{// Binary minus value using the most probable values.
+ // member function so *this.value_ < rhs.value_;
+ return value_ - rhs.value_; <<< wrong here <<<<<<<<<<<<
+ // Only uses the measured value (not order, nor time).
+} // Meas::operator>
+
+
+*/
+
+// Member predicate functions.
+
+// less uses template binary_function and operator<
+ /*
+ // TEMPLATE STRUCT less in functional
+template<class _Ty>
+ struct less
+ : public binary_function<_Ty, _Ty, bool>
+ { // functor for operator<
+ bool operator()(const _Ty& _Left, const _Ty& _Right) const
+ { // apply operator< to operands
+ return (_Left < _Right);
+ }
+ };
+ // So this function is the same as less<Meas> and so not needed.
+ bool Meas::lessM(const Meas& l, const Meas& r) // == less
+ { // Only uses the central measured value (not order, nor time).
+ return l.value_ < r.value_; // Comparison criterion.
+ }
+ // similarly nor is greater needed.
+ */
+
+bool Meas::lessAbsM(const Meas& l, const Meas& r)
+{ // Only uses the absolute central measured value, not order.
+ return ((l.value_ < 0.) ? -l.value_ : l.value_ ) < ((r.value_ < 0.) ? -r.value_ : r.value_);
+ // return std::abs(l.value_) < std::abs(r.value_); // Comparison criterion.
+ // but avoid abs because less efficient.
+} // bool Meas::lessAbsM(const Meas& l, const Meas& r)
+
+bool Meas::precedes(const Meas& l, const Meas& r)
+{ // Comparison criterion is order of measurement.
+ return l.order_ < r.order_;
+}
+
+/* Do we need this?
+bool Meas::succeeds(const Meas& l, const Meas& r)
+{ // Comparison criterion is order of measurement.
+ return l.order_ > r.order_;
+}
+*/
+
+// Call this "before"?
+bool Meas::earlier(const Meas& l, const Meas& r)
+{ // Comparison criterion is time of measurement.
+ // (Opposite, like greater, might be called 'later' - if needed).
+ if (l.time_ == boost::posix_time::not_a_date_time) return true; // not_a_date_time < any other time.
+ if (r.time_ == boost::posix_time::not_a_date_time) return false; // l.time_ IS a time, so r.time_ NOT <
+ return l.time_ < r.time_;
+} // bool Meas::earlier(const Meas& l, const Meas& r);
+
+bool Meas::less(const Meas& l, const Meas& r)
+{ // less using only value comparison.
+ // Note if lhi == rlo same then difference is 1.49012e-9 = numeric_limits<float>::epsilon
+ // (See also Meas::lessU and Meas::lessU2 which handle one and two standard deviations).
+
+ return l.value_ < r.value_;
+} // bool Meas::lessU(const Meas& l, const Meas& r)
+
+bool Meas::lessU(const Meas& l, const Meas& r)
+{ // less using comparison criterion including ONE standard deviation.
+ // Note if lhi == rlo then difference is 1.49012e-9 = numeric_limits<float>::epsilon
+ // (See also Meas::lessU2 which compares using TWO standard deviations).
+ double lhi = (l.value_ + l.uncertainty_); // Upper confidence limit of left.
+ double rlo = (r.value_ - r.uncertainty_); // Lower confidence limit of right.
+ // double diff = (l.value_ + l.uncertainty_) - (r.value_ - r.uncertainty_);
+ // diff = lhi - rlo;
+ // double tol = hypot(l.uncertainty_, r.uncertainty_); // Middle of two uncertainties.
+ bool isLess = lhi < (rlo + hypot(l.uncertainty_, r.uncertainty_)); // == less
+ if (true)
+ { // Output diagnostic info.
+ std::cerr << "<U #" << l.order_ << space << l.value_ << "="
+ << lhi // (l.value_ + l.uncertainty_)
+ << space << ((isLess) ? " < " : " !< ")
+ // << (r.value_ - r.uncertainty_) == rlo
+ << space << rlo << space << rlo + hypot(l.uncertainty_, r.uncertainty_) // tol
+ << " #" << r.order_ << "=" << r.value_
+ // << space << tol
+ // << space << diff
+ // For example: <U #1 1.1 1.2 !< 1.05 1.19142 #2 1.15
+ << std::endl;
+ }
+ return isLess;
+} // bool Meas::lessU(const Meas& l, const Meas& r)
+
+bool Meas::less2U(const Meas& l, const Meas& r)
+{ // less Comparison criterion including TWO standard deviations.
+ double lhi = (l.value_ + l.uncertainty_); // Upper confidence limit of left.
+ double rlo = (r.value_ - r.uncertainty_); // Upper confidence limit of right.
+ double diff = (l.value_ + l.uncertainty_) - (r.value_ - r.uncertainty_);
+ double tol = hypot(l.uncertainty_, r.uncertainty_);
+ // Might chose smallest, or largest uncertainty, or this compromise.
+ // Reverses the order when small uncertainty compared to large uncertainty and large chosen for tol.
+ bool isLess = lhi < (rlo + 0.0 * hypot(l.uncertainty_, r.uncertainty_)); // == less
+ if (true)
+ {
+ std::cerr << "<2U #" << l.order_ << "=" << l.value_ << space
+ << (l.value_ + l.uncertainty_)
+ << space << ((isLess) ? " < " : " !< ")
+ << (r.value_ - r.uncertainty_)
+ << space << rlo + 2.0 * tol
+ << " #" << r.order_ << "=" << r.value_
+// << space << diff
+ << std::endl;
+ }
+ return isLess;
+} // bool Meas::lessU2(const Meas& l, const Meas& r)
+
+bool Meas::greaterU(const Meas& l, const Meas& r)
+{ // l > r
+ // Uses Uncertain measured value, not order.
+ double lhi = (l.value_ + l.uncertainty_); // Upper confidence limit of left.
+ double rlo = (r.value_ - r.uncertainty_); // Lower confidence limit of right.
+ double diff = (l.value_ + l.uncertainty_) - (r.value_ - r.uncertainty_);
+ double tol = hypot(l.uncertainty_, r.uncertainty_);
+ // Might chose smallest, or largest uncertainty, or this compromise.
+ // Reverses the order when small uncertainty compared to large uncertainty and large chosen for tol.
+ bool isLess = lhi < (rlo + 0. * hypot(l.uncertainty_, r.uncertainty_)); // == less
+ return isLess;
+} // bool Meas::greater(const Meas& l, const Meas& r)
+
+bool Meas::equal_toUnc(const Meas& l, const Meas& r)
+{ // l ~== r equal within uncertainty.
+ // Uses Uncertain measured value, not order.
+ double lhi = (l.value_ + l.uncertainty_); // Upper confidence limit of left.
+ double rlo = (r.value_ - r.uncertainty_); // Lower confidence limit of right.
+ double diff = (l.value_ + l.uncertainty_) - (r.value_ - r.uncertainty_);
+ double tol = hypot(l.uncertainty_, r.uncertainty_);
+ // Might chose smallest, or largest uncertainty, or this compromise.
+ // Reverses the order when small uncertainty compared to large uncertainty and large chosen for tol.
+ bool isLess = lhi < (rlo + 0. * hypot(l.uncertainty_, r.uncertainty_)); // == less
+ return isLess;
+} // bool Meas::greater(const Meas& l, const Meas& r)
+
+// Global Output Meas::operator<<
+std::ostream& operator<< (std::ostream& os, const Meas& p) // Definition.
+{
+ // Uses:
+// std::ostream& operator<< (std::ostream& os, boost::posix_time::ptime);
+// std::ostream& operator<< (std::ostream& os, const unc<false>&);
+
+ // std::cout << p; is transformed to operator<< (std::cout, c); which does this:
+
+ //os << p.value_ << " "
+ //<< "+/-" << p.uncertainty_
+ //<< " (" << p.degFree_ << ")"
+ ////<< showuncflags // to display.
+ //<< " {" << std::hex << p.unctypes_ << std::dec << "}";
+ ////<< " {"
+ ////<< showUncTypes(p.unctypes_)
+ ////<< "}";
+
+ uncun u(p.value_, p.uncertainty_, p.degFree_, p.unctypes_);
+ os << u;
+
+ if(p.id_.size() != 0)
+ {// string identifier (if any).
+ os << " " << p.id_;
+ }
+ if (p.order_ >= 0)
+ { // means order is defined.
+ os << " #" << p.order_; // For example # 17
+ }
+ else
+ { // order undefined.
+ // So no output?
+ }
+ if (p.time_ != boost::posix_time::not_a_date_time)
+ {
+ os << ", " << p.time_; // Output t
+ }
+ // else don't output anything.
+ return os; // Allow chaining concatenation of << ... << .
+} // operator<<
+
+istream& operator>> (istream& is, Meas& p)
+{
+ uncun u;
+ is >> u;
+ p.value_ = u.value_;
+ p.uncertainty_ = u.uncertainty_;
+ p.degFree_ = u.degFree_;
+ p.unctypes_ = u.unctypes_;
+ is >> p.order_;
+ is >> p.id_;
+ is >> p.time_;
+
+ // 2 3 (could make smarter and/or require [2,3]).
+ return is; // Allow chaining concatention of >> ... >>.
+} // operator<<
+
+// Defined in unc.hpp, for example:
+
+//template <class T>
+//const double value_of(T&);
+
+template<>
+double value_of(Meas v) //! \return Meas.value() as a double.
+{ //! \return Meas.value() as a double.
+ return v.value();
+}
+
+template<>
+double unc_of(Meas u) //! \return Meas.std_dev() as a double.
+{
+ return u.std_dev();
+}
+
+//! Get values of a pair of values.
+template <> //! \tparam T1 and T2 Built-in floating-point types Meas and unc.
+std::pair<double, double> values_of(std::pair<Meas, uncun> vp)
+{
+ return std::make_pair<double, double>(value_of(vp.first), value_of(vp.second));
+}
+
+template <> //! \tparam T1 and T2 Built-in floating-point types Meas and unc.
+std::pair<double, double> values_of(std::pair<Meas const, uncun> vp)
+{
+ return std::make_pair<double, double>(value_of(vp.first), value_of(vp.second));
+}
+
+//! Get uncertainties (standard deviation) of a pair of values.
+template <> //! \tparam T Built-in floating-point type or unc.
+std::pair<double, double> uncs_of(std::pair<Meas, uncun> vp)
+{
+ return std::make_pair<double, double>(unc_of(vp.first), unc_of(vp.second));
+}
+
+template <> //! \tparam T Built-in floating-point type or unc.
+std::pair<double, double> uncs_of(std::pair<Meas const, uncun> vp)
+{
+ return std::make_pair<double, double>(unc_of(vp.first), unc_of(vp.second));
+}
+
+
+#if defined (BOOST_MSVC)
+# pragma warning(pop)
+#endif
+
+#endif // MEAS_IPP

Added: sandbox/SOC/2007/quan/boost/quan/impl/unc.ipp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/boost/quan/impl/unc.ipp 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,880 @@
+/*!
+ \file
+ \brief Uncertain class definitions.
+ \details Class for simple Propagation of Uncertainties
+ according to a pure Gaussian model.
+ Uncertain subroutines, manipulators & applicators.
+ but not <iomanip> because defined here (as a copy of code in Std iomanip).
+*/
+
+// Copyright Paul A. Bristow 1998, 2012.
+
+// Use, modification and distribution are subject to 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)
+
+// unc.ipp
+
+//#ifndef UNC_IPP
+//#define UNC_IPP
+
+#include <boost/quan/unc.hpp> // Declarations of uncertain items.
+
+#include <iostream>
+//using std::ostream;
+
+//! 'Unique' value used to check xalloc initialised iwords are OK, and are not corrupted.
+const long indexID = 0x48dbaf8; //! Random id value.
+
+/*!
+ \brief Set 16 default values for uncertain output flags.
+ Might be best to make setUncDefaults also set ios_base defaults
+ with void setiosDefaults(ostream&);\n
+ Usage: \code setUncDefaults(cout); \endcode
+ \warning \c setUncDefaults() MUST be called before using a stream.
+ \details
+ Default iword(*) values are all zero - these are not usable.
+ Function \c setUncDefaults() sets some defaults
+ Can set individual value, for example, for 3 sig Digits, os.iword(sigDigitsIndex) = 3;
+ \note Index values must have been initialised by xalloc calls.
+*/
+void setUncDefaults(std::ios_base& os)
+{
+ os.iword(zeroIndex) = indexID; // Mark stream starting to set to defaults:
+
+ os.iword(uncFlagsIndex) = 0; // long& uncFlags == iword(1)
+ // uncFlags defaults mean flex, not set_scaled, not auto_scaled, not +/-,
+ // no symbol, no prefix, no noisy, not setSigDigits.
+ os.iword(oldUncFlagsIndex) = 0; // Old - not set yet. long& oldUncFlagsIndex == iword(2)
+ os.iword(sigDigitsIndex) = 3; // Default 3 significant digits for value.
+ os.iword(oldSigDigitsIndex) = 3; // Old @b set 3 significant digits for value.
+ os.iword(setSigDigitsIndex) = 3; // Default @b set 3 significant digits for value.
+ os.iword(uncSigDigitsIndex) = 2; // Default @b set 3 significant digits for value.
+ os.iword(setUncSigDigitsIndex) = 2; // Default 2 significant digits, as ISO standard.
+ os.iword(oldUncSigDigitsIndex) = -1; // No previous value for unc stdDev.
+ os.iword(scaleIndex) = 0; // Zero scale means was not scaled.
+ os.iword(oldScaleIndex) = -1; // No previous scale.
+ os.iword(setScaleIndex) = 0; // Assigned by uncSetScale(9).
+ os.iword(uncWidthIndex) = 10; // Default width 10 to allow +1.23E+12 & 1 fill_char.
+ os.iword(oldUncWidthIndex) = -1;
+ os.iword(oldUncSetWidthIndex) = -1; // Not used?
+ os.iword(usedIndex) = 0; // No chars output = used.
+ os.iword(oldUncUsedIndex) = -1; // No previous value.
+ os.iword(widthIndex) = -1; // ios setwidth
+ os.iword(oldWidthIndex) = -1; // previous ios setwidth
+ os.iword(roundingLossIndex) = 50; // 0.01 * 1000; // == 0.01
+ os.iword(confidenceIndex) = 50000; // == 0.05 * 1e6
+
+ os.iword(topIndex) = indexID; // last .iword(16) == iword(0)
+ // marking that all have been set to defaults.
+ if (os.iword(zeroIndex) != indexID)
+ { // Initialization of iwords failed!
+ std::cerr << "os.iword(0) = " << std::hex << os.iword(0)
+ << " not expected ID " << indexID << '!'
+ << "\nMissing call of setUncDefaults(ostream)?" << std::endl;
+ // throw; some exception TODO
+ }
+} // void setUncDefaults(std::ios_base& stream)
+
+/*! Output ALL the os.word() values to the ostream log.
+ \param os Current stream to be displayed in log.
+ \param logstream for log.
+*/
+void outUncValues(std::ostream& os, std::ostream& log)
+{ // Output ALL the os.word() values to the ostream log.
+ log //<< hex << "zero " << os.iword(zeroIndex) << dec // = indexID; // Mark if has been set to defaults.
+ << " " "UncValues: "
+ << "uncFlags " << std::hex << os.iword(uncFlagsIndex) << std::dec //= 0; // iword(1)
+ << ", setSigDigits " << os.iword(setSigDigitsIndex) // = 3; // Default set 3 sig digits.
+ << ", uncWidth " << os.iword(uncWidthIndex) // = 10; // Default width 10 to allow +1.234E12
+ << ", uncSetWidth " << os.iword(oldUncSetWidthIndex) // = 0; // Not used
+ << ", uncScale " << os.iword(scaleIndex) // = 0; // Zero scaling means was not scaled.
+ << ", uncSetScale " << os.iword(setScaleIndex) // = 0; // Zero scaling means not scaled.
+ << ", uncUsed " << os.iword(usedIndex) // = 0; // None used.
+ // Values saved by previous calls of uncprint.
+ << ", uncOldFlags " << os.iword(oldUncFlagsIndex) // = 0; // 0xFFFFFFFF to mean not valid?
+ << ", uncOldUncWidth " << os.iword(oldUncWidthIndex) // = 0;
+ << ", uncOldScale " << os.iword(oldScaleIndex) // = 0;
+ << ", uncSigDigits " << os.iword(setUncSigDigitsIndex) // = 2; // Default 2 sig digits.
+ << ", uncoldSigDigits " << os.iword(oldUncSigDigitsIndex) // = 0; // No previous value.
+ << ", oldUncUsed " << os.iword(oldUncUsedIndex) // = 0; // No previous value.
+ << ", oldStdDevSigDigits " << os.iword(oldUncSigDigitsIndex) // = 0; // No previous value for unc stdDev.
+ << ", setUncSigDigits " << os.iword(setUncSigDigitsIndex)
+ << ", roundingLossIndex " << os.iword(roundingLossIndex) / 1.e3
+ << ", confidenceIndex " << os.iword(confidenceIndex) / 1.e6
+
+ // << ", top " << hex << os.iword(topIndex) << dec
+ << std::endl;// = indexID; // last .iword(16) as check.
+} // void outUncValues()
+
+//! Description as a word of each bit in unc type, using enum unc_types.
+const char* uncTypeWords[16] =
+{
+ "zero", //!< 0 VALUE_ZERO value is zero.
+ "integer", //!< 1 VALUE_INTEGER value is an integer.
+ "rational", //!< 2 VALUE_RATIONAL value is rational.
+ "-only", //!< 3 VALUE_NEGATIVE_ONLY Value can ONLY be < 0.. ? or <=0?
+ "+only", //!< 4 VALUE_POSITIVE_ONLY Value can ONLY be >=0.
+ "uncKnown", //!< 5 UNC_KNOWN Uncertainty known
+ "noPlus", //!< 6 UNC_NOPLUS Uncertainty can only be < value, + = zero.
+ "noMinus", //!< 7 UNC_NOMINUS certainty can only be > value - = zero.
+ "quantize10", //!< 8 UNC_QUAN_DECIMAL Quantised by least significant decimal digit.
+ "quantize2", //!< 9 UNC_QUAN_BINARY Quantised by least significant binary digit.
+ "explicit", //!< 10 UNC_EXPLICIT not inferred from sig digits.
+ "uniform", //!< 11 UNC_UNIFORM uniform (or rectangular) probability distribution.
+ "triangular", //!< 12 UNC_TRIANGULAR Triangular probability distribution.
+ //! If neither bits set, then distribution type is normal (or gaussian).
+ //! If BOTH bits are, the distribution is undefined (as yet).
+ "df_exact", //!< 13 DEG_FREE_EXACT Exactly known number of observations.
+ "df_known", //!< 14 DEG_FREE_KNOWN Degrees of freedom defined.
+ "spare" //!< 15 SPARE
+};
+
+/*! Output word description for each unc_type bit.\n
+ Usage: outUncTypes(unc.getUncTypes(), cerr); // logs to cerr.
+ \param uncTypes uncertain types as a short int.
+ \param os ostream for output, default = cerr
+*/
+void outUncTypes(unsigned short int uncTypes, std::ostream& os = std::cerr)
+{// Usage: outUncTypes(unc.getUncTypes(), cerr); // logs to cerr.
+ const int count = 16; // because using 16-bit unsigned short int.
+ os << "uncTypes (" << std::showbase << std::hex << uncTypes << std::dec << ")" ;
+ for(int i = 0, j = 1; i < count; ++i)
+ {
+ if ((uncTypes & j) != 0)
+ {
+ os << ' ' << uncTypeWords[i] ;
+ }
+ j <<= 1;
+ } // for
+ os << ".";
+} // outUncTypes
+
+/*!
+ Usage: `out << showUncTypes(uncType)`
+ \param t Uncertain type flags.
+*/
+showUncTypes::showUncTypes(unsigned short int t) : types(t)
+{ // Constructor.
+}
+
+/*!
+ \nUsage: `out << showUncTypes(uncType)`
+ \param ut Uncertain type flags.
+ \param std::ostream for output of types as words.
+*/
+std::ostream& operator<< (std::ostream& os, const showUncTypes& ut) // Define.
+{
+ const int count = 16; // because using 16-bit unsigned short int.
+ unsigned short int uncTypes = ut.types;
+ os << "uncTypes (" << std::showbase << std::hex << uncTypes << std::dec << ")";
+ for (int i = 0, j = 1; i < count; ++i)
+ {
+ if ((uncTypes & j) != 0)
+ {
+ os << ' ' << uncTypeWords[i];
+ }
+ j <<= 1;
+ } // for
+ os << ".";
+ return os;
+} // ostream& operator<< (ostream& os, const showUncTypes& ut)
+
+/*! Show all the std io stream flags settings as words.\n
+ Usage: \code outIosFlags(cout.flags(), cerr); // logs cout's flag to cerr. \endcode
+ \param flags Iostream flags.
+ \param os Ostream for output.
+ */
+void outIosFlags(long flags, std::ostream& os = std::cerr)
+{ // Show all the std io stream flags settings as words.
+ os << "iosflags (" << flags << ")" << std::dec;
+ if (flags & std::ios_base::boolalpha) // Show bool as word strings "true" or "false".
+ os << " boolalpha";
+ if (flags & std::ios_base::skipws) // Skip white space on input.
+ os << " skipwhite";
+ if (flags & std::ios_base::left) // Left-align values; pad on the right with the fill character.
+ os << " left";
+ if (flags & std::ios_base::right) // Right-align values; pad on the left with the fill character (default alignment).
+ os << " right";
+ if (flags & std::ios_base::internal) // Add fill characters after any leading sign or base indication, but before the value.
+ os << " internal";
+ if (flags & std::ios_base::dec) // Format numeric values as base 10 (decimal) (default radix).
+ os << " dec";
+ if (flags & std::ios_base::oct) // Format numeric values as base 8 (octal).
+ os << " oct";
+ if (flags & std::ios_base::hex) // Format numeric values as base 16 (hexadecimal).
+ os << " hex";
+ if (flags & std::ios_base::showbase) // Display numeric constants in a format that can be read by the C++ compiler.
+ os << " showbase";
+ if (flags & std::ios_base::showpoint) // Show decimal point and trailing zeros for floating-point values.
+ os << " showpoint";
+ if (flags & std::ios_base::showpos) // Display plus sign in non-negative field.
+ os << " showpos";
+ if (flags & std::ios_base::uppercase) // Display uppercase A through F for hexadecimal values and E for scientific values.
+ os << " upper";
+ if (flags & std::ios_base::showpos) // Show plus signs (+) for positive values.
+ os << " show +";
+ if (flags & std::ios_base::scientific) // Display floating-point numbers in scientific format, for example: 1.23457e+001.
+ os << " scientific";
+ if (flags & std::ios_base::fixed) // Display floating-point numbers in fixed format, for example: 12.3456.
+ os << " fixed";
+ if ((flags & std::ios_base::scientific) && (flags & std::ios_base::fixed)) // Display floating-point numbers in hex format.
+ os << " hexFloat";
+ // TR1 adds both fixed and scientific as hexfloat.
+ // This is 15 - fmtflag appears to be limited by Dinkumware/MS fmtflags = 0xffff and most significant bit 15 is also used internally :-(
+ os << ".";
+} // out ios_base::flags(long flags, ostream&)
+
+
+/*! Show the set uncertain class io stream flags settings as words.
+ \param uncFlags Output flags to be displayed as words.
+ \param os Ostream for output.
+ Usage: \code outUncFlags(cout.flags(), cerr); // logs cout's flag to cerr. long& uncFlags = os.iword(uncFlagsIndex); \endcode
+*/
+void outUncFlags(long uncFlags, std::ostream& os = std::cerr)
+{
+ os << "uncFlags (" << std::showbase << std::hex << uncFlags << std::dec << ")";
+ os << ((uncFlags & firm) ? " firm" : "" );
+ if (uncFlags & setScaled) os << " set_scaled";
+ if (uncFlags & autoScaled) os << " auto_scaled";
+ if (uncFlags & plusMinus) os << " add_+/- ";
+ //if (uncFlags & addSISymbol) os << " add_SI_symbol";
+ //if (uncFlags & addSIPrefix) os << " add_SI_prefix";
+ if (uncFlags & limits) os << " addlimits";
+ if (uncFlags & noisyDigit) os << " addnoisy";
+ if (uncFlags & useSetSigDigits) os << " set_sigDigits";
+ if (uncFlags & useSetUncSigDigits) os << " set_uncsigDigits";
+ if (uncFlags & degfree) os << " adddegfree";
+
+ os << '.';
+} //
+
+// Parameterless manipulators to switch format to switch uncFlag bits,
+// flex - width just enough to display, suitable for non-tables,
+// or firm to fit into a set width, suitable for tables,
+// & similarly for scale and autoscale flag bits.
+// Note all lowercase to match convention of hex, oct ...
+
+std::ios_base& flexform(std::ios_base& iostr)
+{
+ iostr.iword(uncFlagsIndex) &= ~firm; // clear bit 0 = 0 to mean flex.
+ return iostr;
+}
+
+std::ios_base& firmform(std::ios_base& iostr)
+{
+ iostr.iword(uncFlagsIndex) |= firm; // set bit 0 = 1 to mean firm not flex.
+ return iostr;
+}
+
+std::ios_base& scale(std::ios_base& iostr)
+{
+ iostr.iword(uncFlagsIndex) |= setScaled; // set bit 1 = 1 to mean scaled.
+ return iostr;
+}
+
+std::ios_base& noscale(std::ios_base& iostr)
+{
+ iostr.iword(uncFlagsIndex) &= ~setScaled; // clear bit 1 = 0 to mean not scaled.
+ return iostr;
+}
+
+std::ios_base& autoscale(std::ios_base& iostr)
+{
+ iostr.iword(uncFlagsIndex) |= autoScaled; // set bit 2 = 1 to mean auto.
+ return iostr;
+}
+
+std::ios_base& noautoscale(std::ios_base& iostr)
+{
+ iostr.iword(uncFlagsIndex) &= ~autoScaled; // clear bit 2 = 0 to mean fixed.
+ return iostr;
+}
+
+std::ios_base& plusminus(std::ios_base& iostr)
+{
+ iostr.iword(uncFlagsIndex) |= plusMinus; // set bit 3 = 1 to mean plusminus.
+ return iostr;
+}
+
+std::ios_base& noplusminus(std::ios_base& iostr)
+{
+ iostr.iword(uncFlagsIndex) &= ~plusMinus; // clear bit 3 = 0 to mean not.
+ return iostr;
+}
+
+std::ios_base& addsisymbol(std::ios_base& iostr)
+{
+ iostr.iword(uncFlagsIndex) |= addSISymbol; // set bit 4 = 1 to add SI symbol.
+ return iostr;
+}
+
+std::ios_base& nosisymbol(std::ios_base& iostr)
+{
+ iostr.iword(uncFlagsIndex) &= ~addSISymbol; // clear bit 4 = 0 for no SI symbol.
+ return iostr;
+}
+
+std::ios_base& addsiprefix(std::ios_base& iostr)
+{ // Prefix (like kilo) used rather than Symbol (like k) if both SI prefix & symbol set.
+ iostr.iword(uncFlagsIndex) |= addSIPrefix; // set bit 5 = 1 to add SI prefix
+ return iostr;
+}
+
+std::ios_base& nosiprefix(std::ios_base& iostr)
+{
+ iostr.iword(uncFlagsIndex) &= ~addSIPrefix; // clear bit 5 = 0 for NO prefix.
+ return iostr;
+}
+
+std::ios_base& addnoisyDigit(std::ios_base& iostr)
+{
+ iostr.iword(uncFlagsIndex) |= noisyDigit; // set bit 6 = 1 to add noisy digit
+ return iostr;
+}
+
+std::ios_base& nonoisyDigit(std::ios_base& iostr)
+{
+ iostr.iword(uncFlagsIndex) &= ~noisyDigit; // clear bit 6 = 0 for NO noisy digit.
+ return iostr;
+}
+
+std::ios_base& autosigdigits(std::ios_base& iostr)
+{ // Use auto (calculated from uncertainty) not sig digits stored with `<< setSigDigits(6)` for value.
+ iostr.iword(uncFlagsIndex) &= ~useSetSigDigits; // clear bit 7 = 0 for auto sigdigits.
+ return iostr;
+}
+
+std::ios_base& setsigdigits(std::ios_base& iostr)
+{ // Use sig digits stored with `<< setSigDigits(6)` for value (not calculated from uncertainty).
+ iostr.iword(uncFlagsIndex) |= useSetSigDigits; // set bit 7 = 1 to use set sigdigits.
+ return iostr;
+}
+
+std::ios_base& autouncsigdigits(std::ios_base& iostr)
+{ // Calculate stdDev sig digits from uncertainty.
+ iostr.iword(uncFlagsIndex) &= ~useSetUncSigDigits; // clear bit 8 = 0 for auto unc sigdigits.
+ return iostr;
+}
+
+std::ios_base& setuncsigdigits(std::ios_base& iostr)
+{ //!< Use stdDev sigDigits stored with `<< useSetUncSigDigits(2) ...`
+ iostr.iword(uncFlagsIndex) |= useSetUncSigDigits; // set bit 8 = 1 to use set uncsigdigits.
+ return iostr;
+}
+
+std::ios_base& adddegfree(std::ios_base& iostr)
+{ // Add degrees of freedom as `(99)`.
+ iostr.iword(uncFlagsIndex) |= degfree; // set bit 9 = 1 to mean show degrees of freedom.
+ return (iostr);
+}
+
+std::ios_base& nodegfree(std::ios_base& iostr)
+{ // Do not add degrees of freedom
+ iostr.iword(uncFlagsIndex) &= ~degfree; // clear bit 9 = 0 to mean no degrees of freedom.
+ return (iostr);
+}
+
+std::ios_base& addreplicates(std::ios_base& iostr)
+{ // Show replicates (but only if if > 1).
+ iostr.iword(uncFlagsIndex) |= replicates; // set bit 0xA = 1 to mean replicates > 1.
+ return (iostr);
+}
+
+std::ios_base& noreplicates(std::ios_base& iostr)
+{
+ iostr.iword(uncFlagsIndex) &= ~replicates; // clear bit 0xA = 0 to mean no replicates.
+ // BUT still show degrees of freedom if required.
+ return (iostr);
+}
+
+std::ios_base& addlimits(std::ios_base& iostr)
+{
+ iostr.iword(uncFlagsIndex) |= limits; // Set bit 0xB = 0 to mean show limits.
+ return (iostr);
+}
+
+std::ios_base& nolimits(std::ios_base& iostr)
+{
+ iostr.iword(uncFlagsIndex) &= ~limits; // clear bit 0xB = 0 to mean no limits shown.
+ return (iostr);
+}
+
+// May need istream operator>> versions too?
+
+std::ios_base& showuncflags(std::ios_base& iostr)
+{
+ showUncFlags(static_cast<unsigned short>(iostr.iword(uncFlagsIndex)));
+ return iostr;
+}
+
+// Two overloaded uFlags functions, like ios_base setf.
+// (1st just returns current, other sets & returns old).
+long uFlags(std::ios_base& str)
+{
+ return str.iword(uncFlagsIndex); // Return streams current unc flags.
+ // Unlike ios_base member function fmtflags ios_base::flags(),
+ // these need to know their ios_base.
+}
+
+long uFlags(std::ios_base& str, long flags) // Assign new & return old.
+{
+ // lock(); may be required for multitasking (MT defined).
+ long oldflags = str.iword(uncFlagsIndex); // Save to return
+ str.iword(uncFlagsIndex) = flags; // Assign all bits.
+ // unlock();
+ return oldflags; // Previous flags.
+}
+
+long setuFlags(std::ios_base& str, long flags) // Set selected bits & return old.
+{
+ long oldflags = str.iword(uncFlagsIndex); // Save to return.
+ // lock();
+ str.iword(uncFlagsIndex) |= flags; // OR Set = 1 specific bits.
+ // unlock();
+ return oldflags; // Previous;
+}
+
+long resetuFlags(std::ios_base& str, long flags) // Reset bits & return old.
+{
+ long oldflags = str.iword(uncFlagsIndex); // to return
+ // lock();
+ str.iword(uncFlagsIndex) &= (~flags); // reset specified bits.
+ // unlock();
+ return oldflags; // Previous.
+}
+
+// Manipulator creation using class whose name is that of the manipulator
+// and << and >> operators.
+// Steve Teale p 182 suggests that this is longer code than using template
+// O, I or Smanip, but simpler to code and understand, and will run faster.
+
+// Manipulator uncFlags. Usage: out << showUncFlags(flags)
+
+// Class showUncFlags whose name is that of the manipulator & << >> operators,
+// defined in unc.hpp header, but constructor defined in unc.cpp.
+
+showUncFlags::showUncFlags(unsigned short int f) : flags(f)
+{ //! Constructor.
+ //! Usage: out << showUncFlags(static_cast<long>(is.iword(uncFlagsIndex))) ...
+}
+
+std::ostream& operator<< (std::ostream& os, const showUncFlags& uf) // Define.
+{ // Output uncFlags to this ostream.
+ unsigned short uncFlags = uf.flags;
+ os << "uncFlags ("<< std::hex << uncFlags << std::dec << ")";
+ os << ((uncFlags & firm) ? " firm" : "" );
+ if (uncFlags & setScaled) os << " setScaled";
+ if (uncFlags & autoScaled) os << " autoScaled";
+ if (uncFlags & plusMinus) os << " add_+/-";
+ if (uncFlags & addSISymbol) os << " add_SI_symbol";
+ if (uncFlags & addSIPrefix) os << " add_SI_prefix";
+ if (uncFlags & noisyDigit) os << " add_noisy";
+ if (uncFlags & useSetSigDigits) os << " use_set_sigfig";
+ if (uncFlags & useSetUncSigDigits) os << " use_set_uncsigfig";
+ os << ".";
+ return os;
+} // ostream& operator<< (ostream& os, const showUncFlags&)
+ //long& uncFlags = os.iword(uncFlagsIndex);
+
+
+// setAllUncflags(int flags);
+// Usage: out << setAllUncFlags(0x5a) ...
+setAllUncFlags::setAllUncFlags(int w) : flags(w) {}
+// Constructor initialisation assigns flags = w.
+
+std::ostream& operator<< (std::ostream& os, const setAllUncFlags& sf)
+{
+ os.iword(oldUncFlagsIndex) = os.iword(uncFlagsIndex); // Save all old flags.
+ os.iword(uncFlagsIndex) = sf.flags; // Set all flags.
+ return os;
+}
+
+std::istream& operator>> (std::istream& is, const setAllUncFlags& sf)
+{
+ is.iword(oldUncFlagsIndex) = is.iword(uncFlagsIndex); // Save all old flags.
+ is.iword(uncFlagsIndex) = sf.flags; // Set all flags.
+ return is;
+}
+
+// setUncflags(int flags, int mask);
+// Usage: out << setUncFlags(0x7) ...
+setUncFlags::setUncFlags(int w) : flags(w)
+{ // Constructor initialisation flags = w.
+
+}
+
+std::ostream& operator<< (std::ostream& os, const setUncFlags& sf)
+{
+ os.iword(oldUncFlagsIndex) = os.iword(uncFlagsIndex); // Save all oldflags.
+ os.iword(uncFlagsIndex) |= sf.flags; // Set (OR in) selected flags.
+ return os;
+}
+
+std::istream& operator>> (std::istream& is, const setUncFlags& sf)
+{
+ is.iword(oldUncFlagsIndex) = is.iword(uncFlagsIndex); // Save all old flags.
+ is.iword(uncFlagsIndex) |= sf.flags; // Set (OR in) selected flags.
+ return is;
+}
+
+// setMaskedUncflags(int flags, int mask);
+// Usage: out << setMaskedUncFlags(0xFFFF, 0x7) ...
+setMaskedUncFlags::setMaskedUncFlags(int w, int m) : flags(w), mask(m) {}
+// flags = w; mask = m; in effect.
+
+std::ostream& operator<< (std::ostream& os, const setMaskedUncFlags& sf)
+{
+ os.iword(oldUncFlagsIndex) = os.iword(uncFlagsIndex); // Save all flags.
+ os.iword(uncFlagsIndex) =
+ (sf.flags & sf.mask) | (sf.flags & ~sf.mask); // Set selected flags to mask.
+ return os;
+}
+
+std::istream& operator>> (std::istream& is, const setMaskedUncFlags& sf)
+{
+ is.iword(oldUncFlagsIndex) = is.iword(uncFlagsIndex); // Save all flags.
+ is.iword(uncFlagsIndex) =
+ (sf.flags & sf.mask) | (sf.flags & ~sf.mask); // Set selected flags to mask.
+ return is;
+}
+
+// resetUncflags(int flags);
+// Usage: out << setMaskedUncFlags(0xF) ...
+resetUncFlags::resetUncFlags(int w) : flags(w) {} // Constructor initialisation flags = w.
+
+std::ostream& operator<< (std::ostream& os, const resetUncFlags& sf)
+{
+ os.iword(oldUncFlagsIndex) = os.iword(uncFlagsIndex); // Save previous.
+ os.iword(uncFlagsIndex) &= ~sf.flags; // Clear specific bits = 0.
+ return os;
+}
+
+std::istream& operator>> (std::istream& is, const resetUncFlags& sf)
+{
+ is.iword(oldUncFlagsIndex) = is.iword(uncFlagsIndex); // Save previous.
+ is.iword(uncFlagsIndex) &= ~sf.flags; // Clear specific bits = 0.
+ return is;
+}
+
+// setMaskedUncflags(int flags, int mask);
+// Usage: out << setMaskedUncFlags(0xFFFF, 0x7) ...
+resetMaskedUncFlags::resetMaskedUncFlags(int w, int m) : flags(w), mask(m) {}
+// Constructor initialisation flags = w.
+
+std::ostream& operator<< (std::ostream& os, const resetMaskedUncFlags& sf)
+{
+ os.iword(oldUncFlagsIndex) = os.iword(uncFlagsIndex); // Save all flags.
+ os.iword(uncFlagsIndex) =
+ (sf.flags & sf.mask) & ~(sf.flags & ~sf.mask); // Clear selected flags to mask.
+ return os;
+}
+
+std::istream& operator>> (std::istream& is, const resetMaskedUncFlags& sf)
+{
+ is.iword(oldUncFlagsIndex) = is.iword(uncFlagsIndex); // Save all flags.
+ is.iword(uncFlagsIndex) =
+ (sf.flags & sf.mask) & ~(sf.flags & ~sf.mask); // Clear selected flags to mask.
+ return is;
+}
+
+// Usage: out << setUncWidth(12) ...
+setUncWidth::setUncWidth(int w) : uncWidth(w)
+ { // Constructor.
+ }
+
+std::ostream& operator<< (std::ostream& os, const setUncWidth& sw)
+{
+ os.iword(oldUncWidthIndex) = os.iword(uncWidthIndex); // Save old.
+ os.iword(uncWidthIndex) = sw.uncWidth; // Set new uncertain width.
+ return os;
+}
+
+std::istream& operator>> (std::istream& is, const setUncWidth& sw)
+{
+ is.iword(oldUncWidthIndex) = is.iword(uncWidthIndex); // Save old.
+ is.iword(uncWidthIndex) = sw.uncWidth;
+ return is;
+}
+
+// setScale(int scale);
+// Usage: out << setScale(6) ... // == 10**6
+// & << scale to use this set scale value, or << noscale to ignore.
+setScale::setScale(int scale) : scale(scale)
+{ // Constructor.
+}
+
+std::ostream& operator<< (std::ostream& os, const setScale& sc)
+{ //
+ os.iword(oldScaleIndex) = os.iword(setScaleIndex); // Save old.
+ os.iword(setScaleIndex) = sc.scale;
+ return os;
+}
+
+std::istream& operator>> (std::istream& is, const setScale& sc)
+{
+ is.iword(oldScaleIndex) = is.iword(setScaleIndex); // Save old.
+ is.iword(setScaleIndex) = sc.scale;
+ return is;
+}
+
+/*! setSigDigits(int sigDigits);
+\brief Set the number of significant digits that can be used.
+(If required by `<< sigfiged` then use set sigDigits value, or noSigfiged to @b NOT use sigDigits).
+// Usage: `out << setSigDigits(5) << setsigdigits ...`
+// & either `<< setsigdigits` to use set sigDigits value, or ` << nosetsigdigits` to not use the set sigDigits.
+*/
+setSigDigits::setSigDigits(int w) : sigDigits_(w)
+{ // Constructor sigDigits = w;
+}
+
+std::ostream& operator<< (std::ostream& os, const setSigDigits& sf)
+{
+ os.iword(oldSigDigitsIndex) = os.iword(setSigDigitsIndex); // Save previous.
+ os.iword(setSigDigitsIndex) = sf.sigDigits_; // Set new sigDigits for value.
+ return os;
+}
+
+std::istream& operator>> (std::istream& is, const setSigDigits& sf)
+{
+ is.iword(oldSigDigitsIndex) = is.iword(setSigDigitsIndex); // Save previous.
+ is.iword(setSigDigitsIndex) = sf.sigDigits_; // Set new sigDigits.
+ return is;
+}
+
+//! setUncSigDigits(int sigDigits);
+//! Usage: `out << setUncSigDigits(3) ...`
+// has the effect `cout.iword[setUncSigDigitsIndex] = 3;`
+setUncSigDigits::setUncSigDigits(int w) // : uncSigDigits_(w)
+{
+ if (w == 0)
+ {
+ w = 2; // ISO default.
+ }
+ else if (w > 3)
+ {
+ w = 3; // Limit to biggest that makes sense.
+ }
+ // Passes negative values through to allow
+ // an auto mode for w < 0 that chooses from degrees of freedom,
+ // (can't read degfree from here).
+ // From table H page 457 in Oliver & Goldsmith, confidence interval
+ // of standard deviation is about +/- 20% at 10 degrees of freedom,
+ // and only < +/- 10% above 100 observations (needing 2 stdDev sig Digits).
+ uncSigDigits_ = w;
+} // Constructor sets uncSigDigits = w.
+
+std::ostream& operator<< (std::ostream& os, const setUncSigDigits& usf)
+{
+ os.iword(oldUncSigDigitsIndex) = os.iword(setUncSigDigitsIndex); // Save previous.
+ os.iword(setUncSigDigitsIndex) = usf.uncSigDigits_; // Set new uncSigDigits.
+ return os;
+}
+
+//! setroundingLoss(double eps);
+//! Usage: out << setroundingLoss(0.01) ... = cout.iword[roundingLoss] = 0.01;
+setRoundingLoss::setRoundingLoss(double eps)
+{ // Constructor sets roundingLoss = parameter eps (scaled by operator<<).
+
+ roundingloss_= eps;
+}
+std::ostream& operator<< (std::ostream& os, const setRoundingLoss& sl)
+{ //! \note Can't store `double` in a `long`, so scale up to an integer.
+ os.iword(roundingLossIndex) = static_cast<long>(sl.roundingloss_ * 1.e3);
+ return os;
+}
+
+//! setConfidence(double alpha);
+//! Usage: out << setConfidence(0.01) ... = cout.iword[confidence] = 0.01;
+setConfidence::setConfidence(double alpha)
+{ // Constructor sets confidence = parameter alpha (scaled by operator<<).
+ confidence_= alpha;
+}
+
+std::ostream& operator<< (std::ostream& os, const setConfidence& sl)
+{ //! \note Can't store `double` in a `long`, so scale up to an integer.
+ os.iword(confidenceIndex) = static_cast<long>(sl.confidence_ * 1.e6);
+ return os;
+}
+
+std::istream& operator>> (std::istream& is, const setUncSigDigits& usf)
+{
+ is.iword(oldUncSigDigitsIndex) = is.iword(setUncSigDigitsIndex); // Save previous.
+ is.iword(setUncSigDigitsIndex) = usf.uncSigDigits_; // Set new uncSigDigits.
+ return is;
+}
+
+// These all fail to link when placed here???? So left in unc.hpp until understand why.
+
+//! Squared function, notationally convenient for a^2, but overflow possible?
+//template <typename Type>
+//inline Type sqr(const Type& a)
+//{
+// return a * a;
+//}
+
+//! Cubed function, notationally convenient for x^3, but overflow possible?
+//template <typename Type>
+//inline Type cube(const Type& a)
+//{
+// return a * a * a;
+//}
+
+////! Quaded function, notationally convenient for x^4, but overflow possible?
+////! Used by Welch-Satterthwaite formula.
+//template <typename Type>
+//inline Type pow4(const Type& a)
+//{
+// return a * a * a * a;
+//}
+/*! Hypot or Square root of the sum of the squares of two numbers,
+ which is equal to the length of the hypotenuse of a right
+ triangle if the two arguments are the lengths of the legs.
+ Used for uncertainty propagation.
+*/
+//template <typename Type>
+//inline Type sqrtSumSqrs (const Type& a, const Type& b)
+//{
+// return (Type)sqrt(a * a + b * b);
+//}
+//
+
+// Definitions for explicit instantiation for double uncun, mMeas.
+// Definitions must only be in .cpp if unc.hpp included more than once
+// or will get link error "already defined".
+
+//
+//!< \tparam T value type convertible to double.
+template<>
+double value_of(double v)
+{ //! \return value as a double.
+ return double(v);
+}
+
+template <class T> //!< \tparam T value type convertible to double.
+double value_of(T v)
+{ //! \return value as a double.
+ double result = static_cast<double>(v.value());
+ return result;
+}
+
+template<>
+double value_of(unc<true> v)
+{ //! \return unc.value() as a double.
+ return v.value();
+}
+
+template<>
+double value_of(unc<false> v)
+{ //! \return unc.value() as a double.
+ return v.value();
+}
+
+template <class T>
+double unc_of(T v)
+{ //! \return zero if no uncertainty information is available (for built-in double, float, or long double).
+ return v.std_dev();
+}
+
+template <>
+double unc_of(double)
+{ //! \return zero if no uncertainty information is available (for built-in double, float, or long double).
+ return 0.F;
+}
+
+template <>
+double unc_of(float)
+{ //! \return zero if no uncertainty information is available (for built-in double, float, or long double).
+ return 0.F;
+}
+
+template <>
+double unc_of(uncun u)
+{ //! \return zero if no uncertainty information is available (for built-in double, float, or long double).
+ return u.std_dev();
+}
+
+// Pairs of values.
+
+template <> //! \tparam T Built-in floating-point type, float, double, long double or unc or Meas.
+std::pair<double, double> values_of(std::pair<double, double> vp)
+{ //!< \return values of a pair of double values.
+ return std::make_pair(value_of(vp.first), value_of(vp.second));
+}
+
+// Const vrsion
+template <> //! \tparam T Built-in floating-point type, float, double, long double or unc or Meas.
+std::pair<double, double> values_of(std::pair<double const, double> vp)
+{ //!< \return values of a pair of double values.
+ return std::make_pair(value_of(vp.first), value_of(vp.second));
+}
+
+template <> //! \tparam T Built-in floating-point type, float, double, long double or unc or Meas.
+std::pair<double, double> values_of(std::pair<uncun, uncun> vp)
+{ //!< \return values of a pair of double values.
+ return std::make_pair(value_of(vp.first), value_of(vp.second));
+}
+
+template <> //! \tparam T Built-in floating-point type, float, double, long double or unc or Meas.
+std::pair<double, double> values_of(std::pair<uncun const, uncun> vp)
+{ //!< \return values of a pair of double values.
+ return std::make_pair(value_of(vp.first), value_of(vp.second));
+}
+
+//! Get uncertainties (standard deviation) of a pair of values.
+template <> //! \tparam T Built-in floating-point type or unc.
+std::pair<double, double> uncs_of(std::pair<double, double> vp)
+{
+ return std::make_pair<double, double>(unc_of(vp.first), unc_of(vp.second));
+}
+
+//! Get uncertainties (standard deviation) as a pair of double values.
+template <> //! \tparam T Built-in floating-point type or unc.
+std::pair<double, double> uncs_of(std::pair<uncun, uncun> vp)
+{
+ return std::make_pair<double, double>(unc_of(vp.first), unc_of(vp.second));
+ //! \return uncs_of uncertainties (standard deviation) as a pair of double values.
+}
+
+//! Get uncertainties (standard deviation) as a pair of const float values.
+template <class T> //! \tparam T Builtin-floating point type or unc.
+const std::pair<float, float> uncs_of(std::pair<const T, T> vp)
+{ //! \return uncertainty parts (if any) as a pair of floats.
+ // so can write
+ // std::pair<const float, float> minmax = values_of(*result.first); // min unc & max unc for example/
+ // whether T is built-in or unc.
+ return std::make_pair(vp.first.unc(), vp.second.unc());
+ //! \return uncs_of uncertainties (standard deviation) as a pair of @b float values.
+}
+
+//// Diagnostic printout version of constructors here just for testing.
+//
+//// Note both correlated and uncorrelated versions needed unless use a template.
+//// C2906: 'unc<is_correlated>::~unc(void)' : explicit specialization requires 'template <>'
+//template<> unc<true>::~unc() // Definition.
+//{
+//#ifdef UNC_CD_TRACE
+// {
+// cerr << "\n___ Destruct unc<true> members: "
+// << value_ << ", Unc " << float(uncertainty_)
+// << ", df " << dec << degFree_
+// << showUncTypes(unctypes_)
+// << endl;
+// }
+//#endif
+//} // Destructor
+//
+//template<> unc<false>::~unc() // Definition.
+//{
+//#ifdef UNC_CD_TRACE
+// {
+// cerr << "\n___ Destruct unc<false> members: "
+// << value_ << ", Unc " << float(uncertainty_)
+// << ", df " << dec << degFree_
+// << showUncTypes(unctypes_)
+// << endl;
+// }
+//#endif
+//} // Destructor
+//#endif // UNC_IPP

Added: sandbox/SOC/2007/quan/boost/quan/impl/unc_input.ipp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/boost/quan/impl/unc_input.ipp 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,421 @@
+/*!
+ \file
+ \brief Testing uncertain classes using Boost Test Tool.
+ \details Class for simple Propagation of Uncertainties
+ according to a pure Gaussian model.
+*/
+
+// Copyright Paul A. Bristow 1998, 2012.
+
+// unc_input.cpp
+
+#include <iosfwd>
+//#include <boost/quan/unc.hpp>
+
+void unc_input(
+ double& value, // mean, central or most probable value.
+ double& stdDev, // float& ??
+ unsigned short int& degreesOfFreedom, // 1 observation.
+ unsigned short int& types, // TODO settings bits.
+ std::istream& is = std::cin)
+{ // Inputs uncertainty as value, (implicitly exact, std deviation = 0).
+ // & optionally [[+]|[-] <standard deviation * 2. >],
+ // (1.0 implies 1. +|- 0.5 and sd of 0.5,
+ // 1.00 implies 1. +|- 0.05 and sd of 0.05)
+
+ // & optionally degrees of freedom [(<short int>)] like (99)
+ // Used by istream& operator>> (istream&, unc<is_correlated>&)
+ // Original simple version:
+ //char plus, slash, minus;
+ //s >> value >> plus >> slash >> minus >> stdDev;
+ //if ((plus != '+') || (slash != '/') || (minus != '-'))
+ //{
+ //cerr << "Unexpected characters encountered in reading "
+ //"value +/- stdDev !" << endl;
+ //is.setf(ios_base::failbit);
+ //}
+
+ using std::istream;
+ using std::ostream;
+ using std::ios_base;
+ using std::char_traits;
+ using std::cout;
+ using std::cerr;
+ using std::cin;
+ using std::endl;
+ using std::flush;
+ using std::ws;
+ using std::streamsize;
+ using std::boolalpha;
+ using std::dec;
+ using std::hex;
+ using std::showbase;
+ using std::fixed;
+ using std::scientific;
+ using std::right;
+ using std::showpos;
+ using std::noshowpos;
+ using std::noshowbase;
+ using std::noshowpoint;
+ using std::showpoint;
+
+ std::streamsize avail = is.rdbuf()->in_avail();
+ if (avail == 0)
+ {
+ std::cerr << "No input available!" << std::endl;
+ value = std::numeric_limits<double>::quiet_NaN();
+ stdDev = std::numeric_limits<float>::quiet_NaN();
+ degreesOfFreedom = 0;
+ types = 0U;
+ return; // todo
+ }
+
+ // 'Default' values for unc_input arguments.
+ value = 0.; // double mean, central or most probable value.
+ stdDev = 0.f; // Exact float std deviation, unless find otherwise.
+ degreesOfFreedom = 1U; // Default == 1 observation.
+ types = 0U;
+ //static_cast<unsigned short>(~(VALUE_ZERO | VALUE_INTEGER | VALUE_RATIONAL| VALUE_NEGATIVE_ONLY | VALUE_POSITIVE_ONLY | UNC_KNOWN | UNC_NOPLUS
+ // | UNC_NOMINUS | UNC_QUAN_DECIMAL | UNC_QUAN_BINARY | UNC_EXPLICIT | UNC_UNIFORM | UNC_TRIANGULAR | DEG_FREE_EXACT | DEG_FREE_KNOWN));
+
+ // All these need to be 'global' to uncertainRead, so declared here.
+ // char_traits<char>::int_type c;
+ // no_unused_variable_warning(c);
+ int iv = 0; // Integer part of floating point number.
+ double fv = 0.; // Fractional part of floating point number.
+ int exponent = 0; // Exponent power of 10, default 10 ^ 0 = 1.
+// bool isPositive = true; // Value input is >= 0.
+ bool isNegativeValue = false; // Value input < 0.
+ bool isPlusMinus = false; // Normal case is +/- or +|-.
+ bool isPlus = false; // +0
+ bool isMinus = false; // -0
+ bool isExactValue = true; // Assume no digits follow.
+ bool isZeroValue = true; // Until find either integer or fractional part != 0
+ bool isIntegerValue = false;
+ bool isExponent = false;
+ // bool isValueZero = false;
+ // Rationale for doing own read rather than using standard is to be able to distinguish
+ // integer "0" or "123" implicitly exact from real "0." implicitly +/- 0.5.
+ // Read integer part as one integer, option decimal as another, and fractional part as another,
+ // then optional exponential part,
+ // before any +/- and degrees of freedom as (999).
+
+ is >> ws; // Skip any leading whitespace.
+ is >> iv; // & read integer part of value (perhaps ii part of floating point number ii.ffe+ddd).
+ // if (is.bad()) // Not useful to distinguish overflow etc.
+ // if (is.eof()) // Sets fail for overflow, so not useful.
+ if (!is)
+ { // No integer part of value.
+ cerr << "No numeric value input! " << showiostate << endl;
+ value = std::numeric_limits<double>::quiet_NaN();
+ stdDev = std::numeric_limits<float>::quiet_NaN();
+ types = static_cast<unsigned short>(~(VALUE_ZERO | VALUE_INTEGER | VALUE_RATIONAL| VALUE_NEGATIVE_ONLY | VALUE_POSITIVE_ONLY | UNC_KNOWN | UNC_NOPLUS
+ | UNC_NOMINUS | UNC_QUAN_DECIMAL | UNC_QUAN_BINARY | UNC_EXPLICIT | UNC_UNIFORM | UNC_TRIANGULAR | DEG_FREE_EXACT | DEG_FREE_KNOWN));
+ // == 0U; // None of the above are true.
+ // is.fail() == true; is.good() == false; // already
+ return;
+ } // is.failed
+ isIntegerValue = true; // but may be negated if find a decimal point later.
+ types |= UNC_KNOWN;
+ types &= ~UNC_EXPLICIT; // Clear bit because implicit from
+ // number of significant decimal digits - unless + or - provided.
+
+ isNegativeValue = (iv < 0) ? true : false;
+ // Overflow possible here if > numeric_limits<long>::max() == 2147483647
+ // for example, 99999999999999.
+ if (is.fail())
+ { // Check for overflow & other problems.
+ std::cerr << "\t" "Uncertain value input failed! "<< showiostate << std::endl;
+ value = std::numeric_limits<double>::quiet_NaN();
+ stdDev = std::numeric_limits<float>::quiet_NaN();
+ types = static_cast<unsigned short>(~(VALUE_ZERO | VALUE_INTEGER | VALUE_RATIONAL| VALUE_NEGATIVE_ONLY | VALUE_POSITIVE_ONLY | UNC_KNOWN | UNC_NOPLUS
+ | UNC_NOMINUS | UNC_QUAN_DECIMAL | UNC_QUAN_BINARY | UNC_EXPLICIT | UNC_UNIFORM | UNC_TRIANGULAR | DEG_FREE_EXACT | DEG_FREE_KNOWN));
+ // == 0U; // None of the above true.
+ return;
+ } // is.fail
+
+ if (is.peek() == '.') // locale.decimal_point[0] better.
+ { // A decimal fractional part may follow.
+ is.get(); // Get (and discard) decimal_point.
+ isIntegerValue = false; // Because . follows digit, so "9" is exact integer but "9." is not,
+ // Even if no digits follow.
+ isExactValue = false;
+ stdDev = 0.5; // Implicit +/- if "9.", implies sd = 0.5.
+ types |= UNC_QUAN_DECIMAL; // Quantised by least significant decimal digit.
+ types &= ~UNC_EXPLICIT; // Clear - explicit because implied by significant digits.
+ int count = 0; // Number of digits. TODO ?? is this info used?
+ if (isdigit(is.peek()))
+ { // There is a decimal fraction part.
+ double fracTen = 1.;
+ while (isdigit(is.peek()))
+ {
+ ++count;
+ stdDev *= 0.1f; // Implicitly 1. means +/- 0.5 == stdDev = 0.05, 0.005 ...
+ fracTen *= 0.1;
+ int digit = (is.get() -'0');
+ fv += digit * fracTen;
+ // Potential for underflow to zero here?
+ }
+ if (isNegativeValue) fv = -fv;
+ if (fv != 0)
+ {
+ isIntegerValue = false;
+ }
+ } // Is a fraction part.
+ } // Is a decimal_point.
+ else if (is.peek() == '/')
+ { // Is a fraction, for example 2/3, so flag as a rational.
+ is.get(); // Get (and discard) /.
+ int denom;
+ is >> denom;
+ if (denom != 0)
+ {
+ value = static_cast<double>(iv)/denom;
+ iv = 0;
+ fv = 0;
+ types |= VALUE_RATIONAL;
+ types &= ~VALUE_ZERO;
+ }
+ }
+ value += iv + fv; // Combine integer and fractional parts.
+
+ if ((is.peek() & 0x5F ) == 'E') // 'e' or 'E'
+ { // Exponential part.
+ is.get(); // and discard 'e' or 'E'.
+ is >> exponent;
+ isExponent = true;
+ } // Exponent
+
+ if (value == 0)
+ {
+ isZeroValue = false;
+ types |= VALUE_ZERO;
+ }
+
+ if (isIntegerValue)
+ {
+ value = iv;
+ types |= (UNC_KNOWN | VALUE_INTEGER | VALUE_RATIONAL );
+// types |= (UNC_KNOWN | VALUE_INTEGER | VALUE_RATIONAL | UNC_NOPLUS | UNC_NOMINUS);
+#ifdef UNC_TRACE
+ { // Implicitly exact +/- 0
+ std::cerr << " URead: Exact integer = " << value << std::endl;
+ }
+#endif
+ }
+ else
+ { // Real NOT integer.
+ types |= UNC_KNOWN; // Known.
+ types &= ~(VALUE_INTEGER | VALUE_RATIONAL | UNC_NOPLUS | UNC_NOMINUS );
+#ifdef UNC_TRACE
+ {
+ std::cerr << " URead: " << value << " implicit +/- " << stdDev << ". ";
+ }
+#endif
+ } // integer or not.
+
+ is >> ws; // Skip optional whitespace between "123.45" and "+/-".
+
+ // Check if explicit uncertainty +/- (or +|-, or +-) or + or - follows,
+ // & read uncertainty if it does.
+ double expUnc = 0.; // Explicit uncertainty.
+ // 0x0F1 is files code for the single char '+-' symbol,
+ if (!is.eof())
+ { // Uncertainty (standard deviation) and degrees of freedom may follow.
+ if ((is.peek() == '+') || (is.peek() == '-'))
+ { // Some uncertainty, for example: +0.123, -0.456 or "+/-2.34"
+ std::char_traits<char>::int_type c = is.get(); // '+' or '-' read and discard.
+ if(c == '+')
+ {
+ isPlus = true;
+ }
+ if(c == '-')
+ {
+ isMinus = true;
+ }
+ std::char_traits<char>::int_type p = is.peek();
+ // 0xdd is File code for | vertical bar.
+ // 0x0F1 is single char in files for '+-' symbol.
+ if (p == '/' || p == '|' || p == '\\' || p == 0xDD || p == 0x0F1)
+ { // Skip over any separator.
+ std::char_traits<char>::int_type c = is.get(); // '/' or '|' or '\' chars.
+ if (c == 0x0F1)
+ { // '+-' symbol, so must be both + and -.
+ isPlus = true;
+ isMinus = true;
+ }
+ // is >> ws; // Ignore any layout. Bad idea to allow "+/ -"
+ p = is.peek(); // Expect + or - after separator.
+ if (p == '+' || p == '-')
+ { // +/- and +|- both allowed (or -/+ or -|+).
+ // Assume +/+ uncertainty means just + and -/-, and uncertainty just -.
+ std::char_traits<char>::int_type c = is.get(); // expect 2nd '+' or '-' char.
+ if (c == '+')
+ {
+ isPlus = true;
+ // else "*/+"
+ is >> expUnc; // Input Explicit uncertainty.
+ if (!is.fail())
+ { // Read OK, set bits.
+ types |= (UNC_KNOWN | UNC_EXPLICIT | UNC_QUAN_DECIMAL | UNC_KNOWN );
+ }
+ else
+ { // Reading uncertainty (standard deviation) value was not OK, so clear.
+ types &= ~(UNC_KNOWN | UNC_EXPLICIT | UNC_QUAN_DECIMAL | UNC_KNOWN );
+ }
+ } // == '+'
+ else if (c == '-')
+ {// else "*/-"
+ isMinus = true;
+ is >> expUnc; // Input Explicit negative uncertainty (have already consumed the - sign).
+ if (!is.fail())
+ { // Read OK, set bits.
+ types |= (UNC_KNOWN | UNC_EXPLICIT | UNC_QUAN_DECIMAL | UNC_KNOWN );
+ }
+ else
+ { // NotOK, so clear.
+ types &= ~(UNC_KNOWN | UNC_EXPLICIT | UNC_QUAN_DECIMAL | UNC_KNOWN );
+ }
+ } // == '-'
+ }
+ else
+ { // Unexpected char (not + or -) after separator!
+ // TODO Need to signal fail!
+ }
+ }
+ else if (c == '+')
+ { // Positive uncertainty only, for example: "+0.123"
+ isPlus = true;
+ is >> expUnc; // Will consume the + sign.
+ if (!is.fail())
+ { // Read OK, set bits.
+ types |= (UNC_KNOWN | UNC_EXPLICIT | UNC_QUAN_DECIMAL | UNC_KNOWN | UNC_NOMINUS);
+ }
+ else
+ { // NotOK, so clear.
+ types &= ~(UNC_KNOWN | UNC_EXPLICIT | UNC_QUAN_DECIMAL | UNC_KNOWN | UNC_NOMINUS);
+ }
+ }
+ else if (c == '-')
+ { // // Negative uncertainty only, for example: "-0.123"
+ isMinus = true;
+ is >> expUnc;
+ // expUnc = -expUnc; // Have already consumed the '-' sign! But stddev is always positive.
+ if (!is.fail())
+ { // OK, so set uncertain type flags.
+ types |= (UNC_KNOWN | UNC_EXPLICIT | UNC_QUAN_DECIMAL | UNC_KNOWN );
+ }
+ else
+ { // NotOK so clear flags.
+ types &= ~(UNC_KNOWN | UNC_EXPLICIT | UNC_QUAN_DECIMAL | UNC_KNOWN );
+ }
+ } // == '-'
+ }
+
+ if (isPlus || isMinus)
+ { // Some plus and/or minus value has been input.
+ types |= (UNC_KNOWN | UNC_EXPLICIT);
+ if ((isPlus) && (isMinus))
+ {
+ isPlusMinus = true; // If both plus and minus uncertainty.
+ types &= ~(UNC_NOMINUS | UNC_NOPLUS); // Clear both exclusive,
+ stdDev = static_cast<float>(expUnc);
+ }
+ else
+ // if (!isPlusMinus) // Only + or -, but not both.
+ {
+ if (isPlus)
+ {
+ types |= UNC_NOMINUS;
+ }
+ else if (isMinus)
+ {
+ types |= UNC_NOPLUS;
+ }
+ stdDev = static_cast<float>(expUnc);
+ } // not both.
+ } // isPlus or isMinus
+ else
+ { // Implicit.
+ stdDev = static_cast<float>(stdDev); //
+ }
+
+#ifdef UNC_TRACE
+ {
+ std::cerr << " Explicit uncertainty ";
+ if (isPlusMinus)
+ {
+ std::cerr << " +/- ";
+ }
+ else
+ {
+ std::cerr << ((isPlus) ? "+ " : "");
+ std::cerr << ((isMinus) ? "- " : "");
+ }
+ std::cerr << expUnc << ", stdDev " << stdDev << endl;
+
+ } // trace
+#endif
+ // Degrees of freedom?
+ is >> ws; // Eat any whitespace before "(99)".
+ if (!is.eof())
+ { // Degrees of freedom as "(99)" may follow.
+ // (Default degreesOfFreedom = 0; == 1 observation.
+ if (is.peek() == '(')
+ { // 99) follows
+ std::char_traits<char>::int_type c = is.get(); // Discard '('
+ long df; // degreesOfFreedom is only unsigned short 16 bit integer, so might overflow,
+ is >> df; // but read into a temporary long int to do some checks.
+ if (is.fail())
+ { // long int not read OK.
+ degreesOfFreedom = (std::numeric_limits<unsigned short int>::max)(); // 0xFFFF; = Not known.
+ types &= ~(DEG_FREE_KNOWN | DEG_FREE_EXACT); // Clear these flags.
+ }
+ else
+ { // long degrees of freedom read OK, so check >=0, and not too big.
+ if (df < 0)
+ { // Can't have negative degrees of freedom!
+ degreesOfFreedom = (std::numeric_limits<unsigned short int>::max)(); // 0xFFFF; = Not known.
+ types &= ~(DEG_FREE_KNOWN | DEG_FREE_EXACT); // NOT defined.
+ }
+ else
+ { // df >= 0
+ degreesOfFreedom =
+ (df >= (std::numeric_limits<unsigned short int>::max)()) ?
+ (std::numeric_limits<unsigned short int>::max)() -1
+ // max df allowed.
+ : static_cast<unsigned short int>(df); // 1 observation == 1 degfree.
+ }
+ c = is.peek(); // Expect ')'
+ if (c == ')')
+ {
+ is.get(); // Discard ')'
+ types |= (DEG_FREE_KNOWN | DEG_FREE_EXACT); // deg_free IS known and integer so exact.
+ }
+ if (c != ')' || (is.fail()) )
+ { // (99 OK but missing bracket.
+ degreesOfFreedom = (std::numeric_limits<unsigned short int>::max)(); // 0xFFFF; = Not known.
+ types &= ~(DEG_FREE_KNOWN | DEG_FREE_EXACT); // NOT defined.
+ }
+ }
+ } // (99)
+ else
+ { // is EOF so NO (df)
+ types |= DEG_FREE_KNOWN ; // deg_free IS implicitly known == 0.
+ // degreesOfFreedom = 0U; // Default == 1 observation.
+ }
+ } // eof
+ } // eof
+#ifdef UNC_TRACE
+ {
+ std::cerr << "\n### unc_input:""\n""\t" "value "
+ << value
+ << ", stdDev " << stdDev
+ << ", df " << dec << degreesOfFreedom << ", "
+ << showUncTypes(types) << ", "
+ << showUncFlags(static_cast<unsigned short>(is.iword(uncFlagsIndex)))
+ << std::endl;
+ } // trace
+#endif
+ // Restore is stream flags - if altered.
+} // void unc_input(double&, double&, unsigned short&, unsigned short&, std::istream&);

Added: sandbox/SOC/2007/quan/boost/quan/impl/unc_output.ipp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/boost/quan/impl/unc_output.ipp 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,552 @@
+/*! \file unc_print.cpp
+ \brief Output of uncertain values.
+ \details Definitions of unc_input declarations in unc.hpp.\n
+ Outline:
+ ~~~~~~~~
+ 1 Get ios info: width, fill & precision, save to restore..
+ 2 Get the requested info from uncflags.
+ 3 Get the value, stddev, degfree & uncTypes..
+ 4 Check value & stdDev for Nan, inf, zero, neg.
+ 5 Determine significant digits and stdDeviation significant digits.
+ 6 Round.
+ 7 Determine padding.
+
+ Output.
+ ~~~~~~
+ Output leading padding.
+ output rounded value & exponent.
+ output +/- value, if requested.
+ output trailing padding, if required.
+ Output degrees of freedom, if required.
+
+ Record width used etc.
+*/
+
+// Copyright Paul A. Bristow 2009, 2012.
+
+// Use, modification and distribution are subject to 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)
+
+#include <boost/quan/unc.hpp>
+
+#include <boost/math/special_functions/fpclassify.hpp>
+ //using boost::math::isnan;
+ //using boost::math::isinf;
+ //using boost::math::isfinite;
+ //using boost::math::isnormal; // isfinite and not denormalised.
+
+#include <boost/math/special_functions/sign.hpp>
+ // using boost::math::signbit;
+ // using boost::math::sign;
+ // using boost::math::copysign;
+
+// Restore ios fill and precision, and set width to zero, as if used.
+#include <boost/io/ios_state.hpp>
+
+#include <cassert>
+#include <ostream>
+#include <sstream>
+ // using std::stringstream;
+
+/*!
+ \brief Output to stream given value as a decimal digit string,
+ rounding properly using the uncertainty information in stdDev,
+ and optionally including uncertainty as +/-, and degrees of freedom,
+ with addition control from additional unc stream manipulators.
+
+ \param value Mean or most likely value.
+ \param stdDev Uncertainty estimate as standard deviation.
+ \param degFree Degrees of freedom -1. (Default zero for 1 observation).
+ \param uncTypes 16 Uncertain type flags about the value.
+ \param os Output stream, default is to `std::ostream`.
+ \exception Throws `std::bad_alloc()` if 'os::iword' has not been initialised correctly,
+ or has been corrupted.
+*/
+void unc_output(double value, // Mean or most likely value.
+ float stdDev, // Standard deviation (uncertainty).
+ unsigned short int degFree, // Degrees of freedom -1.
+ unsigned short int uncTypes, // 16 Uncertain type flags.
+ std::ostream& os = std::cout) // Output stream.
+{
+ using boost::math::isnan;
+ using boost::math::isfinite;
+
+ using std::setprecision;
+ using std::setw;
+ using std::resetiosflags;
+
+ using std::istream;
+ using std::ostream;
+ using std::ios_base;
+ using std::char_traits;
+ using std::cout;
+ using std::cerr;
+ using std::cin;
+ using std::endl;
+ using std::flush;
+ using std::ws;
+ using std::streamsize;
+ using std::boolalpha;
+ using std::dec;
+ using std::hex;
+ using std::showbase;
+ using std::fixed;
+ using std::scientific;
+ using std::right;
+ using std::showpos;
+ using std::noshowpos;
+ using std::noshowbase;
+ using std::noshowpoint;
+ using std::showpoint;
+ using std::noadjust; // Restore to default state.
+ using std::nofixed; // Restore to default state.
+ using std::noscientific; // Restore to default state.
+ using std::defaultfloat; // Restore fixed & scientific to default state.
+ using std::hexbase;
+ using std::lowercase;
+
+ // Check iwords are setup correctly.
+ if ((os.iword(zeroIndex) != indexID) || (os.iword(topIndex) != indexID))
+ { // iwords are corrupt!
+ cerr << "\n!!! unc_output: " "iword corrupt!" << endl;
+ outUncValues(os, cerr); // Log all the iword values to cerr.
+ os << "?????" << endl;
+ throw std::bad_alloc(); // Or which other exception?
+ // This means the function `setUncDefaults(os)` has not been called for the stream os!
+ return; // int notOK might be better?
+ }
+ // References to os.iword()
+ long& uncWidth = os.iword(uncWidthIndex); // Width required for uncertain value.
+ long& oldUncWidth = os.iword(oldUncWidthIndex); // Width required for previous uncertain value.
+ long& uncFlags = os.iword(uncFlagsIndex); //
+ long& Width = os.iword(widthIndex); // Width specified by setw(99).
+ long& oldWidth = os.iword(oldWidthIndex); // width previously specified by setw(99)
+ long& setSigDigits = os.iword(setSigDigitsIndex); // Specified number of digits to use for value.
+ long& setStdDevSigDigits = os.iword(setUncSigDigitsIndex); // Specified number of digits to use for sd.
+ long& setScale = os.iword(setScaleIndex); // Scale factor, stored by `<< setScale(6)`
+ // Only actually scale multiple, if also request to set scale with `out << setscale ...`
+
+ // bools showing output requirements specified using unc additional ostream manipulators.
+ // Note that these bools are NOT initialised here,
+ // assuming compiler will warn if used before being initialised.
+ /*
+ \var bool isNoisyDigit
+ \brief Add an extra 'noisy' guard digit to reduce risk of information loss.
+ */
+ bool isNoisyDigit;
+ bool isPlusMinus;//!< Uncertainty as +/- is required too (but ignore if value is exact or integer).
+ bool isUppercase; //!< Exponential format is, for example, 1E6 else 1e6.
+ bool isScientificFormat; //!< Taken to mean that exponential format wanted (always possible).
+ bool isShowPoint; //!< Means decimal point is always shown, for example 900. even if not needed.
+ bool isShowPos; //!< Show + sign always because ios flag was set with `<< showpo`s.
+ bool isFixed; //!< `os << fixed ...` ios decimal fixed d.dddd format (rather than scientific).
+ bool isWidthSet; //!< `os << setw(9)` has prescribed a width (rather than default width == 0).
+ bool isNoAdjust; //!< std = default but unc usage not defined yet, center?
+ bool isRightJustify; //!< right justify, prepend leading pad before. `<< right << ...`
+ bool isLeftJustify; //!< left justify, append trailing pad after. `<< left ...`
+ bool isInternalJustify; //!< Not defined yet, but use to center in field?
+ bool isCenter; //!< center if BOTH left and right specified.
+ bool isAlign; //!< Align on decimal point?
+
+ // bools showing state of arguments value, stdDev, df.
+ // Note that these bools are NOT initialised here,
+ // assuming the compiler will warn if use before initialized.
+ // They all need to be 'global' to `unc_output`.
+ bool isValueExact = false; //! value is exact (integer, rational, zero stdDev or noplus & nominus).
+ bool isValueInteger = false; //! value is an integer, or stdDev = 0.f.
+ bool isUncKnown = false; //!< StdDev or uncertainty is valid.
+ bool isValueNaN = false; //!< value is NaN.
+ bool isValueInfinite = false; //!< Value is infinite (postive or negative).
+ bool isValueNegative = false; //!< Value is negative.
+ bool isValueZero = false; //!< Value is zero.
+ bool isValueNearZero = false; //!< So near to zero that can't calculate relative stdDev.
+ bool isValueTooBigforUnc = false; //!< Magnitude > 1e38
+ bool isValueTooBigforSI = false; //!< magnitude > 1e24
+ bool isValueZeroFractional = false; //!< Value to output has a non-zero fractional part.
+ bool isStdDevNaN = false; //!< StdDev is NaN.
+ bool isStdDevInf = false; //!< StdDev is inf.
+
+ //int sigDigits = std::numeric_limits<double>::max_digits10; // Default significant digits for value.
+ // Show all potentially significant?
+ int sigDigits = 6; // Default significant digits for value.
+ // For non-zero: 3 means ddd0. or ddd. or dd.d or d.dd or d.dd or 0.ddd or 0.0ddd ...
+ // For zero, sigDigits = 1 means just 0, 2 means 0.0, 3 means 0.00 ...
+ // If sigDigits < 0 means significant digits is undefined.
+ int stdDevSigDigits = 1; // Default significant digits for stdDev.
+
+#ifdef UNC_TRACE
+ { // Log the unc_output arguments:
+ std::cerr << "\n <<< unc_output: "
+ << setprecision(2 + std::numeric_limits<double>::digits * 3010/10000) // aka max_digits10
+ << value // scientific if necessary.
+ << ", stdDev " << stdDev
+ << ", df " << degFree
+ << " ";
+ // and log the info from the unc iwords:
+ outUncFlags(uncFlags, std::cerr);
+ std::cerr << " ";
+ outUncTypes(uncTypes, std::cerr);
+ outUncValues(os, std::cerr);
+ }
+#endif
+ //const int savedUncFlags = uncFlags; // Save to restore.
+ //const int savedUncWidth = os.iword(uncWidthIndex); // Save to restore.
+ // Why restore? - passed by value, so can alter if want to.
+
+ // Width, precision, flags & fillChar data from stream os. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ streamsize iosWidth = os.width(); //!< \warning Width must be read BEFORE any use of os
+ // which would reset width back to zero!
+ // & prevent any ios formatting during os << ...
+ // because unc_output does all its own formatting.
+ isWidthSet = (iosWidth > 0); // For example by os << setw(99)
+ // Fixed width field suits tables.
+ // For example: os << setw(10) means fit into a width of 10, with padding if necessary.
+ // stream width <= 0 means no justification or padding.
+ // Since default width = 0 after each item output so ostream,
+ // defaults to flex format, suitable for flexible non-tabulated layout.
+ const std::streamsize iosPrecision = os.precision();
+ // Number of significant decimal digits prescribed by \c setprecision(int), Default is 6.
+ const char iosFillChar = os.fill(); // Default is a space.
+ // Save format flags from \c ostream, so can restore on exit, and set \c ios default values.
+ const int iosFlags = os.flags(); // Save fmtflagsin case need to restore.
+ os.width(0); // Would be zeroed by any previous use like << avalue ...
+ os.flags(ios_base::dec | ios_base::skipws); // All other format flags are zero (cleared bits).
+ // Leaving fill and precision as on entry.
+#ifdef UNC_TRACE
+ { // Log ios fillchar, precision & width.
+ // fill char set by \c os.fill('~'); or \c << \c setfill('~')
+ // precision by \c << setprecision(10) or cout.precision(10),
+ // width by \c setw(10) or \c cout.width(10)
+ std::cerr << " IOstream: "
+ "fill char " << hex << showbase
+ << int(iosFillChar) << space
+ << '\'' << iosFillChar<< '\''<< dec
+ << ", precision " << iosPrecision << ", width " << iosWidth << ", "
+ << std::endl;
+ std::cerr << " "; outFmtFlags(os.flags(), std::cerr, ".\n");
+ std::cerr << " "; outIOstates(os.rdstate(), std::cerr, ".\n");
+ } // trace
+#endif
+
+ // Get print format requirements from std::ios flags. ****************************
+ isUppercase = static_cast<bool>(iosFlags & ios_base::uppercase); // E not e.
+ // TODO No mechanism to change uppercase at present in round_* functions.
+ isScientificFormat = static_cast<bool>(iosFlags & ios_base::scientific); // exp format wanted.
+ isFixed = static_cast<bool>(iosFlags & ios_base::fixed); // `<< fixed` Fixed format wanted.
+ // means d.dddd format wanted, if possible, rather than scientific or exp format.
+ isNoAdjust = !static_cast<bool>(iosFlags & ios_base::adjustfield); // `<< noadjust`
+ // no adjustfield flags are set (default, and == << right - a waste!).
+ isLeftJustify = static_cast<bool>(iosFlags & ios_base::left);
+ // left justify, append trailing padding with fillchar after.
+ isRightJustify = static_cast<bool>(iosFlags & ios_base::right);
+ // right justify, prepend leading padding with fillchar before.
+ isInternalJustify = static_cast<bool>(iosFlags & ios_base::internal);
+ // IO streams use to output fill char between sign and 1st digit.
+ // And meaning of more than one bit is specially defined for unc_output:
+ isCenter = isLeftJustify && isRightJustify;
+ // center if BOTH left and right ios specified.
+ // Done with ` << ` center rather than `<< left << right ... `.
+ isAlign = isInternalJustify && isLeftJustify && isRightJustify;
+ // Align decimal point with previous value?
+
+ isShowPoint = static_cast<bool>(iosFlags & ios_base::showpoint);
+ // Means decimal point is always shown, for example 900. even if not needed.
+ isShowPos = static_cast<bool>(iosFlags & ios_base::showpos);
+ // Show + sign always.
+
+ // Get print format requirements from unc flags.
+ isNoisyDigit = static_cast<bool>(uncFlags & noisyDigit); // `<< addNoisyDigit`
+ isPlusMinus = static_cast<bool>(uncFlags & plusMinus); // `<< plusminus`
+ // Uncertainty as +/- is required too (but ignore if integer).
+
+ int exponent = 0; // To hold calculated 10 ^ exponent.
+ size_t used = 0; // Count of chars actually output to stream os.
+
+#ifdef UNC_TRACE
+ { // Log display options.
+ std:: cerr << " " "Display: "
+ << (isPlusMinus ? "+/- " : "")
+ << (isUppercase ? "upper " : "lower ")
+ << (isScientificFormat ? "expFormat " : "")
+ << (isWidthSet ? "set_width" : "")
+ << (isFixed ? "fix " : " ")
+ << (isNoAdjust ? "no_adjust " : "")
+ << (isLeftJustify ? "left " : "")
+ << (isRightJustify ? "right " : "")
+ << (isInternalJustify ? "internal " : "")
+ << (isCenter ? "center " : "")
+ << (isAlign ? "align " : "")
+ << (isShowPos ? "show_+ " : "" )
+ << (isShowPoint ? "show_. " : "")
+ << std::endl;
+ } // trace
+#endif
+
+ // Check value, stdDev & unc types for finite, zero, integer, exact. @@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
+ // Check value features first.
+ const double savedValue = value; // Save in case need original (signed & unscaled).
+ isValueInteger = static_cast<bool>(uncTypes & VALUE_INTEGER); // Explicitly flagged as integer.
+ isValueExact = static_cast<bool>
+ (( ((uncTypes & (UNC_NOPLUS | UNC_NOMINUS)) == (UNC_NOPLUS | UNC_NOMINUS))// Both NOPLUS & NOMINUS bits set == 1,
+ || (uncTypes & VALUE_EXACT) == VALUE_EXACT) // or flagged as exact VALUE_EXACT, like 2.54
+ || ((uncTypes & (VALUE_INTEGER | VALUE_RATIONAL)) != 0) ); // Both integers (99) & rationals (22/7) are implicitly exact,
+ // But zero values, for example 0.000 (implicitly +/- 0.0005) or 0. +/- 0.05f
+ // are NOT exact (nor integer), unless stdDev = 0.f, or integer constructed from "0".
+
+ if (isValueExact)
+ { // By convention, uncTypes take precedence over any value of stdDev.
+ // But should also cross-check if VALUE_EXACT and stdDev != 0.f
+ stdDev = 0.f; // Ensuring it is finite in test below.
+ degFree = (unsigned short)0;
+ // By convention, exact values have 1 reading & so degfree == 0
+ if (isValueInteger)
+ { // No +/- because is integer, even if requested y << plusminus.
+ isPlusMinus = false;
+ } //
+ } // isValueExact
+
+ // Check if value is finite.
+ if (!isfinite(static_cast<double>(value)))
+ { // (value == NaN) || (value == SNaN) || (value == INFINITY)
+ if (isnan(value))
+ { // NaN
+ isValueNaN = true;
+ isValueNegative = false; // By convention, only positive zero and positive NaNs.
+ }
+ else
+ { // If not NaN then assume + or - infinity.
+ isValueInfinite = true;
+ isValueNaN = false;
+ // Unlike zero and NaN, can have negative infinity.
+ } // isNaN?
+ isValueZero = false;
+ isValueExact = false;
+ isUncKnown = false;
+ } // value not finite.
+ else
+ { // value IS finite, so can test if value is negative or zero, too big or too small.
+ isValueInfinite = false;
+ isValueNaN = false;
+ isValueZero = (0. == value);
+ if (isValueZero)
+ { // Keep display of zero value simple (& avoid risk of divide by zero!).
+ isValueNegative = false; // By convention, only +0 and +NaNs.
+ isValueNearZero = true; // Use to avoid relative std deviation.
+ isScientificFormat = false;
+ exponent = 0;
+ } // is ZeroValue.
+
+ if (value < 0.)
+ { // is Negative (OK to use < 0. test here because have already eliminated NaN and inf).
+ isValueNegative = true;
+ value = fabs(value); // Can now ignore effect of negativeness, adding sign for output.
+ } // value < 0.
+
+ isValueNearZero = (value < numeric_limits<double>::min() * 10.);
+ // May cause divide-by-zero trouble if use relative std deviation.
+
+ } // value zero, finite, NaN, outsize tests.
+
+ // Check on features of stdDev.
+ isUncKnown = uncTypes && UNC_KNOWN; // Uncertainty is flagged as KNOWN from uncType,
+ // (but still need to check that stdDev is finite).
+ if (!isfinite(stdDev))
+ { // stdDev is NaN or infinity.
+ isValueInteger = false; // ???
+ isValueExact = false; // Uncertainty must be zero for exact, sp can't be exact if uncertainty is undefined, .
+ uncTypes &= ~(UNC_KNOWN | UNC_NOPLUS | UNC_NOMINUS | UNC_QUAN_DECIMAL | UNC_QUAN_BINARY | UNC_UNIFORM | UNC_TRIANGULAR);
+ // and clear many bits for unc_types which cannot be correct.
+ isUncKnown = false; // Despite uncType flag UNC_KNOWN.
+ if (isnan(stdDev))
+ {
+ isStdDevNaN = true; // (So uncertainty undefined)
+ // but value is OK, so leave the value as is.
+ }
+ else // If stdDev not NaN then assume stdDev is infinite (+ or -).
+ { // If stdDev == infinity, then, by convention, value == NaN.
+ value = numeric_limits<double>::quiet_NaN(); // So the value becomes undefined too.
+ isValueNaN = true;
+ isStdDevInf = true;
+ } // stdDev is NaN or infinity.
+ } // stdDev NOT finite.
+ else
+ { // stdDev is finite (normal case).
+ isStdDevInf = false;
+ isStdDevNaN = false;
+ isUncKnown = true;
+ if ((0.f == stdDev) && isUncKnown)
+ { // stdDev is finite zero (& uncertainty is known) so
+ isValueExact = true; // value explicitly exact.
+#ifdef UNC_TRACE
+ {
+ std::cerr << " " "StdDev exact value "<< value;
+ } // trace
+#endif
+ } // stddev finite
+ else
+ { // stdDev != 0, so value cannot be exact.
+ isValueExact = false;
+ }
+ } // End checks on stdDev.
+
+#ifdef UNC_TRACE
+ { // Show output settings.
+ std::cerr
+ << " " "Output Settings: " << boolalpha << dec
+ << (isWidthSet ? "width is set, " : "no width set, ")
+ << (isPlusMinus ? " +/- " : "")
+ << (isUppercase ? "upper " : "lower ")
+ << (isScientificFormat ? "expFormat " : "")
+ << (isFixed ? "fix " : " ")
+ << (isLeftJustify ? "left " : "")
+ << (isNoAdjust ? "no adjust " : "")
+ << (isRightJustify ? "right " : "")
+ << (isInternalJustify ? "int " : "")
+ << (isShowPos ? "show_+ " : "" )
+ << (isShowPoint ? "show . " : "")
+ << (isValueZero ? "isValueZero " : "" )
+ << (isValueNearZero ? "isValueNearZero " : "" )
+ << (isValueExact ? "isValueExact " : "" )
+ << (isValueInteger ? "isValueInteger " : "" )
+ << (isValueNegative ? "isValueNegative " : "" )
+ << (isValueInfinite? "isValueInfinite " : "" )
+ << (isValueNaN ? "isValueNaN " : "" )
+ << (isStdDevNaN ? "isStdDevNaN " : "" )
+ << (isValueTooBigforSI ? "Too_big for_SI " : "")
+ << (isValueTooBigforUnc ? "Too_big_for_unc " : "")
+ << (isUncKnown ? "isUncKnown " : "uncUnknown" )
+ << std::endl;
+
+ std::cerr << " " "Value " << setprecision(18) << value << (isValueNearZero ? "isValueNearZero " : "");
+ } // trace
+#endif
+ // Scale the value, if required by unc flags setScaled or autoScaled. __________________________
+ // 0 == scale10 means (not)scaled by unity. 3 means divided by 1000 ...
+ if (!isValueInteger && !isValueZero && !isValueInfinite && !isValueNaN)
+ { // autoscaled or set scaled.
+ // but NOT isValueInteger, so means output 10000 m not 10.000 km,
+ // nor zero because pointless.
+ } // if (isScaled && !isValueInteger)
+
+ // ScaledValue is in range OK, exponent == 0
+ // so find power of ten of ms digit, 9 = 10 ^ 0, 90 = 10 ^ 2
+ // int stdDevExponent = 0; // If value is d.d, then exponent = 0.
+
+ // Calculate how many significant digits for value, and then for stdDev.
+ // Or, if requested, use the set values.
+
+ // int sigDigits; // Significant digits for value,
+ // for example: 3 means ddd0. or ddd. or dd.d or d.dd or d.dd or 0.ddd or 0.0ddd ...
+ // For zero, sigDigits = 1 means just 0, 2 means 0.0, 3 means 0.00 ...
+ // int stdDevSigDigits; // Significant digits for stdDev.
+ if (isValueInteger)
+ { // Integer 9876
+ stdDevSigDigits = 0; // No uncertainty known!
+ // But even if << plusminus, do NOT output "9 +/- 0" for an integer.
+ // Do output decimal point if requested by showpoint.
+ // Do we want to scale integers if requested by << setscale? TODO
+ sigDigits = exponent + 1; // So for integers 1 to 9: exponent = 0 & sigDigits = 1,
+ // for integers 10 to 19, exponent = 1, sigDigits = 2 ...
+ isPlusMinus = false; // Never show "2 +/-0" for integer value 2.
+ // (even if requested with out << plusminus << integer ... !).
+ } // isValueInteger.
+ else if (isValueExact)
+ { // Show full precision, but NO trailing zeros, so get "2.54" not "2.5400000000000"
+ sigDigits = 1;
+ // sigDigits = numeric_limits<double>::digits10; // Typically 15 digits are guaranteed.
+ // (Although max_digits10 are perhaps significant).
+ // Show "+/-0" if requested for real exact for example: "2.54 +/-0"
+ // (unlike NOT for integer).
+ stdDevSigDigits = 0; // "+/-0" not "+/-0.", "+/-0.0", "+/-0.1" ...
+ exponent = 0;
+ } // isValueExact.
+
+ if (os.iword(uncFlagsIndex) && useSetSigDigits)
+ { // Use set sig digits instead of calculated from uncertainty.
+ sigDigits = setSigDigits;
+ os << setprecision(setSigDigits) << value;
+ }
+
+ // Inexact and known uncertainty (including 0.0000 +/- 0.00019 case).
+#ifdef UNC_TRACE
+ { // scaling.
+ std::cerr << std::setprecision(sigDigits+2) << dec
+ << " "
+ << ", sigDigits " << sigDigits
+ << ", stdDevSigDigits " << stdDevSigDigits;
+ if (os.iword(uncFlagsIndex) && useSetSigDigits);
+ { // Only if flag set.
+ std::cerr << ", setSigDigits " << setSigDigits;
+ }
+ if (os.iword(uncFlagsIndex) && setStdDevSigDigits))
+ { //
+ std::cerr << ", useSetUncSigDigits " << setStdDevSigDigits;
+ << std::endl;
+ }
+ } // trace
+#endif
+
+ const char signChar = (isValueNegative) ? '-': // Always show '-' sign.
+ (isShowPos ? '+' : // show '+' only if isShowPos.
+ //(isWidthSet ? ' ' : 0 ) ); // space where sign char would be only for isWidthSet.
+ (isWidthSet ? 0 : 0 ) ); // zero where sign char would be only for isWidthSet.
+
+ // Save previous before actually output anything, so can restore on exit.
+ os.iword(oldSigDigitsIndex) = os.iword(sigDigitsIndex); // Save previous sigDigitsIndex.
+ os.iword(sigDigitsIndex) = sigDigits; // Save or 'return' sigDigits used next.
+
+ // ################### Actually Output value (append +/- if isPlusMinus). ####################################
+
+#ifdef UNC_TRACE
+ {
+ std::cerr << " " " ios Width " << iosWidth
+ << ", ios fill char " << showbase << hex << int(iosFillChar) << dec
+ << (isprint(iosFillChar) ? iosFillChar : ' ')
+ << ", signChar (" << showbase << hex << int(signChar) << dec << noshowbase << ") " << ((signChar != 0) ? signChar : ' ')
+ << std::endl;
+ } // trace
+#endif
+
+ std::ostringstream oss; // Value etc string to really output, with pre & /or after padding, if necessary.
+
+ bool beenPointed = false; // Decimal point has not been output yet.
+ // Might use this later for alignment of table the decimal points.
+
+ if (isValueInfinite)
+ {
+ oss << ((isValueNegative) ? "-infinity" : "+infinity");
+ }
+ else if(isValueNaN)
+ {
+ oss << "NaN"; // "NaN"
+ }
+ boost::io::ios_precision_saver precision_saver(os); // Save and restore on exit.
+ boost::io::ios_flags_saver flags_saver(os);
+
+ // round here.
+ //os << val.value() << "(+/-" << val.uncertainty() << ")";
+
+ //os << oss.str(); // "1.23 +/- 0.1 (9) mV"
+
+ used = oss.str().size();
+
+#ifdef UNC_TRACE
+ {
+ std::cerr << " " << dec << used << " chars used in total." << std::endl;
+ } // trace
+#endif
+
+ os.iword(oldUncUsedIndex) = os.iword(usedIndex); // Save previous used.
+ os.iword(usedIndex) = static_cast<long>(used); // Record chars actually output to os.
+ // This may be needed to calculate layout of a table,
+ // Std behaviour is to return to default width.
+ // Field width reverts to its default behavior, width = 0
+ // (the necessary width) after one field has been printed,
+ // so must be last item before a ';' to be read. Not ideal!!
+ // os.width = savedWidth; // Restoring width is pointless.
+ os.flags(iosFlags); // Restore ios flags.
+} // void unc_output(double value, float stdDev,
+// unsigned short int degFree, unsigned short int uncTypes, ostream& os);

Added: sandbox/SOC/2007/quan/boost/quan/impl/xiostream.ipp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/boost/quan/impl/xiostream.ipp 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,339 @@
+/*! \file
+ \brief Extra iostream manipulators.
+ \details Definitions of declarations in xiostream.hpp.
+
+ \author Paul A. Bristow
+
+*/
+// file /impl/xiostream.ipp
+
+// Copyright Paul A. Bristow 2009
+
+// Use, modification and distribution are subject to 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)
+
+//#include <boost/quan/xiostream.hpp> // Declarations of items defined below.
+// included from this file.
+
+#ifndef XIOSTREAM_IPP
+#define XIOSTREAM_IPP
+
+#include <boost/math/special_functions/fpclassify.hpp>
+
+std::ios_base& lowercase(std::ios_base& _I)
+{ // lowercase is the inverse of std::ios_base::uppercase.
+ _I.unsetf(std::ios_base::uppercase); // Default is lowercase.
+ return _I;
+} // lowercase
+
+// Function to set base hex & showbase & uppercase too.
+// Usage: out << hexbase << ... for 1234ABCD
+// equivalent to out << hex << showbase << uppercase ...
+std::ios_base& hexbase(std::ios_base& _I)
+{
+ _I.setf(std::ios_base::hex | std::ios_base::showbase | std::ios_base::uppercase, // setbits,
+ std::ios_base::basefield | std::ios_base::showbase | std::ios_base::uppercase); // mask.
+ // Care: std::ios_base::basefield); doesn't set showbase & uppercase!
+ return _I;
+}
+
+// Manipulator template.
+// Copy of template for manipulator (from std iomanip)
+// Usage: omanip<int>setw(int);
+template<typename T> class omanip // Manipulator for ostream.
+{
+ friend std::ostream& operator<< (std::ostream&, const omanip<T>&);
+public:
+ omanip(std::ostream&(*f)(std::ostream&, T), T v) : func(f), val(v)
+ {
+ }
+private:
+ std::ostream&(*func)(std::ostream&, T); // Function like setw
+ T val; // Parameter like width.
+}; // class omanip
+// Could also provide an istream version for operator >>
+
+// Applicator is a class that stores a pointer to a function that takes
+// a reference to an std::ios_base (or derived translator) argument, and
+// an argument of the type for which the applicator is parameterized.
+// Applicator classes have the function call operator overloaded
+// so as to simulate a function call with the argument of the parameter type.
+// Use, for example: oapp<int> spaces(_spaces); // allows << spaces(5) ...
+// where function is std::ostream& _spaces(std::ostream&, int);
+
+// Global ostream applicator using template oapp instantiated for type int,
+// & initialised with the addresss of function with one int parameter.
+// Possible to use oapp<int> spaces(_spaces); which allows << spaces(5) ...
+// but instead spaces, stars & chars done a simpler way, see S Teale p 181-3.
+template<class T> class oapp // Applicator for ostream.
+{
+public:
+ oapp(std::ostream&(*f)(std::ostream&, T)) : func(f)
+ {
+ };
+ // : func(f) {} added from Watcom version to initialise & define.
+ omanip<T> operator()(T v)
+ {
+ return omanip<T>(func, v);
+ }
+private:
+ std::ostream&(*func)(std::ostream&, T);
+}; // class oapp
+
+// Template Manipulator Inserter <<
+template<class T> std::ostream& operator<< (std::ostream& os, const omanip<T>& m)
+{
+ (*m.func)(os, m.val);
+ return os;
+};
+
+// C++ Std Parameterless manipulators not used.
+// std::ostream& operator<<(std::ostream& (*)(std::ostream&) );
+// See \include\ostream for manipulator template eg endl
+// & instantiations of endl, ends, flush near end of file.
+// only narrow char instantiated here, may need wide version too.
+
+// Manipulator with no arguments which inserts into ostream.
+// See MSVC++ 7 "Writing your own manipulators without arguments".
+// No class derivation nor macros.
+// Relies on std::ostream defining overloading of operator<< to accept
+// function type, for example, std::ostream& bold(std::ostream&); declared in unc.h
+// inline std::ostream& ostream::operator<<(std::ostream& (__cdecl * _f)(std::ostream&)) { (*_f)(*this); return *this; }
+// inline std::ostream& ostream::operator<<(std::ios_base& (__cdecl * _f)(std::ios_base& )) { (*_f)(*this); return *this; }
+// Usage: cout << "regular" << bold << "now bold" << endl;
+// std::ostream& bold(std::ostream& os) // perhaps inline
+// {
+// return os << '\033' << '['; // Use if have ANSI terminal emulation.
+// }
+
+// Manipulators like dec, oct, dec ... see \include\std::ios_base
+// Parameterless manipulators like dec, hex ...
+// std::ios_base& (*)(std::ios_base&)
+// Pointer to function taking std::ios_base reference argument
+// & returning std::ios_base reference.
+// These apply to both istream and ostream.
+//
+// std::ostream& (*)(std::ostream&) and istream& (*)(istream&)
+// Pointer to function taking ostream (or istream) reference argument
+// & returning ostream (or istream) reference, but NOT BOTH.
+// Inserters and extractors:
+// std::ostream& operator<<( std::ios_base&(*)(std::ios_base&) )
+// istream& operator<<( std::ios_base&(*)(std::ios_base&) )
+// Eg std::ios_base& dec(std::ios_base& s){s.setf(std::ios_base::dec, std::ios_base::basefield);}
+
+spaces::spaces(int n) : num(n)
+{ // Constructor.
+}
+
+std::ostream& operator<< (std::ostream& os, const spaces& s)
+{
+ for (int i = s.num; i > 0; i--) os << ' ';
+ return os;
+}
+
+tabs::tabs(int n) : num(n)
+{ // Constructor.
+}
+
+std::ostream& operator<< (std::ostream& os, const tabs& s)
+{
+ for (int i = s.num; i > 0; i--) os << '\t';
+ return os;
+}
+
+stars::stars(int n) : num(n)
+{ // Constructor.
+}
+
+std::ostream& operator<< (std::ostream& os, const stars& s)
+{
+ for (int i = s.num; i > 0; i--) os << '*';
+ return os;
+}
+
+// Two parameter manipulator chars (not using template, as spaces)
+// Usage: << chars(5,'_') ... for 5 underlines.
+chars::chars(int n, char c) : num(n) , character(c)
+{ // Constructor.
+}
+
+std::ostream& operator<< (std::ostream& os, const chars& s)
+{
+ for (int i = s.num; i > 0; i--) os << s.character;
+ return os;
+}
+
+// Manipulator to set specified base and to show base letter O or X uppercase.
+// Usage: out << setupperbase(16) ...
+setupperbase::setupperbase(int b) : base(b)
+{ // Constructor.
+}
+
+std::ostream& operator<< (std::ostream& os, const setupperbase& s)
+{
+ os.setf(std::ios_base::showbase | std::ios_base::uppercase |
+ ( 16 == s.base ? 1 : // std::ios_base::hex :std::ios_base::oct;
+ 8 == s.base ? std::ios_base::oct : std::ios_base::dec) , // default dec if not 8 or 16
+ std::ios_base::basefield | std::ios_base::showbase | std::ios_base::uppercase ); // mask
+ return os;
+} // std::ostream& operator<< (std::ostream& os, const setupperbase& s)
+
+void outIOstates(std::ios_base::iostate rdState, std::ostream& os, const char* term)
+{ // Usages:
+ // Default logs cout iostate to cerr, for example "IOstate: good", or "IOstate: fail"
+ // outIOstates(); // Same as:
+ // outIOstates(cout.rdState(), cerr, ".\n");
+ // outIOstates(cin.rdState());
+ // outIOstates(cerr.rdState(), cout, ", ");
+ // outIOstates(cout.rdState(), cerr, " iostate.\n ");
+ std::ios_base::fmtflags const savedflags = os.flags(); // Save to restore.
+ // Clear any unused and invalid bits in rdState.
+ rdState &= std::ios_base::goodbit | std::ios_base::eofbit | std::ios_base::failbit | std::ios_base::goodbit;
+ // enum _Iostate {goodbit = 0x0, eofbit = 0x1, failbit = 0x2, badbit = 0x4, _Statmask = 0x7};
+ // but use std::ios_base::goodbit; for portability.
+ // MSVC /Dinkumware defines _Statmask 0x17, _Hardfail also added recently.
+ os << "rdState ("<< std::showbase << std::hex << rdState << ") " << std::dec ;
+ if (rdState == std::ios_base::goodbit)
+ {
+ os << "good"; // 1st so no leading space.
+ }
+ else
+ { // At least one bit set, so all need a space first.
+ if ((rdState & std::ios_base::eofbit) != 0)
+ {
+ os << " eof";
+ }
+ if ((rdState & std::ios_base::failbit) != 0)
+ {
+ os << " fail";
+ }
+ if ((rdState & std::ios_base::badbit) != 0)
+ {
+ os << " bad";
+ }
+ }
+ os << term; // eg "\n" or ", " or " ".
+ os.flags(savedflags); // Restore.
+} // outIOstates
+
+const char* fmtFlagWords[16] =
+{ // Descriptions of each bit.
+ "skipws", "unitbuf", "uppercase","showbase","showpoint","showpos","left","right",
+ "internal","dec","oct","hex","scientific","fixed","boolalpha", "?"
+ /*
+ enum _Fmtflags
+ { // Show action when bit set == 1
+ skipws = 0x0001, // Skip white space on input.
+ unitbuf = 0x0002, // Output each char - unbuffered.
+ uppercase = 0x0004,// Display uppercase A through F for hexadecimal values and E for scientific values
+ showbase = 0x0008, // Display numeric constants in a format that can be read by the C++ compiler.
+ showpoint = 0x0010, // Show decimal point and trailing zeros for floating-point values.
+ showpos = 0x0020, // Show plus signs (+) for positive values.
+ left = 0x0040, // Left-align values; pad on the right with the fill character.
+ right = 0x0080,// Right-align values; pad on the left with the fill character (default alignment).
+ internal = 0x0100, // Add fill characters after any leading sign or base indication, but before the value.
+ dec = 0x0200, // Format numeric values as base 10 (decimal) (default radix).
+ oct = 0x0400, // Format numeric values as base 8 (octal).
+ hex = 0x0800, // Format numeric values as base 16 (hexadecimal).
+ scientific = 0x1000,// Display floating-point numbers in scientific format.
+ fixed = 0x2000, // Display floating-point numbers in fixed format.
+ boolalpha = 0x4000, // Show bool as word true or false.
+ // 0x8000 un-used. // show as ?
+ adjustfield = 0x01c0,
+ basefield = 0x0e00,
+ floatfield = 0x3000,
+ _Fmtmask = 0x7fff,
+ _Fmtzero = 0
+ };
+ */
+}; // const char* fmtFlagWords
+
+void outFmtFlags(std::ios_base::fmtflags fmtFlags, std::ostream& os, const char* term)
+{// Usage: outFmtFlags(flags, cerr);
+ // For example, logs to cerr "FormatFlags: skipws showbase right dec"
+ // Defaults in xiostream.hpp:
+ // void outFmtFlags(fmtflags fmtFlags = cout.flags(), std::ostream& os = cerr, const char* term = ".\n");
+ const int count = 16; // because using unsigned short int.
+ std::ios_base::fmtflags flags = os.flags(); // save to restore.
+ fmtFlags &= static_cast<std::ios_base::fmtflags>(0x7FFF); // _Fmtmask // clear un-used bits.
+ os << "iosFormatFlags (" << std::showbase << std::hex << fmtFlags << std::dec << ")" ; // hex value.
+ if (fmtFlags != 0)
+ {
+ for(int i = 0, j = 1; i < count; ++i)
+ {
+ if ((fmtFlags & j) != 0)
+ {
+ os << ' ' << fmtFlagWords[i];
+ }
+ j <<= 1;
+ }
+ }
+ os << term; // eg "\n" or ". "
+ os.flags(flags); // Restore.
+} // outFmtFlags
+
+std::ostream& showiostate(std::ostream& os)
+{ // Show IO stream state in words for this stream.
+ // Usage: cout << showiostate ...
+ outIOstates(static_cast<std::ios_base::iostate>(os.rdstate()), os, ". ");
+ // May be problem with output if state is bad!
+ return os;
+}
+
+std::ostream& showformat(std::ostream& os)
+{ // Show IO stream format flags in words for this stream.
+ // Usage: cout << showformat ...
+ outFmtFlags(static_cast<std::ios_base::fmtflags>(os.flags()), os, ". ");
+ return os;
+}
+
+void setiosDefaults(std::ostream& os)
+{ // Return state and flags to same as when initialised.
+ // Would like to use std::ios_base::init, but is protected.
+ // See also setUncDefaults.
+ using std::ios_base;
+ // basic_streambuf<char, char_traits<char> >* os_buf = os.rdbuf();
+ // basic_ios<char, char_traits<char> >::init(os.rdbuf(), true);
+ // Cannot access protected member declared in class.
+ os.clear(std::ios_base::goodbit); // Clearing any 'bad' bits.
+ os.fill(' '); // Default fill char.
+ os.precision(6); // Default precision.
+ os.width(0); // Would be zeroed by any previous use like << 99 ...
+ os.flags(std::ios_base::dec | std::ios_base::skipws); // All others are zero (cleared bits).
+} // setiosDefaults(std::ostream& os)
+
+void outFpClass(double value, std::ostream& os);
+
+std::ostream& FPclass(std::ostream& os, double value)
+{ // Show Floating point type or value.
+ // Usage: cout << FPclass(NaN) ...
+ outFpClass(value, os);
+ return os;
+} // std::ostream& FPclass(std::ostream& os, double value)
+
+void outFpClass(double value, std::ostream& os = std::cerr)
+// Usage: outFpClass(x, std::cerr);
+{ // Custom outputs for NaN, inf ... (rather than default 1#IND ...)
+
+ if (boost::math::isfinite(value))
+ {
+ os << value;
+ }
+ else if (boost::math::isnan(value))
+ {
+ os << "NaN";
+
+ }
+ else if ( boost::math::isinf(value))
+ {
+ os << "inf";
+ }
+ else
+ {
+ os << "?" << value << "?";
+ }
+} // OutFpclass
+
+#endif // #define XIOSTREAM_IPP

Added: sandbox/SOC/2007/quan/boost/quan/meas.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/boost/quan/meas.hpp 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,109 @@
+/*! \file
+ \brief Class for measurement using uncertain class.
+ \details class meas with uncertain type UReal and measurement order & time-stamp.
+*/
+
+// meas.hpp
+// Copyright Paul A. Bristow 2012
+
+#ifndef MEAS_HPP
+#define MEAS_HPP
+
+#include <boost/date_time/gregorian/gregorian.hpp> // include all types plus i/o.
+#include <boost/date_time/posix_time/posix_time.hpp> // include all types plus i/o.
+
+#include <boost/quan/unc.hpp>
+
+// Declaration.
+//class Meas; // Measured uncertain value AND its id and order and/or time-date stamp.
+
+#include <iostream>
+ using std::ostream;
+ using std::istream;
+#include <string>
+ using std::string; // date notadate(not_a_date_time);
+
+typedef unc<false> uncun; // Uncertain Uncorrelated (the normal case).
+
+/*!
+ \brief Measured uncertain value AND its id and order and/or time-date stamp.
+*/
+
+class Meas : public uncun
+{
+ friend ostream& operator<< (ostream&, const Meas&);
+ friend istream& operator>> (istream&, Meas&);
+
+public:
+ //Meas(); // Constructor - all defaults.
+ Meas(double const d = 0.); // Constructor from double (no extra info).
+ //Meas::Meas(uncun u); // Constructor from uncertain uncun.
+ // Meas(int const); // Constructor from int - use automatic conversion int to double.
+ // Meas(uncun u, string id = "", boost::posix_time::ptime ti = boost::posix_time::not_a_date_time);
+ Meas(uncun u, string id = "", boost::posix_time::ptime ti = (boost::posix_time::not_a_date_time), int o = -1);
+ //Meas(uncun u, string id = "", int o = -1);
+ Meas(const Meas&); // Copy constructor.
+ ~Meas(); // Default destructor.
+
+ // Operators.
+ Meas& operator= (const Meas& rhs); //!< Assignment operator.
+ Meas& abs (const Meas& rhs); // abs assignment operator.
+ Meas& abs (Meas& rhs); // abs operator.
+
+ bool operator== (const Meas& p) const; // Equality operator.
+ bool operator!= (const Meas& p) const; // Inequality.
+ bool operator< (const Meas& rhs) const; // Used by less.
+ bool operator> (const Meas& rhs) const; // Used by greater.
+ Meas operator+ (const Meas&) const // Unary +
+ { // All members remain unchanged.
+ return *this;
+ }
+ Meas operator- (void) const // Unary -
+ { // uncun measValue;
+ Meas m(*this); // copy.
+ m.value(-m.value()); // Negate only the value.
+ return m;
+ }
+ Meas operator- (void) // Unary -
+ { // Avoid copy but cannot be const.
+ Meas m(*this); // copy.
+ m.value(-m.value()); // Negate only the value.
+ return *this;
+ }
+
+ // Meas Member functions.
+ // Note static as only one instance of functions for all Meas objects.
+ // Usage: Meas::lessU(a, b);
+ static bool less(const Meas& l, const Meas& r); // l < r value (ignoring uncertainty).
+ static bool lessU(const Meas& l, const Meas& r); // < uncertain value.
+ static bool less2U(const Meas& l, const Meas& r); // < 2 * uncertainty .
+ static bool precedes(const Meas& l, const Meas& r); // < order.
+ static bool earlier(const Meas& l, const Meas& r); // < time.
+ static bool greaterU(const Meas& l, const Meas& r); // > uncertain value.
+ static bool greater2U(const Meas& l, const Meas& r); // > 2 * uncertain value.
+ static bool equal_toUnc(const Meas& l, const Meas& r); //
+ static bool lessAbsM(const Meas& l, const Meas& r); // abs value < abs value.
+
+ // Meas Member variables.
+public: // Inconvenient to make private?
+ std::string id_; // Identification info, if any, else "".
+
+ // Time and order values could be:
+ // 1 no known order.
+ // 2 known order, but no times.
+ // 3 times, from which order can be calculated,
+ // or both order and times given, so may need to be checked for consistency.
+
+ int order_; // Index from 0 (or 1 perhaps?) -1 == unknown?
+ // time_t m_time; // Time too as time_t, notaTime if not known.
+ boost::posix_time::ptime time_; // Posix time from Boost.Date_time.
+}; // class Meas
+
+// Output and input operator<< & operator>>
+ostream& operator<< (ostream& os, const Meas& m);
+istream& operator>> (istream& is, Meas& m);
+
+// Definitions in meas.ipp.
+#include <boost/quan/impl/meas.ipp>
+
+#endif // MEAS_HPP

Added: sandbox/SOC/2007/quan/boost/quan/meas2.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/boost/quan/meas2.hpp 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,48 @@
+/*! \file
+ \brief Class for measurement using @b two uncertain class items.
+ \details class meas2 with @b two uncertain type UReal and measurement order & time-stamp.
+*/
+
+// meas2.hpp
+// Copyright Paul A. Bristow 2012
+
+#ifndef MEAS2_HPP
+#define MEAS2_HPP
+
+#include <boost/quan/meas.hpp>
+
+class meas2;
+
+class meas2
+{
+ friend ostream& operator<< (ostream&, const Meas&);
+ friend istream& operator>> (istream&, Meas&);
+
+ public:
+ //Meas(); // Constructor - all defaults.
+ meas2(uncun ux, uncun uy, string id = "", boost::posix_time::ptime ti= (boost::posix_time::not_a_date_time), int o = -1);
+ // Construct from two values and all other info
+
+ // Meas Member variables.
+public:
+ uncun m_uncx;
+ uncun m_uncy;
+
+ // Time and order values could be:
+ // 1 no known order.
+ // 2 known order, but no times.
+ // 3 times, from which order can be calculated,
+ // or both order and times given, so may need to be checked for consistency.
+
+ std::string m_id; // Identification info, if any, else "".
+
+ int m_order; // Index from 0 (or 1 perhaps?) -1 == unknown?
+ // time_t m_time; // Time too as time_t, notaTime if not known.
+ boost::posix_time::ptime m_time; // Posix time from Boost.Date_time.
+}; // class meas2
+
+// Output and input operator<< & operator>>
+ostream& operator<< (ostream& os, const meas2& m);
+istream& operator>> (istream& is, meas2& m);
+
+#endif // MEAS2_HPP
\ No newline at end of file

Added: sandbox/SOC/2007/quan/boost/quan/pair_io.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/boost/quan/pair_io.hpp 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,28 @@
+ /*! \file pair_io.hpp
+ \brief Provide operator<< to output pair, surrounded by < > and separated by comma,
+ for example: "<1.23, 4.56>".
+ Typically used to show confidence intervals around a mean.
+ \details Polite to keep this a private detail namespace to avoid clash with other implementations!
+ \author Paul A. Bristow
+ \date Oct 2009, 2012
+*/
+
+#include <utility>
+ // using std::pair;
+
+//
+template<typename charT, typename traits, typename T1, typename T2>
+inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, const std::pair<T1, T2>& p)
+{
+ return os << "<" << p.first << ", " << p.second << '>'; // Separated by comma & space.
+}
+
+// Explicit specialization for pair of doubles.
+template<typename charT, typename traits>
+inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, const std::pair<double, double>& p)
+{
+ return os << "<" << p.first << ", " << p.second << '>'; // Separated by comma & space.
+}
+
+
+

Added: sandbox/SOC/2007/quan/boost/quan/rounding.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/boost/quan/rounding.hpp 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,1458 @@
+/*!
+ \file
+ \brief Common rounding
+ \details
+ http://www.diycalculator.com/popup-m-round.shtml#A3
+ all rounding types, including round-to-half and asymmetric and symmetric versions.\n
+ http://www.chem1.com/acad/webtext/pre/mm3.html
+ "The purpose in rounding off is to avoid expressing a value to a greater degree of precision
+ than is consistent with the uncertainty in the measurement."
+ "Observed values should be rounded off to the number of digits
+ that most accurately conveys the uncertainty in the measurement."
+ \author Paul A. Bristow
+ */
+
+// \file rounding.hpp
+
+// Copyright Paul A. Bristow 2009, 2012.
+
+// Use, modification and distribution are subject to 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)
+
+/*! \mainpage <b> Proper rounding testbed documentation. </b>
+ *
+ * \section intro_sec Introduction to proper rounding.
+
+ This is a testbed for the epsilon-Proper rounding for a few distributions
+ assumed to be appropriate for the data observations.\n\n
+ Based on:\n
+ Gejza Wimmer, Viktor Witkovsky, Tomas Duby \n
+ Measurement Science and Technolology, 11 (2000) pages 1659-1665.
+ ISSN 0957-0233 S0957-233(00)13838-X.\n
+ Proper rounding of the measurement results under normality assumptions.\n\n
+ Gejza Wimmer, Viktor Witkovsky, Proper rounding of the measurement result
+ under the assumption of uniform distribution, \n
+ Measurement Science Review, Vol 2, section 1, (2002), pages 1 - 7.\n\n
+ Gejza Wimmer, Viktor Witkovsky, Proper rounding of the measurement result
+ under the assumption of triangular distribution, \n
+ Measurement Science Review, Vol 2, section 1, (2002), pages 21 to 31.\n
+ */
+
+#ifdef _MSC_VER
+#pragma warning(disable: 4127) // conditional expression is constant.
+#pragma warning(disable: 4180) // qualifier applied to function type has no meaning; ignored.
+//# pragma warning(disable: 4702) // unreachable code.
+//# pragma warning(disable: 4511) // copy constructor could not be generated.
+//# pragma warning(disable: 4512) // assignment operator could not be generated.
+//# pragma warning(disable: 4521) // alignment of a member was sensitive to packing.
+//# pragma warning(disable: 4121) // alignment of a member was sensitive to packing.
+//# pragma warning(disable: 4100) // unreferenced formal parameter.
+//# pragma warning(disable: 4701) // local variable may be used without having been initialized.
+//# pragma warning(disable: 4189) // local variable is initialized but not referenced.
+//# pragma warning(disable: 4996) // '' was declared deprecated.
+#endif
+
+#include <boost/math/tr1.hpp>
+// using boost::math::tr1::round; // round floating-point to integer.
+// using std::floor;
+// using std::pow;
+// using std::log10;
+
+#include <boost/math/special_functions/fpclassify.hpp>
+//using boost::math::isnan;
+//using boost::math::isinf;
+//using boost::math::isfinite;
+//using boost::math::isnormal; // isfinite and not denormalised.
+
+#include <boost/math/special_functions/sign.hpp>
+// using boost::math::signbit;
+// using boost::math::sign;
+// using boost::math::copysign;
+
+#include <boost/math/distributions/students_t.hpp>
+// using boost::math::students_t;
+#include <boost/math/distributions/normal.hpp>
+#include <boost/math/distributions/uniform.hpp>
+#include <boost/math/distributions/triangular.hpp>
+// using boost::math::normal;
+//#include "pair_io.hpp"
+// operator<<
+
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_floating_point.hpp> // is_floating_point trait
+#include <boost/concept_check.hpp>
+#include "boost/quan/xiostream.hpp" // Extra std items, defaultfloat & fixed.
+//#include "boost/quan/si_units.hpp"
+//#include "libs/quan/src/si_units.cpp"
+
+#include <iostream>
+//using std::cout;
+//using std::cerr;
+//using std::cin;
+//using std::endl;
+//using std::ends;
+//using std::dec;
+//using std::hex;
+//using std::fixed;
+//using std::left;
+//using std::right;
+//using std::showpoint;
+//using std::nofixed;
+//using std::noscientific;
+//using std::defaultfloat;
+//using std::noadjust;
+//using std::scientific;
+//using std::boolalpha;
+//using std::showpos;
+//using std::noshowpos;
+
+#include <iomanip>
+//using std::setprecision;
+//using std::setw;
+#include <string>
+//using std::string;
+
+#include <fstream> // for fstream
+//using std::fstream;
+//using std::ofstream;
+
+#include <sstream> // stream
+//using std::ostringstream;
+//using std::string;
+//using std::basic_string;
+//using std::ios_base;
+
+#include <limits>
+//using std::numeric_limits;
+
+#include <locale>
+// default loc for isdigit
+
+BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559); // Assume IEEE 754 ONLY.
+// _STATIC_ASSERT (numeric_limits<double>::is_iec559); // and MS STATIC assert.
+// Might also work by checking that std::numeric_limits is specialized?
+
+BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_specialized); //
+
+#ifdef BOOST_NO_CXX11_NUMERIC_LIMITS
+// No support for std::numeric_limits<double>::max_digits10,
+const unsigned int maxdigits10 = 2 + std::numeric_limits<double>::digits * 3010 / 10000;
+#else
+// std::numeric_limits<double>::max_digits10; IS supported.
+// Any noisy or guard digits needed to display any difference are included in max_digits10.
+const unsigned int maxdigits10 = std::numeric_limits<double>::max_digits10;
+#endif
+
+// Explicit specialization for pair of doubles.
+
+std::ostream& operator<<(std::ostream& os, std::pair<double, double>& p) { /*! Output a pair of `double`s, using < > angle brackets and comma separator, using current stream's precision..
+ \detail Explicit specialization for `std::pair` for `double`s.\n
+ For example: <97.8725, 157.798>
+ \param p Pair of doubles.
+ \param os std::ostream for string output.
+ */
+ return os << "<" << p.first << ", " << p.second << '>'; // Angle bracketed, separated by comma & space.
+}
+
+// Explicit specialization for pair of const doubles.
+
+std::ostream& operator<<(std::ostream& os, const std::pair<double, double>& p) { /*! Output a pair of `double`s, using < > angle brackets and comma separator, using current stream's precision..
+ \detail Explicit specialization for @b`const` `std::pair` for `double`s.\n
+ For example: <97.8725, 157.798>
+ \param p Pair of `double`s.
+ \param os `std::ostream` for string output.
+ */
+ return os << "<" << p.first << ", " << p.second << '>'; // Angle bracketed, separated by comma & space.
+}
+
+// Two rounding algorithms returning double values (not strings).
+template<typename FPT> FPT round_sig(FPT v, int n); // v rounded to n significant decimal digits.
+template<typename FPT> FPT round_to_n(FPT v, int p); // Round value v to p decimal digits *after the decimal point*.
+
+// Rounding algorithms returning strings.
+template<typename FPT> std::string round_f(FPT v, int sigdigits); // Round fixed (not-exponential) to sigdigits decimal digits to string.
+template<typename FPT> std::string round_e(FPT v, int sigdigits); // Round fixed (exponential) to sigdigits decimal digits to string.
+template<typename FPT> std::string round_ms(FPT v, int m); // Round not-exponential to order m.
+
+template<typename FPT>
+FPT round_sig(FPT v, int n) { /*! \brief Returns v rounded to n significant decimal digits.\n
+ http://www.jason.mock.ws/wordpress/2007/02/22/round-a-float-to-of-significant-digits,
+ David A. Pimentel
+ \details These use log10 and pow and so are vulnerable to binary rounding errors,
+ as the value may not be exactly representable for the type specified.
+ Should give the same value as printf precision.
+ (int)(x < 0 ? x - 0.5 : x + 0.5))
+ So do we need to do something different for negative doubles?
+ The difference between symmetric and asymmetric rounding?
+ */
+ // Will fail if FPT is not a floating-point type (because will not output in scientific format!).
+ BOOST_STATIC_ASSERT(boost::is_floating_point<FPT>::value);
+
+ using std::pow;
+ using std::log10;
+ using std::ceil;
+ if (n < 0) { // Probably a program error, so might throw?
+ return 0;
+ } else if (n == 0) { // Might also be an error, but make some sense, so
+ return 0.;
+ } else if (n > std::numeric_limits<FPT>::digits10) { // We might use max_digits10, but only digits10 are guaranteed.
+ n = std::numeric_limits<FPT>::digits10;
+ return v; // or just return value as is?
+ }
+ if (v == 0) {
+ return 0.;
+ }
+ FPT l10 = log10(v);
+ int l = static_cast<int> (ceil(l10));
+ int pow10 = n - l;
+ FPT p10 = pow(10., pow10);
+ FPT f = v * pow(10., pow10) + 0.5;
+ f = floor(f);
+ FPT r = f / p10;
+ return r;
+ // return floor(v * pow(10., pow10) + 0.5) / pow(10., pow10);
+} // FPT round_sig(FPT v, int n)
+
+template<typename FPT>
+FPT round_to_n(FPT v, int p) { /*! Round value v to p decimal digits *after the decimal point*.
+ http://www.jason.mock.ws/wordpress/2007/02/22/round-a-float-to-of-significant-digits
+ \note These use log10 and pow and so are vulnerable to binary rounding errors,
+ as the value v may not be exactly representable for the type specified.
+ Should give the same value as printf precision.
+ */
+ // Will fail if FPT is not a floating-point type (because will not output in scientific format!).
+ BOOST_STATIC_ASSERT(boost::is_floating_point<FPT>::value);
+
+ using std::pow;
+ return static_cast<FPT> (floor(v * pow(10., p) + 0.5) / pow(10., p));
+} // template<typename FPT> FPT round_to_n(FPT v, int p)
+
+template<typename FPT>
+std::string round_e(FPT d, int sigdigits) { /*! \brief Show only `sigdigits` digits, in minimal scientific or 'e' format only,
+ rounded asymmetric (round-half-up, arithmetic rounding).\n
+ Round asymmetric avoids values like 0.15,
+ which cannot be stored exactly in binary IEEE 754 floating-point format
+ and are stored internally as 1.499999999999, being rounded unexpectedly to 0.1 rather than 0.2.
+ For example: format -1.2345e12 or 1.2345e-123.
+
+ \note the difference in meaning of precision from default, fixed and scientific, for example:
+ `d = 19.99;` \n
+ `cerr << setprecision(2) << d << endl; // 20 // rounded`\n
+ `cerr << fixed << setprecision(1) << d << endl; // 20.0 - rounded up.`\n
+ `cerr << fixed << setprecision(2) << d << endl; // 19.99 - 2 digits after decimal point.`\n
+ `cerr << scientific << setprecision(2) << d << endl; // 2.00e+001 - 2 digits after decimal point`
+
+ \details Also remove all redundant exponent characters and digits,
+ See http://en.wikipedia.org/wiki/Rounding .
+
+ \note The normal rounding provided by C and C++ is chosen to avoid loss of accuracy and bias
+ in any further *binary* calculations.
+ The rounded decimal digit *strings* returned are provided solely for *b human viewing
+ and should NOT be used for input to other calculations when one or
+ two extra noisy digits are needed to avoid loss of information by rounding.
+ If it is necessary to provide a decimal digit string for input,
+ it should use `std::numeric_limits<FPT>::max_digits10` in C++0x,
+ or `2 + std::numeric_limits<FPT>::digits * 3010/10000`
+ if the platform implementation of C++ Standard IOstream library does not yet provide this.
+ For 64-bit double, `max_digits10` is 17, so write `cout.precision(17)`.
+ This will avoid any bias or loss of accuracy in statistical calculations caused by rounding.
+
+ \note The C++ Standard IOstream library does not specify any guarantee about input
+ from a decimal digits string to internal floating-point format like `double`.\n
+ The compiler will always convert a literal floating-point to the *nearest
+ representable value*, but the C++ Standard IOstream library is not required do this.
+ In particular, MSVC 8.0 (2007) and 10.0 (2010) do not quite always achieve this
+ for `defaultfloat` format -
+ about 1/3 third of significand values in the range 0.0001 to 0.003894 are not
+ input to the nearest representable double, but are 1-bit different.
+
+ It is impracticable to test all floating-point values in a useful time,
+ so random values were tested.
+
+ For details see:
+
+ http://lab.msdn.microsoft.com/productfeedback/viewfeedback.aspx?feedbackid=7bf2f26d-171f-41fe-be05-4169a54eef9e
+
+ aka http://tinyurl.com/mpk72
+
+ This is very significant if you wish to 'round-trip'
+ (outputting a value and reading it back in again)
+ for example with lexical_cast or using Boost.Serialization.
+ A test like
+
+ assert(value_output == value_reinput)
+
+ will fail *very* intermittently.
+
+ So if this is important to you, use the scientific (exponential) format
+ with precision max_digits10 (17 for double) where random tests have not revealed any differences.
+
+ Logic of using C++ std printf-style rounding to start with a decimal digit string with rounded value
+ of digits10, only the guaranteed correct digits
+ to get the best estimate of the digit to be used for the final rounding.
+ Hopefully, any imprecision caused by inexact presentation is (binary) rounded away.
+
+ \note Only lowercase letter e is used, and positive exponents are not preceeded by + sign,
+ and leading zeros are omitted.\n
+ This is done to make the display as compact as possible.\n
+ If a fixed width is needed, the user program must provide any necessary padding,
+ using the size (length) of the string.
+
+ \param d value to be converted to decimal digit string.
+ \param sigdigits number of significant digits to show in string.
+ \return std::string containing value rounded and converted to `sigdigits` decimal digits in exponential format.
+ */
+ // Will fail if FPT is not a floating-point type (because will not output in scientific format!).
+ BOOST_STATIC_ASSERT(boost::is_floating_point<FPT>::value);
+
+ if (boost::math::tr1::isinf(d)) {
+ return (boost::math::tr1::signbit(d) ? "-Inf" : "Inf");
+ }
+ if (boost::math::tr1::isnan(d)) {
+ return (boost::math::tr1::signbit(d) ? "-NaN" : "NaN");
+ }
+ if (sigdigits <= 0) {
+ std::cout << "Trying to display " << sigdigits << " significant decimal digits!" << std::endl;
+ return ""; // Or throw?
+ }
+
+ //const unsigned int max_digits10 = 2 + std::numeric_limits<FPT>::digits * 3010/10000;
+ if (sigdigits >= std::numeric_limits<FPT>::digits10) // C++0X provides std::numeric_limits<double>::max_digits10;
+ {
+ sigdigits = std::numeric_limits<FPT>::digits10; // digits10 (15 for double) decimal digits
+ // *after* the decimal point, so a total of 16 digits (plus a decimal point).
+ }
+
+ BOOST_STATIC_ASSERT(boost::is_floating_point<FPT>::value);
+ // Will fail if FPT is not a floating-point type (because will not output in scientific format!).
+
+ std::ostringstream ss;
+ ss << std::scientific // use 9.99e+123 format
+ << std::showpoint // force decimal point and trailing zeros.
+ //<< setprecision(sigdigits)
+ // output precision decimal digits *after the leading digit and decimal point*
+ // in scientific mode, so this is one more than significant digits.
+ // Or should this be digits10 so that any imprecision
+ // caused by inexact presentation is rounded away?
+ << std::setprecision(std::numeric_limits<FPT>::digits10) //
+ // output precision is
+ // decimal digits *after the leading digit and decimal point*, total digits10+1 digits.
+ << d;
+ std::string s = ss.str(); // "1.294567890123457e+006"
+ // std::cout <<'|' << s <<'|' << ' ' << s.size() << std::endl;
+ //assert(s.size() == std::numeric_limits<FPT>::digits10 + 1 + 1 + 5); // == 22 if positive
+
+ std::string::iterator is = s.begin(); // 1st most significant digit before decimal point.
+ if ((*is) == '-') { // Skip over minus sign.
+ // Can ignore + case as won't ever be output because default std::ostringstream is std::noshowpos.
+ is++;
+ }
+ char s1 = *is; // Copy 1st digit before decimal point.
+ std::string::iterator is1 = is; // Copy 1st digit before decimal point.
+ assert((*is1 >= '0') && (*is1 <= '9'));
+ is++; // Move to decimal point.
+ assert((*is) == '.');
+ // Do not delete decimal point - it will be needed.
+ std::string::iterator isp = is; // Decimal point. Implied position after 1st most significant digit is known.
+ assert((*isp) == '.');
+
+ // Read the exponent part first into an integer.
+ std::string::iterator se = is1 + std::numeric_limits<FPT>::digits10 + 2;
+ assert(*se == 'e');
+ se++; // skip 'e'.
+ // Read exponent into an integer.
+ bool neg_exp = ((*se) == '-') ? true : false;
+ se++; // Skip over sign of exponent.
+ std::locale loc;
+ int exp = 0;
+ do
+ {
+
+ if (std::isdigit(*se, loc))
+ {
+ exp = exp * 10 + (*se - '0');
+ }
+ se++;
+ }
+ while (se != s.end());
+
+ if (neg_exp)
+ {
+ exp = -exp; // Make exponent signed.
+ }
+
+ // std::cout << "Exponent " << ((neg_exp) ? '-' : '+') << exp << std::endl;
+
+ std::string::iterator is2 = is1 + 2; // 2nd digit (after decimal point).
+ assert((*is2 >= '0') && (*is2 <= '9'));
+ std::string::iterator isr = is2 + sigdigits - 1; // 2nd digit (after decimal point) if sigdigits == 1.
+ assert((*isr >= '0') && (*isr <= '9'));
+ int rounder = (*isr) - '0';
+ // std::cout << "rounder " << rounder << std::endl;
+ is = isr; // Least significant digit.
+ is--;
+ if (is == isp)
+ { // Skip back over decimal point.
+ is--;
+ }
+ assert((*is >= '0') && (*is <= '9'));
+
+ s.erase(isr, s.end()); // Erase all the insignificant trailing decimal digits, and exponent.
+
+ // Round the non-exponent part, in case a carry means we must increment the exponent.
+ // For example, 9.9e0 will round up to 10. and so become 1e1.
+ bool carry = false;
+ if (rounder >= 5) {
+ carry = true; // Increment next most significant digit.
+ do {
+ if (*is < '9') // 0 to 8.
+ {
+ (*is)++; // round up by 1.
+ carry = false;
+ } else if (*is == '9') {
+ *is = '0';
+ carry = true;
+ } else {
+ std::cout << "wrong ! *is = " << *is << std::endl;
+ break;
+ }
+ if (is == is1) { // No more significant digit(s).
+ break;
+ }
+ is--; // Next more significant digit.
+ if (is == isp) { // Skip over decimal point.
+ is--;
+ }
+ if (is == is1) {
+ break;
+ }
+ } while (carry == true);
+ } else { // Rounder = 0 to 4, so nothing to do.
+ carry = false;
+ }
+ if (carry == true) { // Add one to 1st most significant digit.
+ if (s1 == '9') { // Carry to most significant 1st digit '9' means now preceeded by a '1' digit.
+ *is1 = '1';
+ exp++; // Add one to signed exponent.
+ // What if it exceeds max exponent?
+ } else { // 0 to 8, so just add one.
+ (*is1)++;
+ }
+ }
+ if (exp != 0) { // Add e, - sign if necessary and exponent
+ s += ('e'); // Since the stream is not known, there is no way to know if to use uppercase 'E'.
+ if (neg_exp) { // Make unsigned.
+ s += ('-');
+ exp = -exp;
+ }
+ if (exp >= 100) { // Need exponent hundreds digit.
+ int ed = exp / 100;
+ s += static_cast<char> (ed + '0');
+ }
+ exp %= 100;
+ if (exp >= 10) { // // Need exponent tens digit.
+ int ed = exp / 10;
+ s += static_cast<char> (ed + '0');
+ }
+ exp %= 10; // // Always need exponent units digit.
+ s += static_cast<char> (exp + '0');
+ }
+ // std::cout << "s = " << s << std::endl;
+ return s; // Rounded decimal digits string.
+} // string round_e(FPT d, unsigned int sigdigits)
+
+template<typename FPT>
+std::string round_ms(FPT v, signed int m) { /*! \brief Round floating-point v (not-exponential) to order m. (m is the index of the rounder digit).
+ This is variously called 'common rounding', 'round_5_up'.
+ \details Gejza Wimmer, Viktor Witkovsky, Tomas Duby\n
+ Measurement Science and Technology, 11 (2000) 1659-1665. ISSN 0957-0233 S0957-233(00)13838-X\n
+ Proper rounding of the measurement results under normality assumptions.\n
+ Uncertainty of measurement -- Part 3: Guide to the expression of uncertainty in measurement (GUM:1995)\n
+ ISO Guide 98 (1995) and updated version 2008.\n\n
+
+ \note `m` is the index of the rounder digit, that is the just insignificant digit
+ used to decide if the m+1th digit is to be rounded up or left as is.
+ So `m == 0` means that the rounder digit is the units digits, used to round the tens digit,
+ `m == +1` the rounder is the tens digit, and the rounded digit is the hundreds digit
+ `m == -1` rounder is the tenths digit (0.1), rounding the hundredths digit (0.01).
+
+ (Other authors specify the nth digit to be significant, where n = m + 1).
+
+ \param v Value to convert to decimal digit string after rounding.
+ \param m Signed digit position to round.
+ \return `std::string` decimal digit string of rounded value.
+ */
+ BOOST_STATIC_ASSERT(boost::is_floating_point<FPT>::value);
+ // Will fail if FPT is not a floating-point type (because will not output in scientific format!).
+
+ // Use Boost.Math portable functions for testing infinity, NaN and their signs.
+ using boost::math::signbit;
+ using boost::math::isnan;
+ using boost::math::isinf;
+ int is_neg = signbit(v);
+ if (isnan(v)) { //! \note that the most significant sign bit of NaN is recognized by using function signbit,
+ //! 'sign' of NaNs cannot reliably and portably be tested using "x < 0"
+ //! because all comparisons using NaN are false - by definition.
+ return (is_neg) ? "-NaN" : "NaN";
+ } else if (isinf(v)) {
+ return (is_neg) ? "-inf" : "inf";
+ }
+ // Treat denormal differently too?
+
+ // m can be up to about exponent 308.
+ // static const int maxDecimalDigits = 1 + 1 + numeric_limits<double>::max_exponent + (2 + numeric_limits<double>::digits * 3010/10000)+1+1;
+ // Number of decimal digits to display FPT max in fixed format with lots of trailing zeros & decimal point.
+ // ostringstream smax;
+ // smax << setprecision(17) << fixed << -numeric_limits<double>::max() << endl; // numeric_limits<double>::max() = 1.7976931348623157e+308 but using fixed.
+ // std::cout << smax.str() << std::endl;
+ //-179769313486231610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00000000000000000
+ // std:: << "length of smax " << smax.str().size() << std::endl; // 329
+ // sign + max_digits10 (17+1 = 18) + 293 significant zeros + decimal point + 17 trailing digits (zeros).
+ // max_exponent = 308, so expect 308 +1 = 309 digits before decimal point.
+ // of these 309, 17 may be non-zero, but always have one digit so only 16, so 293 zeros.
+ // 329 is longest decimal digit string that possibly can be output with double exponent.
+ // But this function never wants to output the 'noisy' extra digits, so limit to digits10 not max_digits10.
+ // So want sign + digits10 (15)
+ // + (max_exponent10 - digits10) (308-15 = 293) significant zeros
+ // + decimal point,
+ // and upto digits10 trailing zeros.
+ static const int maxDecimalDigits = 1 + (std::numeric_limits<FPT>::max_exponent10
+ - std::numeric_limits<FPT>::digits10) + 1 + std::numeric_limits<FPT>::digits10;
+ //std::cout << "max dec " << maxDecimalDigits << std::endl; // 310
+
+ if (m > maxDecimalDigits) { // limit abs(m) to maxDecimalDigits.
+ m = maxDecimalDigits;
+ }
+ if (m < -maxDecimalDigits) {
+ m = -maxDecimalDigits;
+ }
+
+ std::ostringstream ss;
+ ss << std::scientific // Use scientific E format.
+ << std::showpoint; // Force decimal point and trailing zeros.
+ // skipws showpoint dec scientific
+
+ ss.precision(std::numeric_limits<FPT>::digits10); // Output digits10 precision decimal digits (and decimal point).
+ // std::numeric_limits<double>::digits10 is 15 for 64-bit double.
+ // output precision decimal digits *after the leading digit and decimal point*, total digits10+1 digits.
+ ss << v;
+ std::string s = ss.str();
+
+ std::string::iterator is = s.begin();
+ if ((*is) == '-') { // delete minus sign.
+ // Can ignore + case as won't ever be output as default std::ostringstream is std::noshowpos.
+ // is_neg = true; already noted above using signbit.
+ s.erase(is); // is++;
+ }
+ // std::cout <<'|' << s <<'|' << ' ' << s.size() << std::endl; // For example: |1.797693134862316e+308| 22
+ /*
+
+ MSVC always has 3 exponent digits
+ 4.206884193232336e+000
+ 1.797693134862316e+308
+
+ gcc can have two or three exponent digits.
+ 0.00000000000000000e+00
+ 1.23456789012345669e+00
+ 1.23456789012345666e+03
+ 1.23456789012345671e-03
+ 1.23456789012345658e+200
+ 1.23456789012345671e-200
+ */
+
+#ifdef _MSC_VER
+ if (s.size() != std::numeric_limits<FPT>::digits10 + 1 + 1 + 5) { // for double == 22 (would be 23 if value was negative, but we are only dealing with abs value).
+ // 1.23000000000000000e+00
+ outFmtFlags(ss.flags());
+ std::cout << "\n" << v << ", " << m << ", " << s << ", "
+ << s.size() << ", " << std::numeric_limits<FPT>::digits10 + 1 + 1 + 5 << std::endl;
+ assert(s.size() == std::numeric_limits<FPT>::digits10 + 1 + 1 + 5);
+ // This happens if type FPT passed is not floating point (integer?).
+ return s;
+ }
+#endif
+#ifdef __GNUC__
+ // Format varies with size of exponent - either two or three digits.
+ if ((s.size() != std::numeric_limits<FPT>::digits10 + 1 + 1 + 4) // e+00
+ && (s.size() != std::numeric_limits<FPT>::digits10 + 1 + 1 + 5)) // e+308
+ { // for double == 21 (would be 22 if negative).
+ outFmtFlags(ss.flags());
+ std::cout << "\n" << v << ", " << m << ", " << s << ", "
+ << s.size() << ", " << std::numeric_limits<FPT>::digits10 + 1 + 1 + 4 << std::endl;
+ return s;
+ }
+#endif
+ std::string::iterator is1 = s.begin(); // 1st digit.
+ assert(*is1 >= '0');
+ assert(*is1 <= '9');
+ is++;
+ assert(*is == '.');
+ s.erase(is); // Erase decimal point. Implied position after 1st most significant digit is known.
+ std::string::iterator ie = s.begin() + std::numeric_limits<FPT>::digits10 + 1;
+ assert(*ie == 'e');
+ std::string::iterator se = s.end(); // After last exponent digit.
+ se--; // Least significant exponent 'units' digit.
+ assert(*se >= '0');
+ assert(*se <= '9');
+ int exp = (*se - '0'); // Exponent units digit's value.
+ se--;
+ assert(*se >= '0');
+ assert(*se <= '9');
+ std::locale loc;
+ if (std::isdigit(*se, loc))
+ { // Exponent tens.
+ exp += (*se - '0') * 10; // Exponent tens.
+ }
+ se--; // Previous might be exponent hundreds digit (always for MSVC), or sign.
+ if (std::isdigit(*se, loc))
+ { // Exponent tens digit.
+ exp += (*se - '0') * 100; // Exponent hundreds.
+ se--;
+ }
+ if (*se == '-') {
+ exp = -exp;
+ } else if (*se == '+') {
+ exp = +exp;
+ } else {
+ std::cout << "Function round_ms expected digit or sign!" << *se << std::endl;
+ }
+ se--; // Must be the letter 'e' next forward.
+ // std::cout << "exponent " << exp << std::endl;
+ assert((*se == 'e') || (*se == 'E')); // Check is 'e' or 'E'.
+ s.erase(se, s.end()); // Delete all exponent field: "e+123" or "e-01".
+ // leaving an digits10 + 1 = 16 decimal digit string ,
+ // with implied decimal point after the 1st digit, for example 1234567890123456.
+ // std::cout << "digits string = " << s << std::endl;
+ // Now round the string at m.
+ int p = exp - m; // Offset.
+ if (p <= 0) {
+ return "0.";
+ }
+
+ std::string::iterator sr = s.begin(); //
+ int o = (exp - m);
+ assert(o > 0);
+ if (o > std::numeric_limits<FPT>::digits10) { // No rounding possible.
+ o = std::numeric_limits<FPT>::digits10;
+ }
+ sr += (o);
+ // sr* is the rounding digit d subscript m.
+
+ int rounder = *sr - '0'; // Rounding digit.
+ std::string::iterator sis = sr; // Note position of the insignificant trailing decimal digits.
+ s.erase(sis, s.end()); // Erase all the insignificant trailing decimal digits.
+
+ //sr--; // Least significant digit.
+ bool carry = false;
+ if (rounder >= 5) {
+ carry = true; // Increment next most significant digit.
+ do {
+ sr--; // more significant digit.
+ if (*sr < '9') // 5 to 8
+ {
+ (*sr)++; // round up by 1.
+ carry = false;
+ } else
+ if (*sr == '9')
+ { // 9 will cause a carry.
+ *sr = '0';
+ carry = true;
+ } else {
+ std::cout << "wrong ! *sr = " << *sr << std::endl;
+ break;
+ }
+ } while (carry == true && sr != s.begin());
+ } else { // nothing to do.
+ carry = false;
+ }
+ if (carry == true) { // Carry to most significant digit means now preceed by a '1' digit.
+ s.insert(s.begin(), '1');
+ exp++;
+ }
+ if (m >= 0) { // May need zeros before decimal point.
+ int z = exp - s.size() + 1; // Number of significant zeros before decimal point.
+ if (z > 0) { // More efficient to check if any zeros needed before calling insert?
+ s.insert(sis, z, '0'); // Insert any significant zeros.
+ }
+ } else {// Any trailing zeros are already in the string.
+ }
+ std::string::iterator sd = s.begin();
+ if (exp > 0) { // Will try to insert off the end of the string if > maxdigits10+1!
+ sd += exp + 1;
+ s.insert(sd, '.'); // Insert decimal point.
+ } else if (exp == 0) { //
+ sd += exp + 1;
+ s.insert(sd, '.'); // Insert decimal point.
+ } else { // exp < 0
+ // Zero before decimal point might be optional?
+ s.insert(sd, '0'); // Insert zero before point.
+ sd++;
+ s.insert(sd, '.'); // Insert decimal point.
+ sd++;
+ int z = -exp - 1;
+ if (z > 0) {
+ s.insert(sd, z, '0'); // Insert any zeros before significant digits (0.001234).
+ }
+ }
+ if (is_neg) {
+ s.insert(s.begin(), '-');
+ }
+ //std::cout << "Final digits string " << s << std::endl;
+
+ return s;
+} // template <typename FPT> string round_ms(FPT v, signed int m)
+
+bool scaled = true; // want to scale and use prefix to avoid >1000 or < 1.
+
+template <typename FPT>
+std::string round_f(FPT v, int sigdigits) { /*! \brief Round floating-point value `v` (fixed, not-exponential) to `sigdigits` significant digits.
+ This is variously called 'common rounding', 'round_5_up'.
+
+ \details Gejza Wimmer, Viktor Witkovsky, Tomas Duby\n
+ Measurement Science and Technology, 11 (2000) 1659-1665. ISSN 0957-0233 S0957-233(00)13838-X\n
+ Proper rounding of the measurement results under normality assumptions.\n
+
+ Uncertainty of measurement -- Part 3: Guide to the expression of uncertainty in measurement (GUM:1995)\n
+ ISO Guide 98 (1995) and updated version 2008.
+
+ \param v Value to be converted to a decimal digit string, rounded to sigdigits significant digits.
+ \param sigdigits Number of significant digits after rounding.
+ \return `std::string` containing decimal digit string, properly rounded.
+
+ \note All these functions are templated on floating-point type and are not intended to be called
+ (and thus instantiated) for integral (or other) types.
+ This is because the value will not be output in scientific format, assumed by the code.
+ A check is_floating_point == true is provide that will fail in debug mode.
+ (A compile time check would be better).
+ */
+
+ // Will fail if FPT is not a floating-point type (because will not output in scientific format!).
+ BOOST_STATIC_ASSERT(boost::is_floating_point<FPT>::value);
+
+ // Use Boost.Math TR1 portable functions for testing infinity, NaN and their signs.
+ using boost::math::signbit;
+ int is_neg = signbit(v);
+ using boost::math::isnan;
+ using boost::math::isinf;
+
+ if (isnan(v)) { // Note that the most significant sign bit of NaN is recognized by using function signbit.
+ return (is_neg) ? "-NaN" : "NaN";
+ // 'sign' of NaNs cannot reliably and portably be tested using "x < 0"
+ // because all comparisons using NaN are false - by definition.
+ } else if (isinf(v)) {
+ return (is_neg) ? "-infinity" : "infinity";
+ }
+ // Treat denormal differently too?
+
+ // sign + max_digits10 (17+1 = 18) + 293 significant zeros + decimal point + 17 trailing digits (zeros).
+ // max_exponent = 308, so expect 308 +1 = 309 digits before decimal point.
+ // of these 309, 17 may be non-zero, but always have one digit so only 16, so 293 zeros.
+ // 329 is longest decimal digit string that possibly can be output with double exponent.
+ // But this function never wants to output the 'noisy' extra digits, so limit to digits10 not max_digits10.
+ // So want sign + digits10 (15) + (max_exponent10 - digits10) (308-15 = 293) significant zeros + decimal point, and digits10 trailing zeros.
+ static const int maxDecimalDigits = 1 + (std::numeric_limits<FPT>::max_exponent10
+ - std::numeric_limits<FPT>::digits10) + 1 + std::numeric_limits<FPT>::digits10;
+ //std::cout << "max dec " << maxDecimalDigits << std::endl; // 310
+
+ /*! \note C++0X provides @c std::numeric_limits<double>::max_digits10;
+ which is maximum possibly significant,
+ but only @c digit10 are guaranteed to be significant,
+ so limit @c sigdigits to @c digits10 (15 for IEEE 64-bit double).
+ */
+ if (sigdigits > std::numeric_limits<FPT>::digits10) {
+ std::cout << "Maximum significant digits is " << std::numeric_limits<FPT>::digits10 << std::endl;
+ sigdigits = std::numeric_limits<FPT>::digits10; // digits10 (15 for double) decimal digits after the decimal point.
+ }
+
+ if (sigdigits < 0) { // Must be a mistake.
+ std::cout << "Trying to output " << sigdigits << " significant digits!" << std::endl;
+ return "";
+ } else if (sigdigits == 0) { // Might handle zero case differently from sigdigits < 0?
+ std::cout << "Trying to output zero significant digits!" << std::endl;
+ return "";
+ }
+ //else sigdigits > 0, so usable.
+
+ std::ostringstream ss;
+ ss << std::scientific // Use scientific format to get all the value as potentially significant decimal digits.
+ << std::showpoint // Force decimal point and trailing zeros.
+ << std::setprecision(std::numeric_limits<FPT>::digits10) // Output `digits10` precision decimal digits (and decimal point).
+ // `std::numeric_limits<double>::digits10` is 15 for 64-bit double.
+ // output precision decimal digits *after the leading digit and decimal point*, total digits10+1 digits (16 for double).
+ << v;
+ std::string s = ss.str(); // digit string like -1.797693134862316e+308.
+ std::string::iterator is = s.begin();
+ if ((*is) == '-') { // delete minus sign.
+ // Can ignore + case as won't ever be output as default std::ostringstream is std::noshowpos.
+ //is_neg = true; already noted using signbit.
+ s.erase(is); // is++;
+ }
+ // std::cout <<'|' << s <<'|' << ' ' << s.size() << std::endl; // |1.234567890123457e+000| 22
+ assert(
+ (s.size() == std::numeric_limits<FPT>::digits10 + 1 + 1 + 5) // == 22
+ ||( s.size() == std::numeric_limits<FPT>::digits10 + 1 + 1 + 4) // == 21
+ ); // == 21
+ // Might be only two exponent digits on some platforms.
+
+ std::string::iterator is1 = is; // 1st digit.
+ assert(*is1 >= '0');
+ assert(*is1 <= '9');
+ is++;
+ assert(*is == '.');
+ s.erase(is); // erase decimal point. Implied position after 1st most significant digit is known.
+ //std::cout << "digit & exponent string " << s << std::endl;
+
+ // Read the exponent part first into an integer.
+ std::string::iterator se = is1 + std::numeric_limits<FPT>::digits10 + 1;
+ std::string::iterator ie = is1 + std::numeric_limits<FPT>::digits10 + 1;
+
+ assert(*se == 'e');
+ se++; // skip 'e'.
+ // Read exponent into an integer.
+ bool neg_exp = ((*se) == '-') ? true : false;
+ se++; // Skip over sign of exponent.
+ std::locale loc;
+ int exp = 0;
+ do
+ {
+
+ if (std::isdigit(*se, loc))
+ {
+ exp = exp * 10 + (*se - '0');
+ }
+ se++;
+ }
+ while (se != s.end());
+
+ if (neg_exp)
+ {
+ exp = -exp; // Make exponent signed.
+ }
+
+ //std::cout << "exponent " << exp << std::endl;
+ //se = s.end();
+ //se -= 5;
+ s.erase(ie, s.end()); // delete everything from e to end, "e+123" or "e-01"
+ // leaving an digits10+1 decimal digit string,
+ // with implied decimal point after the 1st digit, for example 1234567890123457.
+ // std::cout << "decimal digits string " << s << std::endl;
+ // now round the string at nth decimal digit.
+
+ std::string::iterator sr = s.begin(); //
+ int o = sigdigits;
+ assert(o > 0);
+ if (o > std::numeric_limits<FPT>::digits10)
+ { // No rounding possible.
+ o = std::numeric_limits<FPT>::digits10;
+ }
+ sr += (o);
+ // sr* is the rounding digit d subscript sigdigits+1.
+
+ int rounder = *sr - '0'; // rounding digit.
+ std::string::iterator sis = sr; // Note position of the insignificant trailing decimal digits.
+ s.erase(sis, s.end()); // Erase all the insignificant trailing decimal digits.
+
+ //sr--; // Least significant digit.
+ bool carry = false;
+ if (rounder >= 5) {
+ carry = true; // Increment next most significant digit.
+ do {
+ sr--; // more significant digit.
+ if (*sr < '9') // 5 to 8
+ {
+ (*sr)++; // round up by 1.
+ carry = false;
+ } else if (*sr == '9') {
+ *sr = '0';
+ carry = true;
+ } else {
+ std::cout << "wrong ! *sr = " << *sr << std::endl;
+ break;
+ }
+ } while (carry == true && sr != s.begin());
+ } else { // nothing to do.
+ carry = false;
+ }
+ if (carry == true) { // Carry to most significant digit means now preceed by a '1' digit.
+ s.insert(s.begin(), '1');
+ exp++;
+ }
+ // Check if are to change exponent and use prefix,
+ // or to change to exponential format?
+ //int multiple3 = 0;
+ //bool is_scaled = false;
+ // if (scaled == true)
+ // { // If necessary change to use a prefix so value is in range 1.000000.. to 999.99999..
+ // if (exp > SImaxPowerTen)
+ // { // No SI names above yocto, so need to use exponential format 1.23e+25.
+ // }
+ // else if (exp < SIminPowerTen)
+ // { // No SI names below yotta, so need to use exponential format 1.23e-25.
+ // }
+ // else if (abs(exp) >= 3)
+ // { // Value >= 1000.0, so can use nearest abbreviation, kilo, mega...
+ // int powerten = exp / 3;
+ // multiple3 = powerten * 3;
+ // exp %= 3; // nearest 10^3 can only be 1.20, 12.0 120.0
+ ///*
+ // const char* symbol = SIsymbols[multiple3 + SImaxPowerTen];
+ // const char* prefix = SIprefixes[multiple3 + SImaxPowerTen];
+ // std::cout << powerten << ' ' << symbol << ' ' << prefix << std::endl;
+ //*/ is_scaled = true;
+ // }
+ // else if (exp < 0)
+ // { // value < 1.0000000000000
+ // }
+ // }
+ // Now have the rounded decimal digit string, but may need some zeros.
+ if (sigdigits >= 0) { // May need zeros *before* decimal point.
+ int z = exp - s.size() + 1; // Number of significant zeros before decimal point.
+ if (z > 0) { // More efficient to check if any zeros are needed before calling insert.
+ s.insert(sis, z, '0'); // Insert any significant zeros.
+ }
+ } else {// Any trailing zeros are already in the string.
+ }
+
+ std::string::iterator sd = s.begin();
+ if (exp > 0) {
+ sd += exp + 1;
+ s.insert(sd, '.'); // Insert decimal point.
+ } else if (exp == 0) { //
+ sd += exp + 1;
+ s.insert(sd, '.'); // Insert decimal point.
+ } else { // exp < 0
+ // Zero before decimal point might be optional?
+ s.insert(sd, '0'); // Insert zero before point.
+ sd++;
+ s.insert(sd, '.'); // Insert decimal point.
+ sd++;
+ int z = -exp - 1; // May need zeros after decimal point, before significant digit(s).
+ if (z > 0) {
+ s.insert(sd, z, '0'); // Insert any zeros before significant digit(s) (0.001234).
+ }
+ }
+ if (is_neg) {
+ s.insert(s.begin(), '-');
+ }
+ //if (is_scaled == true)
+ //{ // Append symbol and prefix and trailing space.
+ // bool add_symbol = true;
+ // // const char* symbol = SIsymbols[multiple3 + SImaxPowerTen]; // kilo, mega ...
+ // // const char* prefix = SIprefixes[multiple3 + SImaxPowerTen]; // k, M m ...
+ // // std::cout << ' ' << symbol << ' ' << prefix << std::endl;
+ // if (multiple3 != 0)
+ // {
+ // s.append(" "); // separator between last digit and symbol.
+ // s.append((add_symbol ? symbol : prefix));
+ // }
+ //}
+
+ //std::cout << "Final digits string " << s << std::endl;
+
+ return s;
+} // string round_f(FPT v, signed int m)
+
+
+// Round number v *at* d th decimal place.
+// Note d is different (roundED digit) from the Wimmer definition of m (roundER digit).
+
+inline double round_nth(double v, unsigned int d) { //! round value v to d digits after decimal point, using d+1 digit to round.
+ return std::floor(v * std::pow(10., static_cast<int> (d)) + 0.5) / std::pow(10., static_cast<int> (d));
+}
+
+// Three explicit versions which may be slightly more efficient.
+
+inline double round_1(double v) { //! round value v to 1 digit after decimal point, using 1st digit to round.
+ return std::floor(v * 10. + 0.5) / 10.;
+}
+
+inline double round_2(double v) { //! round value v to 2 digit2 after decimal point, using 2nd digit to round.
+ return std::floor(v * 100. + 0.5) / 100.;
+}
+
+inline double round_3(double v) { //! round value v to 3 digit2 after decimal point, using 3rd digit to round.
+ return std::floor(v * 1000. + 0.5) / 1000.;
+}
+
+enum distribution_type { /*! \brief Distribution type, encoded into two bits in `short int unc_types`.
+ \note `gaussian` name is chosen rather than `normal` to avoid name clash
+ from name of bit 11 and bit 12 in `enum unc_types`.
+ */
+ gaussian = 0, //!< `unc_types` bit 11 and bit 12 == 0, aka normal.
+ uniform = 1, //!< `unc_types` bit 11 == 1, aka rectangular.
+ triangular = 2, //!< `unc_types` bit 12 == 1.
+ undefined = 3 //!< `unc_types` bit 11 and bit 12 == '11' == 3.
+};
+
+double delta(double epsilon, double gamma, distribution_type distrib = gaussian) { /*! \brief Calculate Wimmer delta function using equation 24, p 1664.
+ \details Gejza Wimmer, Viktor Witkovsky, Tomas Duby\n
+ Measurement Science and Technology, 11 (2000) pages 1659-1665.
+ ISSN 0957-0233 S0957-233(00)13838-X.\n
+ Proper rounding of the measurement results under normality assumptions.\n
+ Gejza Wimmer, Viktor Witkovsky, Proper rounding of the measurement result under the assumption of uniform distribution,\n
+ Measurement Science Review, Vol 2, section 1, (2002), pages 1 - 7.\n
+ Gejza Wimmer, Viktor Witkovsky, Proper rounding of the measurement result under the assumtpion of triangular distribution,\n
+ Measurement Science Review, Vol 2, section 1, (2002), pages 21 to 31.\n
+
+ \param epsilon Proper-rounding increase of confidence interval because of rounding, must be positive and 'small'.
+ \note epsilon is usually 0.05 or 95%, values in range 0.2 to 0.01 make good sense,
+ 0.2 (80%) risks a fair bit of loss from rounding, 0.01 (1%) causes almost no loss.
+ \param gamma Ratio rounded / unrounded (gamma is assumed <= 1).
+ \param distrib Distribution type, normal or gaussian(default), uniform, triangular, or laplace.
+
+ \return Approximation of Wimmer delta function using equation 24, p 1664,
+ for normal distribution, and similar for triangular and uniform.
+ Returns -1 if epsilon is too 'tight' so must be increased for delta to be calculated.
+ Throwing an exception might be better here>
+
+ */
+ // gamma > rounded gamma (so gamma < 1.?)
+ // Approximation error is less than 0.0123 for 0.005 <= epsilon < 0.1
+ // and gamma > rounded gamma for this epsilon - see table 1.
+ // assert(gamma > rounded_gamma);
+
+ //assert (gamma <= 1);
+ using std::sqrt;
+ double d;
+ double x;
+ double threshold;
+ double sqrt_3 = 1.7320508075688772935274463415058723669428052543712;
+
+ // TODO use boost.math constant.
+
+ switch (distrib) {
+ case gaussian: // equation 24, p 1664.
+ // Gejza Wimmer, Viktor Witkovsky, Tomas Duby
+ // Measurement Science and Technology, 11 (2000) 1659-1665.
+ // ISSN 0957-0233 S0957-233(00)13838-X.
+
+ d = (1.348 + 0.9886 * epsilon + 0.2288 * sqrt(epsilon));
+ x = gamma - 1.0001 + 2.058 * epsilon - 1.93 * epsilon * epsilon;
+ if (x < (std::numeric_limits<double>::min)() * 100.) // Small value allows for approximation uncertainty.
+ { // Not possible to have epsilon this small!
+ threshold = x; // ???
+ std::cout << "Epsilon " << epsilon << " is too small for gamma rounded/unrounded ratio " << gamma << ", threshold is " << threshold << " for gaussian distribution." << std::endl;
+ // For example:
+ // "Epsilon 0.01 is too small for gamma rounded/unrounded ratio 0.981226, threshold is 0.99."
+ return -1.; // Not sure how to signal the problem here. Throw?
+ }
+ x = sqrt(x);
+ d = d * x;
+ return d; // sqrt(gamma - 1.0001 + 2.058 * epsilon - 1.93 * epsilon * epsilon);
+ break;
+ case uniform:
+ // Gejza Wimmer, Viktor Witkovsky, Proper rounding of the measurement result under the assumption of uniform distribution,
+ // Measurement Science Review, Vol 2, section 1, (2002), pages 1 - 7.
+ threshold = 1 - epsilon; // Wimmer equation 17, page 5
+ if (gamma < threshold) {
+ std::cout << "Epsilon " << epsilon << " is too small for gamma rounded/unrounded ratio " << gamma << ", threshold is " << threshold << " for uniform distribution." << std::endl;
+ return -1; // Not sure how to signal the problem here.
+ }
+ d = sqrt_3 * (gamma + 2 * epsilon - 1); // Wimmer equation 20, page 6.
+ return d;
+ case triangular:
+ // Gejza Wimmer, Viktor Witkovsky, Proper rounding of the measurement result under the assumtpion of triangular distribution,
+ // Measurement Science Review, Vol 2, section 1, (2002), pages 21 to 31.
+ threshold = (1 - gamma) / (1 + gamma);
+ if (epsilon < threshold) {
+ std::cout << "Epsilon " << epsilon << " is too small for gamma rounded/unrounded ratio " << gamma << ", threshold is " << threshold << " for triangular distribution." << std::endl;
+ return -1; // Not sure how to signal the problem here.
+ }
+ // d = sqrt(6 * (epsilon - ((1 - gamma) /(1 + gamma)))); // Wimmer equation 18, page 27.
+ d = sqrt(6 * (epsilon - threshold));
+ return d;
+ default:
+ // Might add one more (4th) distribution here - assuming distribution type is encoded using 2 bits in unc class.
+ return -1;
+ } // switch
+} // double delta(double epsilon, double gamma, distribution_type distrib = gaussian)
+
+double gamma(double rounded, double value) {/*! \brief Calculate Wimmer gamma rounded/unrounded function p 1664.
+ \details Measurement Science and Technolology, 11 (2000) 1659-1665. ISSN 0957-0233 S0957-233(00)13838-X.
+ Gejza Wimmer, Viktor Witkovsky, Tomas Duby
+ Proper rounding of the measurement results under normality assumptions.
+
+ \param rounded Value (as `double`) after rounding.
+ \param value Value (as `double`) before rounding. Assumes `rounded < unrounded value`.
+ \return Ratio rounded / value, a measure of loss of information caused by rounding.
+ */
+ // Is this OK for negative values? Need to check or swap so result is <= 1.
+ // Use abs?
+ if (value == 0.) { // Avoid divide by zero (or very close to zero too?).
+ return 0.;
+ }
+ double g = rounded / value;
+ if (g > 1.) { // This seems necessary for some cases???
+ //std::cout << "value " << value << ", rounded " << rounded << std::endl;
+ g = 1. / g;
+ }
+ if (g > 1.) { // This seems necessary for some cases???
+ std::cerr << "value " << value << ", rounded " << rounded << std::endl;
+ // assert(g <= 1.); // Assumes rounded < unrounded.
+ }
+
+ return g;
+} // double gamma(double rounded, double value)
+
+int round_m(double epsilon = 0.01, double sigma = 0., unsigned int sigma_sigdigits = 2U, distribution_type distrib = gaussian) { /*! \brief Calculate the Wimmer rounding digit m using delta and gamma functions p 1661, equation 12.
+ \details Measurement Science and Technology, 11 (2000) 1659-1665. ISSN 0957-0233 S0957-233(00)13838-X.
+ Gejza Wimmer, Viktor Witkovsky, Tomas Duby\n
+ Proper rounding of the measurement results under normality assumptions.
+
+ \param epsilon Rounding loss (as fraction) accepted (default is 0.01 or 1%).
+ \param sigma Uncertainty as standard deviation.
+ \param sigmasigdigits Number of significant decimal digits
+ for uncertainty to be rounded (range 1 to 4, default = 2), depending on degrees of freedom.\n
+ If degrees_of_freedom <= 2, then 1, else if degrees_of_freedom > 1000, then 3 else default = 2.
+ \param distribution_type Type of distribution (default gaussian, or triangular or uniform).
+
+ \return m Signed position of the digit to be used for rounding,
+ `m == 0` means use the units digit for rounding the tens digit.
+ */
+ if ((sigma_sigdigits < 1) || (sigma_sigdigits > 4)) { // sigma_sigdigits is too big to be plausible from the confidence interval of uncertainty.
+ sigma_sigdigits = 4; // or throw?
+ }
+ // \boost_1_40_0\libs\math\example\chi_square_std_dev_test.cpp
+
+ //Confidence level (two-sided) = 0.0500000
+ //Standard Deviation = 1.0000000
+ //_____________________________________________
+ //Observations Lower Upper
+ // Limit Limit
+ //_____________________________________________
+ // 2 0.4461 31.9102
+ // 3 0.5207 6.2847
+ // 4 0.5665 3.7285
+ // 5 0.5991 2.8736
+ // 6 0.6242 2.4526
+ // 7 0.6444 2.2021
+ // 8 0.6612 2.0353
+ // 9 0.6755 1.9158
+ // 10 0.6878 1.8256
+ // 15 0.7321 1.5771
+ // 20 0.7605 1.4606
+ // 30 0.7964 1.3443
+ // 40 0.8192 1.2840
+ // 50 0.8353 1.2461
+ // 60 0.8476 1.2197
+ // 100 0.8780 1.1617
+ // 120 0.8875 1.1454
+ // 1000 0.9580 1.0459
+ // 10000 0.9863 1.0141
+ // 50000 0.9938 1.0062
+ // 100000 0.9956 1.0044
+ // 1000000 0.9986 1.0014
+
+ // and in Owen L. Davies and Peter L. Goldsmith, Statistical Methods in Research and production, ISBN 0 05 002437, p 457 (1972)
+
+ // So for 2 observations, the uncertainty might be 30 times, or half the central estimate,
+ // meaning that a second digit is not likely to be significant.
+ // But for the more common several degrees of freedom,
+ // a second digit might be significant.
+ // So the ISO GUM pragmatically states that 2 significant decimal digits should be used for the standard uncertainty.
+ // It only when 1000 observations are available (and there are no problems with drift)
+ // a fractional relative standard deviation of uncertainty is about 0.05
+ // and that 3 significant decimal digits are needed avoid loss from rounding.
+ double sigma_rounded = round_sig(sigma, sigma_sigdigits);
+ // ISO GUM always rounds uncertainty to n=2 significant digits,
+ // but elsewhere Wimmer et al round to only *one* significant digit.
+ // So sigdigits is parameterized to allow variation from (possibly very many)
+ // (possibly known) degrees of freedom?
+
+ // Wimmer uses only one significant digit to round sigma, for reasons unclear.
+ // So tests that compare to the paper do not fail when epsilon has values in example 5, p1662.
+
+ double g = gamma(sigma_rounded, sigma);
+ // Check against limits in table 1, page 1662.
+ double gl;
+ double e = epsilon;
+ if (e >= 0.1) { // <= 10% loss from rounding accepted.
+ gl = 0.81271;
+ } else if (e >= 0.05) {
+ gl = 0.90175;
+ } else if (e >= 0.02) {
+ gl = 0.95951;
+ } else if (e >= 0.01) {
+ gl = 0.97954;
+ } else { // // <= 1% loss from rounding accepted.
+ gl = 0.98972;
+ }
+ if (gl > g) {
+ std::cout << "Cannot return a rounding m because epsilon " << e << " is too small!" << std::endl;
+ return -9999;
+ }
+ // Or throw?
+
+ double d = delta(epsilon, g, distrib);
+ if (d < 0.) { // Chosen epsilon is too small! (for example, e = 0.01 loss is too demanding, so try 0.02).
+ std::cout << "Cannot compute a rounding digit index m because epsilon " << epsilon << " is too small!" << std::endl;
+ return -9999; // or throw.
+ }
+ d = d * sigma_rounded / (5 * g); // Wimmer equation 12, page 1661.
+ // (and same for triangular distribution equation 10, page 24,
+ // and uniform distribution equation 22, page 6).
+ d = log10(d);
+ return static_cast<int> (floor(d)); // \return m the position of the digit to be used for rounding.
+ // m == 0 means use the units digit for rounding the tens digit...
+} // int round_m(double epsilon, double sigma, unsigned int sigdigits)
+
+std::string round_ue(double v, double sigma, double epsilon = 0.01, unsigned int sigdigits = 2U) { /*! \brief Properly round value to a decimal digit `std::string`.
+ \details Measurement Science and Technolology, 11 (2000) 1659-1665. ISSN 0957-0233 S0957-233(00)13838-X.\n
+ Gejza Wimmer, Viktor Witkovsky, Tomas Duby,
+ Proper rounding of the measurement results under normality assumptions.
+ p 1661, equation 12.
+
+ \param v Central value, often estimate of mean.
+ \param sigma Uncertainty of value, usually standard deviation.
+ \param epsilon Fraction of loss of accuracy from rounding permitted (default 1%).
+ \param sigdigits Number of digits that are significant (default 2).
+
+ \return Decimal digit `std::string` containing rounded value.
+ */
+ //int round_m(double epsilon, double unc, unsigned int sigdigits, distribution_type t);
+ int m = round_m(epsilon, sigma, sigdigits, gaussian);
+ std::string r = round_ms(v, m);
+ return r;
+} // string round_ue(double v, double unc, double epsilon = 0.01, unsigned int sigdigits = 2U)
+
+std::pair<double, double> conf_interval(double mean, double sigma, double df = 1., double alpha = 0.05, distribution_type distrib = gaussian) { /*!
+ \brief Calculate confidence interval for chosen alpha confidence level and chosen distribution type.
+ \details Uses confidence interval equations from:\n
+ Gejza Wimmer, Viktor Witkovsky, Tomas Duby
+ Measurement Science and Technolology, 11 (2000) 1659-1665. ISSN 0957-0233 S0957-233(00)13838-X.
+ Proper rounding of the measurement result under the assumption of gaussian distribution,\n
+ Confidence interval equation 6, p 1660.
+
+ Gejza Wimmer, Viktor Witkovsky, Tomas Duby\n
+ Measurement Science and Technolology, 11 (2000) 1659-1665. ISSN 0957-0233 S0957-233(00)13838-X.\n
+ Proper rounding of the measurement result under the assumption of triangular distribution,\n
+ Measurement Science Review, Vol 2, section 1, (2002), pages 21 to 31.\n
+ Confidence interval Equation 12, page 25.\n
+
+ Gejza Wimmer, Viktor Witkovsky,\n
+ Proper rounding of the measurement result under the assumption of uniform distribution,\n
+ Measurement Science Review, Vol 2, section 1, (2002), pages 1 - 7.\n
+ Confidence interval, page 5, equation 13.\n
+
+ \param mean Interval estimate for mean mu.
+ \param unc Standard uncertainty sigma from variance sigma &#x03C3; &#x00B2;.
+ \param df Degrees of freedom (usually number of observations -1).
+ \param alpha Confidence (0. < unc < 1.), typically 0.05 for 95% confidence.
+ alpha/2 = 0.025 quantile = -1.96, and 1 - alpha/2 is 1.96 for normal distribution,
+ so typically confidence interval is roughly twice unc either side (+ or - ) of mean.
+ \param distrib distribution type, gaussian(default), uniform, triangular, laplace.
+ \return Confidence interval upper and lower limits as a `std::pair` of doubles.
+ */
+ assert(alpha >= 0.);
+ assert(alpha <= 1.);
+ std::pair<double, double> ci;
+ switch (distrib) {
+ case gaussian:
+ { // Gejza Wimmer, Viktor Witkovsky, Tomas Duby
+ // Measurement Science and Technolology, 11 (2000) 1659-1665. ISSN 0957-0233 S0957-233(00)13838-X.
+ // Wimmer p 1660, equation 6.
+ using boost::math::normal;
+ normal dist; // zero mean and unit sd. == normal dist(0., 1.);
+ // Divide alpha by 2 because estimating upper and lower bounds.
+ double t = quantile(complement(dist, alpha / 2));
+ // std::cout << t << endl; // 1.95996 for alpha 0.05
+ // one-sided confidence interval.
+ double u = (df > 1) ? sigma / sqrt(df) : sigma;
+ double w = t * u; //
+ ci.first = mean - w;
+ ci.second = mean + w;
+ return ci;
+ }
+ break;
+ case triangular:
+ { // Gejza Wimmer, Viktor Witkovsky,
+ // Proper rounding of the measurement result under the assumption of triangular distribution,
+ // Measurement Science Review, Vol 2, section 1, (2002), pages 21 to 31.
+ // Confidence interval Equation 12, page 25.
+ using boost::math::triangular;
+ // boost::math version of triangular includes the mode c, as well as the limits a and b
+ // We really want the symmetric_triangular, but approximate with a = -1, c = 0 and b = +1.
+ // This NOT the boost::math default.
+ // Or could implement symmetric_triangular?
+ double u = (df > 1) ? sigma / sqrt(df) : sigma;
+ static const double sqrt_6 = 2.4494897427831780981972840747058913919659474804966; // sqrt(6)
+ triangular dist(-sqrt_6, 0., +sqrt_6); // Wimmer page 23, below eq 6.
+ double tlo = quantile(complement(dist, alpha / 2));
+ double thi = quantile(dist, alpha / 2);
+ // Wimmer page 24, quantile function (cdf inverse), equation 8.
+ ci.first = mean - tlo * u;
+ ci.second = mean - thi * u;
+ return ci;
+ }
+ case uniform: // aka rectangular distribution.
+ { // Gejza Wimmer, Viktor Witkovsky,
+ // Proper rounding of the measurement result under the assumption of uniform distribution,
+ // Measurement Science Review, Vol 2, section 1, (2002), pages 1 - 7.
+ // Confidence interval, page 5, equation 13.
+ static const double sqrt_3 = 1.7320508075688772935274463415058723669428052543712; // sqrt(3)
+ double u = (df > 1) ? sigma / sqrt(df) : sigma;
+ using boost::math::uniform;
+ uniform udist(-sqrt_3, +sqrt_3);
+ double tlo = quantile(complement(udist, alpha / 2)); // effectively quantile(1 - alpha/2)
+ double thi = quantile(udist, alpha / 2);
+ ci.first = mean - tlo * u;
+ ci.second = mean - thi * u;
+ return ci;
+ }
+ default: // As yet undefined distribution.
+ ci.first = std::numeric_limits<double>::quiet_NaN();
+ ci.second = std::numeric_limits<double>::quiet_NaN();
+ break;
+ } // switch (distribution_type)
+ return ci;
+} // std::pair<double, double> conf_interval(double value, double unc, double alpha = 0.05)
+
+static const double sqrt_2 = 1.4142135623730950488016887242096980785696718751217; // sqrt(2)
+static const double sqrt_6 = 2.4494897427831780981972840747058913919659474804966; // sqrt(6)
+static const double oneDivSqrtSix = 0.40824829046386301636621401245098189866099124674943; // 1/sqrt(6)
+static const double oneDivTwoSqrtSix = 0.20412414523193150818310700622549094933049562337472; // 1/(2*sqrt(6))
+static const double sqrt_3 = 1.7320508075688772935274463415058723669428052543712; // sqrt(3)
+
+double cdf_uni(double z) { /*! Cumulative distribution Function of uniform distribution Un(-sqrt_3, + sqrt_3),
+ with an expectation of mean zero and variance unity.
+ Gejza Wimmer & Victor Witkovsky, Measurement Science Review, volume 2 section 1 2002, page 3, equation 5.
+ \return Cumulative distribution Function of uniform distribution.
+ */
+ if (z <= -sqrt_3) {
+ return 0.;
+ } else if (z >= sqrt_3) {
+ return 1.;
+ } else if (z == 0.) {
+ return 0.5;
+ }
+ return (z + sqrt_3) / (2 * sqrt_3);
+} // double cdf_uni(double z)
+
+double quantile_uni(double alpha) { /*! Quantile of uniform distribution Uniform(-sqrt_3, + sqrt_3), expectation or mean zero and variance unity.
+ Wimmer & Witkovsky, Measurement Science Review, volume 2 section 1 2002, page 3, eq 6.
+ \return Quantile of uniform distribution.
+ */
+ static const double sqrt_3 = 1.7320508075688772935274463415058723669428052543712; // sqrt(3)
+ assert(alpha >= 0.);
+ assert(alpha <= 1.);
+ return sqrt_3 * (2 * alpha - 1);
+} // double quantile_uni(double alpha)
+
+double cdf_tri(double z) { /*! Cumulative distribution function CDF of triangular distribution.
+ Gejza Wimmer, Viktor Witkovsky, Tomas Duby,
+ Proper rounding of the measurement result under the assumption of triangular distribution,
+ Measurement Science Review, Vol 2, section 1, (2002), page 24, equation 7.
+
+ \param z
+ \return CDF of triangular distribution.
+ */
+
+ if (z < -sqrt_6) {
+ return 0.;
+ } else if (z > sqrt_6) {
+ return 1.;
+ } else if (z == 0.) { // Or might check if very near zero too?
+ return 0.5;
+ }
+ double zz = oneDivTwoSqrtSix * z * z;
+ if (z < 0.) {
+ return 0.5 + oneDivSqrtSix * (z + zz);
+ } else { // if (z > 0.)
+ return 0.5 + oneDivSqrtSix * (z - zz);
+ }
+} // double cdf_tri(double z)
+
+double quantile_tri(double alpha) { /*! Quantile or Inverse of cumulative distribution function CDF of triangular distribution.
+ Gejza Wimmer, Viktor Witkovsky, Tomas Duby,
+ Proper rounding of the measurement result under the assumption of triangular distribution,
+ Measurement Science Review, Vol 2, section 1, (2002), page 24, equation 8.
+
+ \param alpha Confidence level.
+ \return Quantile or Inverse of cumulative distribution function CDF.
+ */
+ assert(alpha >= 0.);
+ assert(alpha <= 1.);
+
+ if (alpha < 0.5) { // 0<= alpha < 0.5
+ return sqrt_6 * (sqrt(2. * alpha) - 1.);
+ } else { // 0.5 < alpha < 1.
+ return sqrt_6 * (1. - sqrt(2. * (1. - alpha)));
+ }
+} // double quantile_tri(double z)
+
+void out_confidence_interval(std::pair<double, double> ci, int m, std::ostream& os = std::cout) { /*! Output to os, confidence interval enclosed in brackets and separated by comma.
+ The precision is controlled by the rounding order `m` used for the mean
+ but with one extra decimal digit of precision, so rounding to m-1 th place.
+ For example: <99.5, 156.5> rounding to -1 position
+ (where the mean was rounded with m == 0,
+ using the units digit to round the tens digit to "128.")
+
+ \param ci Confidence interval or limits.
+ \param m Signed position for rounding.
+ \param os `std::ostream` for output.
+ */
+ std::streamsize osp = os.precision(); // Save to restore.
+ os.precision(3); // Uncertainty always rounded to 2 decimal digits.
+ using boost::lexical_cast;
+ os << "<" << lexical_cast<double>(round_ms(ci.first, m - 1)) << ", "
+ << lexical_cast<double>(round_ms(ci.second, m - 1)) << ">";
+ os.precision(osp); // Restore saved.
+} // void out_confidence_interval(std::pair ci)
+
+void out_value_limits(double mean, double unc, std::pair<double, double> ci, int m, std::ostream& os = std::cout) { /*! Output mean, uncertainty and confidence interval.
+ For example: \verbatim 128. +/- 15 <99.5, 156.5> \endverbatim
+
+ \param mean Mean or central estimate of value.
+ \param unc Uncertainty estimate as standard deviation.
+ \param Signed position for rounding.
+ \param m
+ \param os `std::ostream` for output.
+ */
+ std::streamsize osp = os.precision(); // Save to restore.
+ os.precision(2); // Uncertainty always rounded to 2 decimal digits.
+ double unc_rounded = round_sig(unc, 2); // Round to 2 significant digit - ISO rules.
+ // TODO increase here if noisydigit wanted,
+ // and/or if degress of freedom > 100.
+ os << round_ms(mean, m) << " +/- " << unc_rounded;
+ os.precision(6); //
+ using boost::lexical_cast;
+ os << " <" << lexical_cast<double>(round_ms(ci.first, m - 1)) << ", "
+ << lexical_cast<double>(round_ms(ci.second, m - 1)) << ">";
+ os.precision(osp); // Restore saved.
+} // void out_value_limits
+
+void out_value_df_limits(double mean, double unc, int degfree = 1, std::ostream& os = std::cout) { /*! Output mean, uncertainty and confidence interval.
+ For example: \verbatim 128. +/- 15 <99.5, 156.5> \endverbatim
+
+ \param mean Mean or central estimate of value.
+ \param unc Uncertainty estimate as standard deviation.
+ \param Signed position for rounding.
+ \param m
+ \param os `std::ostream` for output.
+ */
+ std::streamsize osp = os.precision(); // Save to restore.
+
+ int round_m(double epsilon, double unc, unsigned int sigdigits, distribution_type t);
+ // int round_m(double epsilon = 0.01, double unc = 0., unsigned int uncsigdigits = 2U, distribution_type distrib = gaussian)
+
+ double e = 0.01;
+ int m = round_m(e, unc, 2U, gaussian);
+
+ std::pair<double, double> ci;
+ ci = conf_interval(mean, unc, degfree);
+
+ os.precision(2); // Uncertainty always rounded to 2 decimal digits.
+ double unc_rounded = round_sig(unc, 2); // Round to 2 significant digit - ISO rules.
+ // TODO increase here if noisydigit wanted,
+ // and/or if degress of freedom > 100.
+ os << round_ms(mean, m) << " +/- " << unc_rounded;
+ os.precision(6); //
+ using boost::lexical_cast;
+ os << " <" << lexical_cast<double>(round_ms(ci.first, m - 1)) << ", "
+ << lexical_cast<double>(round_ms(ci.second, m - 1)) << ">";
+ os.precision(osp); // Restore saved.
+} // void out_value_limits
+
+// Above is missing degrees of freedom included in unc type.

Added: sandbox/SOC/2007/quan/boost/quan/si_units.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/boost/quan/si_units.hpp 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,281 @@
+/*!
+ \file
+ \brief SI Unit, names and abbreviations & conversion factors.
+
+ \details
+ See NIST 811 Special publication, Barry N Taylor (1995)
+ "Guide for the Use of the International System of Units (SI)
+ & ISO 31, a closely aligned document.
+ NIST version contains more on non-SI units and many useful notes.
+ */
+
+// Data & code to show units in si_units.cpp which includes this header.
+// Changed to unit starting with capital so time doesn't clash with C time()
+
+// SIunits.hpp
+
+// Copyright Paul A. Bristow 2009, 2012.
+
+// Use, modification and distribution are subject to 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 SIUNITS_HPP
+#define SIUNITS_HPP
+
+#ifdef _MSC_VER
+# pragma once
+#endif
+
+#include <iostream> // Used by show units functions.
+using std::ostream;
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::size_t;
+
+const unsigned int notOK = 0xffffffff;
+
+const int maxPowerTen = 38;
+// == std::numeric_limits<float>::max_exponent10;
+// == FLT_MAX_10_EXP in float.h, so can represent FLT_MAX = 3.402823466e+38F;
+// to FLT_MIN_10_EXP in float.h, so can represent FLT_MIN = 1.175494351e–38F;
+// Done to limit the size of the power of Ten lookup table below,
+// and make code same if store value in a 32-bit double.
+// For real-life data, value of a unit is unlikely to exceed 10**38,
+// despite DBL_MAX_10_EXP == 308.
+
+extern const double powersOfTen [maxPowerTen + 1 + maxPowerTen];
+ // 1 is middle zeroth power.
+const int maxRounds = 17;
+extern const double rounds[maxRounds];
+
+const int maxPowerTens = maxPowerTen + 1 + maxPowerTen;
+const int SImaxPowerTen = 24; // Define array sizes.
+// SImaxPowerTen < maxPowerTen, until new names invented for more units.
+const int SIminPowerTen = -24; // yotta & min 10**-24
+const char* SIprefixes[]; // [0] to [48], countof = 49 (defined in si_units.cpp).
+const char* SIsymbols [];
+const int SImaxPowers = SImaxPowerTen + 1 + SImaxPowerTen;
+const int SIprefixesLength = SImaxPowerTen + 1 + SImaxPowerTen;
+// = sizeof SIprefixes /sizeof (const char*);
+
+struct SImultiple;
+
+// Fundamental units: Mass, Length, Time, Charge, Temperature, Luminous Intensity & angle.
+
+struct unit
+{
+public:
+ const char* unitOf; // "mass", "length", "time" ...
+ // unsigned char here causes need to int( )
+ // better to use short int?
+ // if const.
+ // C2552: non-aggregates cannot be initialized with initializer list.
+ // but can't see why - looks aggregate enough to me.
+ unsigned char unitSINameCount; // Countof SI unitName (meter = 5 + 1 = 6).
+ // = length of SIunitsNames[0] ????????? not used and wrong?
+ unsigned char unitAbbrevCount; // Count of chars in abbreviation (Hz = 2).
+ unsigned char unitNamesCount; // Count of units (no plurals or aliases or abbreviations)
+ // : meter, feet, inch...
+ // = length of array unitNames.
+ unsigned char unitsNamesCount; // Total number of all names for all units.
+ // (including plurals, abbreviations & aliases).
+ // None of these include terminating zero.
+ // Can't be const or triggered C2552 - wrongly?
+ // So instantiate as const unit ...
+ const int* unitLengths; // Count of aliases & abbreviations for each unit.
+ const char** SIunitNames; // SI or preferred unit, for example: "meter"
+ // SI unit MUST be always FIRST in list of unitNames = unitsNames[0],
+ // & SI abbreviation second.
+ const char* SIunitAbbrev; // "m", "Hz" = SIunitNames[1];
+ const char*** unitNames; // "meter", "feet", "mile" ...
+ // By convention, unitNames[0] is the base or full unit name, like meter,
+ // & unitNames[1] is the abbreviation, like m.
+ const double* unitToSIfactors; // factors to convert to SI unit.
+ // Dimensions here? - see project algebra, but not workable with MSVC++5SP3.
+};
+
+// Attempts to define a structure
+// const char s[];
+// const int l; // const here produces C2552
+// failed for compiler reasons - Quincy GNU seems to allow.
+// so for now keep array lengths separate from arrays themselves.
+
+// Definitions in SIunits.cpp for separate compilation.
+
+// Dimensionless units.
+extern const int noUnitCount;
+extern const char* noUnits [];
+extern const unit noUnit;
+extern const int perCentUnitCount;
+extern const char* perCentUnits [];
+extern const int perMilleUnitCount;
+extern const char* perMilleUnits [];
+extern const int perMillionUnitCount;
+extern const char* perMillionUnits[];
+extern const int perBillionUnitCount;
+extern const char* perBillionUnits [];
+extern const int perTrillionUnitCount;
+extern const char* perTrillionUnits [];
+extern const char** dimlessNoUnits [];
+extern const int dimlessUnitsCounts[];
+extern const double NoUnitsFactors [];
+extern const unit noUnit;
+
+// Units of mass: gram, kg, ton, cwt, lb, oz...
+extern const int massUnitCount;
+extern const int gramMassUnitCount;
+extern const char* gramMassUnits [];
+extern const int tonMassUnitCount;
+extern const char* tonMassUnits[];
+extern const int cwtMassUnitCount;
+extern const char* cwtMassUnits[];
+extern const int lbMassUnitCount;
+extern const char* lbMassUnits [];
+extern const int ozMassUnitCount;
+extern const char* ozMassUnits [];
+extern const char** massUnits [];
+extern const int massUnitsCounts [];
+extern const double massToSIfactors[];
+extern const unit mass;
+
+// Units of Length.
+extern const int lengthUnitCount; // meter, mile, yard, feet, inch, point
+extern const int meterLengthUnitCount;
+extern const char* meterLengthUnits[];
+extern const int mileLengthUnitCount;
+extern const char* mileLengthUnits[];
+extern const int yardLengthUnitCount;
+extern const char* yardLengthUnits [];
+extern const int feetLengthUnitCount;
+extern const char* feetLengthUnits [];
+extern const int inchLengthUnitCount;
+extern const char* inchLengthUnits [];
+extern const int pointLengthUnitCount;
+extern const char* pointLengthUnits [];
+extern const double lengthToSIfactors[];
+extern const char** lengthUnits [];
+extern const int lengthUnitsCounts[];
+extern const unit length;
+
+// Units of time: second, minute, hour ...
+extern const int timeUnitCount;
+extern const int secondTimeUnitCount;
+extern const char* secondTimeUnits [];
+extern const int secondTimeUnitCount;
+extern const char* secondTimeUnits [];
+extern const int minuteTimeUnitCount;
+extern const char* minuteTimeUnits [];
+extern const int hourTimeUnitCount;
+extern const char* hourTimeUnits [];
+extern const int dayTimeUnitCount;
+extern const char* dayTimeUnits [];
+extern const int monthTimeUnitCount;
+extern const char* monthTimeUnits [];
+extern const int yearTimeUnitCount;
+extern const char* yearTimeUnits [];
+extern const int fortnightTimeUnitCount;
+extern const char* fortnightTimeUnits [];
+extern const double timeToSIfactors[];
+extern const char** timeUnits [];
+extern const int timeUnitsCounts [];
+extern const unit Time; // Upper case to avoid clash with C global time.
+// time() is in C time.h
+
+// Units of current: amp
+extern const int currentUnitCount;
+extern const int ampCurrentUnitCount;
+extern const char* ampCurrentUnits[];
+extern const double currentToSIfactors [];
+extern const char** currentUnits [];
+extern const int currentUnitsCounts [];
+extern const unit current;
+
+// Units of Temperature: degress Kelvin & Celsius
+extern const int temperatureUnitCount;
+extern const int kTemperatureUnitCount;
+extern const char* kelvinTemperatureUnits[];
+extern const int cTemperatureUnitCount;
+extern const char* celsiusTemperatureUnits[];
+extern const int fTemperatureUnitCount;
+extern const char* fahrenheitTemperatureUnits[];
+extern const double temperatureToSIfactors[];
+extern const char** temperatureUnits[];
+extern const int temperatureUnitsCounts [];
+extern const unit temperature;
+
+// Units of substance: Mole.
+extern const int substanceUnitCount; // just moles
+extern const int molSubstanceUnitCount;
+extern const char* molSubstanceUnits[];
+extern const double substanceToSIfactors[];
+extern const char** substanceUnits [];
+extern const int substanceUnitsCounts [];
+extern const unit substance;
+
+// Units of luminous intensity: candela ...
+extern const int lumintensityUnitCount;;
+extern const int candelaLumintensityUnitCount;
+extern const char* candelaLumintensityUnits[];
+extern const double lumintensityToSIfactors[];
+extern const char** lumintensityUnits [];
+extern const int lumintensityUnitsCounts [];
+extern const unit lumintensity;
+
+// Frequency: Hertz.
+extern const int freqUnitCount;
+extern const int hertzFreqUnitCount;
+extern const char* hertzFreqUnits [];
+extern const double freqToSIfactors [];
+extern const char** freqUnits [];
+extern const int freqUnitsCounts [];
+extern const unit freq;
+
+ // Charge: Coulomb.
+extern const int chargeUnitCount;
+extern const int coulombChargeUnitCount;
+extern const char* coulombChargeUnits[];
+extern const int ampHourChargeUnitCount;
+extern const char* ampHourChargeUnits[];
+extern const double chargeToSIfactors[];
+extern const char** chargeUnits [];
+extern const int chargeUnitsCounts [];
+extern const unit charge;
+
+// Unknown unit.
+extern const int unknownUnitCount;
+extern const int unknownCount;
+extern const char* unknownunit [];
+extern const int unknownUnitsCount;
+extern const char** unknownUnits [];
+extern const int unknownUnitsCounts [];
+extern const double unknownUnitsFactors [];
+extern const unit unknownUnit;
+
+// Array of all units.
+extern const int unitsCount;
+extern const unit* unitps[]; // 7 SI base units: & then others.
+
+// Declarations of functions to show units (see SIunits.txt)
+extern void showAllUnits(const unit*, ostream&); // mass, length, time ...
+extern void showSIunit(const unit*, ostream&); //
+extern void showSIunits(const unit*, ostream&); // Show the SI unit & aliases.
+extern void showNonSIunits(const unit*, ostream&);
+ // Show just the base Non SI units, but not aliases.
+extern void showAllNonSIunits(const unit*, ostream&);
+ // Show all the Non SI units.
+
+unsigned int findUnit(const string, // multiple unit
+ const unit*, // unit
+ unsigned int&, // index of name, alias or abbrev given unit.
+ unsigned int&); // SIindex.
+
+const unit& findAnyUnit(const string, // multiple unit
+ unsigned int&, // index.
+ unsigned int&, // index of name, alias or abbrev given unit.
+ unsigned int&); // SIindex.
+
+#endif // SIUNITS_HPP

Added: sandbox/SOC/2007/quan/boost/quan/type_erasure_printer.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/boost/quan/type_erasure_printer.hpp 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,231 @@
+// Boost.TypeErasure decor printer
+//
+// Copyright 2011 Steven Watanabe
+// Copyright 2012 Paul A. Bristow
+//
+// 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)
+//
+// from \boost-sandbox\type_erasure\libs\type_erasure\example\print_sequence.cpp
+
+#ifndef BOOST_TYPE_ERASURE_PRINTER
+#define BOOST_TYPE_ERASURE_PRINTER
+
+#include <boost/type_erasure/any.hpp>
+#include <boost/type_erasure/iterator.hpp>
+#include <boost/type_erasure/operators.hpp>
+#include <boost/type_erasure/tuple.hpp>
+#include <boost/type_erasure/same_type.hpp>
+#include <boost/type_erasure/callable.hpp>
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/iterator.hpp>
+
+#include<iostream>
+#include <iomanip>
+
+using namespace boost::type_erasure;
+
+// Placeholders used by the abstract printer during specification of requirements.
+struct _t : boost::type_erasure::placeholder {};
+struct _iter : boost::type_erasure::placeholder {};
+struct _os : boost::type_erasure::placeholder {};
+// This is more readable than using the 'out of the box' _a, ... _g placeholders.
+// See placeholder.hpp.
+
+template<class T, class U = _self>
+struct base_and_derived
+{ // Template parameter for concept_interface.
+ // and in list of requirements in abstract printer.
+ // base_and_derived<std::ios_base, _os>, // _os must derive from std::ios_base.
+ static T& apply(U& arg) { return arg; }
+};
+
+namespace boost {
+namespace type_erasure {
+
+template<class T, class U, class Base>
+struct concept_interface<base_and_derived<T, U>, Base, U> : Base
+{
+ operator typename rebind_any<Base, const T&>::type() const
+ {
+ return call(base_and_derived<T, U>(), const_cast<concept_interface&>(*this));
+ }
+ operator typename rebind_any<Base, T&>::type()
+ {
+ return call(base_and_derived<T, U>(), *this);
+ }
+};
+
+// Fully specialized for const std::pair<const int, double>&
+//std::ostream& operator<< (std::ostream& os, const std::pair<const int, double>& p)
+//{ /*! Output a pair of values.
+// \details For example: "1.23 , 3.45".
+// */
+// os << p.first << ", " << p.second;
+// return os;
+//} // std::ostream& operator<<
+
+// But more useful is just providing the two template version:
+
+template <typename T1, typename T2>
+std::ostream& operator<< (std::ostream& os, const std::pair<T1, T2>& p)
+{ /*! Output a pair of values with space as delimiter.
+ \details For example: "1.23 3.45".
+ */
+ os << p.first << " " << p.second;
+ return os;
+} // std::ostream& operator<< (std::ostream& os, const std::pair<T1, T2>& p)
+
+// Or can use a version defined elsewhere, for example, in namespace my_detail?
+
+// using my_detail::operator<<;
+
+// Partial specialization of struct ostreamable for pair<const int, double>:
+//template<class Os>
+//struct ostreamable<Os, std::pair<const int, double> >
+//{
+// static void apply(Os& out, const std::pair<const int, double>& arg)
+// {
+// out << arg;
+// }
+//};
+
+// Partial specialization of struct ostreamable for pair<T1, T2>:
+template<class Os, typename T1, typename T2>
+struct ostreamable<Os, std::pair<T1, T2> >
+{
+ static void apply(Os& out, const std::pair<T1, T2>& arg)
+ {
+ out << arg;
+ }
+};
+
+} // namespace type_erasure
+} // namespace boost
+
+/*! An abstract sequence printer - a 'template' that is inherited
+ to implement the examples of actual printers defined below.
+ */
+
+template< class CharT = char, class Traits = std::char_traits<char> >
+class abstract_printer
+{
+public:
+ //! \tparam Range must be a Forward Range whose elements can be printed to `ostream os`.
+ //! \param r Container to be printed, for example, a C array, std::vector, std::list ...
+ //! \param os `std::ostream` for printing, for example std::cout.
+
+ template<class Range, class CharT, class Traits>
+ void print(const Range& r, std::basic_ostream<CharT, Traits>& os = std::cout) const
+ {
+ // Capture the print arguments.
+ // Range iterators.
+ typename boost::range_iterator<const Range>::type
+ first(boost::begin(r)),
+ last(boost::end(r));
+ // Assemble requirements into tuple: range pair of iterators and ostream.
+ tuple<requirements, _iter, _iter, _os&> args(first, last, os);
+ // and forward to the real implementation.
+ do_print(get<0>(args), get<1>(args), get<2>(args));
+ // get<0>() is first, get<1>() is last, get<2>() is ostream.
+ }
+ virtual ~abstract_printer() {}
+protected:
+ // Define the requirements in an mpl::vector for containers to be printed.
+ typedef boost::mpl::vector<
+ base_and_derived<std::ios_base, _os>, // _os must derive from std::ios_base.
+ ostreamable<_os, _t>, // type _t must be ostreamable.
+ ostreamable<_os, const char*>, // C string must be ostreamable.
+ forward_iterator<_iter, const _t&>, // t range must have forward iterator.
+ same_type<_t, forward_iterator<_iter, const _t&>::value_type> // _t's type value and iterator must match.
+ > requirements;
+
+ // Use type_erasure::any to enforce the requirements onto ostream and iterator.
+ typedef boost::type_erasure::any<requirements, _os&> ostream_type;
+ typedef boost::type_erasure::any<requirements, _iter> iterator_type;
+ // Declare the pure virtual function `do_print` that is defined in all real printers.
+ virtual void do_print(iterator_type first, iterator_type last, ostream_type os) const = 0;
+}; // class abstract_printer
+
+/*!
+ Outputs items in a specified number of columns across rows with a separator (often comma and/or space(s)),
+ and a suffix (usually newline) every `num_column`s items.\n
+ Usage: `decor_printer simple_printer(3, 0, "\n", ", ", "\n", "\n");`\n
+ Provide a container to be printed: `double da[] = {1., 2., 3., 4., 5., 6.};`\n
+ Print to std::cout using: `simple_printer.print(std::cout, da);` \n
+ Output:\n
+ 1, 2, 3,\n
+ 4, 5, 6,\n
+ 7, 8, 9,\n
+ 10, 11, 12\n
+ The order of parameters is chosen to try to allow use of the defaults as much as possible,
+ including all defaults placing all items on one line or row separated by spaces.
+
+ \param num_columns number of columns (default 0, so all items are on the same line or row).
+ \param width ostream width to use to each items (default 0 so that columns may be jagged).
+ \param pre string to be output before the first column,
+ (default newline which ensures that the first item is at the left margin).
+ \param sep string to separate (or delimit) items on each row (default space).
+ \param suf suffix at the end of each row (default newline).
+ \param term string to terminate the last row
+*/
+class decor_printer : public abstract_printer<>
+{
+public:
+ explicit decor_printer(
+ std::size_t num_columns = 0,
+ std::size_t wid = 0,
+ const std::string& pre = "\n",
+ const std::string& sep = " ",
+ const std::string& suf = "\n",
+ const std::string& term = "\n")
+ :
+ cols(num_columns), width(wid), prefix(pre), separator(sep), terminator(term), suffix(suf)
+ { /*! Constructor.\n
+ Usage: for example: ``3, 10, "double testd[] = {\n ", ", ", "\n ", "\n };\n"``
+ 3 columns with width 10, prefix "double testd[] = {\n ", separator string comma space,
+ suffix (newline at the end of a column),
+ and a terminator string "\n };\n".\n
+ Defaults are provided for all parameters, so can contruct: `my_default_printer decor_printer;`\n
+ that places all items on one line or row with space between items, and a final newline.
+ */
+ }
+protected:
+ // Print all items in rows.
+ virtual void do_print(iterator_type first, iterator_type last, ostream_type os) const
+ {
+ os << prefix.c_str();
+ std::size_t count = 0;
+ for(; first != last; ++first)
+ {
+ if (width > 0)
+ {
+ static_cast<std::ios_base&>(os).width(width);
+ }
+ os << *first;
+ boost::type_erasure::any<requirements, _iter> temp = first;
+ ++temp;
+ if(temp != last)
+ {
+ os << separator.c_str();
+ }
+ ++count;
+ if((cols != 0) && (count % cols == 0))
+ { // Last column.
+ os << suffix.c_str(); // Usually newline at end of a row.
+ }
+ }
+ os << terminator.c_str(); // Perhaps useful to have a terminating newline?
+ }
+private:
+ std::size_t cols; // Set by constructor, number of columns (default 10).
+ std::size_t width; // Set by constructor, optional column width (default zero).
+ std::string prefix; // Set by constructor, for example, "{ ".
+ std::string separator; // Set by constructor, for example, ", ".
+ std::string suffix; // Set by constructor, for example "\n".
+ std::string terminator; // Set by constructor, for example, "}\n".
+}; // class decor_column_printer
+
+#endif // ifndef BOOST_TYPE_ERASURE_PRINTER

Added: sandbox/SOC/2007/quan/boost/quan/unc.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/boost/quan/unc.hpp 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,2114 @@
+/*! \file
+ \brief Class for simple Propagation of Uncertainties according to a pure Gaussian model.
+
+ \details Based on code by Evan Manning (manning_at_[hidden])
+ Evan Marshal Manning, C/C++ Users Journal, March 1996 page 29 to 38.
+ original downloaded from ftp://beowulf.jpl.nasa.gov/pub/manning
+ This is a simple model of uncertainties, designed to
+ accompany an article published in C/C++ Users Journal March 1996
+ at http://www.ddj.com/cpp/184403147 .
+ A fuller collection of even fancier classes also given in unc.h.
+
+ Standard deviation & its uncertainty added Paul A Bristow 31 Mar 98 to May 2012.
+
+ \mainpage
+ \n
+ \b Boost.Quan
+
+This is the standalone Doxygen main page of the proposed Boost.Quan library.
+
+This library provides a collection of classes and functions for handling uncertain reals.
+
+Uncertainty as standard deviation and degrees of freedom are
+propagated through calculations using the uncertain type,
+and are input and output including the uncertainty estimates.
+
+See Boost.Quan HTML Manual at
+
+ https://svn.boost.org/svn/boost/sandbox/quan/libs/quan/doc/html/index.html
+
+and/or equivalent PDF Manual at:
+
+ https://svn.boost.org/svn/boost/sandbox/quan/libs/quan/doc/quan.pdf
+
+Examples are in folder:
+
+ https://svn.boost.org/svn/boost/sandbox/quan/libs/quan/example/
+
+and C++ include files are in folder:
+
+ https://svn.boost.org/svn/boost/sandbox/quan/boost/quan/
+
+*/
+
+// unc.hpp
+
+// Use, modification and distribution are subject to 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)
+
+// Copyright Paul A. Bristow 1998, 2012.
+
+#ifndef UNC_HPP
+#define UNC_HPP
+
+#ifdef _MSC_VER
+# pragma once
+# pragma warning (disable : 4127) // conditional expression is constant.
+# pragma warning (disable : 4800)// forcing value to bool 'true' or 'false' (performance warning).
+# pragma warning (disable : 4189) // local variable is initialized but not referenced.
+// Could use no_unused_variable_warning(x);
+//template<class T> // Avoid MSVC warning "C4189 variable initialised but not used".
+//inline void no_unused_variable_warning(const T&) {}
+#endif// _MSC_VER
+
+#include <boost/math/special_functions/fpclassify.hpp>
+ //using boost::math::isnan;
+ //using boost::math::isinf;
+ //using boost::math::isfinite;
+ //using boost::math::isnormal; // isfinite and not denormalised.
+// Might instead use the std TR1 versions?
+
+#include <cstdlib> //
+#include <cmath> // for log, exp etc
+#include <iostream> //
+ //using std::istream;
+ //using std::ostream;
+ //using std::ios_base;
+ //using std::char_traits;
+ //using std::cout;
+ //using std::cerr;
+ //using std::cin;
+ //using std::endl;
+ //using std::flush;
+ //using std::ws;
+ //using std::streamsize;
+ //using std::boolalpha;
+ //using std::dec;
+ //using std::hex;
+ //using std::showbase;
+ //using std::fixed;
+ //using std::scientific;
+ //using std::right;
+ //using std::showpos;
+ //using std::noshowpos;
+ //using std::noshowbase;
+ //using std::noshowpoint;
+ //using std::showpoint;
+
+#include <iomanip> //
+ //using std::setprecision;
+ //using std::setw;
+ //using std::resetiosflags;
+#include <algorithm>
+ //using std::max;
+ //using std::min;
+
+#include <sstream> //
+ // using std::ostringstream;
+#include <limits> // for numeric_limits<unsigned short>::max() etc
+// using std::numeric_limits;
+//#include <locale> // for . or , for decimal point
+#include <exception> //
+ //using std::exception;
+ //using std::bad_alloc;
+
+#include <boost/quan/xiostream.hpp> // for extra manipulators, spaces.
+// These extra manipulators have been placed in std for convenience.
+ //using std::noadjust; // Restore to default state.
+ //using std::nofixed; // Restore to default state.
+ //using std::noscientific; // Restore to default state.
+ //using std::defaultfloat; // Restore fixed & scientific to default state.
+ //using std::hexbase;
+ //using std::lowercase;
+
+#include <boost/quan/unc_init.hpp> // Defines indexes to xalloc iword(index) variables.
+#include <boost/quan/rounding.hpp> // Rounding functions.
+#include <boost/lexical_cast.hpp>
+
+#include <boost/static_assert.hpp>
+BOOST_STATIC_ASSERT (std::numeric_limits<double>::is_iec559); // Assume IEEE 754 ONLY.
+// == _STATIC_ASSERT (numeric_limits<double>::is_iec559); // and MS STATIC assert.
+
+#include <boost/io/ios_state.hpp>
+#include <boost/units/io.hpp>
+#include <boost/units/static_rational.hpp>
+#include <boost/type_traits.hpp>
+
+void outIosFlags(long, std::ostream&); // Output ios flags.
+void outUncTypes(unsigned short int, std::ostream&);
+
+//namespace boost {
+//namespace units {
+
+// Forward declarations.
+template <bool is_correlated> // Default is uncertainties that are NOT correlated.
+class unc;
+
+// Two actual uncertain floating-point types for the user:
+
+typedef unc<false> uncun; //! Uncertainties are NOT correlated.
+//! Uncorrelated is the normal case when uncertainties add.
+
+typedef unc<true> unccorr; //! Uncertainties ARE correlated.
+//! This is the unusual case where the sum must be exact,
+//! so the uncertainties are subtracted.
+//! Example: two blocks which fit into a box perfectly.
+//! So if both have an uncertainties, they must cancel when the uncertainties are added.
+//! Also applies to items like concentrations which must add up to 100% or unity.
+
+// Obselete - now implemented directly as operator <<
+//void unc_output(double value, // Mean or most likely value.
+// float stdDev, // Standard deviation.
+// unsigned short int degFree, // Degrees of freedom.
+// unsigned short int uncTypes, // 16 Uncertain type flags.
+// ostream& os); // Output stream, default std::cout.
+
+
+void unc_input(double& mean, // mean (central or most probable) value.
+ double& stdDev,
+ unsigned short int& degreesOfFreedom, // 1 observation.
+ unsigned short int& uncTypes,
+ std::istream& is);
+
+//template<typename correlated> std::ostream& operator<< (std::ostream& os, const unc<false>& u);
+//template<typename correlated> std::ostream& operator<< (std::ostream& os, const unc<false>& u);
+// Need to declare so that can make a friend (in unc), and thus access private data value_ etc.
+// See http://www.parashift.com/c++-faq-lite/templates.html#faq-35.16
+// This avoids failure to instantiate these operators, and thus link failures.
+// May need for input operator>> too.
+// template<typename correlated> std::istream& operator>> (std::istream& is, const unc<false>& u);
+// friend istream& operator>> (istream& is, UReal<correlated>& u)
+
+template <typename Type> inline Type sqr(const Type& a);
+template <typename Type> inline Type cube(const Type& a);
+template <typename Type> inline Type pow4(const Type& a);
+
+// These should be defined elsewhere, but will not compile.
+//! Quaded function, notationally convenient for x^4, but overflow possible?
+//! Used by Welch-Satterthwaite formula.
+template <typename Type>
+inline Type pow4(const Type& a)
+{
+ return (Type)(a * a * a * a);
+}
+
+template <typename Type> inline Type sqrtSumSqrs (const Type& a, const Type& b);
+template <typename Type>
+inline Type sqrtSumSqrs (const Type& a, const Type& b)
+{
+ return (Type)sqrt(a * a + b * b);
+}
+
+// SI units from CRC Handbook of Chemistry & Physics 76th edition 1995,
+// ISBN 08493 0476-8 page 1-22.
+
+// SI Usage, ISO 30-0 to 30-13:1992 is 'International Consensus Document'.
+
+// ANSI/IEEE Std 268-1992 Americal National Standard for Metric Practice,
+// (adopted for US Department of Defence)
+
+// ASTM E 380-93 now consolidated with ANSI 268.
+
+// NIST Special Publication 811, Barry N Taylor
+// Guide for the Use of the International System of Units 1995
+// which was derived from IEEE Std 268, IEEE Standard Metric Practice (1982)
+
+// Most useful commentary on the these standards, and annotated bibliography.
+// (available from www.physics.NIST.gov)
+
+// ISO 2955 = BS 6430 :1983 (1988)
+// Method for representing SI and other units in information processing
+// system with limited character sets.
+
+// Gives two sets of representation, for SI units and other ISO 1000 units,
+// for use in data interchange by systems with limited graphic character sets.
+// Mainly important for allowing u instead of greek mu.
+
+// Gunther Schadow & Clement J. McDonald,
+// The Unified Code for Units of Measure,
+// A critique and proposals of ISO and ANSI, and ENV 12435
+// http://aurora.rg.iupui.edu/~schadow/units/UCUM/ucum.html
+
+void outUncValues(std::ostream& os, std::ostream& log); // Output uncertain values.
+void setUncDefaults(std::ios_base& os); // Set I=Unc class defaults for stream os.
+
+ //! 16 type bits used by unc uncTypes. Bit set = 1 means a positive attribute.
+enum unc_types
+{
+ VALUE_ZERO = 1 << 0, //!< bit zero = 1 means value is zero.
+ //! (Too near zero to allow relsd = sd /mean.)
+ //! A few times std::numeric_limits<float>::min() may be a suitable limit?
+ VALUE_INTEGER = 1 << 1, //!< Exact integer 2,3,4 ... may not be possible to store `int` into `double`?
+ VALUE_RATIONAL = 1 << 2, /*!< Integers & Fractions 1/2, 1/3, 2/3, 5/4 ...
+ so don't need irrational - must be if not rational.
+ Irrational like pi, e ... represented as accurately as possible by the double floating-point type,
+ usually for 64-bit double, 15 to 17 decimal digits.
+ */
+ VALUE_NEGATIVE_ONLY = 1 << 3, //!< Value can ONLY be < 0.. ? or <=0?
+ VALUE_POSITIVE_ONLY = 1 << 4, //!< Value can ONLY be >=0..
+ UNC_KNOWN = 1 << 5, //!< Uncertainty known (but if not, value may still be known OK).
+ UNC_NOPLUS = 1 << 6, //!< Uncertainty can only be < value, + = zero.
+ UNC_NOMINUS = 1 << 7, /*!< Uncertainty can only be > value - = zero.
+ Integer, Rational or Exact by definition like 25.4 mm per inch,
+ if unc = 0.0f or both UNC_NOPLUS & UNC_NOMINUS.
+ */
+ UNC_QUAN_DECIMAL = 1 << 8, //!< Quantised by least significant decimal digit.
+ UNC_QUAN_BINARY = 1 << 9, //!< Quantised by least significant binary digit.
+ UNC_EXPLICIT = 1 << 10, /*!< If bit set = 1, uncertainty implicit from read significant digits,
+ for example: unc_input of 10.0 will set this bit and set uncertainty = 0.05,
+ or explicit if +/- or calculated (normal default case, bit = 0).
+ */
+ UNC_UNIFORM = 1 << 11, //!< Uncertainty has rectangular or uniform probability distribution.
+ UNC_TRIANGULAR = 1 << 12, //!< Uncertainty has triangular probability distribution.
+ //! If not rectangular or triangular bits set, then normal or Gaussian distribution, the default.
+ //! Both bits 11 and 12 == 1 then has distribution un-defined as yet.
+ //! Distribution type is used to estimate confidence intervals and rounding.
+ DEG_FREE_EXACT = 1 << 13, //!< Known number of observations -1,
+ //! so default zero means 1 observation.
+ //! else estimated, for example, using Welch-Satterthwaite.
+ DEG_FREE_KNOWN = 1 << 14, //!< Degrees of freedom is defined.
+ SPARE = 1 << 15 //!< This last unc_type is spare.
+}; // enum unc_types
+
+const unsigned short int VALUE_EXACT = (UNC_NOMINUS | UNC_NOPLUS); //!< Both set.
+const unsigned short int UNC_DEF = (UNC_KNOWN | UNC_NOMINUS | UNC_NOPLUS | //!< Any defined means that uncertainty is defined.
+ UNC_QUAN_DECIMAL | UNC_QUAN_BINARY |
+ UNC_EXPLICIT //!< Not implicit from number of significant digits.
+ | UNC_UNIFORM | UNC_TRIANGULAR); //
+const unsigned short int DEG_FREE_DEF = (DEG_FREE_EXACT | DEG_FREE_KNOWN);
+
+extern const char* uncTypeWords[];
+
+enum uncertainflags
+{ //! \enum uncertainflags Control of printing uncertain values, similar to ios flags.
+ defaults = 0, //!< Default.
+ firm = 1 << 0, //!< bit 0: == 0 == false means flex, or firm == 1 == true.
+ setScaled = 1 << 1, //!< bit 1 Set scaled == 1 or not scaled == 0.
+ //! by fixed factor SetScale and << scale ...
+ //! power10 in range -max to +max.
+ autoScaled = 1 << 2, //!< bit 2: auto = 1 with << autoscale ...
+ plusMinus = 1 << 3, /*!< bit 3 = 1 means add +/- uncertainty
+ Usage: `std::cout << plusminus << u;`
+ */
+ addSISymbol = 1 << 4, //!< bit 4 = 1, add suffix SI symbol G, M, k, m, u, n, p ...
+ //! If one is applicable, else = 0 do nothing.
+ addSIPrefix = 1 << 5, //!< bit 5 = 1, add suffix SI prefix Giga, Mega, kilo ...
+ noisyDigit = 1 << 6, /*!< Add extra 'noisy' decimal digit to value & sd.
+ Usage: std::cout `<< addnoisyDigit << u;`
+ This means is suitable for input to other calculations because the
+ random extra 2 to 3 bits will approximate a continuous function.
+ Quantization to fewer digits would distort statistical calculations.
+ Default is to use minimum decimal digits for clearer display.
+ Extra digit also added when degrees of freedom > 10.
+ */
+ useSetSigDigits = 1 << 7, //!< if bit 7 = 1 use set sig digits else calculate from sd(isUseSetSigDigits).
+ useSetUncSigDigits = 1 << 8, //!< if bit 8 = 1 use set Unc sigfig (isStdDevSigDigitsSet).
+ //! else calculate from degrees of freedom.
+ degfree = 1 << 9, //!< 0x200, If bit 9 == 1, add output of degrees of freedom as (99).
+ // Usage: std::cout `<< adddegfree << u;`
+ replicates = 1 << 0xA, //!< 0x400 If == 1, add output of replicates as [99] if > 1.
+ limits = 1 << 0xB, //!< 0X800 add limits.
+ // 0xC, D, E and F spare - and iword is actually a long so could use 32 flags.
+}; // enum uncertainflags
+
+void outFpClass(double, std::ostream&); // Special output for inf, NaN...
+
+// Declarations of parameterless Manipulators,
+// similar to ios_base flags but for uncertain printing.
+// Use upperand lower case convention for these,
+// but all lowercase for manipulators like hex, oct ...
+// Usage: out << scale << noscale << autoscale << noautoscale
+// firmform << flexform << plusminus << noplusminus ....
+
+//! All ios_base functions declared below are defined in unc.ipp
+//! \note that all of these are entirely lower case names, like std::ios manipulators.
+
+std::ios_base& scale(std::ios_base&); //!< To use value set with setScale(int)
+std::ios_base& noscale(std::ios_base&); //!< or not scale.
+std::ios_base& autoscale(std::ios_base&); //!< Automatically Scale to suitable prefix symbol like M, k, m...
+std::ios_base& noautoscale(std::ios_base&); // or not to scale to prefix symbol.
+std::ios_base& firmform(std::ios_base&); //!< Firm fixed layout using setUncWidth.
+std::ios_base& flexform(std::ios_base&); //!< Flexible free format.
+std::ios_base& plusminus(std::ios_base&); //!< Add +/- uncertainty.
+std::ios_base& noplusminus(std::ios_base&); //!< Do not add +/- uncertainty
+std::ios_base& addsiprefix(std::ios_base&); //!< Add SI prefix like kilo, micro ..
+std::ios_base& nosiprefix(std::ios_base&); //!< (Takes precedence over SI symbol if both set).
+std::ios_base& addsisymbol(std::ios_base&); //!< Add SI symbol like M, k, m.
+std::ios_base& nosisymbol(std::ios_base&); //!< Do not add SI symbol like M, k, m.
+std::ios_base& addnoisyDigit(std::ios_base&); //!< Add an extra 'noisy' digit for less risk of loss.
+std::ios_base& nonoisyDigit(std::ios_base&); //!< No noisy to suit human reading.
+std::ios_base& autosigdigits(std::ios_base&); //!< Calculate sigdigits from uncertainty (default).
+std::ios_base& setsigdigits(std::ios_base&); //!< Use sig digits stored with `<< setSigDigits(6)` for value.
+std::ios_base& autouncsigdigits(std::ios_base&); //!< Calculate stdDev sig digits from uncertainty.
+std::ios_base& uncsigdigits(std::ios_base&); //!< Use stdDev sigDigits stored with << useSetUncSigDigits(2) ...
+std::ios_base& adddegfree(std::ios_base&); //!< Add degrees of freedom as (99).
+std::ios_base& nodegfree(std::ios_base&); //!< Do not add degrees of freedom to output of value.
+//
+std::ios_base& addlimits(std::ios_base&); //!< Add lower and upper limits a 0.95 > 1.00 > 1.05.
+std::ios_base& nolimits(std::ios_base&); //!< Do not add lower and upper limits.
+
+// Obselete
+//std::ios_base& confidence(std::ios_base&);
+/*!< Use stdDev sigDigits stored with `<< setconfidence( 0.01) ...`
+ or alpha to control estimation of confidence interval. 0.01 means 99% confidence.
+ */
+//std::ios_base& roundingloss(std::ios_base&); //!< Set the acceptable loss from rounding.
+//std::ios_base& addreplicates(std::ios_base&); //!< Add degrees of replicates > 1 as [99].
+//std::ios_base& noreplicates(std::ios_base&); //!< Do not add degrees of freedom or replicates >1.
+
+/*! Functions to change uncertain flags on specified ios_base.
+ Usage: \code f = uFlags(out); f = uFlags(out, 0xFF);
+ f = setuFlags(out, 0xFF); f = resetuFlags(out, 0xFF);
+ \endcode
+*/
+long uFlags(std::ios_base&); //!< Returns current uncertain flags.
+long uFlags(std::ios_base&, long); //!< Assigns all uncertain flags & returns previous.
+long setuFlags(std::ios_base&, long); //!< Set specific flags = 1
+long resetuFlags(std::ios_base&, long); //!< Reset/clear specific flags = 0
+
+// Forward declarations, defined in unc.ipp.
+class showUncFlags; //!< Output uncertain flags to `ostream << showUncFlags `.
+class setAllUncFlags; //!< Assign value to set (and/or clear) all unc flags.
+class setUncFlags; //!< Set specific unc flags bits.
+class setMaskedUncFlags; //!< Clear mask & then set unc flag bits.
+class resetUncFlags; //!< Reset all unc flags bits.
+class resetMaskedUncFlags; //!< Reset specific unc flags bits.
+class setUncWidth; //!< Set width of uncertainty output.
+class setScale; //!< Set scaling factor like 1e3, 1e6 ... `<< setScale(6)`.
+class setSigDigits; //!< sigdigits to use for value if `<< setsigdigits(4)`.
+class setUncSigDigits; //!< sigdigits to use for uncertainty if `<< setuncsigdigits(1)`.
+class setRoundingLoss; //!< Set acceptable loss due to rounding.
+class setConfidence; //!< Set acceptable loss due to rounding.
+
+// Operator declarations, classes defined below, with constructors in unc.ipp.
+std::ostream operator<< (std::ostream, const showUncFlags&);
+std::ostream operator<< (std::ostream, const setAllUncFlags&);
+std::istream operator>> (std::istream, const setAllUncFlags&);
+std::ostream operator<< (std::ostream, const setUncFlags&);
+std::istream operator>> (std::istream, const setUncFlags&);
+std::ostream operator<< (std::ostream, const setMaskedUncFlags&);
+std::istream operator>> (std::istream, const setMaskedUncFlags&);
+std::ostream operator<< (std::ostream, const resetUncFlags&);
+std::istream operator>> (std::istream, const resetUncFlags&);
+std::ostream operator<< (std::ostream, const resetMaskedUncFlags&);
+std::istream operator>> (std::istream, const resetMaskedUncFlags&);
+std::ostream operator<< (std::ostream, const setUncWidth&);
+std::istream operator>> (std::istream, const setUncWidth&);
+std::ostream operator<< (std::ostream, const setScale&);
+std::istream operator>> (std::istream, const setScale&);
+std::ostream operator<< (std::ostream, const setUncSigDigits&);
+std::istream operator>> (std::istream, const setUncSigDigits&);
+std::ostream operator<< (std::ostream, const setRoundingLoss&);
+std::ostream operator<< (std::ostream, const setConfidence&);
+std::ostream operator<< (std::ostream, const setSigDigits&);
+std::istream operator>> (std::istream, const setSigDigits&);
+
+void outUncFlags(long uncflags, std::ostream);
+
+class showUncFlags
+{ // Constructor & operator<< defined in unc.ipp
+ friend std::ostream operator<< (std::ostream, const showUncFlags&);
+public:
+ showUncFlags(unsigned short int); // Definition in unc.ipp.
+ unsigned short int flags;
+};
+
+class showUncTypes
+{ // Constructor & operator<< defined in unc.ipp
+ // Usage: out << showUncTypes(unc) ...
+ friend std::ostream operator << (std::ostream, const showUncTypes&);
+public:
+ showUncTypes(unsigned short int); // Definition in unc.ipp.
+ unsigned short int types;
+};
+
+// setAllUncflags(int flags, int mask);
+// Usage: out << setAllUncFlags(0x5a) ...
+class setAllUncFlags // Set ALL uncertain flags (not just OR selected bits).
+{
+ friend std::ostream operator<< (std::ostream, const setAllUncFlags&);
+ friend std::istream operator>> (std::istream, const setAllUncFlags&);
+public:
+ setAllUncFlags(int); // w) : flags(w) {} // Constructor initialisation flags = w.
+ int flags; // setAllUncFlags.flags used by operators << and >>
+};
+
+class setUncFlags // Set selected uncertain flags.
+{// Usage: out << setUncFlags(0xFFFF, 0x7, 0x3) ...
+ // or setUncFlags(out, 0x7);
+
+ friend std::ostream operator<< (std::ostream, const setUncFlags&);
+ friend std::istream operator>> (std::istream, const setUncFlags&);
+public:
+ setUncFlags(int); // Constructor initialisation flags.
+ int flags; // setUncFlags.flags used by operators << and >>
+};
+
+// setMaskedUncflags(int flags, int mask);
+// Usage: out << setMaskedUncFlags(0xFFFF, 0x7, 0x3) ...
+// or setUncFlags(out, 0x7);
+class setMaskedUncFlags
+{
+ friend std::ostream operator<< (std::ostream, const setMaskedUncFlags&);
+ friend std::istream operator>> (std::istream, const setMaskedUncFlags&);
+public:
+ setMaskedUncFlags(int, int); // : flags(w), mask(m) {} // Constructor initialisation flags = w.
+ int flags; // setMaskedUncFlags.flags used by operators << and >>
+ int mask; // Selected bits to deal with by zeroing before setting flags.
+};
+
+class resetUncFlags // Reset = 0 selected uncertain flags.
+{// Usage: out << resetUncFlags(0xFFFF, 0x7, 0x3) ...
+ // or setUncFlags(out, 0x7);
+
+ friend std::ostream operator<< (std::ostream, const resetUncFlags&); // Declarations
+ friend std::istream operator>> (std::istream, const resetUncFlags&);
+public:
+ resetUncFlags(int);// w) : flags(w) {} // Constructor initialisation flags = w.
+ int flags; // setUncFlags.flags used by operators << and >>
+};
+
+// setMaskedUncflags(int flags, int mask);
+// Usage: out << resetMaskedUncFlags(0xFFFF, 0x7, 0x3) ...
+// or setUncFlags(out, 0x7);
+class resetMaskedUncFlags
+{
+ friend std::ostream operator<< (std::ostream, const resetMaskedUncFlags&);
+ friend std::istream operator>> (std::istream, const resetMaskedUncFlags&);
+public:
+ resetMaskedUncFlags(int, int); // : flags(w), mask(m) {} // Constructor initialisation flags = w.
+ int flags; // setMaskedUncFlags.flags used by operators << and >>
+ int mask; // Selected bits to deal with by zeroing before setting flags.
+};
+
+class setUncWidth // Set uncertain width.
+{
+ friend std::ostream operator<< (std::ostream, const setUncWidth&); // Declarations
+ friend std::istream operator>> (std::istream, const setUncWidth&); // Defined below.
+ // Allows ostream operator>> and << to access private member width.
+public:
+ setUncWidth(int);
+ int uncWidth; // setUncWidth used by operators << and >>
+};
+
+// setScale(int scale);
+// Usage: out << setScale(6) // == 10**6) ...
+class setScale // Set uncertain scale.
+{
+ friend std::ostream operator<< (std::ostream, const setScale&); // Declarations
+ friend std::istream operator>> (std::istream, const setScale&); // Defined below.
+ // Allows ostream operator>> and << to access private member scale.
+public:
+ setScale(int); // n) : scale(n) {} // Constructor - initialisation scale = n.
+ int scale; // setScale.scale used by operators << and >>
+};
+
+// Usage via class: setSigDigits(int sigDigits);
+// Usage via operator << : out << setSigDigits(6) ...
+class setSigDigits
+{
+ friend std::ostream operator<< (std::ostream, const setSigDigits&); // Declarations
+ friend std::istream operator>> (std::istream, const setSigDigits&);
+public:
+ setSigDigits(int);// w) : sigDigits(w) {} // Constructor in unc.ipp
+ // Initialisation means sigDigits = w.
+ int sigDigits_; // setSigDigits.flags used by operators << and >>
+};
+
+/*! setUncSigDigits(int uncSigDigits);
+ Permits choice of number of uncertain or stddev value:\n
+ 2 is the ISO recommendation.\n
+ Uncertainty of measurement -- Part 3: Guide to the expression of uncertainty in measurement (GUM:1995)\n
+ ISO Guide 98 (1995) and updated version 2008.\n
+ 1 is more appropriate for very small degrees of freedom,
+ (but it gives a big step when the value starts with 1 or 2,
+ when the difference between 1.4 (rounded to 1) and 1.6 (rounded to 2.) is a doubling.
+ 3 is appropriate only for large degrees of freedoms, >= 1000.
+ \warning Values < 1 or > 3 are silently ignored.
+ -1 passes through to allow dymanic choice based on degress of freedom.
+ Usage: out << setUncSigDigits(3) ...
+*/
+class setUncSigDigits
+{
+ friend std::ostream operator<< (std::ostream, const setUncSigDigits&); // Declarations
+ friend std::istream operator>> (std::istream, const setUncSigDigits&);
+public:
+ setUncSigDigits(int);// w) : uncSigDigits(w) {} // Constructor
+ // Initialisation means uncSigDigits = w.
+ //protected:
+ int uncSigDigits_; // Set by constructor.
+}; // class setUncSigDigits
+
+//! setRoundingLoss(int setRoundingLoss); to control the acceptable rounding loss.
+//! Usage: `out << setRoundingLoss(0.01)` ...
+
+class setRoundingLoss
+{
+ friend std::ostream operator<< (std::ostream, const setRoundingLoss&); // Declarations
+ friend std::istream operator>> (std::istream, const setRoundingLoss&);
+public:
+ setRoundingLoss(double);// eps) : setRoundingLoss(eps) {} // Constructor
+ // Initialisation means setRoundingLoss = epsilon
+ //protected:
+ double roundingloss_; // Set by constructor.
+}; // class setRoundingLoss
+
+//! setConfidence(int setConfidence); to control the confidence interval.
+//! Usage: `out << setConfidence(0.01)` ...
+
+class setConfidence
+{
+ friend std::ostream operator<< (std::ostream, const setConfidence&); // Declarations
+ friend std::istream operator>> (std::istream, const setConfidence&);
+public:
+ setConfidence(double);// alpha) : setConfidence(alpha) {} // Constructor
+ // Initialisation means setConfidence = alpha
+ //protected:
+ double confidence_; // Set by constructor.
+}; // class setConfidence
+
+
+/*! Uncertain number template class unc,
+ using mean and uncertainty (equivalent to std deviation if pure Gaussian),
+ but also includes information about uncertainty as degrees of freedom & distribution.
+*/
+template <bool is_correlated = false> //! \tparam is_correlated if true, standard deviation is correlated, else not.
+class unc : public std::char_traits<char>
+{
+ typedef double value_type;
+
+
+ friend void unc_input(double& mean, // Mean (central or most probable) value.
+ double& stdDev, // Uncertainty estimate as Standard deviation.
+ unsigned short int& degreesOfFreedom, // Degrees of freedome -1. (Default zero for 1 observation).
+ unsigned short int& types, // 16 Uncertain type flags showing type of value.
+ std::istream& is);
+ //friend void unc_output(double value, // Mean(central or most probable) value.
+ // float stdDev, // Uncertainty estimate as Standard deviation.
+ // unsigned short int degFree, // Degrees of freedom.
+ // unsigned short int uncTypes, // 16 Uncertain type flagsshowing type of value.
+ // std::ostream& os); // Output stream, default std::cout.
+
+ // using char_traits<char>::int_type; // Derivation from public \c std::char_traits<char> needed for \c int_type.
+
+//#pragma warning (disable : 4520) //!< 'unc<1>' : multiple default constructors specified.
+ // This is by design so that it is possible construct from integer or double.
+ // Doubtful if this is necessary or useful?
+public:
+ /*! \note It is convenient to use 64-bit floating-point value
+ (so even really accurate values like weights are OK),
+ 32-bit floating-point is ample accuracy for standard deviation fractional variation,
+ leaving two 16-bit for degrees of freedom and other flags,
+ so that total is same as two doubles & can be efficiently aligned.
+ */
+ double value_; //!< aka mean, estimate, or most likely value.
+ float uncertainty_; //!< Standard deviation, if known.
+ //! Reduced precision (float guarantees 6 decimal digits not 15) and range e38 not E304
+ //! should not be a problem unless value is (near) less than 1e38.
+ //! Can be zero, meaning exact, and can be negative or anti-correlated,
+ //! for example when values must add up to a total like 100%.
+ //! Relative (Fraction) Coefficent of variation =
+ //! Standard deviation / value (aka % +|- /100)
+ //! Relative is a problem if value near zero.
+ //! +|- is std deviation, so
+ //! for input of "1.0" implicit standard deviation and uncertainty limits +|- 0.05.
+ short unsigned int degFree_; /*!< degrees of freedom, usually = number of observations;
+ so for 2 observations assign 1 to degFree_ degree of freedom.
+ Range from 1 (usally 1 observation) to 65534 = std::numeric_limits<unsigned short int>::max() - 1
+ Higher numbers of observations are indistinguishable from infinite observations.
+ Max unsigned value 0xFFFF == 65535 is used to indicate degFree_ is NOT meaningful.
+ Zero is as yet undefined?
+ BUT many programs seem to use NON-integer degrees of freedom,
+ so a float might seem better, but is 32 bits not 16, so use 16 for compact struct.
+ (Might use an explicit 16 bit unsigned integer type?)
+ */
+ short unsigned int unctypes_; //!< Information about the value and uncertainty,
+ //! encoded as a bitmap 16 bits, 0 to 15 See enum unc_types,
+
+ //! \note These sizes mean that total size of a unc is 64 = 32 + 32 = 128 bits
+ // for IEEE-754 systems with 64-bit double.
+public:
+ // Member functions to get & value, stdDev, degfree & uncTypes.
+ //! \return Central estimate of value of uncertain type.
+ double value()
+ {
+ return value_;
+ }
+ //! \return Estimate of uncertainty as standard deviation of value of uncertain type.
+ float std_dev()
+ {
+ return uncertainty_;
+ }
+ //! \return Estimate of number of degrees of freedom, usually = number of observations -1.
+ unsigned short int deg_free()
+ {
+ return degFree_;
+ }
+ //! \return Types of uncertain real, encoded as a bitmap.
+ unsigned short int types()
+ {
+ return unctypes_;
+ }
+
+ // Set functions.
+ //! \param value Central estimate of value of uncertain type.
+ void value (double value)
+ {
+ value_ = value;
+ } // void setValue (double value)
+
+ //! \param unc Estimate of uncertainty as standard deviation of value of uncertain type.
+ void std_dev (float unc)
+ {
+ uncertainty_ = unc;
+ if (boost::math::isfinite(static_cast<double>(unc)))
+ {
+ unctypes_ |= UNC_KNOWN; // set unc is known
+ if (unc > 0.f)
+ { // NOT exact.
+ unctypes_ &= ~(VALUE_EXACT | VALUE_RATIONAL | VALUE_INTEGER | UNC_NOPLUS | UNC_NOMINUS); // Clear.
+ }
+ else
+ { // Exact.
+ unctypes_ |= (VALUE_EXACT | UNC_NOPLUS | UNC_NOMINUS); // Set
+ }
+ }
+ else
+ { // unc not finite!
+ unctypes_ &= ~UNC_KNOWN; // Clear as unc not known.
+
+ }
+ } // void std_dev (float unc)
+
+ //! \param df Number of degrees of degrees of freedom, usually = number of observations -1.
+ void deg_free (short unsigned int df)
+ {
+ degFree_ = df;
+ unctypes_ |= DEG_FREE_KNOWN; // set.
+ } // void deg_free (short unsigned int df)
+
+ // TODO rename these.
+ //! \param type bits indicating type of uncertain real.
+ void setUncTypes (short unsigned int type)
+ {
+ unctypes_ = type;
+ } // Set all type flag(s).
+
+ void types (short unsigned int type)
+ {
+ unctypes_ &= ~type;
+ } // Clear type flag(s).
+
+ // Constructors.
+
+ /*! Default constructor from double value & float uncertainty.
+ Constructor from just a double value assumed exact,
+ so behaves like a normal double.
+ Normal conversion from double to unc.
+ (See also constructor from integer which alone sets integer flag.)
+ */
+ unc(
+ // Default values: exact zero? with no uncertainty, 1 observation.
+ const double val, // = 0., // also const int = 0.
+ // Ignore warning C4520: 'unc<1>' : multiple default constructors specified
+ // (because they will be the same default values).
+ const float unc = 0.0f, // Default value exact.
+ const short unsigned int df = 1, // df means observations = 1.
+ const short unsigned int uncTypeFlags = UNC_KNOWN | UNC_EXPLICIT| DEG_FREE_EXACT | DEG_FREE_KNOWN) // unc type flags.
+ : value_(val), uncertainty_(unc), degFree_(df), unctypes_(uncTypeFlags)
+ {
+#ifdef UNC_CD_TRACE
+ {
+ cerr << "\n ^^^ Construct from double value " << dec << val << ", unc " << unc
+ << ", df " << df << ", types" << showUncTypes(uncTypeFlags) << endl;
+ }
+#endif
+ // Check on value.
+ if (
+ (boost::math::isfinite(value_)) // Value is finite, so neither infinity nor NaN!
+ && (0.0f == uncertainty_) // Uncertainty parameter is zero (default).
+ && (unctypes_ & UNC_KNOWN) // In case UNC_KNOWN flag is cleared by value of uncTypeFlags.
+ // default unc = 0.f to suit construction from a double uncun(2.)
+ // but NOT exact if more than one value or unc unknown signaled.
+ )
+ { // Value is Exact double.
+ //unctypes_ |= VALUE_EXACT;
+ if (value_ == 0.)
+ { // Speed simplest & common zero integer case.
+ unctypes_ |= (VALUE_ZERO | VALUE_INTEGER | VALUE_RATIONAL);
+ }
+ else
+ { // Not exact.
+ // Only if construct from int, then set flag as VALUE_INTEGER.
+ // Else leave unctypes_ as set by constructor, perhaps setting VALUE_INTEGER and/or VALUE_RATIONAL.
+ }
+ }
+ else
+ { // Value is Nan or Infinity.
+ // Use a flag here? VALUE_NONFINITE ??
+ }
+
+ // Check if unc (std dev) is NaN or infinity.
+ if (!boost::math::isfinite(unc))
+ { // unc (std dev) is NaN or infinity.
+ unctypes_ &= ~(UNC_KNOWN | UNC_EXPLICIT| DEG_FREE_EXACT | DEG_FREE_KNOWN) ; // Clear all UNC_KNOWN flag.
+ }
+ else
+ { // unc (stdDev) is finite.
+ if (unc == 0.0f)
+ {
+ unctypes_ |= VALUE_EXACT; // Set.
+ }
+ else if (unc < 0.0f)
+ { // Negative uncertainty.
+ if (!is_correlated) // NOT correlated case.
+ { // Error! Throw? Or set uncertainty to zero?
+ unctypes_ &= ~UNC_KNOWN;
+ std::cerr << "Negative uncertainty " << unc << ", Value " << val << "!" << std::endl;
+ // uncertainty_ = 0.0f; or NaN?
+ }
+ else // is correlated.
+ { // But CAN have negative uncertainty for correlated case.
+ std::cout << "Negative uncertainty for correlated case is not yet implemented." << std::endl;
+ }
+ if (unctypes_ && (UNC_NOPLUS | UNC_NOMINUS | UNC_QUAN_DECIMAL | UNC_QUAN_BINARY | UNC_UNIFORM | UNC_TRIANGULAR | UNC_EXPLICIT) != 0)
+ { // Any uncertainty specifier bit means uncertainty is known.
+ unctypes_ |= UNC_KNOWN; // But do NOT specify as explicit.
+ }
+ }
+ if ((uncTypeFlags & VALUE_EXACT) == VALUE_EXACT)
+ { // Check for a valid uncertainty, but type parameter is exact.
+ if (uncertainty_ != 0.f)
+ {
+ std::cout << "Value " << value_ << " flagged as exact, but uncertainty " << uncertainty_ << " is not zero!" << std::endl;
+ uncertainty_ = 0.f; // Override any unc provided.
+ // This indicates a programmer logic error!
+ }
+ if (degFree_ != 0)
+ {
+ std::cout << "Value " << value_ << " flagged as exact, but degfree " << degFree_ << " is not zero!" << std::endl;
+ degFree_ = 0; // Override any degfree provided.
+ // This indicates a programmer logic error!
+ }
+ } //
+ } // unc finite check
+#ifdef UNC_CD_TRACE
+ {
+ cerr << " Constructed from double: value_ "
+ << value_ << ", m_unc " << uncertainty_ << ", m_df "
+ << dec << degFree_ << ", " << showUncTypes(unctypes_)
+ << endl;
+ }
+#endif
+ }; // unc constructor from double.
+
+ // A specific constructor from int (as well as double) leads to this warning.
+ // #pragma warning (disable : 4520) //!< 'unc<1>' : multiple default constructors specified.
+
+ //!< Constructor from integer value.
+ unc(
+ const int ivalue = 0, // Default value integer zero.
+ const float unc = 0.0f, // Exact.
+ const short unsigned int df = 1, // means observations = 1.
+ const short unsigned int uncTypeFlags = // unc type flags.
+ DEG_FREE_DEF | // See also constructor from double.
+ VALUE_INTEGER | VALUE_RATIONAL | // If integer, must be rational too.
+ UNC_NOPLUS | UNC_NOMINUS | UNC_KNOWN) // Both so Exact.
+ : value_(ivalue),
+ uncertainty_(unc), // Not quite sure if sensible to allow uncertainty?
+ degFree_(df) // OK to allow degrees of freedom (many integers).
+ , unctypes_(uncTypeFlags) // Don't allow this as a parameter to avoid conflicting settings?
+ {
+ if (value_ == 0.)
+ { // Zero integer case.
+ unctypes_ |= VALUE_ZERO;
+ }
+#ifdef UNC_CD_TRACE
+ {
+ cerr << "\n ^^^ Constructed from int: value "
+ << ivalue << ", value_ " << value_ << ", unc " << uncertainty_ << ", df "
+ << dec << degFree_ << ", " << showUncTypes(unctypes_)
+ << endl;
+ }
+#endif
+ } // Constructor from integer value.
+
+ unc(const unc& ud) //!< Constructor copy from another unc.
+ : value_(ud.value_), uncertainty_(ud.uncertainty_),
+ degFree_(ud.degFree_), unctypes_(ud.unctypes_)
+ { // Just copy all 4 member data.
+#ifdef UNC_CD_TRACE
+ {
+ cerr << "\n ^^^ Constructed from unc: value_ "
+ << value_ << ", m_unc " << uncertainty_ << ", m_df "
+ << dec << degFree_ << ", " << showUncTypes(unctypes_)
+ << endl;
+ }
+#endif
+ } // Constructor from unc.
+
+ //! Destructors. Two versions defined in unc.ipp to provide diagnostic output.
+ // ~unc(); // Declaration, .
+
+ // Unary operators + and -.
+ // No change to degrees of freedom or unc_types.
+ // (unc<is_correlated> operator +(void) const; produces:
+ // C2535 member function already defined or declared).
+
+ unc<is_correlated> operator+ (void) const // Unary +
+ { // 'slope' d f(x)/dx = +1
+ return *this; // All members remain unchanged.
+ }
+
+ unc<is_correlated> operator- (void) const // Unary -
+ { // 'slope' d f(x)/dx = -1
+ if (is_correlated) // Negate BOTH value & uncertainty.
+ return unc<is_correlated>(-value_, -uncertainty_);
+ else // Don't negate sign of uncertainty if not correlated, only value.
+ return unc<is_correlated>(-value_, uncertainty_);
+ }
+
+ // Binary add & subtract operators.
+ // (Implemented using += and -= operators).
+ friend unc<is_correlated> operator+ (unc<is_correlated> a,
+ const unc<is_correlated>& b)
+ {
+ return a += b;
+ }
+
+ friend unc<is_correlated> operator+ (unc<is_correlated> a,
+ const double& b)
+ {
+ return a += b;
+ }
+
+ friend unc<is_correlated> operator+ (const double& b,
+ unc<is_correlated> a)
+ {
+ return a += b;
+ }
+
+ friend unc<is_correlated> operator- (unc<is_correlated> a,
+ const unc<is_correlated>& b)
+ {
+ return a -= b;
+ }
+
+ friend unc<is_correlated> operator- (unc<is_correlated> a,
+ const double& b)
+ {
+ return a -= b;
+ }
+
+ friend unc<is_correlated> operator- (const double& b,
+ unc<is_correlated> a)
+ {
+ a -= b; return -a;
+ }
+
+ // Pre-Increment & pre-decrement operators.
+ // (Implemented using += and -= operators).
+ // Since using integer unity, uncertainty & rationality is unchanged.
+ unc<is_correlated> operator++ (void)
+ { return (*this += 1.); }
+
+ unc<is_correlated> operator-- (void)
+ { return (*this -= 1.); }
+
+ unc<is_correlated> operator++ (int)
+ {
+ unc<is_correlated> retval(*this);
+ *this += 1.;
+ return retval;
+ }
+
+ unc<is_correlated> operator-- (int)
+ {
+ unc<is_correlated> retval(*this);
+ *this -= 1.;
+ return retval;
+ }
+
+ // Multiply & divide operators (using *= etc assignment operators).
+ friend unc<is_correlated> operator* (unc<is_correlated> a,
+ const unc<is_correlated>& b)
+ {
+ return a *= b;
+ }
+
+ // Uncertainty unchanged by all operations using a double.
+ friend unc<is_correlated> operator* (unc<is_correlated> a,
+ const double& b)
+ {
+ return a *= b;
+ }
+
+ friend unc<is_correlated> operator* (const double& b,
+ unc<is_correlated> a)
+ {
+ return a *= b;
+ }
+
+ friend unc<is_correlated> operator/ (unc<is_correlated> a,
+ const unc<is_correlated>& b)
+ {
+ return a /= b;
+ }
+
+ friend unc<is_correlated> operator/ (unc<is_correlated> a,
+ const double& b)
+ {
+ return a /= b;
+ }
+
+ friend unc<is_correlated> operator/ (const double& b,
+ unc<is_correlated> a)
+ {
+ unc<is_correlated> retval;
+ retval.uncertainty_ = -b * a.uncertainty_ / (a.value_ * a.value_);
+ retval.value_ = b / a.value_;
+ retval.unctypes_ &= ~(VALUE_RATIONAL | VALUE_INTEGER);
+ // Must assume double b is irrational and NOT integer.
+ // (Use a unc instead to divide by a rational).
+ return retval;
+ }
+
+ // Assignment operators +=, -=, *=, /=
+ // (Used by plain +, -, * and / operators).
+ // If VALUE_NEGATIVE_ONLY might check that value is still < 0?
+ // If VALUE_POSITIVE_ONLY might check that value is still > 0?
+
+ unc<is_correlated>& operator+= (const unc<is_correlated>& ud)
+ { // unc += unc
+ if (is_correlated)
+ {
+ uncertainty_ += ud.uncertainty_; // If correlated then just add.
+ degFree_ = // Choose degrees of freedom of the max uncertainty.
+ (uncertainty_ > ud.uncertainty_) ? degFree_ : ud.degFree_;
+ // Exact method of estimating not known, but is a reasonable approximation
+ // provided really is highly correlated because less well predicted
+ // variance can be predicted well with the better predicted.
+ // See email from Steve LR Ellison, Lab of Government Chem, 24 Apr 98.
+ }
+ else
+ { // Uncorrelated so Propagation of Uncertainty rules apply.
+ // Barry N Taylor & Chris E Kuyatt, NIST Technical note 1297 (1994),
+ // Guidelines for Evaluating & Expressing the Uncertainty of Measurements.
+ // http:// physics.nist.gov/pubs/guidelines.appa.html
+ // 'Combined uncertainty' Appendix A formula A-3 = "sqrt(sum of squares)"
+ double comb_uncertainty = sqrtSumSqrs(uncertainty_, ud.uncertainty_);
+ degFree_ = // Welch-Satterthwaite - see NIST Appendix A3 & Appendix B-1.
+ // Effective degrees of freedom <= - see Eq B-2, so use floor function.
+ static_cast<unsigned short>( // Degrees of freedom must be integer by definition.
+ floor(
+ pow4<double>(comb_uncertainty)/
+ (pow4<double>(uncertainty_)/degFree_ + pow4<double>(ud.uncertainty_) / ud.degFree_))
+ );
+ uncertainty_ = float(comb_uncertainty);
+ }
+ unctypes_ &= ~DEG_FREE_EXACT; // This warns of an approximation - no longer exact.
+ unctypes_ &= ud.unctypes_; // Imposes rules for all additions of uncs.
+ // zero + zero = zero, restrictions on pos & neg only only retained if both,
+ // int + int is int, rational + rational is rational, int + rational is rational.
+ // either or both plusminus same if BOTH.
+ // Quantisation retains only if both.
+ value_ += ud.value_;
+ return *this;
+ }
+
+ operator value_type() const
+ {
+ return value_;
+ }
+
+ unc<is_correlated>& operator+= (const double& a)
+ { // unc += double
+ value_ += a;
+ // Uncertainty & Degrees of freedom both unchanged.
+ unctypes_ &= ~(VALUE_ZERO | VALUE_RATIONAL | VALUE_INTEGER | VALUE_NEGATIVE_ONLY | VALUE_POSITIVE_ONLY);
+ // All restrictions on value removed.
+ return *this;
+ }
+
+ unc<is_correlated>& operator-= (const unc<is_correlated>& ud)
+ { // unc -= double
+ if (is_correlated)
+ { // Correlated.
+ uncertainty_ -= ud.uncertainty_;
+ degFree_ = // Biggest - see +=
+ (uncertainty_ > ud.uncertainty_) ? degFree_ : ud.degFree_;
+ }
+ else
+ { // Uncorrelated.
+ float comb_uncertainty = sqrtSumSqrs(uncertainty_, ud.uncertainty_);
+ degFree_ = // Welch-Satterthwaite - see NIST Appendix A3 Appendix B-1.
+ (unsigned short) // Must be integer by definition.
+ floor( // Round or floor?
+ pow4(comb_uncertainty)/
+ (pow4(uncertainty_)/degFree_+pow4(ud.uncertainty_)/ud.degFree_)
+ );
+ uncertainty_ = float(comb_uncertainty);
+
+ }
+ unctypes_ &= ~DEG_FREE_EXACT; // No longer exact.
+ unctypes_ &= ud.unctypes_; // See += operator.
+ value_ -= ud.value_;
+ return *this;
+ }
+
+ unc<is_correlated>& operator-= (const double& a)
+ {
+ value_ -= a;
+ // Uncertainty & Degrees of freedom both unchanged.
+ unctypes_ &= ~(VALUE_ZERO | VALUE_RATIONAL | VALUE_INTEGER | VALUE_NEGATIVE_ONLY | VALUE_POSITIVE_ONLY);
+ // All indicators & restrictions on value removed.
+ return *this;
+ }
+
+ unc<is_correlated>& operator*= (const unc<is_correlated>& ud)
+ {
+ if (is_correlated)
+ {
+ uncertainty_ = float(uncertainty_ * ud.value_ + ud.uncertainty_ * value_);
+ degFree_ = // Choose degrees of freedom of the max uncertainty.
+ (uncertainty_ > ud.uncertainty_) ? degFree_ : ud.degFree_;
+ }
+ else // Uncorrelated.
+ {
+ double comb_uncertainty =
+ sqrtSumSqrs(uncertainty_ * ud.value_, ud.uncertainty_ * value_);
+ degFree_ = // Welch-Satterthwaite - see NIST Appendix A3 Appendix B-1.
+ static_cast<unsigned short> ( // must be integer by definition. Round or floor?
+ pow4(comb_uncertainty)/
+ (pow4(uncertainty_)/degFree_+pow4(ud.uncertainty_)/ud.degFree_) );
+ uncertainty_ = float(comb_uncertainty);
+ }
+ unctypes_ &= ~DEG_FREE_EXACT; // No longer exact.
+ unctypes_ &= ud.unctypes_; //
+ value_ *= ud.value_;
+ return *this;
+ }
+
+ unc<is_correlated>& operator*= (const double& a)
+ {
+ value_ *= a;
+ uncertainty_ *= (float)a; // Relative uncertainty unchanged.
+ // Multiplying by constant doesn't change degrees of freedom.
+ unctypes_ &= ~(VALUE_ZERO | VALUE_RATIONAL | VALUE_INTEGER | VALUE_NEGATIVE_ONLY | VALUE_POSITIVE_ONLY);
+ // All indicators & restrictions on value removed.
+ return *this;
+ }
+
+ unc<is_correlated>& operator/= (const unc<is_correlated>& ud)
+ { // unc /= unc
+ if (is_correlated)
+ { // Correlated.
+ uncertainty_ = uncertainty_ / ud.value_
+ - (ud.uncertainty_ * value_) / (ud.value_ * ud.value_);
+ degFree_ = // Choose degrees of freedom of the max uncertainty.
+ (uncertainty_ > ud.uncertainty_) ? degFree_ : ud.degFree_;
+ }
+ else
+ { // Uncorrelated.
+ float comb_uncertainty = sqrtSumSqrs(uncertainty_ / ud.value_,
+ (ud.uncertainty_ * value_) / (ud.value_ * ud.value_));
+ degFree_ = // Welch-Satterthwaite - see NIST Appendix A3 Appendix B-1.
+ (int) // must be integer by definition. Round or floor?
+ pow4(comb_uncertainty)/
+ (pow4(uncertainty_)/degFree_+pow4(ud.uncertainty_)/ud.degFree_);
+ uncertainty_ = float(comb_uncertainty);
+ }
+ unctypes_ &= ~DEG_FREE_EXACT; // No longer exact.
+ if ((unctypes_ & VALUE_INTEGER) && (ud.unctypes_ & VALUE_INTEGER) )
+ { // int / int
+ unctypes_ |= VALUE_RATIONAL; // becomes rational,
+ unctypes_ &= ~VALUE_INTEGER; // but no longer int.
+ }
+ else
+ {// rational / rational is still rational.
+ unctypes_ &= ud.unctypes_;
+ }
+ if (ud.unctypes_ & VALUE_ZERO != 0)
+ { // Avoid divide by zero, unless both zero!
+ value_ = (value_ != 0.) ? INFINITY : 0.;
+ }
+ else
+ { // Probably safe to divide. Check value == 0 as well??
+ value_ /= ud.value_;
+ }
+ { // Check if result is really an integer.
+ double i; // For integer part from modf.
+ double frac = modf(value_, &i); // modf only works for doubles,
+ // so can't test frac = 0.0f and this is better anyway.
+ if (frac <= std::numeric_limits<double>::epsilon()) // nearly == 0
+ // numeric_limits<double>::epsilon() = 2.22045e-016 aka DBL_EPSILON
+ {
+ unctypes_ |= (VALUE_INTEGER | VALUE_RATIONAL);
+ }
+ // TODO Any perhaps check if value is (near) zero?
+ }
+ return *this;
+ }
+
+ /*! operator /=
+ \note Dividing by constant doesn't change degrees of freedom or uncertainty.
+ All indicators & restrictions on value removed.
+ Must assume double is irrational and not integer,
+ NOT int/int becomes rational as operator /= .
+ */
+ unc<is_correlated>& operator/= (const double& a)
+ {
+ value_ /= a;
+ uncertainty_ /= float(a);
+ unctypes_ &= ~(VALUE_ZERO | VALUE_RATIONAL | VALUE_INTEGER | VALUE_NEGATIVE_ONLY | VALUE_POSITIVE_ONLY);
+ return *this;
+ }
+
+ inline bool operator== (const unc<is_correlated>& x) const
+ { // Predicate compare equal.
+ return value_ == x.value_; // Compare values EXACTLY.
+ // Might also close_to compare within uncertainty - see equalU
+ } // operator==
+
+ inline bool operator!= (const unc<is_correlated>& x) const
+ { // Predicate compare not equal.
+ return value_ != x.value_; // Compare values EXACTLY.
+ // Might also close_to compare within uncertainty - see equalU
+ } // operator!=
+
+ inline bool operator< (const unc<is_correlated>& x) const
+ { // Predicate compare operator< for use by std::sort etc.
+ // (Note const needed to use with less!)
+ return value_ < x.value_;
+ // Use normal signed values (no allowance for uncertainties).
+ // Might also compare within uncertainty - see lessU
+ } // operator<
+
+ // Insert and extract operator>> and operator<< for unc.
+ friend std::ostream& operator<< (std::ostream& os, const unc<is_correlated>& val)
+ {
+ boost::io::ios_precision_saver precision_saver(os);
+ boost::io::ios_flags_saver flags_saver(os);
+ // Changes are restored on destruction.
+ std::ostringstream oss; // Build up string.
+ oss.flags(os.flags()); // Copy flags to restore TODO not needed?).
+
+ double mean = val.mean();
+ float uncertainty = val.deviation();
+ unsigned short int degFree = val.degFree();
+ unsigned short int unc_flags = val.uncFlags();
+
+ // bools showing output requirements specified using unc additional ostream manipulators.
+ // Note that these bools are NOT initialised here,
+ // assuming compiler will warn if used before being initialised.
+ /*
+ \var bool isNoisyDigit
+ \brief Add an extra 'noisy' guard digit to reduce risk of information loss.
+ */
+ bool isNoisyDigit; //!<
+ bool isDegFree; //!< Append degrees of freedom.
+ bool isPlusMinus; //!< Uncertainty as +/- is required too (but ignore if value is exact or integer).
+ bool isUppercase; //!< Exponential format is, for example, 1E6 else 1e6.
+ bool isScientificFormat; //!< Taken to mean that exponential format wanted (always possible).
+ bool isShowPoint; //!< Means decimal point is always shown, for example 900. even if not needed.
+ bool isShowPos; //!< Show + sign always because ios flag was set with `<< showpo`s.
+ bool isFixed; //!< `os << fixed ...` ios decimal fixed d.dddd format (rather than scientific).
+ bool isWidthSet; //!< `os << setw(9)` has prescribed a width (rather than default width == 0).
+ bool isNoAdjust; //!< std = default but unc usage not defined yet, center?
+ bool isRightJustify; //!< right justify, prepend leading pad before. `<< right << ...`
+ bool isLeftJustify; //!< left justify, append trailing pad after. `<< left ...`
+ bool isInternalJustify; //!< Not defined yet, but use to center in field?
+ bool isCenter; //!< center if BOTH left and right specified.
+ bool isAlign; //!< Align on decimal point?
+ bool isConfidenceInterval; //!< Append confidence interval, for example, "<1.23, 1.56>"
+ bool isSetSigDigits; //!< Use set sigdigits instead of calculate from uncertainty.
+ bool isSetUncSigDigits; //!< Use set sigdigits instead of calculate from uncertainty.
+ // Get print format requirements from std::ios flags. ****************************
+ const int iosFlags = os.flags(); // Save fmtflags in case need to restore.
+
+ // Width, precision, flags & fillChar data from stream os. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ std::streamsize iosWidth = os.width(); //!< \warning Width must be read BEFORE any use of os
+ // which would reset width back to zero!
+ // & prevent any ios formatting during os << ...
+ // because unc_output does all its own formatting.
+ isWidthSet = (iosWidth > 0); // For example by os << setw(99)
+
+ isUppercase = static_cast<bool>(iosFlags & std::ios_base::uppercase); // E not e.
+ // TODO No mechanism to change uppercase at present in round_* functions.
+ isScientificFormat = static_cast<bool>(iosFlags & std::ios_base::scientific); // exp format wanted.
+ isFixed = static_cast<bool>(iosFlags & std::ios_base::fixed); // `<< fixed` Fixed format wanted.
+ // means d.dddd format wanted, if possible, rather than scientific or exp format.
+ isNoAdjust = !static_cast<bool>(iosFlags & std::ios_base::adjustfield); // `<< noadjust`
+ // no adjustfield flags are set (default, and == << right - a waste!).
+ isLeftJustify = static_cast<bool>(iosFlags & std::ios_base::left);
+ // left justify, append trailing padding with fillchar after.
+ isRightJustify = static_cast<bool>(iosFlags & std::ios_base::right);
+ // right justify, prepend leading padding with fillchar before.
+ isInternalJustify = static_cast<bool>(iosFlags & std::ios_base::internal);
+ // IO streams use to output fill char between sign and 1st digit.
+ // And meaning of more than one bit is specially defined for unc_output:
+ isCenter = isLeftJustify && isRightJustify;
+ // center if BOTH left and right ios specified.
+ // Done with ` << ` center rather than `<< left << right ... `.
+ isAlign = isInternalJustify && isLeftJustify && isRightJustify;
+ // Align decimal point with previous value?
+
+ isShowPoint = static_cast<bool>(iosFlags & std::ios_base::showpoint);
+ // Means decimal point is always shown, for example 900. even if not needed.
+ isShowPos = static_cast<bool>(iosFlags & std::ios_base::showpos);
+ // Show + sign always.
+
+ // Get print format requirements from unc flags.
+ long& uncFlags = os.iword(uncFlagsIndex); //
+ isPlusMinus = static_cast<bool>(uncFlags & plusMinus); // `<< plusminus`
+ isNoisyDigit = static_cast<bool>(uncFlags & noisyDigit); // `<< addNoisyDigit`
+ isConfidenceInterval = static_cast<bool>(uncFlags & limits); // `<< addlimits`
+ isDegFree = static_cast<bool>(uncFlags & degfree); // `<< addDegrees`
+ isSetSigDigits = static_cast<bool>(uncFlags & useSetSigDigits); // `<< setsigdigits`
+ isSetUncSigDigits = static_cast<bool>(uncFlags & useSetUncSigDigits); // `<< setsigdigits`
+
+ // Pick up distribution type from unc_flags.
+ // UNC_UNIFORM = 1 << 11, //!< Uncertainty has rectangular or uniform probability distribution.
+ // UNC_TRIANGULAR = 1 << 12, //!< Uncertainty has triangular probability distribution.
+ distribution_type distrib;
+ if (unc_flags & UNC_UNIFORM)
+ {
+ distrib = uniform;
+ }
+ else if (unc_flags & UNC_TRIANGULAR)
+ {
+ distrib = triangular;
+ }
+ else
+ {
+ distrib = gaussian;
+ }
+
+ long& roundloss = os.iword(roundingLossIndex);
+ double epsilon;
+ if (roundloss == 0)
+ { // Not been set,
+ epsilon = 0.05; // so use a default.
+ }
+ else
+ { // Has been set by a call like `out << confidence(0.01);`.
+ // rounding loss is stored as a long, so scaled by 1000,
+ // so that 0.05 or 1% is stored as 50.
+ epsilon = roundloss / 1000.; // `<< roundingloss(0.05)`
+ }
+ //! Confidence or alpha to compute confidence interval is similarly scaled.
+ //! Usage: `out << confidence(0.01) << ...` means 1 - confidence = 99% confidence.
+ //! double confidence = os.iword(conf) / 1000.; // `<< confidence(0.05)` aka 95%
+
+ //int round_m(double epsilon = 0.01, double unc = 0., unsigned int uncsigdigits = 2, distribution_type distrib = gaussian);
+ //void out_confidence_interval(std::pair<double, double> ci, int m, std::ostream& os = std::cout);
+ //void out_value_limits(double mean, double unc, std::pair<double, double> ci, int m, std::ostream& os = std::cout);
+
+ long& conf = os.iword(confidenceIndex);
+ double confidence;
+ if (conf <= 0)
+ { // Has not been set, so use default.
+ confidence = 0.05; // 95% confidence.
+ }
+ else
+ {
+ confidence = conf / 1.e6;
+ }
+ using boost::math::isfinite;
+ using boost::math::isnan;
+ using boost::math::isinf;
+
+ double intpart;
+ int max_digits10 = std::numeric_limits<double>::digits10 * 3010/10000;
+ // std::numeric_limits<double>::max_digits10))
+ if (boost::math::isfinite(mean))
+ {
+ if(isSetSigDigits)
+ { // Use explicit number of digits of precision.
+ long& sigDigits = os.iword(setSigDigitsIndex);
+ if ((sigDigits <= 0) || (sigDigits > max_digits10) )
+ { // show all potentially significant digits.
+ sigDigits = max_digits10;
+ }
+ oss << std::showpoint << std::setprecision(sigDigits) << mean;
+ }
+ else
+ { // Use uncertainty to control digits of precision.
+ if (mean == 0)
+ { // isValueZero = true;
+ if ((uncertainty == 0.F) )
+ { // Is exact integer zero, so not rounded, and no decimal point.
+ oss << "0";
+ }
+ else if (!isfinite(uncertainty))
+ { // Show all possibly significant digits for NaN and inf uncertainty.
+ oss << std::showpoint << std::setprecision(max_digits10) << mean;
+ }
+ else
+ { // Inexact zero.
+ int m = round_m(epsilon, uncertainty, 2, distrib);
+ if (isNoisyDigit)
+ { // Move rounding digit to one less significant position.
+ m--;
+ }
+ oss << round_ms(0., m);
+ }
+ } // mean == 0
+ else if(unc_flags & VALUE_INTEGER)
+ { // Value is flagged as an integer (used integer constructor or set flag).
+ double fracpart = std::modf(mean, &intpart);
+ oss << static_cast<long>(intpart); // Integer, so not rounded, and no decimal point,
+ // even if decimal point is specified by showpoint!
+ }
+ else if (unc_flags & VALUE_EXACT)
+ { // Value flagged as exact because sd == 0 (but NOT integer)
+ // (used double constructor or set flag) so show decimal point.
+ oss.unsetf(std::ios_base::showpoint); // Ignore showpoint so NO trailing zeros.
+ // Kinda want a decimal point here, but causes trouble with setw :-(
+ oss << std::setprecision(std::numeric_limits<double>::digits10) << mean;
+ double fracpart = std::modf(mean, &intpart);
+ if (fracpart == 0.)
+ { // Avoid two decimal points!
+ oss << '.';
+ }
+ }
+ else
+ { // Non-zero uncertainty, sd != 0.
+ if (isfinite(uncertainty))
+ { // Rounding is appropriate.
+ int m = round_m(epsilon, uncertainty, 2, distrib); // m is rounding digit index.
+ if (isNoisyDigit)
+ { // Move rounding digit to one less significant position.
+ m--;
+ }
+ if (isShowPos)
+ {
+ oss << '+';
+ }
+ if (mean <= 1e15)
+ { // Will fit into 1000000000000 (digits10 = 15).
+ oss << round_ms(mean, m);
+ }
+ else
+ { // Won't fit into 1000000000000 (digits10 = 15), so switch to exponent format.
+ oss << mean;
+ //round_e(mean, m); // This value of m is wrong TODO !!!
+ // Need to round but and not display exp as "e+009" TODO.
+ }
+ }
+ else
+ { // Uncertainty NAN or infinite, so show all possibly significant digits.
+ oss << std::showpoint << std::setprecision(max_digits10) << mean;
+ }
+ }
+ }
+ }
+ else
+ { // Mean is NaN or infinity.
+ if (isnan(mean))
+ {
+ oss << "NaN" ;
+ }
+ else if (isinf(mean))
+ {
+ oss << ((mean < 0) ? "-inf" : (isShowPos) ? "+inf" : "inf");
+ }
+ // Or could leave as native output, but MSVC format is ugly.
+ } // Mean
+
+ if (isPlusMinus && !(unc_flags & VALUE_INTEGER))
+ { // Want estimate of uncertainty.
+ if (isfinite(uncertainty))
+ {
+ if (uncertainty == 0.F)
+ { // Special case short version.
+ oss << " +/-0";
+ }
+ else
+ { // Non-zero uncertainty.
+ int uncSigDigits = os.iword(setUncSigDigitsIndex);
+ // Default is round to 2 sig digit - ISO rule.
+ if (uncSigDigits <= 0)
+ { // Automatically choose uncSigDigits based on degrees of freedom.
+ // Passed negative values through to allow
+ // an auto mode for w < 0 that chooses from degrees of freedom,
+ // From table H page 457 in Oliver & Goldsmith, confidence interval
+ // of standard deviation is about +/- 20% at 10 degrees of freedom,
+ // and only < +/- 10% above 100 observations (needing 2 stdDev sig Digits).
+ uncSigDigits = abs(uncSigDigits);
+ if (degFree > 100)
+ {
+ uncSigDigits = 3;
+ }
+ else if (degFree > 10)
+ {
+ uncSigDigits = 2;
+ }
+ else
+ { // degFree in common range 1 to 10.
+ // Choose between 1 and 2 digits based on 1st digit of uncertainty.
+ // Would be too big a step if most significant digit was 1 or 2.
+ std::ostringstream oss;
+ oss << std::scientific << std::setprecision (1) << uncertainty; // Assume sd positive.
+ if(oss.str()[0] == '1') // Check 1st digit before decimal point.
+ { // Would be too big a step if most significant digit was 1 or 2.
+ uncSigDigits = 2;
+ }
+ else if (oss.str()[0] == '2')
+ {
+ uncSigDigits = 2;
+ }
+ else
+ { // 1st digit > 2 so can use just 1 digit.
+ uncSigDigits = 1;
+ }
+ }
+ }
+
+ if (unc_flags & UNC_NOPLUS)
+ {
+ oss << " +0/-";
+ }
+ else if (unc_flags & UNC_NOMINUS)
+ {
+ oss << " -0/+";
+ }
+ else
+ { // normal plus and minus.
+ oss << " +/-";
+ }
+ //oss.unsetf(std::ios_base::scientific);
+ oss << std::noshowpos // Prefixed by " +/-" so never add +.
+ << std::fixed // << std::noscientific
+ << std::showpoint
+ << std::setprecision(uncSigDigits); // switches to e format :-(
+ //double unc_rounded = round_sig(uncertainty, uncSigDigits);
+ //oss << unc_rounded;
+ //std::string round_f<FPT>(FPT v, int sigdigits);
+ std::string s = round_f<float>(uncertainty, uncSigDigits);
+ oss << s;
+ }
+ }
+ else
+ { // Not finite uncertainty - NaN or inf.
+ if (isnan(uncertainty))
+ {
+ oss << " +/-?";
+ }
+ else if (isinf(uncertainty))
+ {
+ oss << " +/-inf";
+ }
+ }
+ } // uncertainty.
+
+ if(isConfidenceInterval)
+ { // Want to append confidence interval as <1.23, 2.34>.
+ if (boost::math::isfinite(mean) && boost::math::isfinite(uncertainty) && degFree >= 1)
+ { // Possible to compute confidence limits or interval in < > angle brackets.
+ std::streamsize osp = os.precision();
+ oss.precision(4); //
+ //std::pair<double, double> conf_interval(double mean, double unc, double df = 1., double alpha = 0.05, distribution_type distrib = gaussian);
+ double alpha = os.iword(confidenceIndex) / 1.e6; // Pick up and unscale alpha.
+ double epsilon = os.iword(roundingLossIndex) / 1.e3; // Pick up and rounding loss and unscale.
+ int uncSigDigits = os.iword(setUncSigDigitsIndex); // Pick up significant digits for uncertainty.
+ if(isNoisyDigit)
+ {
+ uncSigDigits++;
+ }
+ std::pair<double, double> ci = conf_interval(mean, uncertainty, degFree, alpha, distrib);
+ int m = round_m(epsilon, uncertainty, uncSigDigits, distrib);
+ using boost::lexical_cast;
+ oss << " <"
+ << lexical_cast<double>(round_ms(ci.first, m-1)) << ", "
+ << lexical_cast<double>(round_ms(ci.second, m-1))
+ << ">";
+ }
+ else
+ { // Not possible to compute confidence limits or interval.
+ oss << " < ? >" ;
+ }
+ } // Appended confidence interval.
+
+ if (isDegFree)
+ {
+ if (degFree == (std::numeric_limits<unsigned short int>::max)())
+ { // Is valid.
+ oss << " (?)";
+ }
+ else if (degFree == 0u)
+ {
+ oss << " (0?)";
+
+ }
+ else
+ {
+ oss << " (" << degFree << ")";
+ }
+
+ }
+ os << oss.str();
+ return os;
+ } // friend ostream& operator<< (ostream& os, const unc<is_correlated>& val)
+
+ friend std::istream& operator>> (std::istream& is, unc<is_correlated>& ud)
+ {
+ double mean;
+ double stdDev;
+ unsigned short int degreesOfFreedom;
+ unsigned short unctypes;
+ unc_input(mean, stdDev, degreesOfFreedom, unctypes, is);
+ // At present, uses a separate function for input (unlike output).
+ ud = unc<is_correlated>(mean, float(stdDev), degreesOfFreedom, unctypes);
+ // Inputs mean, SD & degrees of freedom & set unc types...
+ return is;
+ }
+
+ // Math functions for uncertain class.
+ friend unc<is_correlated> ceil(unc<is_correlated> arg)
+ {
+ arg.value_ = ceil(arg.value_);
+ arg.uncertainty_ = 0.; // Becomes exact & rational integer.
+ arg.unctypes_ |= UNC_NOPLUS | UNC_NOMINUS | VALUE_INTEGER | VALUE_RATIONAL; // Exact.
+ arg.degFree_ = (std::numeric_limits<unsigned short>::max)(); //= USHRT_MAX; = 0xFFFF
+ return arg;
+ }
+
+ friend unc<is_correlated> floor(unc<is_correlated> arg)
+ {
+ arg.value_ = floor(arg.value_);
+ arg.uncertainty_ = 0.; // Becomes exact & rational integer.
+ arg.unctypes_ |= UNC_NOPLUS | UNC_NOMINUS| VALUE_INTEGER | VALUE_RATIONAL; // Exact.
+ arg.degFree_ = (std::numeric_limits<unsigned short>::max)(); // USHRT_MAX; = 0xFFFF
+ return arg;
+ }
+
+ friend unc<is_correlated> fabs(unc<is_correlated> arg)
+ {
+ if (is_correlated && (arg.value_ < 0.))
+ arg.uncertainty_ *= -1.;
+ // Else uncorrelated so uncertainty unchanged?
+ arg.value_ = fabs(arg.value_);
+ unsigned short int plusMinus = arg.unctypes_ & (UNC_NOPLUS | UNC_NOMINUS);
+ if (( plusMinus != 0) // Neither, & not both
+ && (plusMinus != (UNC_NOPLUS | UNC_NOMINUS))
+ )
+ { // Just one asymetric uncertainty.
+ plusMinus = ~plusMinus; // Switch bits over.
+ arg.unctypes_ &= ~(UNC_NOPLUS | UNC_NOMINUS); // Clear both.
+ arg.unctypes_ |= plusMinus; // Set switched.
+ }
+ return arg;
+ }
+
+ friend unc<is_correlated> abs(unc<is_correlated> arg)
+ { // Copy of fabs version above.
+ if (is_correlated && (arg.value_ < 0.))
+ arg.uncertainty_ *= -1.;
+ // Else uncorrelated so uncertainty unchanged?
+ arg.value_ = fabs(arg.value_);
+ unsigned short int plusMinus = arg.unctypes_ & (UNC_NOPLUS | UNC_NOMINUS);
+ if (( plusMinus != 0) // Neither, & not both
+ && (plusMinus != (UNC_NOPLUS | UNC_NOMINUS))
+ )
+ { // Just one asymetric uncertainty.
+ plusMinus = ~plusMinus; // Switch bits over.
+ arg.unctypes_ &= ~(UNC_NOPLUS | UNC_NOMINUS); // Clear both.
+ arg.unctypes_ |= plusMinus; // Set switched.
+ }
+ return arg;
+ }
+
+
+ friend unc<is_correlated> ldexp(unc<is_correlated> arg,
+ int intarg) // Real from significand or mantissa arg & exponent intarg.
+ {
+ if (is_correlated)
+ arg.uncertainty_ *= ldexp(1., intarg);
+ else
+ arg.uncertainty_ *= fabs(ldexp(1., intarg));
+ arg.value_ = ldexp(arg.value_, intarg);
+ arg.unctypes_ &= ~(UNC_KNOWN | UNC_NOPLUS | UNC_NOMINUS); //
+ return arg; // arg * 2**intarg
+ }
+
+ friend unc<is_correlated> modf(unc<is_correlated> arg, double* intpart)
+ { // Split unc into updated integer and return fraction parts.
+ arg.value_ = modf(arg.value_, intpart); // value = fractional part.
+ // Must assume not rational fraction, so clear many bits.
+ arg.unctypes_ &= ~(VALUE_INTEGER | VALUE_RATIONAL | UNC_KNOWN | UNC_NOPLUS | UNC_NOMINUS | UNC_EXPLICIT | DEG_FREE_EXACT | DEG_FREE_KNOWN);
+ return arg; // Fractional part (mantissa or significant).
+ }
+
+ friend unc<is_correlated> frexp(unc<is_correlated> arg, int* intarg)
+ { // Raise arg to integer power.
+ arg.uncertainty_ *= float(pow(2., double(-*intarg)));
+ arg.value_ = frexp(arg.value_, intarg);
+ // If zero, integer or rational remains so.
+ return arg;
+ }
+
+ friend unc<is_correlated> fmod(const unc<is_correlated>& arg,
+ const unc<is_correlated>& divisor)
+ { // Floating-point remainder of x / divisor such that
+ // x = i * divisor + remainder,
+ // where i is an integer, remainder has the same sign as x, and
+ // absolute value of remainder is less than the absolute value of y.
+ unc<is_correlated> remainder(0.); // For remainder.
+ if (divisor.value_ == 0.)
+ { // ANSI 4.5.6.4 if divisor == zero return zero.
+ remainder.value_ = 0.;
+ remainder.uncertainty_ = std::numeric_limits<float>::infinity();
+ remainder.unctypes_ = 0U; //
+ }
+ else
+ {
+ double slope1 = 1. / divisor.value_; // If zero would cause divide by zero!
+ double slope2 = ((arg.value_ / divisor.value_) > 0.) ?
+ -floor(arg.value_ / divisor.value_) :
+ floor(-arg.value_ / divisor.value_);
+ if (is_correlated)
+ remainder.uncertainty_ = float(slope1 * arg.uncertainty_
+ + slope2 * divisor.uncertainty_);
+ else
+ remainder.uncertainty_ = float(sqrtSumSqrs(slope1 * arg.uncertainty_,
+ slope2 * divisor.uncertainty_));
+ remainder.value_ = fmod(arg.value_, divisor.value_);
+ remainder.unctypes_ = arg.unctypes_; // Better choice than divisor?
+ remainder.unctypes_ &= ~(VALUE_INTEGER | VALUE_RATIONAL);
+ // Remainder can't be integer & unlikely to be rational, so clear these.
+ }
+ return remainder; // remainder.
+ }
+
+ friend unc<is_correlated> sqrt(unc<is_correlated> arg)
+ { // sqrt(unc)
+ arg.value_ = sqrt(arg.value_);
+ if (is_correlated)
+ arg.uncertainty_ /= 2. * arg.value_;
+ else // Uncorrelated.
+ arg.uncertainty_ /= fabs(2. * arg.value_);
+ arg.unctypes_ &= ~(VALUE_INTEGER); // Must assume not integer.
+ // sqrt of rational reamins rational?
+ return arg;
+ }
+
+ friend unc<is_correlated> sin(unc<is_correlated> arg)
+ {
+ if (is_correlated)
+ arg.uncertainty_ *= cos(arg.value_);
+ else
+ arg.uncertainty_ *= fabs(cos(arg.value_));
+ arg.value_ = sin(arg.value_);
+ arg.unctypes_ &= ~(VALUE_INTEGER | VALUE_RATIONAL); // Must assume not.
+ return arg;
+ }
+
+ friend unc<is_correlated> cos(unc<is_correlated> arg)
+ {
+ if (is_correlated)
+ arg.uncertainty_ *= -sin(arg.value_);
+ else
+ arg.uncertainty_ *= fabs(sin(arg.value_));
+ arg.value_ = cos(arg.value_);
+ return arg;
+ }
+
+ friend unc<is_correlated> tan(unc<is_correlated> arg)
+ {
+ double costemp = cos(arg.value_);
+ arg.uncertainty_ /= costemp * costemp;
+ arg.value_ = tan(arg.value_);
+ return arg;
+ }
+
+ friend unc<is_correlated> asin(unc<is_correlated> arg)
+ {
+ arg.uncertainty_ /= sqrt(1. - arg.value_ * arg.value_);
+ arg.value_ = asin(arg.value_);
+ return arg;
+ }
+
+ friend unc<is_correlated> acos(unc<is_correlated> arg)
+ {
+ if (is_correlated)
+ arg.uncertainty_ /= -sqrt(1. - arg.value_ * arg.value_);
+ else
+ arg.uncertainty_ /= sqrt(1. - arg.value_ * arg.value_);
+ arg.value_ = acos(arg.value_);
+ return arg;
+ }
+
+ friend unc<is_correlated> atan(unc<is_correlated> arg)
+ {
+ arg.uncertainty_ /= 1. + arg.value_ * arg.value_;
+ arg.value_ = atan(arg.value_);
+ return arg;
+ }
+
+ friend unc<is_correlated> atan2(const unc<is_correlated>& arg1,
+ const unc<is_correlated>& arg2)
+ {
+ unc<is_correlated> retval;
+ double slope1 = 1., slope2 = 1.; // slope = d f(x)/dx or f'(x).
+ double sum2 = arg2.value_ * arg2.value_ + arg1.value_ * arg1.value_;
+ if (sum2 != 0.)
+ {
+ slope1 = arg2.value_ / sum2;
+ slope2 = -arg1.value_ / sum2;
+ }
+ if (is_correlated)
+ {
+ retval.uncertainty_ = slope1 * arg1.uncertainty_
+ + slope2 * arg2.uncertainty_;
+ }
+ else
+ { // Uncorrelated.
+ retval.uncertainty_ = sqrtSumSqrs(slope1 * arg1.uncertainty_,
+ slope2 * arg2.uncertainty_);
+ }
+ retval.value_ = atan2(arg1.value_, arg2.value_);
+ return retval;
+ }
+
+ friend unc<is_correlated> exp(unc<is_correlated> arg)
+ {
+ arg.value_ = exp(arg.value_);
+ if (is_correlated)
+ arg.uncertainty_ *= arg.value_;
+ else
+ arg.uncertainty_ *= fabs(arg.value_);
+ return arg;
+ }
+
+ friend unc<is_correlated> log(unc<is_correlated> arg)
+ {
+ if (is_correlated)
+ arg.uncertainty_ /= arg.value_;
+ else
+ arg.uncertainty_ /= fabs(arg.value_);
+ arg.value_ = log(arg.value_);
+ return arg;
+ }
+
+ friend unc<is_correlated> log10(unc<is_correlated> arg)
+ {
+ const double oneDivLog10 = 0.434294481903251827651128918917;
+ // Use Boost.Math?
+ if (is_correlated)
+ arg.uncertainty_ *= oneDivLog10 / arg.value_;
+ else
+ arg.uncertainty_ *= oneDivLog10 / fabs(arg.value_);
+ arg.value_ = log10(arg.value_);
+ return arg;
+ }
+
+ friend unc<is_correlated> sinh(unc<is_correlated> arg)
+ {
+ arg.uncertainty_ *= cosh(arg.value_);
+ arg.value_ = sinh(arg.value_);
+ return arg;
+ }
+
+ friend unc<is_correlated> cosh(unc<is_correlated> arg)
+ {
+ if (is_correlated)
+ arg.uncertainty_ *= sinh(arg.value_);
+ else
+ arg.uncertainty_ *= fabs(sinh(arg.value_));
+ arg.value_ = cosh(arg.value_);
+ return arg;
+ }
+
+ friend unc<is_correlated> tanh(unc<is_correlated> arg)
+ {
+ double coshtemp = cosh(arg.value_);
+ arg.uncertainty_ /= coshtemp * coshtemp;
+ arg.value_ = tanh(arg.value_);
+ return arg;
+ }
+
+ // Power
+ friend unc<is_correlated> pow(const unc<is_correlated>& arg1,
+ const unc<is_correlated>& arg2)
+ {
+ unc<is_correlated> retval;
+ retval.value_ = pow(arg1.value_, arg2.value_);
+ double slope1, slope2;
+
+ if (0 == arg1.value_)
+ {
+ slope2 = 0.; slope1 = 0.;
+ if (1. == arg2.value_)
+ slope1 = 1.;
+ }
+ else if (arg1.value_ < 0.)
+ { // pow(arg1, arg2) for arg1 < 0. is only defined for integer arg2.
+ slope1 = arg2.value_ * retval.value_ / arg1.value_;
+ slope2 = 0.;
+ }
+ else
+ {
+ slope1 = arg2.value_ * retval.value_ / arg1.value_;
+ slope2 = log(arg1.value_) * retval.value_;
+ }
+ if (is_correlated)
+ retval.uncertainty_ = slope1 * arg1.uncertainty_
+ + slope2 * arg2.uncertainty_;
+ else
+ retval.uncertainty_ = sqrtSumSqrs(slope1 * arg1.uncertainty_,
+ slope2 * arg2.uncertainty_);
+ return retval;
+ }
+
+ // Getter functions for read-only access to private data members:
+ // uncertainty_, value_, degrees of freedom and unc type.
+
+ // These are duplicates.
+
+ double mean(void) const {return value_;}
+
+ float deviation(void) const {return uncertainty_;} //
+
+ unsigned short int degFree(void) const {return degFree_;}
+
+ unsigned short int uncFlags(void) const {return unctypes_;} // 16 flags.
+
+ // For testing single argument functions like sin,cos, tan, log, exp.
+ friend unc<is_correlated> PropagateUncertaintiesBySlope(
+ double (* certain_func)(double), // For example sin
+ const unc<is_correlated>& arg) // (angle)
+ {
+ unc<is_correlated> retval;
+ double std_deviation_up_value, std_deviation_down_value;
+ retval.value_ = certain_func(arg.value_);
+ std_deviation_up_value = certain_func(arg.value_ + arg.uncertainty_);
+ std_deviation_down_value = certain_func(arg.value_ - arg.uncertainty_);
+ retval.uncertainty_ = (std_deviation_up_value - std_deviation_down_value) * 0.5;
+ if (!is_correlated) retval.uncertainty_ = fabs(retval.uncertainty_);
+ return retval;
+ }
+
+ // For testing double argument functions like atan2, pow.
+ friend unc<is_correlated> PropagateUncertaintiesBySlope
+ (
+ double (*certain_func)(double, double), // for example atan2 or pow
+ const unc<is_correlated>& arg1, // For example arg1 is number to be raised to
+ const unc<is_correlated>& arg2) // arg2 power.
+ {
+ unc<is_correlated> retval;
+
+ retval.value_ = certain_func(arg1.value_, arg2.value_);
+ if (is_correlated)
+ {
+ double up_val = certain_func(arg1.value_ + arg1.uncertainty_,
+ arg2.value_ + arg2.uncertainty_);
+ double down_val = certain_func(arg1.value_ - arg1.uncertainty_,
+ arg2.value_ - arg2.uncertainty_);
+ retval.uncertainty_ = 0.5 * (up_val - down_val);
+ }
+ else
+ {
+ double up_val1 = certain_func(arg1.value_ + arg1.uncertainty_,
+ arg2.value_);
+ double down_val1 = certain_func(arg1.value_ - arg1.uncertainty_,
+ arg2.value_);
+ double up_val2 = certain_func(arg1.value_,
+ arg2.value_ + arg2.uncertainty_);
+ double down_val2 = certain_func(arg1.value_,
+ arg2.value_ - arg2.uncertainty_);
+ retval.uncertainty_ = 0.5 * sqrtSumSqrs(up_val1 - down_val1,
+ up_val2 - down_val2);
+ }
+ return retval;
+ }
+
+ // Predicate Comparison functions.
+ // Should be global to allow leftmost argument to use implicit type conversion
+ // according to Scott Meyers, Effective C++ Item 19 p 68 - 71.
+ // But these are member functions and seem to work OK.
+ // Note MUST be static bool.
+
+ static bool lessU(const unc<is_correlated>& l, const unc<is_correlated>& r)
+ { // less using Comparison criterion including ONE standard deviation.
+ // (Comparison is possibly different for correlated case but not implemented yet).
+ double lhi = (l.value_ + l.uncertainty_); // Upper confidence limit of left.
+ double rlo = (r.value_ - r.uncertainty_); // Lower confidence limit of right.
+ double diff = (l.value_ + l.uncertainty_) - (r.value_ - r.uncertainty_);
+ // diff = lhi - rlo;
+ double tol = hypot(l.uncertainty_, r.uncertainty_); // 'Average' of two uncertainties.
+ bool isLess = lhi < (rlo + hypot(l.uncertainty_, r.uncertainty_)); // == less
+ if (true)
+ { // Output diagnostic info.
+ std::cerr << "lessU " << l.value_ << space
+ << lhi // (l.value_ + l.uncertainty_)
+ << space << ((isLess) ? " < " : " >= ")
+ // << (r.value_ - r.uncertainty_) == rlo
+ << space << rlo << space << rlo + hypot(l.uncertainty_, r.uncertainty_) // tol
+ << space << r.value_
+ << space << tol
+ << space << diff
+ << std::endl;
+ }
+ return isLess;
+ } // bool lessU(const unc<is_correlated>& l, const unc<is_correlated>& r)
+
+
+ static bool lessU2(const unc<is_correlated>& l, const unc<is_correlated>& r)
+ { // less using Comparison criterion including TWO standard deviations.
+ // (Comparison is possibly different for correlated case but not implemented yet).
+ double lhi = (l.value_ + l.uncertainty_ + l.uncertainty_ ); // Upper confidence limit of left.
+ double rlo = (r.value_ - r.uncertainty_ - r.uncertainty_); // Lower confidence limit of right.
+ // double diff = (l.value_ + l.uncertainty_) - (r.value_ - r.uncertainty_);
+ double diff = lhi - rlo;
+ double tol = hypot(l.uncertainty_ + l.uncertainty_, r.uncertainty_ + r.uncertainty_); // 'Average' of two uncertainties.
+ bool isLess = lhi < (rlo + hypot(l.uncertainty_+ l.uncertainty_, r.uncertainty_ + r.uncertainty_)); // == less
+ if (true)
+ { // Output diagnostic info.
+ std::cerr << "lessU " << l.value_ << space
+ << lhi // (l.value_ + l.uncertainty_ * 2)
+ << space << ((isLess) ? " < " : " >= ")
+ // << (r.value_ - r.uncertainty_ * 2) == rlo
+ << space << rlo << space << rlo + tol
+ << space << r.value_
+ << space << tol
+ << space << diff
+ << std::endl;
+ }
+ return isLess;
+ } // bool lessU2(const unc<is_correlated>& l, const unc<is_correlated>& r)
+
+ static bool moreU(const unc<is_correlated>& l, const unc<is_correlated>& r)
+ { // less using Comparison criterion within ONE standard deviation.
+ // Comparison is possibly different for correlated case but not implemented yet.
+ return l.value_ - l.uncertainty_ > r.value_ + r.uncertainty_; // Values with uncertainty.
+ } // bool moreU
+
+ static bool equalU(const unc<is_correlated>& l, const unc<is_correlated>& r)
+ { // less using Comparison criterion outside ONE standard deviation.
+ // Comparison is possibly different for correlated case but not implemented yet.
+ return !((l.value_ - l.uncertainty_ > r.value_ + r.uncertainty_) // >
+ || (l.value_ + l.uncertainty_ < r.value_ - r.uncertainty_)); // <
+ } // bool equalU
+
+ static bool equalU2(const unc<is_correlated>& l, const unc<is_correlated>& r)
+ { // less using Comparison criterion outside TWO standard deviations.
+ // Comparison is possibly different for correlated case but not implemented yet.
+ return !((l.value_ - l.uncertainty_ - l.uncertainty_> r.value_ + r.uncertainty_ + r.uncertainty_) // >
+ || (l.value_ + l.uncertainty_ + l.uncertainty_ < r.value_ - r.uncertainty_ - r.uncertainty_)); // <
+ } // bool equalU2
+
+
+}; // class unc<is_correlated>
+
+template <bool correlated>
+std::ostream& operator<< (std::ostream& os, const std::pair< unc<correlated>, unc<correlated> >& u)
+{ /*! Output a pair (X and Y) of uncertain values with (if defined) uncertainty and degrees of freedom.
+ \details For example: "1.23 +/- 0.01 (13), 3.45 +/- 0.06 (78)".
+ */
+ os << u.first << ", " << u.second;
+ return os;
+} // std::ostream& operator<< (ostream& os, const pair<unc<correlated>, unc<correlated> >& u)
+
+
+//template std::ostream& operator<< (std::ostream& os, const std::pair< unc<false>, unc<false> >& u);
+
+//! Two helper functions to provide values and uncertainties as pairs.
+//! \note Names value_of and plural valueS_of.
+
+/*! Allow value part of variables of class unc to be assigned to, and compared with double.
+\tparam T Built-in floating-point type, float, double or long double, or uncertain type unc.
+*/
+template <class T>
+double value_of(T);
+
+/*! Allow uncertainty (standard deviation) part of variables of class unc to be assigned to, and compared with float.
+\tparam T Built-in floating-point type, float, double or long double, or uncertain type unc.
+*/
+template <class T>
+double unc_of(T);
+
+// Pairs
+template <class T> //! \tparam T Built-in floating-point type, float, double, long double or unc or Meas.
+std::pair<double, double> values_of(std::pair<T, T>);
+
+template <class T1, class T2> //! \tparam T Built-in floating-point type, float, double, long double or unc or Meas.
+std::pair<double, double> values_of(std::pair<T1, T2>);
+
+template <class T> //! \tparam T Built-in floating-point type, float, double, long double or unc or Meas.
+std::pair<double, double> uncs_of(std::pair<T, T>);
+
+template <class T1, class T2> //! \tparam T Built-in floating-point type, float, double, long double or unc or Meas.
+std::pair<double, double> uncs_of(std::pair<T1, T2>);
+
+/* already defined.
+template <class T> //! \tparam T Builtin-floating point type or unc.
+std::pair<double, double> values_of(std::pair<T, T> up)
+{ //! \return values (parts) as a pair of doubles.
+ //! \note so can write
+ //! @c std::pair<const double, double> minmax = value_of(*result.first); // x min & max
+ //! whether T is double or unc, or ...
+
+ double vp1 = up.first.value();
+ double vp2 = up.second.value();
+ std::pair<double, double> minmax = std::make_pair(up.first.value(), up.second.value());
+ return minmax;
+}
+*/// Global Predicates compare LessThan or operator< now static member functions.
+// was bool lessUnc(const unc<false>& a, const unc<false>& b);
+
+namespace std
+{ // Fudge until MSVC becomes compliant.
+ template<typename Type> inline
+ Type abs(const Type& a)
+ { // Should be std::abs but is NOT in cstdlib - only provides global ::abs.
+ return Type((a < Type(0)) ? -a : a);
+ }
+} // namespace std
+
+// Predicate compare operators for use by sort etc.
+// Functors are _preferred_ to functions for STL algorithms.
+// Scott Meyers, ESTL, item 46, page 201..
+
+template<typename Type> // Predicate Functor modelled on STL less in functional.
+// Used below by min_element, etc.
+struct lessAbs : public std::binary_function<Type, Type, bool>
+{ // Usage: if (lessAbs<Meas>()(lm, hm)) ...
+ bool operator() (const Type& a, const Type& b) const
+ { // Note const to prevent modification - must be pure function.
+ // (Implies operator< for Type must also be const!)
+ return ((a < static_cast<Type>(0)) ? -a : a) < ((b < static_cast<Type>(0)) ? -b : b);
+ // Allows use with both POD like int and double,
+ // and other types for which both operator< and operator- are defined.
+ // Instead of:
+ // return fabs(a) < fabs(b); // fabs allows use with int and double,
+ // at price of conversion to double.
+ // But will fail for other types,
+ // so abs function written here using only operator< and operator-.
+ }
+
+}; // template <bool is_correlated> class unc
+
+// Specialization of autoprefix_norm for UDT boost::units::uncun
+// See /boost-trunk/libs/units/example/measurement.hpp
+// For autoprefix_norm see /boost-trunk/boost/units/io.hpp.
+// This specialization is required to get autoprefix to work with this class.
+
+using boost::units::autoprefix_norm_impl;
+
+autoprefix_norm_impl<unc<false>, true>::type
+autoprefix_norm(const unc<false> & arg)
+{
+ return autoprefix_norm_impl<double, true>::call(arg);
+}
+
+// Destructor Definitions need to go into unc.ipp, not unc.hpp
+// or will fail to link because two versions.
+
+#include <boost/quan/impl/unc.ipp> // Definitions.
+#include <boost/quan/impl/unc_input.ipp> // Definitions.
+// #include <boost/quan/impl/unc_output.ipp> // Definitions.
+
+#endif // UNC_HPP

Added: sandbox/SOC/2007/quan/boost/quan/unc_init.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/boost/quan/unc_init.hpp 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,57 @@
+// Use, modification and distribution are subject to 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)
+
+// Copyright Paul A. Bristow 1998, 2012.
+
+/*!
+ \file
+ \brief Initialisation of std::stream iword to store uncertainty information.
+ \details This sets the index values for data stored using the xalloc mechanism.
+ This is included from unc.hpp and accessed from unc.ipp for many functions.
+ Function setUncdefaults is used to set default values for these items for an iostream.
+*/
+
+#ifndef UNC_INIT
+#define UNC_INIT
+
+// unc_init.hpp called by unc.hpp
+
+#include <ios> // for ios_base.
+
+// This block of definitions MUST be positioned before main.
+// 14 indexes of long iwords allocated by calls of ios_base.xalloc();
+// 1st call of xalloc() returns 0 so ios_base.iword(0) used for magic id,
+// 2nd call of xalloc() returns 1 so ios_base.iword(1) used for uncFlags,
+// 3rd calls returns 2, so iosword(2) used for sigDigits ...
+// Order of assignment must ensure these match enum uncindex (if used).
+const long zeroIndex = std::ios_base::xalloc(); // 1st iword[0] to hold a 'magic' id.
+
+const long uncFlagsIndex = std::ios_base::xalloc(); // long& uncFlags = iword(1)
+const long oldUncFlagsIndex = std::ios_base::xalloc(); // long& olduncFlags = iword(2)
+const long sigDigitsIndex = std::ios_base::xalloc(); // sigDigits = iword(3)
+const long oldSigDigitsIndex = std::ios_base::xalloc(); // oldsigDigits = iword(4)
+const long setSigDigitsIndex = std::ios_base::xalloc(); // setsigDigits = iword(5)
+const long uncSigDigitsIndex = std::ios_base::xalloc(); // setUncSigDigitsIndex = iword(6)
+const long setUncSigDigitsIndex = std::ios_base::xalloc(); // setUncSigDigitsIndex = iword(7)
+const long oldUncSigDigitsIndex = std::ios_base::xalloc(); // oldUncSigDigitsIndex = iword(8)
+const long scaleIndex = std::ios_base::xalloc(); // scale = iword(9)
+const long oldScaleIndex = std::ios_base::xalloc(); // oldScale = iword(10)
+const long setScaleIndex = std::ios_base::xalloc(); // setScale = iword(11)
+const long uncWidthIndex = std::ios_base::xalloc(); // uncWidth = iword(12)
+const long oldUncWidthIndex = std::ios_base::xalloc(); // oldUncwidth = iword(13)
+const long oldUncSetWidthIndex = std::ios_base::xalloc(); // oldUncSetWidth = iword(14)
+const long usedIndex = std::ios_base::xalloc(); // used = iword(15)
+const long oldUncUsedIndex = std::ios_base::xalloc(); // oldUsed = iword(16)
+const long widthIndex = std::ios_base::xalloc(); // width = iword(17)
+const long oldWidthIndex = std::ios_base::xalloc(); // oldWidth = iword(18)
+const long roundingLossIndex = std::ios_base::xalloc(); // roundingLoss = iword(19)
+const long confidenceIndex = std::ios_base::xalloc(); // roundingLoss = iword(20)
+
+const long topIndex = std::ios_base::xalloc(); // long& topIndex = iword(21] == iword(0] check!
+
+extern const long indexID; // 'Magic' value defined in unc_init.hpp.
+bool isIndexed = true; // Above indexes have been initialised.
+
+#endif

Added: sandbox/SOC/2007/quan/boost/quan/uncbools.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/boost/quan/uncbools.hpp 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,33 @@
+ long& uncWidth = os.iword(uncWidthIndex); //
+ long& oldUncWidth = os.iword(oldUncWidthIndex); //
+ long& uncFlags = os.iword(uncFlagsIndex);
+ long& Width = os.iword(widthIndex);
+ long& oldWidth = os.iword(oldWidthIndex);
+ long& setSigDigits = os.iword(setSigDigitsIndex);
+ long& setStdDevSigDigits = os.iword(stdDevSigDigitsIndex);
+
+ // bools showing output requirements.
+ bool isNoisyDigit; // Extra 'noisy' guard digit to reduce risk of information loss.
+ bool isPlusMinus;// Uncertainty as +/- is required too (but ignore if exact or integer).
+ bool isSetScale; // Defined to mean scale to specified power of 10.
+ bool isAutoScale; // is to scale automatically to SI multple of 1000.
+ bool isUppercase; // Exponential format is, for example, 1E6 else 1e6.
+ bool isExpFormat; // Taken to mean that exponential format wanted (always possible).
+ bool isShowPoint; // Means decimal point is always shown, for example 900. even if not needed.
+ bool isShowPos; // Show + sign always.
+ bool isFixed; // Taken to mean that d.dddd format wanted, if possible.
+ bool isLeftJustify; // left justify, trailing pad after.
+ bool isRightJustify; // right justify, leading pad before.
+ bool isInternalJustify; // Not defined yet, but use to center in field?
+ // bools showing state of arguments value, stdDev, df.
+ bool isExactValue; // value is exact (integer, rational, zero stdDev or noplus & nominus).
+ bool isIntegerValue; // value is an integer, or stdDev = 0.f.
+ bool isUncKnown; // StdDev or uncertainty is valid.
+ bool isValueNaN; // value is NaN
+ bool isStdDevNaN; // StdDev is NaN
+ bool isValueInfinite; // value is infinity.
+ bool isNegativeValue = false; // Value is negative.
+ bool isZeroValue; // Value is zero.
+ bool isCenter; // Both left and right, so center (on decimal point if possible).
+ bool isFirmFormat; // os << setw(9) has prescribed a width.
+

Added: sandbox/SOC/2007/quan/boost/quan/uncdata.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/boost/quan/uncdata.hpp 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,79 @@
+/*!
+\file
+\brief Summary of uncFlagsIndex, unc_types and uncertainflags.
+
+*/
+
+extern const long uncFlagsIndex; // uncertain flags for unc_output
+// by << flex << plusminus ...
+extern const long oldUncFlagsIndex; // Saved previous uncertain flags.
+extern const long sigDigitsIndex; // sigDigits auto calc in unc_output.
+extern const long setSigDigitsIndex; // sigfigs to use if setSigDigits flag set.
+extern const long oldSigDigitsIndex; // Previous value of sigDigitsIndex
+// by << setsigdigits ... Value assigned by << setSigDigits(4) ...
+extern const long stdDevSigDigitsIndex; // Sigfigs to use for +|- output,
+// if setuncsigfigs flag bit set by << setuncsigfigs...// Value set by << setUncSigDigits(3) ...
+extern const long oldStdDevSigDigitsIndex; // Previous value of stdDevSigDigitsIndex.
+extern const long ScaleIndex; // Auto scale factor calculated by unc_output.
+extern const long setScaleIndex; // Use if set scaled flag set by << setscale...
+// Scale value set by << setScale(6) ...
+extern const long oldScaleIndex; // Previous value of ScaleIndex.
+extern const long uncWidthIndex; // width to use by unc_output if
+// firm format uncFlags set by << flexform ...// Value assigned by << setUncWidth(9) ...
+extern const long oldUncWidthIndex; // Previous value of uncWidthIndex.
+extern const long oldUncSetWidthIndex; // Not used yet.
+extern const long usedIndex; // output chars actually used.
+extern const long oldUncUsedIndex; // Previous value of usedIndex.
+extern const long widthIndex; // ios setwidth.
+extern const long oldWidthIndex; // Previous value of ios setwidth.
+
+enum unc_types
+{ // 16 type bits used by unc uncTypes. Bit set = 1 means a positive attribute.
+ VALUE_ZERO = 1 << 0, // Too near zero to allow relsd = sd /mean
+ // A few times std::numeric_limits<float>::min() is a suitable limit?
+ VALUE_INTEGER = 1 << 1, // Exact integer 2,3,4 ... may not be possible to store.
+ VALUE_RATIONAL = 1 << 2, // Integers & Fractions 1/2, 1/3, 2/3, 5/4 ...
+ // so don't need irrational - must be if not rational.
+ // Irrational like pi, e ... representated as accurately as possible.
+ VALUE_NEGATIVE_ONLY = 1 << 3, // Value can ONLY be < 0.. ? or <=0?
+ VALUE_POSITIVE_ONLY = 1 << 4, // Value can ONLY be >=0..
+ UNC_KNOWN = 0x20, // Uncertainty known (but if not value may known OK).
+ UNC_NOPLUS = 0x40, // Uncertainty can only be < value, + = zero.
+ UNC_NOMINUS = 0x80, // Uncertainty can only be > value - = zero.
+ // Integer, Rational or Exact by definition like 25.4 mm per inch,
+ // if unc = 0.0f or both UNC_NOPLUS & UNC_NOMINUS.
+ UNC_QUAN_DECIMAL = 0X100, // Quantised by least significant decimal digit.
+ UNC_QUAN_BINARY = 0X200, // Quantised by least significant binary digit.
+ UNC_EXPLICIT = 0x400, //If bit set = 1, uncertainty implicit from sig digits.
+ // or explicit if +/- or calculated (normal default case, bit = 0).
+ UNC_UNIFORM = 0x800, // Uncertainty has rectangular probability distribution.
+ UNC_TRIANGULAR = 0x1000, // Uncertainty has triangular probability distribution.
+ // If not rectangular or triangular, then normal or Gaussian.
+ // But is triangular & gaussian different in real life?
+ DEG_FREE_EXACT = 0x2000, // Known number of observations -1,
+ // so default zero means 1 observation.
+ // else estimated, for example, using Welch-Satterthwaite.
+ DEG_FREE_KNOWN = 0x4000, // Degrees of freedom defined.
+ SPARE = 0x8000 // This unc_type is spare.
+};
+
+enum uncertainflags
+{ // For control of printing.
+ none, // Default.
+ firm = 1, // bit 0: == 0 == false means flex, or firm == 1 == true.
+ setScaled = 2, // bit 1 Set scaled == 1 or not scaled == 0.
+ // by fixed factor SetScale and << scale ...
+ // power10 in range -max to +max.
+ autoScaled = 4, // bit 2: auto = 1 with << autoscale ...
+ plusMinus = 8, // bit 3 = 1 means add +/- uncertainty << plusminus ...
+ addSISymbol = 0x10, // bit 4 = 1, add suffix SI symbol G, M, k, m, u, n, p ...
+ // If one is applicable, else = 0 do nothing.
+ addSIPrefix = 0x20, // bit 5 = 1, add suffix SI prefix Giga, Mega, kilo ...
+ noisyDigit = 0x40, // Add extra 'noisy' decimal digit to value & sd
+ // This means is suitable for input to other calculations because the
+ // random extra 2 to 3 bits will approximate a continuous function.
+ // Quantisation to fewer digits would distort statistical calculations.
+ // Default is to use minimum decimal digits for clearer display.
+ // Extra digit also added when degrees of freedom > 10.
+ setSigFig = 0x80, // if bit 7 = 1 use set sigfig else calculate from sd.
+ setUncSigFig = 0x100 // if bit 8 = 1 use set Unc sigfig else calculate from degrees of freedom.
\ No newline at end of file

Added: sandbox/SOC/2007/quan/boost/quan/uncs.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/boost/quan/uncs.hpp 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,122 @@
+// unc reference info from unc.hpp
+
+enum unc_types
+{ // 16 type bits used by UReal uncTypes. Bit set = 1 means a positive attribute.
+ VALUE_ZERO = 1 << 0, // Too near zero to allow relsd = sd /mean
+ // A few times std::numeric_limits<float>::min() is a suitable limit?
+ VALUE_INTEGER = 1 << 1, // Exact integer 2,3,4 ... may not be possible to store.
+ VALUE_RATIONAL = 1 << 2, // Integers & Fractions 1/2, 1/3, 2/3, 5/4 ...
+ // so don't need irrational - must be if not rational.
+ // Irrational like pi, e ... representated as accurately as possible.
+ VALUE_NEGATIVE_ONLY = 1 << 3, // Value can ONLY be < 0.. ? or <=0?
+ VALUE_POSITIVE_ONLY = 1 << 4, // Value can ONLY be >=0..
+ UNC_KNOWN = 0x20, // Uncertainty known (but if not value may known OK).
+ UNC_NOPLUS = 0x40, // Uncertainty can only be < value, + = zero.
+ UNC_NOMINUS = 0x80, // Uncertainty can only be > value - = zero.
+ // Integer, Rational or Exact by definition like 25.4 mm per inch,
+ // if unc = 0.0f or both UNC_NOPLUS & UNC_NOMINUS.
+ UNC_QUAN_DECIMAL = 0X100, // Quantised by least significant decimal digit.
+ UNC_QUAN_BINARY = 0X200, // Quantised by least significant binary digit.
+ UNC_EXPLICIT = 0x400, //If bit set = 1, uncertainty implicit from sig digits.
+ // or explicit if +/- or calculated (normal default case, bit = 0).
+ UNC_RECTANGULAR = 0x800, // Uncertainty has rectangular probability distribution.
+ UNC_TRIANGULAR = 0x1000, // Uncertainty has triangular probability distribution.
+ // If not rectangular or triangular, then normal or Gaussian.
+ // But is triangular & gaussian different in real life?
+ DEG_FREE_EXACT = 0x2000, // Known number of observations -1,
+ // so default zero means 1 observation.
+ // else estimated, for example, using Welch-Satterthwaite.
+ DEG_FREE_KNOWN = 0x4000, // Degrees of freedom defined.
+ SPARE = 0x8000 // This unc_type is spare.
+};
+
+const unsigned short int VALUE_EXACT = (UNC_NOMINUS | UNC_NOPLUS); // Both set.
+const unsigned short int UNC_DEF = (UNC_KNOWN | UNC_NOMINUS | UNC_NOPLUS |
+ UNC_QUAN_DECIMAL | UNC_QUAN_BINARY |
+ UNC_EXPLICIT | UNC_RECTANGULAR | UNC_TRIANGULAR); //
+const unsigned short int DEG_FREE_DEF = (DEG_FREE_EXACT | DEG_FREE_KNOWN);
+
+enum uncertainflags
+{ // For control of printing.
+ none, // Default.
+ firm = 1, // bit 0: == 0 == false means flex, or firm == 1 == true.
+ setScaled = 2, // bit 1 Set scaled == 1 or not scaled == 0.
+ // by fixed factor SetScale and << scale ...
+ // power10 in range -max to +max.
+ autoScaled = 4, // bit 2: auto = 1 with << autoscale ...
+ plusMinus = 8, // bit 3 = 1 means add +/- uncertainty << plusminus ...
+ addSISymbol = 0x10, // bit 4 = 1, add suffix SI symbol G, M, k, m, u, n, p ...
+ // If one is applicable, else = 0 do nothing.
+ addSIPrefix = 0x20, // bit 5 = 1, add suffix SI prefix Giga, Mega, kilo ...
+ noisyDigit = 0x40, // Add extra 'noisy' decimal digit to value & sd
+ // This means is suitable for input to other calculations because the
+ // random extra 2 to 3 bits will approximate a continuous function.
+ // Quantisation to fewer digits would distort statistical calculations.
+ // Default is to use minimum decimal digits for clearer display.
+ // Extra digit also added when degrees of freedom > 10.
+ setSigFig = 0x80, // if bit 7 = 1 use set sigfig else calculate from sd.
+ setUncSigFig = 0x100 // if bit 8 = 1 use set Unc sigfig
+ // else calculate from degrees of freedom.
+};
+
+void uncertainPrint( // Declaration, defined below.
+ double, // Mean or most likely value.
+ float, // Standard deviation.
+ unsigned short int, // Degrees of freedom.
+ unsigned short int, // 16 Uncertain type flags.
+ ostream&); // Output stream.
+
+
+void uncertainRead(double& mean, // mean (central or most probable) value.
+ double& stdDeviation,
+ unsigned short int& degreesOfFreedom, // 1 observation.
+ unsigned short int& types,
+ istream& is);
+
+// Parameterless Manipulators declarations.
+// Similar to ios_base flags but for uncertain printing.
+// Use uppercase convention for these,
+// but all lowercase for manipulators like hex, oct ...
+// Usage: out << scale << noscale << autoscale << noautoscale
+// firmform << flexform << plusminus << noplusminus ....
+
+// All ios_base functions declared below are defined in unc.cpp
+// Note that all of these are entirely lower case, like ios manipulators.
+ios_base& scale(ios_base&); // To use value set with setUncScale(int)
+ios_base& noscale(ios_base&); // or not scaled.
+ios_base& autoscale(ios_base&); // Scale to suitable symbol like M, k, m...
+ios_base& noautoscale(ios_base&); // or not.
+ios_base& firmform(ios_base&); // Firm fixed layout using setUncWidth.
+ios_base& flexform(ios_base&); // Flexible free format.
+ios_base& plusminus(ios_base&); // Add +/- uncertainty.
+ios_base& noplusminus(ios_base&); // No +/- uncertainty
+ios_base& addSIprefix(ios_base&); // Add SI prefix like kilo, micro ..
+ios_base& noSIprefix(ios_base&); // (Takes precedence over SI symbol if both set).
+ios_base& addSIsymbol(ios_base&); // Add SI symbol like M, k, m.
+ios_base& noSIsymbol(ios_base&); // No SI symbol like M, k, m
+ios_base& addNoisyDigit(ios_base&); // Add an extra 'noisy' digit for computer.
+ios_base& noNoisyDigit(ios_base&); // No noisy for human reading.
+ios_base& setsigdigits(ios_base&); // Use sigDigits set with << setSigDigits(4) ...
+ios_base& autouncsigfigs(ios_base&); // Calculate sigfigs from uncertainty.
+ios_base& setuncsigfigs(ios_base&); // Use sigDigits set with << setUncSigDigits(2) ...
+ios_base& autosigfigs(ios_base&); // Calculate sigfigs from uncertainty.
+
+// Functions to change uncertain flags on specified ios_base.
+// Usage: f = uFlags(out); f = uFlags(out, 0xFF);
+// f = setuFlags(out, 0xFF); f = resetuFlags(out, 0xFF);
+long uFlags(ios_base&); // Returns current uncertain flags.
+long uFlags(ios_base&, long); // Assigns all uncertain flags & returns previous.
+long setuFlags(ios_base&, long); // Set specific flags = 1
+long resetuFlags(ios_base&, long); // Reset/clear specific flags = 0
+
+// Forward declarations, defined in unc.cpp.
+class showUncFlags; // Output uncertain flags to ostream << showUncFlags ...
+class setAllUncFlags; // Assign value to set (aand/or clear) all unc flags.
+class setUncFlags; // Set specific unc flags bits.
+class setMaskedUncFlags; // Clear mask & then set unc flag bits.
+class resetUncFlags; //
+class resetMaskedUncFlags;
+class setUncWidth;
+class setUncScale; //
+class setSigDigits; // sigfigs to use for value if << setsigdigits
+class setUncSigDigits; // sigfigs to use for uncertainty if << setuncsigfigs
\ No newline at end of file

Added: sandbox/SOC/2007/quan/boost/quan/xiostream.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/boost/quan/xiostream.hpp 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,120 @@
+/*! \file xiostream.hpp
+ \brief Extra iostream manipulators
+ \details Definitions in xiostream.cpp
+
+ \author Paul A. Bristow
+ \date Sep 2009
+*/
+
+// Copyright Paul A. Bristow 2009
+// Use, modification and distribution are subject to 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 XIOSTREAM_HPP
+#define XIOSTREAM_HPP
+
+#include <iostream>
+#include <cfloat> // for <float.h> for _isnan, _finite, _fpclass & values.
+
+//using std::ios_base;
+//using std::ostream;
+//using std::istream;
+//using std::cout;
+//using std::cerr;
+//using std::endl;
+//using std::hex;
+//using std::dec;
+//using std::showbase;
+//using std::ios_base::fmtflags;
+//using std::ios_base::iostate;
+
+// Parameterless ostream manipulators space, newline, bell, etc.
+// Usage: out << bell << newline << tab << space << twobackslash ...
+// Now done more simply using:
+const char nl = '\n';
+const char tab = '\t';
+const char space = ' ';
+const char sp = ' ';
+const char bell = '\a';
+
+// Single int parameter manipulators.
+// Usage: out << spaces(12) << stars(8) << tabs(2) ...
+// spaces & stars done with simple way, NOT using template,
+// See S Teale p 181-3, said to be longer but faster.
+
+// TODO these should be declared here, and *defined* elsewhere?
+
+class spaces;
+class tabs;
+class stars;
+class chars;
+
+class spaces // Definition for this file.
+{ // Usage: out << spaces(12) ...
+ friend std::ostream& operator<< (std::ostream&, const spaces&);
+public:
+ spaces(int); // Constructor defined in xiostream.cpp.
+private:
+ int num;
+};
+
+class tabs // Definition for this file.
+{ // Usage: out << tabs(2) ...
+ friend std::ostream& operator<< (std::ostream&, const tabs&);
+public:
+ tabs(int); // Constructor defined in xiostream.cpp.
+private:
+ int num;
+};
+
+class stars // Definition for this file.
+{ // Usage: out << stars(10) ...
+ friend std::ostream& operator<< (std::ostream&, const stars&);
+public:
+ stars(int); // Constructor defined in xiostream.cpp.
+ // private:
+ int num;
+};
+
+// Manipulator class with int repeat count & character chars.
+class chars // Definition for this file.
+{ // Usage: out << chars(10, '_') ....
+ friend std::ostream& operator<< (std::ostream&, const chars&);
+public:
+ chars(int, char); // Constructor defined in xiostream.cpp.
+private:
+ int num;
+ char character;
+};
+
+class setupperbase
+{
+ friend std::ostream& operator<< (std::ostream&, const setupperbase&);
+ friend std::istream& operator>> (std::istream&, const setupperbase&);
+public:
+ setupperbase(int); // Constructor defined in xiostream.cpp.
+private:
+ int base;
+}; // class setupperbase
+
+void outIosFlags(long flags, std::ostream& os); // Show std iostream flags.
+void outFpClass(double value, std::ostream& os); // Show Floating-point type.
+
+void outIOstates(std::ios_base::iostate rdstate = std::cout.rdstate(), std::ostream& os = std::cerr, const char* term = ". ");
+// Outputs rdstate as words "good", "eof", "fail" and/or "bad".
+void outFmtFlags(std::ios_base::fmtflags fmtFlags = std::cout.flags(), std::ostream& os = std::cerr, const char* term = ". ");
+// Outputs ios_base fmtflags as words like "skipws", "scientific", "left"...
+// Note that the default values must be in the header file, NOT in the .cpp or .ipp file.
+
+// Ostream manipulators to show state of stream.
+std::ostream& showiostate(std::ostream& os); // Show IO stream state in words for this stream.
+// Usage: cout << showiostate ...
+
+std::ostream& showformat(std::ostream& os); // Show IO stream format flags in words for this stream.
+// Usage: cout << showformat ...
+
+#include <boost/quan/impl/xiostream.ipp>
+
+#endif // XIOSTREAM_HPP

Added: sandbox/SOC/2007/quan/libs/quan/doc/doxygen/draft.png
==============================================================================
Binary file. No diff available.

Added: sandbox/SOC/2007/quan/libs/quan/doc/doxygen/draft.svg
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/libs/quan/doc/doxygen/draft.svg 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="652"
+ height="694"
+ id="svg2">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <image
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAowAAAK2CAIAAABLsFpKAAAAA3NCSVQICAjb4U/gAAAgAElEQVR4 nO3d23bbuJaFYQA8y066R7//M/boim1RPKIv1g63to+SCIAg+H9XrlRCMXLMqQUsANpaqwAAiM80 TVmWbX0XWzJb3wAAAJ/ouq5t277vt76RLeVb3wAAAO91XXe5XKZpmudZKVWW5dZ3tA0qaQBAXJaE VkqN43i5XA5bT1NJAwAicp3QYhgG+eKA9bSmcQwAEImPCb3I87yqqqqqwt/VhqikAQBR+CahlVLj OCqltNaHqqcJaQDA9r5PaCHj3tba49TThDQAYGO3JLRSSmst9bRS6iA5TUgDALZ0Y0IvDpXThDQA YDP3JrQ4Tk4T0gCAbfR9/0BCi4PkNCENANjAYzX0tSPkNCENAAhtTQ19bdnnJNWcJqQBAEH1fd+2 7fqEVgfo92bvbgBAOA4TejEMwzAMS1qnhJAGAITjPKGVUnmeG2OSPHmakAYABPLPP/84T+gsy4qi aJpGa+32yjEgpAEAIZDQDyCkAQDekdCPIaQBAH6R0A8jpAEAHpHQaxDSAABfSOiVCGkAgBc+EtoY c5yEVuw4BgDwgRraCUIaAODY//3f/83z7PaaB0xoxXA3AMCtf/75h4R2hZAGADjDPLRbDHcDANxg Hto5KmkAgAMktA+ENABgLRLaE0IaALAKCe0PIQ0AeBydYl7ROAYAeBA1tG9U0gCAR5DQARDSAIC7 kdBhENIAgPswDx0Mc9IAgDv4q6Hruiah3yGkAQC3YpQ7MIa7AQA3oYYOj5AGAPzMa0IbQxh9jvcF APADf51iJPT3eGsAAN/xlNBlWZLQP+LdAQB8iYTeFm8QAOBzJPTmeI8AAJ8goWPA2wQAeI+EjgTv FADgP5DQ8eDNAgD8GwkdFd4vAMC//Pnzh4SOCnt3AwCUooaOEu8aAIAaOlK
8cQBwdH/+/BnH0e01 SWgneO8A4NBI6JgxJw0Ax8U8dOR4BwHgoEjo+PEmAsAR0Sm2C7yPAHA4PuahlVLTNBVFQUI7xFsJ AMfyzz//+EhopZTW+vX11dPFj4mQBoAD8TEPfc1a+/LyQk67QkgDwFH4mIf+iJx2iJAGgEPwNA/9 KXLaFUIaANIXMqEFOe2EttZufQ8AAI98z0N/Q2v969evPGfjrAdRSQNAysLMQ3+FenolKmkASNaG NfQ16umHUUkDQJq2raGvUU8/jJAGgASF7xT7Hjn9GEIaAFITW0ILcvoBzEkDQFIimYf+CvPTd6GS BoB0RJ7Qinr6ToQ0ACQink6x70lOD8Ow9Y3sACENACnwd7aVD9Zazsu6BSENALu3lxr6GvX0LWgc A4B989HLbYwpikIpNY6j1/jXWj8/P8tr4SNCGgB2zF9CN02jtb5cLn3f+y7Tf/36RU5/iuFuANgr rwltjNFa13VdlmWWZW5f5Z3X11fGvT9FSAPALvlOaPmVMDktfWTk9EeENADsj4+E1lq/S+jl18np rRDSALAznhK6LMuPCb3837qui6IgpwOjcQwA9iR8Qi+stQH6yOj3vkZIA8BuhJmH/kaYnFb0e//F cDcA7EPIeehvfn+AcW+lFPucCCppANiBzWvoa4x7B0MlDQCxiyqhFX1kARHSABC1GEa5P71C0zRF UTx8hVuQ0wx3A0C8NuzlvgV9ZL4R0gAQqdhGuT9FTnvFcDcAxGgXCa1C7UemjtrvTSUNANH5559/ nBemPhJ6QT3tCZU0AMRldwmtruppr31k6nj1NCENABH58+fP7hJaSE5XVcW4t0OENADEYi/z0F9h fto5QhoAorD3hBbktFuENABsL42EFuS0Q4Q0AGwspYQW5LQrhDQAbCm9hBbBcvrPnz8J5zTrpAFg M6km9IL10ytt/y0EgGOK8+QMtzh/eiUqaQDYQPI19DWpp7uum+fZ6wulV0/H9Y0EgCN4eXk5TkKr gPuc
pDc/Hd33EgDSNs+z8+0zY05oEaaPTGud2Lh3pN9OAEiVMSbP86ZptNauLhh5QgvWZT2AOWkA 2MA0TeM4tm27cpp2Lwm9oN/7Lvv4pgJAYrIsy/O8rus14bq7hFbU03eikgaAzaypp/eY0Avq6Rvt 71sLAMl4uJ6ObT30vainb0QlDQAbu7eelhq6rmvfCecb9fSPdvkRDABSIvX0jWXxMsq994RW7O99 A0IaALa35PT367J2PQ/9qSWnvf6N9rt+muFuAIjFNE3DMFwul0/HvdNL6Gtt2/oe97bW/v79e1/j 3oQ0AETkq/npZOahvxEgp9Xe5qcT/DgGABtauTnJp/3eR0hopVTTNPR7v0MlDQDOvL6+yiTryqS5 rqcPktAL6ulrhDQAuCGnT7rKVMnpruuyLDtOQgtyekFIA4AD1+dDu8rpeZ6nacqyLMlOse+R04KQ BoC1rhNauMppa62rw7J2h5xWhDQArPQxocXR5pJ9IKcPN4QCAA59ldBKqXmeZdGz74xJGP3ehDQA POibhBbk9HqS075n5aPNaUIaAB7xY0ILcnq9pmmqqjrm/t7MSQPA3W5M6AXz0+uFmZ9+fn4uy9Lr S9yFShoA7vPy8nJXQivqaRfCzE+/vr72fe/1Je5CSAPAHR6evCSn1wszPx1VThPSAHCrle1F5PR6 Mj8doI8skpxmThoAbuKqAVhrXZYl89NrHGd+mkoaAH7msPXXWks9vdJx5qcJaQD4wQOdYt+b53kc x3EcGct82EFympAGgO/42OZCa53neZ7nh92X24kj9JExJw0AX/KR0KyZdqtt267r5nn2+ipbzU9T SQPA50joXQizH9lW/d6ENAB8goTekQDz01rrTXKa4W4AeI+E3qMk12VRSQPAfyChdyrJfm8qaQD4 t3tPzrgFCR1SYvU0lTQA/Ivz9dCKhA4usXVZVNIAoBSj3GlJpp6mkgYAXzuWkNBbSaaeppIGcHTU 0KlKoJ6mkgZwaJ4SOs9zEnpzCf
R7U0kDOC5q6CPYdT1NJQ3goEjog9j1/DSVNIAjYj300ey0nqaS BnA4rIc+oJ3OTxPSAI6FUe7D2mNOE9IADoSEPrjd5TQhDeAoSGioveU0IQ3gEFgPjUXTNFVV7SKn CWkA6fO062ee503TkNB7VNf1LnKakAaQOH+j3CT0rtV1Hf+4NyENIGX+RrlJ6ATEPz9NSANIFqPc +FHk89OENIA0+Tt9koROTMzz02wLCiBBnnb9pIZO2OVy6boutn1DqaQBpMbTrp8kdNrirKcJaQBJ oVMMD4swpwlpAOmgUwwrxZbThDSARLAeGk5EtX6axjEAKWCUG25F0kdGJQ1g90hoOBfJuDchDWDf SGh4EkNOE9IAdoyEhlebz08T0gD2ioRGANvu703jGIBdYk8xhLRVHxmVNID98bGnGOuh8Y2t5qcJ aQA7w8kZ2MQmOU1IA9gTEhobCp/ThDSA3WBPMWwuWE7LP3VCGsA+sC83IhEgp/M8t9Zaa3N/rwEA rrDaClGp61op5anfuyiKqqqKotBaU0kDiB0JjQh5qqevE1ox3A0gciQ0ouV8P7J3Ca3YzARAzEho xM/VPicfE1pRSQOIFgmNXXAy7v1pQitCGkCcSGjsyMqc/iqhFSENIEIk9BrTNDl/9/Cjh3P6m4RW SrEEC0BcSOg1xnEchmEYhnEcm6bZ+naO5YF1Wd8ntCKkAUSFhF5DErptW6XUPM9KKXI6sLty+seE Vgx3A4gHCb3GdUIrpeZ57rpu+U8Ec+O49y0JraikAUSChF7jXUILyWlFPR2c1NN93391oOqNCa0I aQAxIKHX+DShxTzPcp4SOR2Y5LRS6mNO357QipAGsDkSeo1vElpM00ROb+LTnL4roRUhDWBb/hK6 rmsSWkzTxLj3Jt7l9L0JrQhpABuihl7jxoQWjHtvZclprfW9Ca3YuxvAVkjoNe5K6EWWZWVZktPh 9X0vh5ffldCKkAawCa+j3Hme+BjhYwktyOmtWGvvTWjFOmkA
4ZHQa0hCn8/nx/649JGxfjq8BxJa UUkDCMxHQmuti6I4TkKvj1hjTFVV1NPxo5IGEA4JvcY4jn3fP1xDX5M+Murp+BHSAAIhodeQGvpy uTw2avoR4967QEgDCIGEXsPVKPc70zRN0/TV1pWIASENwDtPCX2oTjEfJW+e50VRJP8G7hohDcAv fzV00zTJB8zKXu5v5HleVVVVVc6vDIfo7gbgEaPca3itoUnoXaCSBuALo9xrUENDEdIAPHl9fXWe 0Eop2fXzOAntqpdbWGtJ6H0hpAG49/r6Ksc5ODfPszGJP7iWUW4SGsxJA3DMX0KLLMt+/fqValR7 moe21so5iST0vqT5rxzAVuZ51lp7TdBpml5eXuZ59vcSW/HXKUZC7xQhDcAlY0xd10VRkNP3opcb HxHSABzLsoycvhcJjU8R0gDcI6fvQkLjK4Q0AC+WnHbbovxOAjktZ1uR0PgUIQ3AF8npsizJ6a8s Z1u5vaystirLkoTeO5ZgAfBrmqbL5TIMg9cc3eO6LEa58aM9/YMGsEfMT3/K33poEjolhDQA78jp d6ZpYscS3ILhbgCBMO4tpmmiUww3ivffMYDEUE8rEhp3IqQBhHPwnCahcS9CGkBQh81pSWjnq60U CZ005qQBbOBo89PU0HjM9v92ARzQoeppamg8jEoawGaOUE/727FEPuiQ0GmjkgawmeT395b10D5q aBL6IKikAWws1Xp6GeV2/phllPs4qKQBbCzJ+WkSGk4Q0gC2l1hOk9BwhZAGEIVkcpqEhkPMSQOI yDzPbdvud36ahIZbhDSAuOw3p2W1FQkNhxjuBhAXY0zTNLsb915OnySh4RAhDSA6u8tpT7t+WmtJ 6IMjpAHEaMnp+Pc58bfrZ1EUJPTBMScNIF7xz0/TKQavCGkAUQuT08aY379/35vTJDR8Y7gbQNTC zE/P83zvuDcJjQAIaQCxi7CPbOkUc57QWZaR0FgQ0gB2wBgTz3lZXs+H5mwrXGNOGsBuBO
sje35+ zrLs0//rdZS7LMu6rt1eFrtGJQ1gN4KNe7++vn76OcBTQltrZZSbhMY7VNIAdkbq6b7vvT6+PtbT nnYsUXSK4WtU0gB2RurpsiwD1NPTNC3/6Smh6RTDN6ikAexSyPlppRQ1NDZBSAPYqzA5rbWuqqrr OjrFEB4hDWDHwsxP+0BC4xbMSQPYsWV+2uv6aedIaNwo3/oGAGAVyWmllO9xb1dIaNyOShrA7oVZ P+0ECY27xP4PGgBusYucJqFxr3j/NQPAXSLPaRIaD4jxnzIAPCbanCah8Zi4/h0DwEoR5jQJjYfF 8o8YAFyJKqdJaKyx/b9gAHBuyelt10+T0FiJddIA0rT5+mkSGutRSQNI1ob1NAkNJwhpACnbZN9Q EhquENIAEhc4p0loOMScNID0hZyfzvOchIYrVNIADiHYuqy+76dp8voSOA5CGsBRhMnpeZ5fXl7I aThBSAM4kDD93uQ0XNHW2q3vAQCCmue5bVvf89PGmF+/fmVZ5u8lkDwqaQCHw7g39oKQBnBE5DR2 geFuAMc1z/Plcun7nnFvxIlKGsBxGWPqui7LknoacSKkARzaktP0eyNCDHcDAOPeiBSVNAAw7o1I EdIAoBQ5jSgR0kBcxnH0fQIEvkJOIzbMSQMReX197fu+LEs57lAp5fs0CHwUZn5aa/3792/mp/E9 QhqIhST08p95nmdZVlWVMYaoDow+MkSCkAai8C6hr1VVlee5nAnhdZkQrpHTiAEhDWzvm4RWSllr tdZFUeR5XlUVUR0M497YHCENbOz7hBaS00JmrH0ftghBPY1tEdLAlm5J6E/RXBYMOY0NEdLAZh5O aKG1NsaUZVkURZZlFNb+MO6NrRDSwDZWJvQ1a23TNFmWSWFNWvtATmMThDSwAYcJvTDGyKotOSuC MXDnGPdGeIQ0EJqPhF5IGV3XdZZlRVEoCmunyGkERkgDQb29vXVdF+a1ZIE1Y+BukdMIiZAGwgmZ 0LJqyxijtZbCmuY
yV8hpBENIA4GETOhPSVRTWDtBTiMMQhoIYfOEXgrrPM9lLxQpsje8pb2j3xsB ENKAd5sn9Duyc5kU1nmeKwrrR1FPwzdCGvArtoQWS2EtO5flec6W4I8hp+EVIQ14FGdCv/OusCaq 7xUsp5+fn2XkA8dBSAO+7CKhr0lb2dJchtuR0/CEkAa8GMfx7e1tmqatb+Ruxpgsy6qqyrKM5rLb kdPwgZAGvLDWys5iOw05rbVEtTSEK5rLbkBOwzlCGvBlHMeXl5e9/4jJLijSX0Zz2Y/IabhFSAO+ TNPUtm3XdQkEm4x7N00jg+EJ/I38IafhECENeNR13dvb22N/VmtdFEU8GW+tlYSWvVDoA/8GOQ1X CGnAo2mazufzMAwP/FlrbV3XeZ5fLhdrrdfH/b2kp6yua2MMzWWfIqfhBCEN+NW2raTsvX/QWpvn +el0MsYMw9D3/TRN8fzAWmtl3FuiWo7FxDVyGusR0oBf1to/f/48thZLIrCqKq21tbbrumEYxnGU /cKc3+rDZAxcWsFpLrsmOT0Mg9fFeFrrX79+kdNJIqQBv6y1Ukw/fIVfv34tdaqE9GOluVdS90tz mdaawFhQT2MNQhrwbhzHP3/+PPzH8zx/enq63rdZorrrummaIixbl4O2aC4TYeppcjpJhDTgnRTT bds+llhSnpZlaYxZflHKsrZtp2mKbQBcbkYWWMsYOCdDkNN4DCENhND3/dvb28M/bh+LaWGtnaZp GIau66Jq/17I0LdsCX7w8GB+Gg8gpIEQrLVvb2993z98haqqnp6evvq/8ujvui62xVrqb2EtY+DS BHfY5jJyGvcipIEQrLV935/P54d/4owxTdNUVfXNS8zzPPz16J36dX16xzHHwGXug5zGjQhpIJB5 nl9eXsZxfLiILMuyaZrvs81aKx8IZGl1hAWrPHNkAFwK6+u59iOQnPbd701Op4GQBgKR7Hx4l1Bx Op3qur7ld47jOE1ThLuVCXnyFEWxRPWhCmvqa
dyIkAbCWX/ItNb6+fn5xu29JJ5lHlQ6wKNqAl/I LuWyaus4m4xST+MWhDQQlKzFeviPL3uQ3TtELIuq1+yp4tUyBi5T70qpI4yBk9P4ESENBDUMw/l8 XlNMZ1n2/Pz8QMVprZWeMkmFaAtWY8yyaiv5MfAwOa2U+v37Nzm9R4Q0EJS19nw+d1235gplWT4/ Pz+WsssA+DzP4zg+fBteyXNJmsCloT3hwjrM/LQip/eJkAaCknnil5eXNZWT1vp0OpVl+XA1LLch TeDRRrXI8zz55jLqaXyFkAZCk0OmV66PKstSTrF8+ArSRDaO4zzP5/NZ/d1qNE7SXCb9ZUk2l9Hv jU8R0sAG+r5/eXlZmTS3L8f60TRNsmGZNIE7uaYP1zuXqeTGwMlpfERIAxuQYnrlvmBFUTRN4+pp K4W1NIHLlHnMDwdjzHVhvfXtOMP8NN4hpIFtrFyLpZTSWj89PZVl6eqWhLV2HMdxHPu+9x0VK2mt pQlc3oQ00pqcxjVCGtjGPM+vr68rm7aMMb9///YRTrJGS3ZBiXYn8EWWZVJYZ1mWQFSHyek8z2Ut n7+XwHp8jAI2k+f5MAwrZ6b7vpfOZ1d3JeTZXde1rNSSPnC3L+GQzKlfLpe6riWwd33QlpwgLl97 yuksy1w1NMArKmlgM+M4vry8rPwZLIri6enJdyZN0zTPs8xYS/UfcwQWf+26D9zfuqwsy6SbgTI6 foQ0sBmJvfP5vDJImqZZCi9/ZOvvaZr6vpdJ68jzzxhT17W0mKm4P1V8xce4Nwm9Lwx3A5uRw5XX h8cwDHI6hZO7+or+qygKiQ05YivaD/qy/ns5vUNWbe0rqpdxb1dHmZHQu0MlDWzs7e1tzS6hSilr 7fPzs4RQMFJVL03gkT9JZLcyaQXP83xfUe2qniah94iQBrYkh16cz+eVdZKcuhF+10xZXX25XGR1 dZxHYS7k3pYtwSO/22vrc9oYczqdSOjdYbgb2JIMxmZZtjKkZXFz+D4peTl
pAi+KQprAo/3oLzd2 uVy01n3fy1lbWuv4c2tlvzc19H5RSQMbk2L69fV15XXyPP/9+7eTW3rYPM/WWjliS9I65lJV4rks S5nRj/xu1aP1NAm9a4Q0sL1xHF9fX6dp2kWb94+km0x2Au/7XsXdrmWtvY7qyBdY35vTJPTeEdJA FC6XixxFtcb6o7HckiO22rZ11ZzslTTbS3OZk657T27PadmxRNaLh7k3OMecNBAFOTV5Zftu13VF UQRu8/6GbA0tM+5SWMcc1fM8yyj9UliXZRnhGPiN67JI6DRQSQOxcLIWS4rp8G3e35PnjBR/6zdv CUOOxZTtUCLcuez7epqETgaVNBAFa21VVcMwrKk1tdZxHggtCSdnVeV5LtuWRb66Whr6pGdeVm1F 1Vz2Tb+3bLVGQqeBShqIheyQJZ1Wa8Q2M/3R9RFb8XeWKaWstRLSVVVJVR3JDX+sp40xTdOQ0Mmg kgZiIRXb+pCWI6FifkYvR2zJ+PwwDDKEEEnyfaS1liNGZMa6rmtZ4L71fb2vpxnlTg+VNBCRaZra tu26bmVc1XV9Op1c3ZVvMu4t25Z5PUHZIekDz/NcmuO2/Xgh9fQ0TWVZktCJIaSBuDhZi2WMeXp6 iqHUu500V/d933VdzFW1kMlpWawlhfW2zXqylbr0uG14G3CO4W4gLmVZLjO1D5PAi6fL6RYy1yt7 i259Lz+TN1ZKfxkDl+nqrVZtSS964BdFAHxTgbhITab1qlEua+35fJa11w7vzbdxHOX4yx19tlB/ N04fx1EO8ZTtUKho4QQhDcRFa12WpZwoteYiSimp8PYSeMMwyMTqHufg5E2WqF6ay4wxeZ7v7jMH osKcNBAd6QO6XC4rr1MUxfPz8y4SYtcJ/SlrbfGXjGfs4huB2FBJA9FZ5hdXFmHjOHZdV9e1u1vz YhgGWTO99Y24JBvLSHuBHF8te4NvfV/YGSppIEauiumyLJ+enmKu4dKroT8lrQayRCrLMsbAcSMq aSBG
TtrHlFJ935dlKftxRkhq6OQTWv3dZHQYBglpWbVFcxl+RCUNRMpa+/Lysn4QuKqqpmkizIOD 1NCfkqFv2RKcwhrfoJIG4lVV1foMG4Yhwmlp5zW07OOxl4nteZ7llBFZr1VVFYU1PkUlDcRrmqbX 19eVO2XK+VpRzUwvnWIOE7osy7qup2mSXi3Zy8XJxQOIZ+cyxIaQBuJlre37/vX1dWW+Zln2/Pwc ydNfEnoYBlcXXBJaKlE567PrOlmy7OpVfLPWGmOKosjzvCzLeA7awrYIaSBqwzCcz+dxHFc+spum WY5L2pDvhF5Ya+XQKonq+DcDvybndsgpYZF8tMJWCGkgdm9vb13XrbxInuen02nb7Z19JHRRFN+3 xck25m3byjSwq5cOQDYsq+uaTbmPjO89EDtpH1vZEiXHIbu6pQcEq6E//jY5E0yO2JINRlzdg1fy qUJOid7RMADcIqSB2DnZf1t2R8nzfJMW4mW1lasL3pjQ179fa306ncZxlEO7rbWRjyNKK1me5yT0 kRHSQOyMMU3TrO+FlsOaiqII/NB3vh763oQW8rfO/5IVUFKqOrkrt+SIjqIoWJd1cHz7gR2Q3bxX hpyM94ZPaOfroR9I6HeyLJPTR+q6rqpKRXb6RZZlTdOQ0FA0jgF70XXd+rVYWuunp6dgu4RGUkN/ TwYYpmnqui6GqloGTkhoCEIa2Id5nt/e3tY3XtV13TRNgMLR344lPtJLpqil6N9wdbXMQ5PQWBDS wD5IhLRtu/I6Wuvn5+eiKJzc1Vf2ldALiWqZq5Zty0IOg5PQ+IiQBnZjnuc/f/6sXEmltZaJWH9J sNOEviZD9FJYhxkDJ6HxKf41AHsiG0auuYJUiv4KROcJrbUOnNBKqSzLZPuXp6enANuJkND4CpU0 sCfjOL68vKxfi3U6neQ4B1c3JhKood+RQyRlCxQZBnc+Bk5C4xuskwb2xBhTVdXlcllzEUmdeZ7d 7gudRg398R6UUnmey6qteZ5lDN
zV9m0kNL5HSAN7Yoxxkqx93xdF4TCk06uh35FDJI0xz8/PS2fZ ym3LSGj8iJAGdqaqqr7v1y8TGobBVU5vtS93eFJYy0LzoiiWHUYfuNSy62dsf0dEhZAGdsZaK0du rBlx1VrLAY7rNwZfaug1F7kWbUIv5B2Ts5+LohiGQc7EvD2tl4TmJEp8L9KfAQBfkXFXJ71Ll8tl 5eh08qPc35PvRVVVT09Pp9OpLMtb3odlX24SGj+iuxvYH1lG9fb2tvI6WZbJIdOPRf7BE/ojWVQt VfU4jp++q+z6ibsw3A3sj9ZajkmepmlNSS3dT4/tPkZCf5RlmSywVkrJpuXvZgFIaNyLShrYq7Zt 1+8Saox5enq6N6dJ6Fss53bM8yzT/03TMA+Nu1BJA7tkrS2KQtYCrbmOVHt3jXiT0Ddazq6W1dVV VUmpvfV9YU8IaWCXpGUpy7L1O0u3bSuNyrf8ZhL6XssYuLU21b8j/OFfDLBXWuv1h07KH78xdH3s KVYURcIJvZA2gq3vAvvDPxpg35wcOtl13Y+/x9Oun03TkF7AV/jZQNTsf9r6dqKTZZnsfrWSTJp+ 8xtIaGATzEkjIhIAsqzIWjvPs5xBJFtrLR038oXWWn6bv1MXd0EOfli5Jae829KB/PH/+piHLoqC hAZ+REhjS0sGT9MkG3QopZbTACU55At1NatnjJHe5qV5Sl1F+NFIU9L6fbO7rsvzvKqqd79OQgMb Yp00tiEBrJTquk621HisLJZ6WoJKakr1txnqOKy1Ly8vK3fPttbWdV3X9fXHHRIa2BaVNIKSGB6G QTZ5WKJaYvWBcJW56nmeh2GQTbhkZeqhFqRaa/M8l9GIhy+ite77/rqSJqGBzVFJIxyZ9ey6TkLa a71bluUyeHuEwnocx5eXl5U/ztbasiyfnp6MMSQ0EANCGiFIsSsPfRvkC+AAACAASURBVCn4wgRn 8VfyVbW19nK5nM/nlW9slmVPT09yNRIa2BwhDe8kmNu23WQZ
lUxaN02znHyQqr7vX19f138Aknl9 EhqIASENv7qu67puZU/TetJcJttPbnsn/lhrz+fzLduShERCA2ukXFhgQ9ZaOVhXCujNZ4WttXLK r6zdyrJs81vyQdZiSS9eDGTXTxIaeBiVNNyTFc99369fvOuDzFJXVZVeTs/z/Pr6uvm4haCGBtaj koZj1tq2bfu+j6eee0d6y6dpSi8/jDFVVcUQ0iQ04AQ/P3BG+sJeX1/llPutb+c78zxLm5XsPLr1 7bgUwwJxEhpwheFuuCHbicTQI3aXLMtOp5MxZvNgc6ht27Ztt3p1EhpwiJ8iOCA9YrKydut7uc80 TTKJO03T1vfijGy4tslLk9CAW/wgYa1xHM/nc9u2O805mURPKaeLosjzPPwgGQkNOMfPElYZx1EK 6Mgnob83z3NiOV1VVeCdW0howAd+nPC4YRjO5/MwDAl0NiSW07LPWrCXI6EBT/iJwoP6vpfjERNI aJFSTmdZVtd1mG8NO5YA/vBDhUfI+qWt78K9eZ7P53Ma67KyLKuqyvdfxBhTliUJDXjCzxXulmpC C2vt29tbGiHtu8ebUW7AN360cJ+2bRNOaDHP88vLy65b4URVVXKklQ8kNBAAP124gyy12vouQpD5 6b3X01prTz3ezEMDYfADhludz+fL5bL1XQQip2Z1XbfrnNZa+zhHRGvNPDQQBj9juEnghJZtwK+/ CE/29957+7rktMML0ikGhMQpWPhZmISWLDTGyNNfa22MsdbO82yMmed5miat9TzPwVYAj+M4DIO/ ad0AjDF5nmvtZpd+5qGBwAhp/MBrQltrJYyzLJMAkP+83otDfo8si5JRaDloUvLbd2C3bWuMqeva 66t4led5WZZd162/lNaahAZCIqTxHa8JLUlc13We57LX9KdPf4nhZTVRURRSVUuZK2nt6Q7FMAxZ lu23npZiuu/79W+Utbbv+11/ZAH2haMq8SV/Ca21lq02six7uP1Y/unK4Zh93zu9wfcv9P
T0tOtk knO++75fP/BQVdXpdAq55yhwZIQ0PucvoeWMJuk6Xv+slzHwvu/7vh+GwV94/Nd//dd+z5yWt+h8 Pjv5ef/169d+xxWAfWG4G5+Q9dBuA89am2VZWZZlWWZZ5uriy5i5TGw7GdT99FVkmHenFaQMXbhq H+v7XnoI1l8KwPf4McN7UkM7T6O6rk+n0+l0cpjQ18qyrOva06C0NKz5uHIwcuSGk0uN4+jkOgB+ REjjP3jaU+x0OlVVVZal+tsI5oPMc//+/dtHkTeOo5MG6a1IMe1kxH6aJlcj5wC+R0jj33zU0Frr X79+lWXpaX/Kd6ST+fn52cdHgQCd5F5JN4CTv4I02K+/DoDvEdL4F+edYrK9szQZBZ6/zPP8169f bl/UWtt13a6TyVorHfXrLyXr39ZfB8D3CGko5WGUW7Z3Pp1OYQroj6SedpjTUprvOqSXfWPWX0o+ spDTgG+ENNyPcsvccF3X265ZyrKsaRqHF5SFTLse8TbGOHlPZA842QZu/dUAfIWQPjrnNXSe503T bJ7Q6u9BjQ77vSWZdl1Mq7/TEE4udblcEjh1G4gZIX1ozmtoCcU8zyNZRCsrsx3uvCHlo6urbcLh FqcJDC0AkYviSYpNOO8Uiy2hhRwv4epqywGari64iaIonOT0PM/DMOz93QBiFtHDFCE5T2jZKyO2 hBZlWTo8U9nrPuFhuGofU0pN05TAGwJEK7rnKQLwNA8dZ0ILh8vA5OhMJ5faipw46arNW04OXX8p AB9F+kiFP8735Y5zlPuatEplWeZkYFZOyVx/nW1Za8uydPLP4HK5ENKAJ5E+VeFJ8p1iX3FYO6ax 7ki2ZnN1tb1v8wJEK+oHK9w6SKfYV5ycjLlcJ4GcluXs66+jtZYNUxN4T4DY7ODZCicOntBKKWOM k0ySpdJ7n5ZWrtvHnJ9tCkAR0gdBQqu/m2Kuv+GUoqiqKidrsaSYps0bcG43T1g8jIReOLlnCek0 hnblyA0nHzvmeR7
HMY23BYjHzh6yuBcJ/c766WRrbQLd3UIOmXY1NtD3fTLvDBCJXT5ncSMS+h3Z zdvJdZIZ9JZdaJxUwPLxZe/bpgJR2eWjFrc41J5iN3IyLZ3AZibvZFnm5LOLtfZyuTDiDTi016ct vuejho58T7Ebrc9XaYpOKYqKonC4vXnXdSm9OcC29v3AxacY5f6GMWZlTstmJikV09Za2ZHNyaVk zfT6SwFQhHR6SOgfrYkQieeUElr9bR9zNTwwDEPXdeuvA0AR0okhoW+xJmLd5lk8tNZ1Xbva22QY Btq8ASfSefKChL7RynzVf7m6n0i4an1XStHjDbiS1MP3yEjoG83zvCY/ZLg7sTJaZFnmZPcxpZS1 tm1bjtwA1kvq+XtYrLa63TzPa/5SMtyd3tsi8jx3tUsoG5ABTqT5rDkUVlvdTnqP11fS6Y11C4fT 7dbarutSfaOAYFJ7Ch8No9x3keMU1yRHlmUOlxRHSL77Ti41jiNt3sBKCT6Ij6NtWxL6LnLK5Jor HGH81uGnEDrIgJXSfBYfQdu2bds6vGDyCS1l9JqQljOjUn1/hDGmKApXn0W6rmMtFrBGyo+bhJHQ j1k/+rp+w7L4Sdugq6v1fU+bN/CwlJ/IqTqfzyT0A6y1K4de3e5xHS1ZMO3qH8MwDMl/rAH8Sfmh nCTmoR+28rRja23yb9GiLEtX7WOyZvoIc/mAD0d56KSBUe6HrW8Z01pXVXWcorAoCld/2WmaWDMN PCbxR3NKSOg1pmlaMyFtrc2yLOEV0u9orYuiMMa4OnKDQW/gMek/ndNAQq8xTdP6EVeHI8C7ICMH Dmemh2FwcingUNJ/QCeAhF5j2WVsTSVXFIWrfa33wmH7mNZ6HEfOmQYekP4zeu/o5V5Ja9113cq+ bmOMq2Mcd8ThkRta67Zt2dgEuNchHtP7xa6f653P55X7aRhjmqZxdT87IjPTDj+dDMNAMQ3c5ShP 6j1ilHu9vu/XB4NMRR+z78lh+5i1tu/79dcBD
uUoD+vdadv2fD47DIYDJvQ0TcMwrN/uqizLA451 C2tt0zSu/vore+yBAzrK83pfpIZ2mNAJnw/9jWEY1kdCXddHaxm7JqvOHJ5f6eRjE3AcB3pk74WP Ue5Uz4f+Rtd15/N55UXyPHe4p8dOZVnmcBeXYRg4cgO43YGe2rsgo9wOL3jAUW6l1DAMThruHLY3 75ocjeXqahy5AdzuQA/u+Dkf5T5sQjtZ7SMjEE5uae/yPHe4kYssW3d1NSBtB3p2R44a2omlWWzl HKox5lA7df+oqipXOT3P8+VyYS0WcIsDPb5jRg3thBzk0Pf9+gCQ2pGQXkj7mKtLFUVBSAO3ONAT PFrOa2ittWw0faiEnud5HMfz+bx+KFW2rT7ssqtPaa3rul7/qUVr3TSNLL92cmNA2vg52Zjs+um2 YrPWzvN8qEpF/squzi0+nU6HOkvjRvLZZeUVJKH5AATciCfRltq2dbvr56LrOqlUDvI0tNa+vb2t r6GttVJDf/qxyVorvy7HdVx/IJD/XH5xOdRy+SPLF/tljJEpgMc+CZHQwAMI6c10Xed2PfQ1a+1y 8eSfifM8v76+rl/VY63N8/zjkZTLyMQ8z9KStryWtdZaKxtnyhdyP1mWyS9qrY0x1xO68oX8r93F tiwcf2B3TxIaeAwhvQ15oOd57m9jh4PktCS0q7exLMuyLNXfYFZK9X0v2Sw5vRSR7+rm5dfl64+f GCSPrzNbvinygUB+Mf5qW86vvHc7dBIaeNiDI1dYz1o7juPlchmGwd+rpP18dJvQVVU1TSPfl2WX 6ZUHUX9Ffu4km5VS0uW3jCfHnNnW2j9//tw1bnE6nVL9Fwj4RkhvKUxOq0Sfkm4TWilV1/U4jp/W wb4tFbnEs0S11PRLkEcS2HKY1fl8vuXRIT3hRz6hBFiJ4e4tyeO4rmullNecTm/c23lCK6Wct9nf bnldGWOXTwlSysvm4bIx5/VZFxve6u3/ihIexQHCoJLentTTbdt6PXggpXF
vHwkdrWVgfOljkN3Q 5D+3KrIvl8v3i/tT+vcGbIiQjgLz07c7VEK/s3SryXdQesjzPJc1Y1JkhwnsYRjO5/M38wJJzrAA 4THcHYUw494J9HvP8/zy8nLYM5SWullGxZf+c6WUtIsvrWcS2/4yuyiKPM8//Uak8VkQiASVdESo p7935Br6R+8mqsuylNYzWY0tC7gdBra0172+vr7bQGa//7qAOFFJR4R6+hsk9PeuA1gasNXfIvt6 fZcxxknrmQS/MWaapuU6JDTgHJV0dILV0ztaG3PwUe6VriNZTqCS7/6yIZp6NLCHYXh5eZGvSWjA B0I6Rox7X7PWvry8UEM7scxSyzC4TF1L69kDRfY0TW3b9n2/l39LwO4Q0pFinxNBQochJbVEdVEU 6m/r+I+tZ3JIDAkNeEJIx4t6moQOaVnfJaksRz7L2PiygcnHwJZjvJetyAG4RUhH7cg5TUJv6HpU XCl1XWTL8Pi7k0Ui2bIUSA8hHbtj5vQDpzjAn3dJLEW2dB1K3xkAT1iCFbsDrsuSGpqEjse79V3D MFyftgnAH0J6Bw6V04xyR06mqGXchTIa8I2Q3oeD5DQJHb/YZkaAtPFBeDeWnJYVMp5Ya8/n8zAM m5ypTEJHTnZBIaGBYKik9yTh86c3SWhZHDzPswzbXrdHLVtSyxd0LytqaGALhPTOJDnuHaaXW5YV ySFRMp9qrZXVRNfrg5f/nOfZ/iX3No6j/KfX+4wWNTQQHiG9P4nltO9ebkliGadVSsnX6ubieIlk iW05UmKaJkluCfJxHL2eC7m5fe30DqSEddJ7lcb6ad+j3LIrdV3X+q/111xKbfnZkbSWhUlKKfk6 sYK7aRoSGtgEIb1jez8vy19CyyresizzPM/zQMNF8qMkc9jzPA/DIN8gKcHD3INz1NDAtgjpfdtv TvtL6CzLqqqSGnqr8efriW2t9TAM8zxLciulZGw//rFxEhrYHCG9e3vMaX8Jnef58/Ozq5Ftt2QM XE6k
kOHxpSUtwh2wSWggBoR0CvaV054SOsuyPM9Pp1NUUfcVCWxjjCxJH8dR0jqSzVBJaCAShHQi 9pLTnlZbyQy0NIi5vXIYy0y2dIy/K7ID/6VIaCAehHQ64s9pTzV0URRFUVRVtdOEfmfpDF9az2Q+ e5qmAH9BEhqICiGdFHmmd13X973XF3pgTY6nhC7LUtrE0kjodySwtdYyHr60ni0brbj9W5PQQGwI 6dTEWU+T0E5c74Bmre37Xorspfhe8z6Q0ECECOkEhamnb3+mk9A+XLeeyWD4sib7gR9qEhqIE9uC Jkj2DZWv/eW0tfZyuSilvn+yk9CeLMvM5FS0pci+Xt+11Nnq2yKbhAaiRSWdrBjqaRJ6E+9msoUE tvrQLk5CAzEjpFO2bU6T0JGQn/ElqqVdfNkNjYQGYkZIJ26rPjISOk7XrWfq7xFhJDQQLUI6feHr aRJ6FyLcixTAOzSOpS9wH1lRFOfzmYSOH+8kED8q6aMIVk9rrZ2fzEhCAzgmKumjCFZPO//YR0ID OCxC+kDC5LRbJDSAIyOkj2VfOU1CAzg4Qvpw9pLTJDQAENJHFH9Ok9AAoAjpw4o5p0loABCE9HHF mdMkNAAsCOlDiy2nSWgAuEZIH92S03K+4YZ3QkIDwDtm6xvA9iSn67qWk4k3QUIDwEdsC4p/CbNv 6KdIaAD4FMPd+Jet5qdJaAD4CiGNfws/P01CA8A3mJP+3HJQxPUXy+FOH/9vMpb56bIsfb+WMSbP cxIaAL5CJa2WuJX/nKbJWqu1nqZp+RX1N4+NMVrrLMvk9xtjjDFKKa21MUb+4N4jJ9i49zRN8zxP 07S8HADg2qEfjvM8S7fUPM+SFpLE745Dlui9/uKaviKloaT4kt97FCantdaXy0XeUnIaAD463JNx nmdjTNd10zQNwyAFsdTKX1XAy69/+huuR7yttV3XLfFcFEWWZXmeL9W2h7+QL8Hq6bZt5eWyLPP3 KgCwR4dYgiUV8DiO1tq+76dpWo
pmf8Epb+xSVZdlaYyRr72+rlth1mVprWUWnJwGgGuJh7QksRTN 4zhKTm8SkPKiRVEYY6qqWkbIw9/JvYKtn26ahpwGgGsph7SUy23bzvM8jqOKZsA5yzKpHWUOe+vb +Rk5DQCbSDOkpXSW6jnav6C1Ns/zoihk6jrywpqcBoDwEgzpruuGYei6TkVTOn9P6um6riNvngqZ 00VR7GKMAQC8SiekZd3U+XyWJVVb387dtNZFUZRlWRRFtJ8tyGkACCmRh+AwDH3fj+O47ECyO9J5 PgxDWZZ5nldVFWETeOB1WYr10wCObfdPQGkKe3t7S2NIQFZaj+M4DEPTNLJBytY39R/IaQAIZt/D 3eM49n2/7Iax9e04lmWZDIBHmFJhxr2ttafTiXFvAIe145CWhAhzWNOGtNan0ynP89h6yshpAPBt fw8+mak9n8/DMOx3Bvp28zy/vb3JeY5VVW19O/8WbH9vxr0BHNbOnnqyfdjlcvHdXRwPGcaXgnWa ptPpFE9DWcj5aRnyIacBHMqeHnnW2mEYLpeLbB92NPM8Xy6XaZpkmVYkDWXBcprzsgAc0G6ed/M8 yy4lx0xo9bekHoZBGtrruo5klpp+bwDwZB8Pu3me27aVfNr6XrYne5LP83w6nYwxMQx9Lzktox3+ Xuh8PjdNo8hpAMewg+5uEvorxpimaeJp/JZ+78vl4rvlnv3IABxE7CE9TVPbtjvd6TMArXXTNLKi eut7UYqcBgCnog7paZpeXl6I5+/JUHNVVWVZbn0vSgVcPy3nZZHTABIW7wOOhL6RTANba621MSyk DjM/rbWm3xtA8iJ9usWT0MtIw8f+rHjWKyulxnGUSQHpq9qW5LQcvkm/NwA8LMZH2zAMb29vwRJa YljiVg600H8ta5G11tJTLV/In5rnOaqcVn83/aiqavOub9ZlAcB60T3XLpfLsr1UABLGZVlKqGRZ Zq2VhLsOb/W3bpZRZa31PM8S2+M4yj5o8zwvf2pDl8tlnmfZ
RvQ4Oc1+ZACSFNdDLUxCy/Wl3JRg XlL5OtXeJdxSai//mee5lK1aaxlqnqZJpoeXstvrX+QrSyIeJ6cvl4t8QU4DSElET7S2bS+Xi++E 1lpXVVUURZZl75YX35Vn7zJ7aZWq61qmh5fAdnfvd5BEtNYWRUFOA8BObT88K7zW0FLUSio3TXM9 2eyPFNNd10laqy1OvM6yrCxLaeAK/NLvsC4LAB4QxbMsQELLMuKQw79Spsskt0R113WBw3Kapr7v JbqOUE+zLgtAYrZ/kPlO6KIoyrKUBcThg0oa05qmkdOr5BirkKMXy5HbB8lpRR8ZgIRs/BTz3Skm m0fGsGWmDLYbY2TUd8nOAA6Y09TTANKw5SPMd0L//v3bGBPJuctCmsmrqjqfz9M0BTt284A5zfpp AAnYrHHMX0IbY6RBLPKn8zAMfd93XRfsFeUcjs1zWtFHBgC32ebh5TWh8zyXg6GcX9wtWQaW53nX dWFK6qPV01rrtm0Z9wawXxs8ufwltBTQHxdAR8sYI3uqSE4H2An1mDktX5PTAHYn9GPrcrl42rFE TnTI8zyqSehbFEUhDWVt24bJaXn/D5LTivlpALsV9JklCe0jh4qiOJ1OYXYp8UEav4uieHl5CdD4 Pc+z7K9CTgNAzMI9sPwldFmWz8/PsR1IdS9ZUf3r16/L5TIMg++oluvneX6cfUPJaQC7E+hp5Tuh 1RYblfhgjFkOhA6Q033fS0YeJKfP5/PpdFLkNICdCPGo8pTQWuuiKCShUyI7lBVF4XuFkjreeVn0 kQHYF+/PKU+93HJ0xFJ0JmZJLGutTB77c7ScVox7A9gPv5uZeKqhZdOuuq7dXjY28q2RTzm+X6uu axkH3lywfU5Op1NRFOQ0gJh5fEL5q6GPkNDq7yy7jBb4zmk5jDmGnA427s38NID4+Xo8eVoPvRyQ 7PaykQuW0zId7vVVbhEyp+XvS04DiJOXZxOj3M41TbNsTObpJay1l8tFNkHz9BK3C3n+tH
xNTgOI kPsHEwntSVVVEiqeclprPc9z13Va67IsfbzEvfcT7FxL+YKcBhAbx08lEtoryU6vOT0Mg2x/FkNi 0e8N4OBcPpJI6AAC5HTXdcYYrXUM55Qw7g3gyJw9j0joYHzntFw8z/MYQlr93bVGvmbcG8ChuDmO goQOTFrc/WWJtfb19TXMKdc3Koqiqirfk+Vt2/Z9H9VfHMCROXjKk9CbWOrpYRh87BQmzd5yPrfz iz8mQD3NuDeAqKx9DJHQGyrLUlaie6r8pImsqqp4DgBl3BvAoax6BpHQm/O6Lsta2/e9fBSI55Ax chrAcTxeIZHQkZD56SzLfGzDPk3T+XyOJ6EF89MADuLBKoGEjkpZlvM8+xv0bts2hu1CrzE/DeAI HqmkSegI1XXtL0eHYfB9svUDpJ72vYmpbEHv9bA4APjK3fUBZ1tF63Q6aa19nMMxjuMwDHmex9NB JpZ6uus6H9e31jZNo7WObcAfwEHc98z1d7YVCe1E0zSe3kavZ3usURRFWZae6ummacqyZKwbwFbu ePp4GuWWY5dIaFfqup7n2cfotJyRFWFieaqn67omoQFs69YHEPPQe6G1lrLSeU5P0zRNkzEmtkFv 5TqnZZSbhAawuZueQf4SWpYPub3swS0nUjjv95Y9yGI4xfJTDnOahAYQiZ9LIq8JHdvCnjRITvs4 IUOWTUfb6uxkfppRbgDx+OFJ5K+Xm4T2Smstb+88z26/fdM0jeO4lK2xWVlPk9AAovJdJe2vl5uE DkBy2nkxLcux3F7TrYfraRIaQGy+DGl/vdwkdDBa61+/fjnP6b7vE8tpay0JDSBCn4e0115uEjqw uq7d9mPP8zxNU7Qz0+KunKZTDECcPnl2yzw0nWJpkCaysizd7pnl4zOcc7fkNDU0gJi9D2nmodOT ZVlRFG4Hved57rou8mJa3ZDT1NAAYvYfIc08dKqKonC+Hn0cx/iLafVtTlNDA4jcv0Oaeei0Oc/p aZoibx9bfJrTJDS
A+P0rpLuuo4ZOm9a6LEuH+4VZa4dhmKbJ1QW9epfTJDSAXciVUl3X+egUk02k Seh4ON+DbBiGeZ6dL/HyZNnnRD6vkNAA4pd3Xedpo0e5prWWs3jj0TTNNE0Oz97o+z7LsgiP3PhU URRyq3v5YAHg4IyPXT8Xfd/76BXHw2TFkcNMjfOQ6W9kWUZCA9gL89///d/+ri5FGzkdD621MaYo ClfDG27rcgDANaOU+p//+R9/L0BOx8YYU1WVw2/HXtZiAcDu/GvYk5w+lCzLTqeTq2/Hjnq8AWBf /j03GSCnvc5/43Za6yzLHLY3Oz8QEwCg3u045junh2EgpyMh64adXEoWTDu5FADg2vsuX+rp43C4 bJpKGgB8+GQpjtecnueZejoSDkN6GAZ6vAHAuc/XyzLufQSyJZyrtVh8NwHAuS83tSCnj8AYk+e5 k+9C3/csxAIAt77beYr56eS52thEa22t5VsJAG79sD0k89Np01rnee5kLRY93gDg3M97OFNPpy3P c2PM+vff/uXkrgAA6paQVtTTqSvL0smRG9M08U0EAIdufTTTR5YwSej1b/48zxxLCgAO3VE/kdOp kvax9deZ55liGgAcum+Qk5xOkjEmy7KVRbC1dp5nimkAcOjumUhyOj3W2qIoVk5Lyyosxa4mAODO I89lcjoxWmtjjKvV0k5uCQCgHgtpxbqsFGVZtv4Nn6aJ4W4AcOXxEU7WZaVETphefx2+XwDg0Kpp SMa9k6G1lkHvldfhzEoAcGjtQ5mcTsb6SpodxwDALQf7TJHTaVjf9iWz0XynAMAVByGtyOlUrCym Zam0q5sBALgJaUVO758xxskO3nyPAMAVZyGtyOn9W7mpp6v11gAA4TKkFTm9Z+u7u2kcAwC3HIe0 Iqd3y1orC7HWXIQlWADgkPuQVuxHtlsrS2GGuwHALS8hrdiPbJ/Wv58kNAA45CukFfX0Dq2vgwlp AHDIY0gr6uldkdOg17yZTma1AQALvyGt6CPbD
2vtyjOs5JQOQhoAXPEe0oqc3gmpg1dexBjDNwIA XAkR0ipUTrMn5RrjOK5/A52cdwkAEIFCWgXpI7tcLpRxj5HZ6PWVtJOLAABEuJBW9JFFTN69lRfJ 89zJ7t8AABH6kcq4d4RcfaxZv7EoAODaBo/UADnNuPe9+r6fpmnNFbTWeZ67uh8AgNokpBX93pFZ v/hKLpLnORPSAODQZoOTjHvHo+/7lRPS1lr6ugHAuS1nEMP0e5PT35vneeVAt/o71l0UhZNbAgCI jdt8AvR7k9Pfm+e57/uVF5G9xphfAAC3tu/FpZ7ekCT0+jdHa12WJRPSAODW9iGt/NfT5PSnpPAd x3F9yxgD3QDgQxQhrcjpLWitu64bx3H9pdjGBAB8iOjBSk4H1vf9+tlopVRRFLR2A4APEYW0IqcD krXR6/u6lVJ5nrONCQD4EFdIK3I6lHEc27Zdfx1jTFVV668DAPgoupBW5LR/4zheLhcnl2KXMQDw J8aQVuS0T7J83Em/mFKqqipaxgDAk3gfr+S0D9Zaa23XdU42HqnrmpYxAPAn3pBW5LQHWuvz+ezk rywHU1JGA4A/sT9hyWm3zufzyrM0FkVR1HXt5FIAgE/FHtKKnHanbVtXCZ1lWV3XbNYNAF7tIKQV Oe3CMAzDMDhZGC3HaRhj6OsGAK/2EdKKnF5nGIa+7111dGutm6ZhNhoAfNvTc5acfoz81bquc3XB pmlo6gaAAPYU0oqcfojbhC7LkoQGgDB2FtKKnL7T5XI5n8+u23p6IwAAA81JREFUrqa1LoqCnboB IIz9hbQip2/mNqGVUlVVsVM3AASzy5BW5PQN+r53m9BlWZLQABDSXkNakdPfGobB4Ty0UsoYUxQF Hd0AENK+n7nk9KeGYbhcLq4WXCmljDFlWZZlycJoAAhp3yGtyOkPloR2uB2YMaZpGhIaAALbfUgr /znddd1ectpTQj8/P5PQABBeCiGtPOe0tXYX9bSnhD6dTiQ0AGwikZBWhx/
3loQehsFhQmut5cRo QhoANpFOSKsD57TzTjGR53lRFOwvBgBbSSqk1SFz2scot/p7XDQJDQAbSi2k1cFyehiGtm3dJrS1 Vga6i6JwdU0AwAMSDGl1mJyWGnqaJrc1tNb6dDqR0ACwuTRDWh0gpz2Nciulnp6e2P4TAGKgnT/i o/K///u//i6uta6qqq7r8JtlktAAcATJVtIiyfXT/hK6aZqyLN1eEwDwsMRDWgUZ927bNlhO+0vo qqrYnRsAopJ+SCv/OS0t1gFy2ndCs+AKAKJyiJBWSeS0v4SWE65o5waA2CTeOPaO1z4yOXG5aRof fWS+a2gSGgAidJRKWuy0niahAeCYjhXSaoc5TUIDwGEdLqTVrnKahAaAIzvWnPS1+Oenl9MnHd6Y IKEBYBeOWEmLyOtpT6dPKhIaAPbjuCGtIs5pRrkBAOrIw92L2Ma9GeUGAIhDV9IiqnqahAYALAhp paLJaeahAQDXCOl/2TynmYcGALzDnPR/2Gp+WiJ8miYSGgCwoJL+D5vU01JDk9AAgHcI6fcC5zSj 3ACArzDc/bkw497TNJHQAICvENJf8p3TWZZZa+nlBgB8hZD+jteclndea+32siQ0ACSDkP6B15x2 joQGgJTQOPYDr31kbpHQAJAYQvpnu8hpEhoA0kNI3yTynCahASBJhPStos1pEhoAUkVI3yHCnCah ASBhhPR9osppEhoA0kZI3y2SnCahASB5hPQjNs9pEhoAjoCQftCGOU1CA8BBENKP2ySnSWgAOA5C epXAOU1CA8ChENJrBcvpsixJaAA4FELagQA5XZZlVVUkNAAcCqdgOePvvCxGuQHgmKiknfFUT5PQ AHBYhLRLznOahAaAIyOkHXOY03SKAcDBEdLuOclpOsUAAIS0FytzmoQGAChC2p+Hc5qEBgAIQtqj B3KahAYALAhpv+7KaRIaAHCNkPbuxpwmoQEA7xDSIfyY0yQ0AOAjQjqQb3JaEjrP85D3AwCIHyEd zqc5
vSS01jr8LQEAYkZIB/Uup0loAMA3COnQlpwmoQEA3+Ooym28vr6S0ACA7/0/YBJ1/NDwq84A AAAASUVORK5CYII= "
+ x="0"
+ y="0"
+ width="652"
+ height="694"
+ id="image10" />
+</svg>

Added: sandbox/SOC/2007/quan/libs/quan/doc/doxygen/important.png
==============================================================================
Binary file. No diff available.

Added: sandbox/SOC/2007/quan/libs/quan/doc/doxygen/proposed_for_boost.png
==============================================================================
Binary file. No diff available.

Added: sandbox/SOC/2007/quan/libs/quan/doc/doxygen/quan_doxyfile.txt
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/libs/quan/doc/doxygen/quan_doxyfile.txt 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,1810 @@
+# Doxyfile 1.8.0
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or sequence of words) that should
+# identify the project. Note that if you do not use Doxywizard you need
+# to put quotes around the project name if it contains spaces.
+
+PROJECT_NAME = Boost.Quan
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF = "Boost.Quan library of uncertain functions"
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is
+# included in the documentation. The maximum height of the logo should not
+# exceed 55 pixels and the maximum width should not exceed 200 pixels.
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO = Proposed_for_Boost.png
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful if your file system
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 12
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding
+# "class=itcl::class" will allow you to use the command class in the
+# itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this
+# tag. The format is ext=language, where ext is a file extension, and language
+# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
+# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
+# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
+# comments according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you
+# can mix doxygen, HTML, and XML commands with Markdown formatting.
+# Disable only in case of backward compatibilities issues.
+
+MARKDOWN_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also makes the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
+# unions are shown inside the group in which they are included (e.g. using
+# @ingroup) instead of on a separate page (for HTML and Man pages) or
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
+# unions with only public data fields will be shown inline in the documentation
+# of the scope in which they are defined (i.e. file, namespace, or group
+# documentation), provided this scope is documented. If set to NO (the default),
+# structs, classes, and unions are shown on a separate page (for HTML and Man
+# pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penalty.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will roughly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+SYMBOL_CACHE_SIZE = 0
+
+# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
+# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
+# their name and scope. Since this can be an expensive process and often the
+# same symbol appear multiple times in the code, doxygen keeps a cache of
+# pre-resolved symbols. If the cache is too small doxygen will become slower.
+# If the cache is too large, memory is wasted. The cache size is given by this
+# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = NO
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = NO
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
+# do proper type resolution of all parameters of a function it will reject a
+# match between the prototype and the implementation of a member function even
+# if there is only one candidate or it is obvious which candidate to choose
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = NO
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = NO
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= NO
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or macro consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and macros in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page. This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = NO
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. The create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files
+# containing the references data. This must be a list of .bib files. The
+# .bib extension is automatically appended if omitted. Using this command
+# requires the bibtex tool to be installed. See also
+# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
+# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
+# feature you need bibtex and perl available in the search path.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE = doxywarn.log
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = ../../../../boost/quan \
+ ../../src
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS = *.cpp \
+ *.ipp \
+ *.hpp
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE = "../../../../boost/quan/meas - all const.hpp" \
+ ../../../../boost/quan/meas2.hpp \
+ "../../../../boost/quan/unc - all const.hpp" \
+ ../../../../boost/quan/uncbools.hpp \
+ ../../../../boost/quan/uncdata.hpp \
+ ../../../../boost/quan/uncs.hpp \
+ "../../src/Boost CHECK expanded macros.cpp"
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
+# and it is also possible to disable source filtering for a specific pattern
+# using *.ext= (so without naming a filter). This option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header. Note that when using a custom header you are responsible
+# for the proper inclusion of any scripts and style sheets that doxygen
+# needs, which is dependent on the configuration options used.
+# It is advised to generate a default header using "doxygen -w html
+# header.html footer.html stylesheet.css YourConfigFile" and then modify
+# that header. Note that the header is subject to change so you typically
+# have to redo this when upgrading to a newer version of doxygen or when
+# changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER = quan_doxygen_header.html
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER = quan_doxygen_footer.html
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# style sheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET = quan_doxygen.css
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the style sheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT = 104
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA = 82
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+# will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
+# at top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it. Since the tabs have the same information as the
+# navigation tree you can set this option to NO if you already set
+# GENERATE_TREEVIEW to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+# Since the tree basically has the same information as the tab index you
+# could consider to set DISABLE_INDEX to NO when enabling this option.
+
+GENERATE_TREEVIEW = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML
+# documentation. Note that a value of 0 will completely suppress the enum
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE = 4
+
+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list.
+
+USE_INLINE_TREES = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
+# (see http://www.mathjax.org) which uses client side Javascript for the
+# rendering instead of using prerendered bitmaps. Use this if you do not
+# have LaTeX installed or if you want to formulas look prettier in the HTML
+# output. When enabled you may also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you need to specify the location relative to the
+# HTML output directory using the MATHJAX_RELPATH option. The destination
+# directory should contain the MathJax.js script. For instance, if the mathjax
+# directory is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to
+# the MathJax Content Delivery Network so you can quickly see the result without
+# installing MathJax. However, it is strongly recommended to install a local
+# copy of MathJax from http://www.mathjax.org before deployment.
+
+MATHJAX_RELPATH = http://www.mathjax.org/mathjax
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a PHP enabled web server instead of at the web client
+# using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server
+# based approach is that it scales better to large projects and allows
+# full text search. The disadvantages are that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
+# the generated latex document. The footer should contain everything after
+# the last chapter. If it is left blank doxygen will generate a
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load style sheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = YES
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED = __declspec(x)=
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. For each
+# tag file the location of the external documentation should be added. The
+# format of a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths
+# or URLs. Note that each tag file must have a unique name (where the name does
+# NOT include the path). If a tag file is not located in the directory in which
+# doxygen is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS = 0
+
+# By default doxygen will use the Helvetica font for all dot files that
+# doxygen generates. When you want a differently looking font you can specify
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find
+# the font, which can be done by putting it in a standard location or by setting
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the Helvetica font.
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
+# set the path where dot can find it.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside
+# the class node. If there are many fields or methods and many nodes the
+# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
+# threshold limits the number of items for each type to make the size more
+# managable. Set this to 0 for no limit. Note that the threshold may be
+# exceeded by 50% before the limit is enforced.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are svg, png, jpg, or gif.
+# If left blank png will be used. If you choose svg you need to set
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible in IE 9+ (other browsers do not have this requirement).
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+# Note that this requires a modern browser other than Internet Explorer.
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG = NO
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES

Added: sandbox/SOC/2007/quan/libs/quan/doc/doxygen/quan_doxygen.css
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/libs/quan/doc/doxygen/quan_doxygen.css 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,504 @@
+/*
+ The standard CSS for Doxygen but
+ with changed C++ code (syntax) colorization checks_doxygen.css */
+/*
+ Copyright Paul A. Bristow 2011
+ Use, modification and distribution are subject to 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)
+*/
+
+body, table, div, p, dl
+{
+ font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif;
+ font-size: 12px;
+}
+
+/* @group Heading Levels */
+
+h1 {
+ text-align: center;
+ font-size: 150%;
+}
+
+h2 {
+ font-size: 120%;
+}
+
+h3 {
+ font-size: 100%;
+}
+
+dt {
+ font-weight: bold;
+}
+
+div.multicol {
+ -moz-column-gap: 1em;
+ -webkit-column-gap: 1em;
+ -moz-column-count: 3;
+ -webkit-column-count: 3;
+}
+
+p.startli, p.startdd {
+ margin-top: 2px;
+}
+
+p.endli {
+ margin-bottom: 0px;
+}
+
+p.enddd {
+ margin-bottom: 4px;
+}
+
+/* @end */
+
+caption {
+ font-weight: bold;
+}
+
+span.legend {
+ font-size: 70%;
+ text-align: center;
+}
+
+div.qindex, div.navtab{
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
+ text-align: center;
+ margin: 2px;
+ padding: 2px;
+}
+
+div.qindex, div.navpath {
+ width: 100%;
+ line-height: 140%;
+}
+
+div.navtab {
+ margin-right: 15px;
+}
+
+/* @group Link Styling */
+
+a {
+ color: #153788;
+ font-weight: normal;
+ text-decoration: none;
+}
+
+.contents a:visited {
+ color: #1b77c5;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+a.qindex {
+ font-weight: bold;
+}
+
+a.qindexHL {
+ font-weight: bold;
+ background-color: #6666cc;
+ color: #ffffff;
+ border: 1px double #9295C2;
+}
+
+.contents a.qindexHL:visited {
+ color: #ffffff;
+}
+
+a.el {
+ font-weight: bold;
+}
+
+a.elRef {
+}
+
+a.code {
+}
+
+a.codeRef {
+}
+
+/* @end */
+
+dl.el {
+ margin-left: -1cm;
+}
+
+.fragment {
+ font-family: monospace, fixed;
+ font-size: 105%;
+}
+
+pre.fragment {
+ border: 1px solid #CCCCCC;
+ background-color: #f5f5f5;
+ padding: 4px 6px;
+ margin: 4px 8px 4px 2px;
+}
+
+div.ah {
+ background-color: black;
+ font-weight: bold;
+ color: #ffffff;
+ margin-bottom: 3px;
+ margin-top: 3px
+}
+
+div.groupHeader {
+ margin-left: 16px;
+ margin-top: 12px;
+ margin-bottom: 6px;
+ font-weight: bold;
+}
+
+div.groupText {
+ margin-left: 16px;
+ font-style: italic;
+}
+
+td.indexkey {
+ background-color: #e8eef2;
+ font-weight: bold;
+ border: 1px solid #CCCCCC;
+ margin: 2px 0px 2px 0;
+ padding: 2px 10px;
+}
+
+td.indexvalue {
+ background-color: #e8eef2;
+ border: 1px solid #CCCCCC;
+ padding: 2px 10px;
+ margin: 2px 0px;
+}
+
+tr.memlist {
+ background-color: #f0f0f0;
+}
+
+p.formulaDsp {
+ text-align: center;
+}
+
+img.formulaDsp {
+
+}
+
+img.formulaInl {
+ vertical-align: middle;
+}
+
+div.center {
+ text-align: center;
+ margin-top: 0px;
+ margin-bottom: 0px;
+ padding: 0px;
+}
+
+div.center img {
+ border: 0px;
+}
+
+img.footer {
+ border: 0px;
+ vertical-align: middle;
+}
+
+/* @group Code (syntax) Colorization */
+
+span.keyword {
+ color: blue
+}
+
+span.keywordtype {
+ color: blue
+}
+
+span.keywordflow {
+ color: blue
+}
+
+span.comment {
+ color: green
+}
+
+span.preprocessor {
+ color: darkblue
+}
+
+span.stringliteral {
+ color: brown
+}
+
+span.charliteral {
+ color: brown
+}
+
+span.operator {
+ color: red
+}
+span.vhdldigit {
+ color: red
+}
+
+span.vhdlchar {
+ color: brown
+}
+
+span.vhdlkeyword {
+ color: blue
+}
+
+span.vhdllogic {
+ color: magenta
+}
+
+/* @end */
+
+.search {
+ color: #003399;
+ font-weight: bold;
+}
+
+form.search {
+ margin-bottom: 0px;
+ margin-top: 0px;
+}
+
+input.search {
+ font-size: 75%;
+ color: #000080;
+ font-weight: normal;
+ background-color: #e8eef2;
+}
+
+td.tiny {
+ font-size: 75%;
+}
+
+.dirtab {
+ padding: 4px;
+ border-collapse: collapse;
+ border: 1px solid #84b0c7;
+}
+
+th.dirtab {
+ background: #e8eef2;
+ font-weight: bold;
+}
+
+hr {
+ height: 0;
+ border: none;
+ border-top: 1px solid #666;
+}
+
+/* @group Member Descriptions */
+
+.mdescLeft, .mdescRight,
+.memItemLeft, .memItemRight,
+.memTemplItemLeft, .memTemplItemRight, .memTemplParams {
+ background-color: #FAFAFA;
+ border: none;
+ margin: 4px;
+ padding: 1px 0 0 8px;
+}
+
+.mdescLeft, .mdescRight {
+ padding: 0px 8px 4px 8px;
+ color: #555;
+}
+
+.memItemLeft, .memItemRight, .memTemplParams {
+ border-top: 1px solid #ccc;
+}
+
+.memItemLeft, .memTemplItemLeft {
+ white-space: nowrap;
+}
+
+.memTemplParams {
+ color: #606060;
+ white-space: nowrap;
+}
+
+/* @end */
+
+/* @group Member Details */
+
+/* Styles for detailed member documentation. */
+
+.memtemplate {
+ font-size: 80%;
+ color: #606060;
+ font-weight: normal;
+ margin-left: 3px;
+}
+
+.memnav {
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
+ text-align: center;
+ margin: 2px;
+ margin-right: 15px;
+ padding: 2px;
+}
+
+.memitem {
+ padding: 0;
+ margin-bottom: 10px;
+}
+
+.memname {
+ white-space: nowrap;
+ font-weight: bold;
+}
+
+.memproto, .memdoc {
+ border: 1px solid #84b0c7;
+}
+
+.memproto {
+ padding: 0;
+ background-color: #d5e1e8;
+ font-weight: bold;
+ -webkit-border-top-left-radius: 8px;
+ -webkit-border-top-right-radius: 8px;
+ -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+ -moz-border-radius-topleft: 8px;
+ -moz-border-radius-topright: 8px;
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
+
+}
+
+.memdoc {
+ padding: 2px 5px;
+ background-color: #eef3f5;
+ border-top-width: 0;
+ -webkit-border-bottom-left-radius: 8px;
+ -webkit-border-bottom-right-radius: 8px;
+ -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+ -moz-border-radius-bottomleft: 8px;
+ -moz-border-radius-bottomright: 8px;
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
+}
+
+.paramkey {
+ text-align: right;
+}
+
+.paramtype {
+ white-space: nowrap;
+}
+
+.paramname {
+ color: #602020;
+ white-space: nowrap;
+}
+.paramname em {
+ font-style: normal;
+}
+
+/* @end */
+
+/* @group Directory (tree) */
+
+/* for the tree view. */
+
+.ftvtree {
+ font-family: sans-serif;
+ margin: 0.5em;
+}
+
+/* These are for tree view when used as main index. */
+
+.directory {
+ font-size: 9pt;
+ font-weight: bold;
+}
+
+.directory h3 {
+ margin: 0px;
+ margin-top: 1em;
+ font-size: 11pt;
+}
+
+/*
+The following two styles can be used to replace the root node title
+with an image of your choice. Simply uncomment the next two styles,
+specify the name of your image and be sure to set 'height' to the
+proper pixel height of your image.
+*/
+
+.directory h3.swap {
+ height: 61px;
+ background-repeat: no-repeat;
+ background-image: url("draft.png");
+}
+.directory h3.swap span {
+ display: none;
+}
+/*
+*/
+
+.directory > h3 {
+ margin-top: 0;
+}
+
+.directory p {
+ margin: 0px;
+ white-space: nowrap;
+}
+
+.directory div {
+ display: none;
+ margin: 0px;
+}
+
+.directory img {
+ vertical-align: -30%;
+}
+
+/* These are for tree view when not used as main index. */
+
+.directory-alt {
+ font-size: 100%;
+ font-weight: bold;
+}
+
+.directory-alt h3 {
+ margin: 0px;
+ margin-top: 1em;
+ font-size: 11pt;
+}
+
+.directory-alt > h3 {
+ margin-top: 0;
+}
+
+.directory-alt p {
+ margin: 0px;
+ white-space: nowrap;
+}
+
+.directory-alt div {
+ display: none;
+ margin: 0px;
+}
+
+.directory-alt img {
+ vertical-align: -30%;
+}
+
+/* @end */
+
+address {
+ font-style: normal;
+ color: #333;
+}

Added: sandbox/SOC/2007/quan/libs/quan/doc/doxygen/quan_doxygen_footer.html
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/libs/quan/doc/doxygen/quan_doxygen_footer.html 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,29 @@
+<!-- custom Doxygen footer quan_doxygen_footer.html -->-
+
+<!-- Copyright 2012 Paul A. Bristow -->
+<!-- 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) -->
+
+<hr size="1"/>
+<table width="100%">
+<tbody>
+ <tr>
+ <address style="text-align: left;">
+ <p>Use, modification and distribution are subject to the Boost Software License, Version 1.0.<br/>
+ (See accompanying file LICENSE_1_0.txt or copy at&nbsp;
+ http://www.boost.org/LICENSE_1_0.txt )</p>
+ <!-- Change copyright to YOUR name (and affiliation, if any) below: -->
+ <p>Copyright © $year Paul A. Bristow</p>
+ <!-- $year becomes the current year, for example 2010, so claims copyright for a range of years, 2009 - 2010. -->
+ <p>Doxygen Documentation generated by&nbsp; doxygen logo $doxygenversion, Revised at $datetime</p>
+ </address>
+ </tr>
+</tbody>
+</table>
+ <!-- You can also add a footer logo, taking care that the location of the footer.png is correct. -->
+ <!-- <img src="../images/my_footer.png" alt="Boost Doxygen documentation footer.png" -->
+ </body> <!-- <body> is in doxygen_header.html -->
+</html><!-- <html> is in doxygen_header.html -->
+
+

Added: sandbox/SOC/2007/quan/libs/quan/doc/doxygen/quan_doxygen_header.html
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/libs/quan/doc/doxygen/quan_doxygen_header.html 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,47 @@
+
+<!-- quan_doxygen_header.html -->
+
+<!-- From Sample custom Doxygen header from my_doxygen_header.html -->-
+
+<!-- Copyright 1998 - 2012 Paul A. Bristow. -->
+
+<!-- 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) -->
+
+<html> <!-- </html> is in footer. -->
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+
+ <!-- Add your title here ! -->
+ <title>Boost.quan $datetime $projectname $projectnumber</title>
+
+ <!-- Add your custom stylesheet here ! -->
+ <link href="../quan_doxygen.css" rel="stylesheet" type="text/css"/>
+ <!-- Note that this overrides any stylesheet specified in doxyfile setting HTML_STYLESHEET="mystylesheet.css" ! -->
+ <link href="tabs.css" rel="stylesheet" type="text/css"/>
+</head>
+
+<!-- Add draft background here if, for example, not yet accepted or otherwise not finalised. -->
+<body style="background-image: url(../../images/draft.png);">
+</body>
+
+<!-- You could also flag status by using a color? -->
+<!--<body style="background-image: url(../../images/draft.png) ; color : darkblue"> -->
+
+<!-- </body> is in footer. -->
+
+<!-- Add your logo here or -->
+<!-- Boost logo here if accepted after review, else some "Proposed for Boost" logo, for example the one below, or "proposed for Boost" ! -->
+<table cellpadding="5" width="100%">
+ <tbody>
+ <tr>
+ <td valign="top"><img alt="Proposed for Boost." src="../proposed_for_boost.png" height="80" width="250"/></td>
+ </tr>
+ </tbody>
+</table>
+<p>
+ <br/> <!-- Some space below logo, if needed. -->
+</p>
+

Added: sandbox/SOC/2007/quan/libs/quan/example/quan_simple/quan_simple.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/libs/quan/example/quan_simple/quan_simple.cpp 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,59 @@
+// Use, modification and distribution are subject to 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)
+
+// Copyright Paul A. Bristow 1998, 2012.
+
+
+#include <boost/version.hpp>
+#include <boost/quan/unc.hpp>
+#include <boost/quan/unc_init.hpp>
+
+#include <iostream>
+
+std::string versions()
+{
+ std::stringstream mess;
+ mess << "Program: " __FILE__ << "\n";
+#ifdef __TIMESTAMP__
+ mess << __TIMESTAMP__;
+#endif
+ mess << "\nBuildInfo:\n" " Platform " << BOOST_PLATFORM;
+ mess << "\n Compiler " BOOST_COMPILER;
+#ifdef _MSC_FULL_VER
+ mess << "\n MSVC version "<< BOOST_STRINGIZE(_MSC_FULL_VER) << ".";
+#endif
+ mess << "\n STL " BOOST_STDLIB;
+ mess << "\n Boost version " << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100 << endl;
+ return mess.str();
+} // std::string versions()
+
+int main()
+{
+ std::cout << std::endl;
+
+ std::cout << versions() << std::endl;
+ setUncDefaults(std::cout);
+ uncun u(1.23, 0.45F);
+ std::cout << "URealCorr u(1.23, 0.45); = " << u << plusminus << std::endl;
+
+
+} // int main()
+
+/*
+ Description: Autorun J:\Cpp\quan\MSVC\Debug\quan_simple.exe
+
+ Program: ..\..\libs\quan\example\quan_simple\quan_simple.cpp
+ Thu Jul 19 16:06:56 2012
+ BuildInfo:
+ Platform Win32
+ Compiler Microsoft Visual C++ version 10.0
+ MSVC version 160040219.
+ STL Dinkumware standard library version 520
+ Boost version 1.50.0
+
+ URealCorr u(1.23, 0.45); = 1.2
+
+
+*/
\ No newline at end of file

Added: sandbox/SOC/2007/quan/libs/quan/test/Quan1In.txt
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/libs/quan/test/Quan1In.txt 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,3 @@
+0.05 (9)
+1.1 +/-0.1 1.2 1.0 1.1+/-0.001
+1.25 0.97

Added: sandbox/SOC/2007/quan/libs/quan/test/TestQuan1.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/libs/quan/test/TestQuan1.cpp 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,1047 @@
+// TestQuan1.cpp
+// Test unc fully first.
+// Compiles and run 8 Aug but results wrong in unc
+// Using atime seems to work but is messy - use Boost posixTime?
+
+// Test of Quan1 - univariate using uncertainty and statistical tests.
+
+// see QuanOne word document for description.
+#ifdef _MSC_VER
+# pragma warning(disable : 4189) // 'argument' : conversion from 'time_t' to 'unsigned short', possible loss of data
+# pragma warning(disable : 4996) // _CRT_SECURE_NO_WARNINGS.
+# pragma warning(disable : 4702) // Unreachable code.
+#endif
+
+#include <cmath> // for sqrt, exp ...
+#include <iostream> //
+#include <iomanip> // for setw, setprecision ...
+#include <fstream> // for filing.
+#include <string> // for C++ Std strings.
+#include <sstream> // for stringstreams.
+#include <vector> // for vectors.
+#include <functional> // for less...
+#include <algorithm> // for sort, copy, swap ...
+#include <numeric> // for accumulate...
+#include <locale>
+#include <ctime> // C time.h defines time_t time(time_t* timer);
+#include <cassert> // for testing only.
+
+#include "unc.hpp" // Declaration of Uncertain Classes.
+#include "meas.hpp" // uncertain plus order.
+#include "to_string.hpp" //
+
+using std::ofstream;
+using std::ifstream;
+using std::istringstream;
+using std::getline;
+using std::ios;
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::flush;
+using std::hex;
+using std::ws;
+using std::skipws;
+using std::noskipws;
+using std::string;
+using std::istringstream;
+using std::ostringstream;
+using std::boolalpha;
+using std::uppercase;
+using std::scientific;
+using std::setprecision;
+using std::resetiosflags;
+using std::fixed;
+using std::vector;
+using std::iterator;
+using std::allocator;
+using std::abs;
+using std::copy;
+using std::sort;
+using std::accumulate;
+using std::transform;
+using std::less;
+using std::swap;
+using std::locale;
+using std::use_facet;
+using std::ctype;
+using std::numpunct;
+
+time_t timeNow(); // return C time(0);
+std::ostream& operator<< (std::ostream& os, time_t t);
+
+char const outFilename[] = "Quan1Out.txt";
+char const logFilename[] = "Quan1Log.txt";
+char const testInputFilename[] = "Quan1In.txt";
+
+// This block of definitions MUST be positioned before main.
+// 14 indexes of long iwords allocated by calls of ios_base.xalloc();
+// 1st call of xalloc() returns 0 so ios_base.iword(0) used for magic id,
+// 2nd call of xalloc() returns 1 so ios_base.iword(1) used for uncFlags,
+// 3rd calls returns 2, so iosword(2) used for sigDigits ...
+// Order of assignment must ensure these match enum uncindex (if used).
+const long zeroIndex = ios_base::xalloc(); // 1st iword[0] to hold a 'magic' id.
+
+const long uncFlagsIndex = ios_base::xalloc(); // long& uncFlags = iword(1)
+const long oldUncFlagsIndex = ios_base::xalloc(); // long& olduncFlags = iword(2)
+const long sigDigitsIndex = ios_base::xalloc(); // sigDigits = iword(3)
+const long oldSigDigitsIndex = ios_base::xalloc(); // oldsigDigits = iword(4)
+const long setSigDigitsIndex = ios_base::xalloc(); // setsigDigits = iword(5)
+const long stdDevSigDigitsIndex = ios_base::xalloc(); // stdDevSigDigits = iword(6)
+const long oldStdDevSigDigitsIndex = ios_base::xalloc(); // oldStdDevSigDigits = iword(7)
+const long ScaleIndex = ios_base::xalloc(); // scale = iword(8)
+const long oldScaleIndex = ios_base::xalloc(); // oldScale = iword(9)
+const long setScaleIndex = ios_base::xalloc(); // setScale = iword(10)
+const long uncWidthIndex = ios_base::xalloc(); // uncWidth = iword(11)
+const long oldUncWidthIndex = ios_base::xalloc(); // oldUncwidth = iword(12)
+const long oldUncSetWidthIndex = ios_base::xalloc(); // oldUncSetWidth = iword(13)
+const long usedIndex = ios_base::xalloc(); // used = iword(14)
+const long oldUncUsedIndex = ios_base::xalloc(); // oldUsed = iword(15)
+const long widthIndex = ios_base::xalloc(); // width = iword(16)
+const long oldWidthIndex = ios_base::xalloc(); // oldWidth = iword(17)
+
+const long topIndex = ios_base::xalloc(); // long& topIndex = iword(18] == iword(0] check!
+
+extern const long indexID; // 'Magic' value defined in unc.cpp.
+
+bool isIndexed = true; // Above indexes have been initialised.
+
+char const* Ctime(time_t* t); // Timestamp as string "Tue Apr 24 16:57:31 2001""\n"
+
+// #include <boost/test/minimal.hpp> // Boost minimal test
+#define BOOST_TEST_MAIN // Required for int test_main() (must come FIRST).
+#define BOOST_LIB_DIAGNOSTIC "on"// Show library file details.
+// Linking to lib file: libboost_unit_test_framework-vc100-mt-s-1_49.lib
+
+#include <boost/config.hpp>
+#include <boost/cstdlib.hpp> // needed for boost::exit_failure;
+
+#include <boost/test/unit_test.hpp> // Enhanced for unit_test framework autolink,
+#include <boost/test/floating_point_comparison.hpp> // Extra test tool for FP comparison.
+ using boost::unit_test::test_suite;
+ using boost::unit_test::unit_test_log;
+
+ // Direct use of std predicate function less using
+ // TEMPLATE STRUCT less in <functional>
+ // Used below for URealUncorr and Meas which both have operator< defined.
+ // if (std::less<double>()(l, h))
+ // if (std::less<URealUncorr>()(l, h))
+ // if (std::less<Meas>()(lm, hm))
+
+ //template<typename Type>
+ //struct less
+ // : public binaryfunction<Type, Type, bool>
+ //{ // functor for operator<
+ // bool operator()(const Type& Left, const Type& Right) const
+ // { // apply operator< to operands
+ // return (Left < Right);
+ // } // operator<
+ //};
+
+
+BOOST_AUTO_TEST_CASE(quan1_test_0)
+{
+ string message("Quan1 test: " __FILE__ );
+#ifdef __TIMESTAMP__
+ message += " at " BOOST_STRINGIZE(__TIMESTAMP__);
+#endif
+#ifdef _MSC_FULL_VER
+ message += ", MSVC version " BOOST_STRINGIZE(_MSC_FULL_VER) ".";
+#else
+ message += "."
+#endif
+ BOOST_MESSAGE(message);
+ BOOST_CHECK(std::numeric_limits<double>::is_iec559 == true);
+ // IEE745 is assumed by code.
+
+ setUncDefaults(cout);
+ BOOST_CHECK(isIndexed); // Should pass.
+ BOOST_CHECK(cout.iword(zeroIndex) == indexID); // Should pass.
+ BOOST_CHECK(cout.iword(topIndex) == indexID); // Should pass.
+ cout.iword(0) = indexID; // 1st iword[0] to hold a 'magic' id.
+
+ // Integrity check on iword begin and end no longer needed in CHECK.
+ {
+ ostringstream oss;
+ setUncDefaults(oss);
+ BOOST_CHECK(oss.iword(zeroIndex)== indexID);
+ BOOST_CHECK(oss.iword(0) == indexID);
+ BOOST_CHECK(oss.iword(topIndex)== indexID);
+ BOOST_CHECK(oss.iword(0) == indexID);
+ }
+} // BOOST_AUTO_TEST_CASE(quan1_test_0)
+
+// Macros to test output strings and inputusing unc and meas classes.
+ // Note uses setUncDefaults(oss); to initialise unc iostream data.
+ // Example: CHECK(plusminus << u123, "1.234 +/-0.02");
+#define CHECK(manips, result)\
+{\
+ ostringstream oss;\
+ setUncDefaults(oss);\
+ oss << manips;\
+ BOOST_CHECK_EQUAL(oss.str(), result);\
+}// #define CHECK(manips, result)
+
+BOOST_AUTO_TEST_CASE(quan1_test_1)
+ { // Some examples of testing uncertaint class without using macro CHECK.
+ {
+ ostringstream oss;
+ setUncDefaults(oss);
+ URealUncorr u0(0., 0.F);
+ oss << u0;
+ BOOST_CHECK_EQUAL(oss.str(),"0");
+ }
+ {
+ ostringstream oss;
+ setUncDefaults(oss);
+ URealUncorr u2(2., 0.F);
+ oss << u2;
+ BOOST_CHECK_EQUAL(oss.str(), "2.");
+ //cout << "URealUncorr u2(2., 0.F) == " << u2 << endl;
+ }
+ {
+ ostringstream oss;
+ setUncDefaults(oss);
+ URealUncorr u123(1.23, 0.01F);
+ oss << plusminus << u123;
+ BOOST_CHECK_EQUAL(oss.str(),"1.230 +/-0.02");
+ // cout << "URealUncorr u123(1.23., 0.01F) == " << plusminus << u123 << endl;
+ }
+} // BOOST_AUTO_TEST_CASE(quan1_test_1)
+
+
+BOOST_AUTO_TEST_CASE(quan1_test_2)
+{ // Tests on display of uncertain flags and uncertain types.
+
+ unsigned short int uncFlags = plusMinus | noisyDigit;
+ //cout << showUncFlags(uncFlags) << endl;
+ CHECK(showUncFlags(uncFlags), "uncFlags (48) add_+/- add_noisy.");
+ unsigned short int uncTypes = UNC_QUAN_DECIMAL | UNC_KNOWN;
+ //cout << showUncTypes(uncTypes) << endl; // uncTypes: (120) uncKnown quantize10
+ CHECK(showUncTypes(uncTypes), "uncTypes (0x120) uncKnown quantize10.");
+ unsigned short defType = UNC_KNOWN | UNC_EXPLICIT | DEG_FREE_EXACT | DEG_FREE_KNOWN; // 0x6420
+ //cout << showUncTypes(defType) << endl;
+ CHECK(showUncTypes(defType), "uncTypes (0x6420) uncKnown explicit df_exact df_known.");
+} // BOOST_AUTO_TEST_CASE(quan1_test_2)
+
+
+BOOST_AUTO_TEST_CASE(quan1_test_3)
+{
+
+ // +/- symbol = dec 177, hex F1 messy!! fout is different to cout!
+ ofstream fout(outFilename, ios::out); // use default overwrite/ iso::replace.
+ BOOST_CHECK(fout);
+ //if (!fout)
+ //{ // failed to open OK.
+ // cerr << "File " << outFilename << " failed to open!" << endl;
+ // return notOK;
+ //}
+ cout << "Quan1 Test output to " << outFilename << space << __TIMESTAMP__ << endl;
+
+ ifstream fin(testInputFilename, ios::in);
+ BOOST_CHECK(fin.is_open());
+ //if (!fin.is_open())
+ //{
+ // cerr << "File " << testInputFilename << " failed to open!" << endl;
+ // return notOK;
+ //}
+ cout << "Quan1 input from " << testInputFilename << space << __TIMESTAMP__ << endl;
+
+
+ if (false)
+ {// Test of comparison operators and predicates for UReals now in unc.h.
+ // Rely on unc tests.
+ URealUncorr u0(0.,0.F); // Exact integral zero gave problems before, now OK - all zero.
+ cout << noplusminus << endl;
+ cout << "URealUncorr u0(0.,0.F) == " << u0 << endl; // plain 0
+ cout << plusminus << flush;
+ cout << "URealUncorr u0(0.,0.F) == " << u0 << endl; // still plain 0 as expected.
+ cout << noplusminus << u0 << endl; // still plain 0 as expected.
+ cout << plusminus << u0 << endl; // 9.89 < 9.99 < 10.1
+ cout << addlimits << plusminus << u0 << endl; // 9.89 < 9.99 +/-0.10 < 10.1
+ cout << uppercase << boolalpha << endl;
+ cout << showformat << endl; // FormatFlags (0x4205) skipws, uppercase, dec, boolalpha.
+ // ostream& showuncflags(ostream& os);
+ cout << showuncflags << endl; // uncFlags (0x808) add +/-, add limits.
+ // void outUncFlags(unsigned short int uncFlags = std::cout.iword(uncFlagsIndex), ostream& os = std::cerr);
+ //outUncFlags(unsigned short(cout.iword(uncFlagsIndex)), cout); // Using defaults above.
+ cout << endl;
+ }
+
+
+ /* to_string doesn't appear to work - causes bad_alloc - come back to this?
+ if(false)// Test to_string, and some specializations.
+ {
+ double dd = 3.333333333333333333333333333333;
+ std::string xx;
+ xx = to_string<double>(dd);
+ cout << xx << endl; // to_string default is precision(10) not std default 6.
+ CHECK(xx, "3.333333333"); // Expect precision 10 digits.
+ xx = to_string<bool>(true);
+ cout << xx << endl; // to_string default is boolalpha.
+ CHECK(xx, "true"); // Expect boolalpha so "true" not "1".
+
+ URealUncorr uu(1.6, 0.1f);
+ setUncDefaults(cout);
+ xx = to_string<URealUncorr>(uu);
+ cout << xx << endl;
+ CHECK(xx, "1.5 < 1.6 +/-0.10 < 1.7"); // Expect addlimits & plusminus.
+
+ //const char* cs = "test";
+ //xx = to_string("test");
+ //CHECK(xx, "test");
+ //URealUncorr hhh(1.6, 0.1f); // even at 2 standard deviations.
+ //string hs = "to_string<URealUncorr>(hhh) " + to_string<URealUncorr>(hhh) +" is cool!";
+ //cout << hs << endl;
+ } // tostring
+ */
+
+ // Check operators which only use value taking no account of uncertainty.
+ URealUncorr l(1.1, 0.1f); // Two test values l and h whose confidence intervals DO overlap.
+ URealUncorr h(1.1, 0.1f);
+ URealUncorr ll(1.1, 0.1f); // Test values ll and hh whose confidence intervals DON'T overlap at one sd.
+ URealUncorr hh(1.4, 0.1f);
+ URealUncorr lll(1.1, 0.1f); // Test values lll and hhh whose confidence intervals DON'T overlap,
+ URealUncorr hhh(1.6, 0.1f); // even at 2 standard deviations.
+
+ cout << "top of lower " << l.getValue() << " = " << l.getValue() + l.getStdDeviation() << endl
+ << "bottom of higher " << h.getValue() << " = " << h.getValue() - h.getStdDeviation() << endl;
+ // If linearly combining SDs adding or subtracting two values, use sqrt sum squares or hypot.
+ BOOST_CHECK_GE((l.getValue() + l.getStdDeviation()), (h.getValue() - h.getStdDeviation()));
+
+ cout << "sqrt_sumsquares sds = " << hypot(h.getStdDeviation(), l.getStdDeviation()) << nl;
+ // But that isn't relevant when comparing means - see below NR in C .
+
+ cout << "Difference of values in max sds between " << plusminus << h << " and " << l << " == "
+ << (h.getValue() - l.getValue())/ std::max(l.getStdDeviation(), h.getStdDeviation()) << endl; // max
+
+ cout << "Difference in sds between " << h << " and " << l << " == "
+ << (h.getValue() - l.getValue())/ hypot(h.getStdDeviation(), l.getStdDeviation()) << endl; // hypot
+
+ cout << "Difference in sds between " << hh << " and " << ll << " == "
+ << (hh.getValue() - ll.getValue())/ hypot(hh.getStdDeviation(), ll.getStdDeviation()) << endl; // hypot
+
+ cout << "Difference in sds between " << hhh << " and " << lll << " == "
+ << (hhh.getValue() - lll.getValue())/ hypot(hhh.getStdDeviation(), lll.getStdDeviation()) << endl; // hypot
+
+ // NR in C 13.4.3 p 512 comparing means with unequal variance, degrees of freedom and uncertainty.
+ double meandiff = hh.getValue() - ll.getValue();
+ URealUncorr meandiffu;
+ meandiffu = ( hh - ll);
+ cout << "Means " << plusminus << ll << tab << hh << ", Difference of means is " << meandiffu << endl;
+ cout << "SDs " << ll.getStdDeviation() << tab << hh.getStdDeviation() << endl;
+ double cdf = hypot(hh.getStdDeviation(), ll.getStdDeviation());
+ cout << "hypot sds " << cdf << nl; // Cruder combined uncertainty - wrong?
+ double dfll = ll.getDegFree() +1; // N1
+ double dfhh = hh.getDegFree() +1; // N2
+ cout << "Degrees of freedom " << dfll << tab << dfhh << nl;
+ double sell = (ll.getStdDeviation() * ll.getStdDeviation() )/ (ll.getDegFree() +1);
+ double sehh = (hh.getStdDeviation() * hh.getStdDeviation() )/ (hh.getDegFree() +1);
+ double se = sqrt(sell + sehh);
+ cout << "Standard errors " << sell << tab << sehh << ", mean se " << (sell + sehh) * 0.5 << " sqrt() " << se << nl;
+
+ double varll = ll.getStdDeviation() * ll.getStdDeviation();
+ double varhh = hh.getStdDeviation() * hh.getStdDeviation();
+ cout << "Variances " << varll << tab << varhh << nl;
+ double varlln = varll / dfll ; // variances/N
+ double varhhn = varhh / dfhh;
+ cout << "variance/df " << varlln << tab << varhhn << nl;
+ double dftop = (varlln + varhhn) * (varlln + varhhn); // top of 13.4.4
+ cout << "df top " << dftop << endl;
+ double dfbot = (varlln * varlln)/ dfll + (varhhn * varhhn) / dfhh; // bottom of 13.4.4
+ cout << "df bot " << dfbot << endl;
+ double df = dftop/dfbot;
+ cout << "df " << df << nl; // Final 13.4.4 degrees of freedom (not integer).
+
+ cout << "sqrt(varlln + varhhn) " << sqrt(varlln + varhhn) << endl;
+
+ double st = meandiff/ sqrt(varlln + varhhn); // Student's t 13.4.3
+ cout << "Student's t " << st << ", df " << df << nl;
+
+// double prob = betai(0.5 * df, 0.5, df/(df + st * st));
+// cout << "Probability that are different is " << prob << endl;
+
+
+ if (l < h)
+ { // Uses URealUncorr::operator< - only uses central value, no uncertainty.
+ cout << noplusminus << l << " is < " << h << endl; // 0.90 < 1.1 < 1.3 is < 1.0 < 1.2 < 1.4
+ }
+ if (l == h)
+ { // Uses URealUncorr::operator== - only uses central value, no uncertainty.
+ cout << " l == h " << endl;
+ }
+ if (l != h)
+ { // Uses URealUncorr::operator!= - only uses central value, no uncertainty.
+ cout << " l != h " << endl;
+ }
+
+
+
+ double ld = 1.2;
+ double hd = 3.4;
+ if (std::less<double>()(ld, hd))
+ {
+ cout << "(less<double>(" << ld << ", " << hd << " )) " << endl;
+ }
+ if (std::less<URealUncorr>()(l, h))
+ {
+ cout << "(std::less(l, h)) " << " l < h " << endl;
+ }
+ if (lessAbs<URealUncorr>()(l, h))
+ {
+ cout << "(lessAbs(l, h)) " << " l < h " << endl;
+ }
+ cout << "Test member predicate function " << plusminus << l << " < " << h << endl;
+ cout << plusminus << "(lessUnc(l, h)) ";
+ if (URealUncorr::lessU(l, h))
+ { //
+ cout << " l < h " << endl;
+ }
+ else
+ { // Not less so check if
+ if (URealUncorr::moreU(l, h))
+ { // greater
+ cout << " l > h " << endl;
+ }
+ else
+ { // or approximate equal.
+ cout << " l ~= h " << endl;
+ }
+ }
+ cout << " l " << l << ((URealUncorr::equalU(l, h) ? " ~= " : " != ")) << " h " << h << endl;
+ cout << " ll " << ll << ((URealUncorr::equalU(ll, hh) ? " ~= " : " != ")) << " hh " << hh << endl;
+ cout << " l " << l << ((URealUncorr::equalU2(l, h) ? " ~= " : " != ")) << " h " << h << endl;
+ cout << " ll " << ll << ((URealUncorr::equalU2(ll, hh) ? " ~= " : " != ")) << " hh " << hh << endl;
+
+ cout << "Testing static memberfunction predicate lessU<isCorrelated>" << nl;
+ // bool lessU(const UReal<isCorrelated>& l, const UReal<isCorrelated>& r)
+
+ if (UReal<false>::lessU(ll, hh) )
+ { // Not using typedef for UReal<false>::
+ cout << ll << " is < " << hh << endl;
+ }
+ else
+ {
+ cout << ll << " is >= " << hh << endl;
+ }
+ // if (UReal<true>::lessU(ll, hh) ) // fails because ll and hh are correlated.
+ // and anyway is not really implemented yet for correlated,
+ // but would use the same code silently.
+ UReal<true> lc(1.); UReal<true> hc(2.);
+ // Two correlated reals.
+
+ if (UReal<true>::lessU(lc, hc) )
+ { // Full UReal<true>::
+ cout << " lc < hc " << endl;
+ }
+ // global bool lessUnc not longer implemented for UReal<false> or <true>
+ // and will fail to compile if "if (lessUnc(lc, hc) ... " is used.
+ //
+
+ if (URealUncorr::lessU(ll, hh) )
+ { // Full URealUncorr:: qualification is essential - uses typedef for URealUncorr.
+ cout << ll << " is < " << hh << endl;
+ }
+ else
+ {
+ cout << ll << " is >= " << hh << endl;
+ }
+ if (URealUncorr::lessU2(ll, hh) )
+ { // Two sd version.
+ cout << ll << " is << " << hh << endl;
+ }
+ else
+ {
+ cout << ll << " is >= " << hh << endl;
+ }
+
+ if (URealUncorr::lessU2(lll, hhh) )
+ { // Two sd version.
+ cout << lll << " is << " << hhh << endl;
+ }
+ else
+ {
+ cout << lll << " is >= " << hhh << endl;
+ }
+
+ if (URealUncorr::lessU(0., hh) )
+ { // Left most argument needs conversion from double.
+ cout << " 0. < " << hh << endl;
+ }
+ else
+ {
+ cout << " 0. >= " << hh << nl;
+ }
+
+ const URealUncorr vh(99.);
+ if (URealUncorr::lessU(ll, vh) )
+ { // right most argument needs conversion from double.
+ cout << ll << " is < " << vh << endl;
+ }
+ else
+ {
+ cout << ll << " is >= " << vh << endl;
+ }
+
+// typedef UReal<false>::lessU UlessU; doesn't work
+ // Check moreU
+ if (URealUncorr::moreU(ll, vh) )
+ { // right most argument needs conversion from double.
+ cout << ll << " is > " << vh << endl;
+ }
+ else
+ {
+ cout << ll << " is <= " << vh << endl;
+ }
+
+ if (URealUncorr::equalU(l, h) )
+ { // right most argument needs conversion from double.
+ cout << l << " is ~= " << h << endl;
+ }
+ else
+ {
+ cout << l << " is !~= " << h << endl;
+ }
+
+
+// time_t* nowp = &now;
+// cout << " now = " << localtime(&now) << endl; // Outputs 004BCDD0 address of struct* tm?
+// cout << Ctime(nowp) << endl; // outputs: "Fri Jul 21 15:31:41 2000" = asctime(localtime(now))
+// cout << asctime(localtime(&now)) << endl; // outputs: "Fri Jul 21 15:31:41 2000""\n" = asctime(localtime(now))
+
+
+ URealUncorr u0(0., 0.F);
+
+ Meas zz; // Default constructor.
+ //cout << "Meas zz; = " << zz << endl;
+ CHECK(zz, "0");
+
+ zz = 1.;
+ //cout << "zz = 1; == " << zz << endl;
+ CHECK(zz, "1");
+
+ Meas z0(0.); // Construct from double zero.
+ //cout << "Meas z0(0.) == " << z0 << endl;
+ CHECK(z0, "0");
+
+ Meas z0i(0); // Construct from int zero.
+ //cout << "Meas z0i(0) == " << z0i << endl;
+ CHECK(z0i, "0");
+
+ Meas one(1.);
+
+ ptime now = ptime(day_clock::local_day());
+ Meas m0(u0, "m0", now); // Using now defaults.
+ // CHECK(m0, "m0 0 @ 15:42:45"); // Doesn't work because time now keeps changing!
+ Meas m01(u0, "m01", 2); // Using unity value defaults.
+ //cout << m01 << endl;
+ CHECK(m01, "m01 0 # 2");
+
+
+ //Meas(URealUncorr u, string id, time_t ti); // <<<<<<<<<<<<<<<<< test these
+ //Meas(URealUncorr u, string id, unsigned short int);// <<<<<<<<<<<<<<<<< test these
+
+ Meas zm1(-1.); // negative double value to allow check of abs function below.
+ Meas z1m(-1.); // negative double value to check ==
+ BOOST_CHECK(zm1 == z1m);
+ BOOST_CHECK(zm1 != z0);
+
+ //bool c = (zz < z0); // Check operator<
+ BOOST_CHECK(z0 < zz); // Check operator<
+ BOOST_CHECK(zz > z0); // Check operator>
+ //cout << zz << " < " << z0 << " is " << boolalpha << c << endl;
+ //c = (zm1 < 0 );
+ BOOST_CHECK(zm1 < 0 );
+ // BOOST_CHECK(0 > zm1); // No operator >
+
+ //cout << zm1 << " < " << z0 << " is " << boolalpha << c << endl;
+ //bool c = (zm1 < Meas(0) );
+ BOOST_CHECK(zm1 < Meas(0) );
+ // cout << zm1 << " < " << Meas(0) << " is " << boolalpha << c << endl;
+ BOOST_CHECK(Meas(0) > zm1 );
+
+ Meas mone = -one;
+ //cout << "-one == " << mone << endl;
+ CHECK(mone, "-1");
+ //cout << "Meas zm1(-1.) == " << zm1 << endl;
+ CHECK(zm1, "-1");
+
+ Meas z1 = fabs(zm1); // double to check abs function.
+ BOOST_CHECK(z1 == 1 );
+ Meas z11 = abs(zm1); // double to check abs function.
+ BOOST_CHECK(z11 == 1 );
+ //cout << "abs(zm1) = std::abs(zm1) = " << abs(zm1) << endl; // Should lookup type Meas, and does!
+ //cout << "abs<Meas>(zm1) == " << abs<Meas>(zm1) << endl; // explicit Type Meas fails!
+ //cout << "abs(zm1).m_value == " << abs(zm1.m_value) << endl;
+
+ //Meas lmNow(l, "low", now);
+ //cout << "Meas lmNow(l, \"low\", now) == " << lmNow << endl;
+ //Meas hmNow(h, "hi", 2);
+ //cout << "Meas hmNow(h, \"hi\", 2); == " << hmNow << endl;
+ //time_t nnow = now + 90; // Add 90 seconds to time for Meas hi.
+ //Meas nmNow(h, "hi", nnow); // Show time has advanced.
+ //cout << "Meas nmNow(h, \"hi\", nnow); == " << nmNow << endl; // Meas nmNow(h, "hi", nnow); == hi 1.2 @ 22:59:49
+ // Some comparisons.
+
+
+ Meas lm(l, "low", 1);
+ Meas hm(h, "high", 2);
+
+
+ if (lm < hm)
+ { // Using bool operator< (Meas&)
+ cout << "(lm < hm) "<< lm << " < " << hm << endl;
+ }
+ if (std::less<Meas>()(lm, hm))
+ { // Using std functor less which uses operator<
+ cout << "less(lm, hm) " << lm << " < " << hm << endl;
+ }
+ if (lessAbs<Meas>()(lm, hm))
+ { // Using Meas functor lessAbs
+ cout << "lessAbs<Meas>()(lm, hm) " << lm << " < " << hm << endl;
+ }
+ if (lessAbs<Meas>()(lm, hm))
+ { // Using Meas functor lessAbs again
+ cout << "lessAbs<Meas>()(lm, hm) " << lm << " < " << hm << endl;
+ }
+ if (Meas::lessAbsM(lm, hm))
+ { // Compare absolute value within uncertainty using Meas::lessAbsM function.
+ cout << "lessAbsM(lm, hm) " << lm << " < " << hm << endl;
+ }
+
+
+ int vCount = 0;
+ vector<URealUncorr> vs;
+ vector<Meas> vms;
+ vs.reserve(20); // More efficient than repeated push_backs.
+ cout << "Space reserved for " << vs.capacity() << " values." << endl;
+
+ string line; // = " 123.45 +/- 0.1 mA (99) ! description";
+ int lineCount = 0;
+ int valueCount = 0;
+ while(!fin.fail())
+ {
+ URealUncorr v;
+ Meas vm;
+ if (fin)
+ { // More to get.
+ getline(fin, line); // 1.1 1.2 1.0 1.1 ...
+ }
+ if (line.size() == 0) break; // Blank line (key return) to quit.
+ if (line.size() > 0)
+ { // Not a blank line.
+ ++lineCount;
+ fout << "Input line: " << line << endl; // Echo input line to file.
+ istringstream is(line);
+ do
+ {
+ is >> v; // Read uncertain "1.2" or "1.2 +/-0.05".
+ //cout << v << endl; // Echo input URealUncorr &
+ Meas vm(v, "", valueCount); // Assign order of measurements.
+ // No ID so far? time is default not_a_date_time.
+ valueCount++;
+ vs.push_back(v); // push onto the back of the UReal vector vs.
+ vms.push_back(vm); // push vm onto the back of the Meas vector vms.
+
+ if (is.eof() == true)
+ { // Tried to read more but no units given.
+ cout << "is.eof() == true" << " after " << v << "(no unit)." << endl;
+ break;
+ } // if
+ if (is.fail() == true)
+ { // Always seems to be fail == true when eof
+ cout << "is.fail == true!" << endl;
+ cout << v << "(no unit)." << endl;
+ break;
+ }
+ // int avail = is.rdbuf()->in_avail();
+ } // do
+ while (is.good() && (is.rdbuf()->in_avail() != 0));
+ } // Not blank line.
+ } // while
+ // cout << "vs.front() == " << vs.front() << ", vs.back() == " << vs.back() << endl;
+ // cout << "*vs.begin() == " << *vs.begin() << ", *vs.end() -1 == " << *(vs.end() -1) << endl;
+ // vector<URealUncorr>::ostream_iterator vi = vs.begin();
+ // ostream_iterator<URealUncorr> voi(cout, " ");
+ // ostream_iterator<URealUncorr> vi1(cout); // default delimiter.
+
+
+ vCount = vs.size()-1; // -1 becos 1st is expected uncertainty
+ double expectUncValue = vs[0].getValue(); // Expected +/- uncertainty.
+ float expectUncUnc = vs[0].getStdDeviation();
+ vs[0].setStdDeviation(float(vs[0].getValue() /10.));
+ vs[0].setDegFree(6);
+ URealUncorr expectUnc = vs[0];
+ cout << vCount << " values, with expected uncertainty "
+ << plusminus
+ //<< adddegfree
+ << addreplicates // Only show degrees of freedom > 1.
+ << expectUnc
+ << ", on " << lineCount << " lines." << endl;
+
+
+
+
+ // Output to file using copy.
+
+ setUncDefaults(fout);
+
+ fout << nl << vCount << " uncertain Values with expected uncertainty "
+ << plusminus
+ << addreplicates // show degrees of freedom if > 1.
+ << expectUnc
+ << "\n""Input from file:" << testInputFilename << endl;
+
+
+ copy(vs.begin() + 1, vs.end(), std::ostream_iterator<URealUncorr>(fout, "\n"));
+ // vs.begin() is vs[0] which is expected uncertainty.
+ fout << endl; // vs[1] = 1.10 1.20 1.00 ...
+
+ fout << vms.size() << " measurements " << endl;
+ copy(vms.begin() + 1, vms.end(), std::ostream_iterator<Meas>(fout, "\n"));
+ // vms.begin() is vs[0] which is expected uncertainty.
+ fout << endl; // vs[1] = 1.10 1.20 1.00 ...
+
+ if(true)
+ {
+ std::vector<URealUncorr>::iterator vuBegin = vs.begin() + 1; // 0th is expected unc.
+ std::vector<URealUncorr>::iterator vuEnd = vs.end();
+ URealUncorr total(0.);
+ total = accumulate(vuBegin, vuEnd, total);
+ setUncDefaults(cout);
+ cout << total << endl;
+ sort(vuBegin, vuEnd);
+ sort(vuBegin, vuEnd, lessAbs<URealUncorr>() ); // Functor using binary_function in <functional>
+ sort(vuBegin, vuEnd, URealUncorr::lessU ); // static member function
+ sort(vuBegin, vuEnd, URealUncorr::moreU );
+ //sort(vuBegin, vuEnd, URealUncorr::equalU ); // asserts invalid operator<
+ }
+
+ // Now calculate mean and check for outliers etc.
+ { // Sum uncertain values using while loop.
+ cout << vCount << " Uncertain Values:" << plusminus << addlimits << endl;
+ std::vector<URealUncorr>::iterator vi = vs.begin() + 1;
+ // +1 because 0th value is expected uncertainty.
+ unsigned int i = 0;
+ URealUncorr sum(0.);
+ while(vi != vs.end())
+ {
+ sum += *vi;
+ ++i; // # number from 1 to n
+ cout << "Value #" << i << space << *vi
+ // << ", sum " << sum
+ << nl; // Value 1 1.10, ...
+ ++vi;
+ } // while, leaving vi == vs.end();
+ if ( i != (vs.size() - 1) ) // Check i is correct.
+ cout << i << space << vs.size() << endl;
+ cout << "mean = " << sum / i << endl;
+ }
+
+ std::ostream_iterator<Meas> osmit(cout, ", "); // Set up iterator and comma separator.
+ cout.iword(uncFlagsIndex) &= ~plusMinus; // clear bit 3 = 0 to mean Do NOT add +/-.
+ cout << showuncflags << endl;
+ cout << nl << "plusMinus " << noplusminus << nolimits << showuncflags << endl;
+
+ // Examples of sorting by various criteria.
+ sort(vms.begin() +1, vms.end()); // begin and (past the) end.
+ cout << "Sorted Meas vector using default operator<." << nl;
+ copy(vms.begin() +1, vms.end(), osmit); // using std::ostream_iterator osmit for 1-based.
+ cout << endl;
+
+ //sort(vms.begin() +1, vms.end(), less); // begin at [1] and (past the) end.
+ // cannot deduce template arguments. Should be Meas::less
+
+
+ // Using other member functors precedes and lessU
+ //bool Meas::precedes(const Meas& l, const Meas& r); // Needs to be static member function.
+ sort(vms.begin() +1, vms.end(), Meas::precedes); // Sort by m_order.
+ cout << "Sorted by order using static member functor Meas::precedes." << nl;
+ copy(vms.begin() +1, vms.end(), osmit); cout << endl;
+
+ cout << nl << "plusMinus " << plusminus << showuncflags << endl;
+ cout << vs.at(1) << endl;
+
+ // Demo use of:
+// bool Meas::precedes(const Meas& l, const Meas& r); // Needs to be static member function.
+// bool Meas::lessU(const Meas& l, const Meas& r); // Needs to be static member function.
+// bool Meas::lessU2(const Meas& l, const Meas& r); // Needs to be static member function.
+
+ sort(vms.begin() +1, vms.end(), Meas::precedes); // Sort by m_order.
+
+ sort(vms.begin() +1, vms.end()); // begin at [1] and (past the) end.
+ cout << "Sorted by value using static member functor Meas::less." << nl;
+ copy(vms.begin() +1, vms.end(), osmit); cout << nl << endl;
+ sort(vms.begin() +1, vms.end(), Meas::precedes); // Sort by m_order.
+ cout << "Sorted by order using static member functor Meas::precedes." << nl;
+ copy(vms.begin() +1, vms.end(), osmit); cout << nl << endl;
+
+ sort(vms.begin() +1, vms.end(), Meas::lessU); // Sort by uncertain value within 1 sd.
+ cout << "Sorted by uncertain value using static member functor Meas::lessU." << nl;
+ copy(vms.begin() +1, vms.end(), osmit); cout << nl << endl;
+
+ sort(vms.begin() +1, vms.end(), Meas::lessU2); // Sort by uncertain value within 2 sd.
+ cout << "Sorted by uncertain value using static member functor Meas::lessU2." << nl;
+ copy(vms.begin() +1, vms.end(), osmit); cout << nl<< endl;
+
+ sort(vms.begin() +1, vms.end(), Meas::lessAbsM); // begin at [1] and (past the) end.
+ cout << "Sorted using functor lessAbsM." << nl;
+ copy(vms.begin() +1, vms.end(), osmit); cout<< nl << endl;
+
+
+
+ // Now consider use of Wilcoxon test.
+ fin.close(); // Input file.
+ fout.close(); // Output file.
+ cout << '\n' << __FILE__ << " ended " << __TIMESTAMP__ << endl;
+} // BOOST_AUTO_TEST_CASE(quan1_test_3)
+
+ //return 0;
+
+
+/*
+
+
+*/
+ /*
+ { // Output to console using while loop.
+ cout << vCount << " Uncertain Values input from file:" << plusminus << adddegfree << endl;
+ std::vector<URealUncorr>::iterator vi = vs.begin() + 1; // 0th value is expected uncertainty.
+ int i = 1;
+ while(vi != vs.end())
+ {
+ // cout << "Value " << i << space << *vi << endl; // Value 1 1.10, ...
+ ++i;
+ ++vi;
+ } // while, leaving vi == vs.end();
+ }
+ // Copy to two C arrays containing separate values and uncertainties.
+ // Use vector or valarray instead?
+ double* vvs = new double[vCount+1]; // Values.
+ float* vus = new float[vCount+1]; // Uncertainties.
+ { // Output using for loop.
+ int count = 1;
+ for (std::vector<URealUncorr>::iterator vi = vs.begin()+1; vi != vs.end(); ++vi, ++count)
+ {
+ cout << "Value #" << count << space << *vi << space; // "Value# 1 1.10 implicit"
+ cout << (((*vi).getUncTypes() & UNC_IMPLICIT) ? "implicit" : "explicit") << endl;
+ vvs[count] = (*vi).getValue();
+ vus[count] = (*vi).getStdDeviation();
+ } // for
+ cout << endl; // Value 2 1.20 Value 3 1.00
+ }
+
+ cout << setprecision(16) << endl; // full precision, including noisy digit.
+
+ { // Check against expected uncertainty using a for loop.
+ int count = 1;
+ for (std::vector<URealUncorr>::iterator vi = vs.begin()+1; vi != vs.end(); ++vi, ++count)
+ {
+ if ((vus[count] - expectUncValue) > expectUncUnc ) // absolute uncertainty.
+ {
+ bool im = ((*vi).getUncTypes() & UNC_IMPLICIT);
+ cout << "Value " << count << space << *vi << ", "
+ << (((*vi).getUncTypes() & UNC_IMPLICIT) ? "implicit" : "explicit")
+ << " uncertainty "
+ << vus[count]
+ << " is greater than expected "<< vs[0] << '!' << endl;
+ }
+ } // for
+ }
+
+ delete[] vvs; // Need explicit destruction.
+ delete[] vus;
+ */ // Change in global locale, and thus that imbued to input and output,
+ // used to check that uncertainRead and uncertainPrint
+ // do fail (as expected) for input 1.23.
+
+ //locale krautLocale(std::locale::classic(), locale("German_Germany"), locale::numeric | locale::monetary); // category
+ //locale::global(krautLocale);
+ //// making decimal point a comma not a period.
+ ////locale krautLocale("German_Germany");
+ //locale aussieLocale ("English_Australia");
+ //locale frogLocale("French");
+ //BOOST_CHECK(use_facet<ctype<char> >(aussieLocale).is(std::ctype_base::alpha, 'a') == true);
+
+ //const numpunct <char>& npunctK = use_facet <numpunct <char> >(krautLocale);
+ //cout << krautLocale.name( ) << " truename "<< npunctK.truename() << endl;
+ //cout << aussieLocale.name( ) << " falsename "<< npunctK.falsename() << endl;
+ //BOOST_CHECK(npunctK.decimal_point() == ',');
+
+ //BOOST_CHECK(use_facet <numpunct <char> >(frogLocale).truename() == "true");
+ //BOOST_CHECK(use_facet <numpunct <char> >(aussieLocale).decimal_point() == '.');
+
+ //cout.imbue(locale("German_Germany")); // X Open == De_DE
+ //URealUncorr v(1.234, 0.002F, 20);
+ //cout << " v(1.234, 0.002, 20) == "<< v << endl; // v(1.234, 0.002, 20) == 1,2340 Note , !
+
+/*
+
+other code to handle file input?
+
+{
+ std::vector<URealUncorr> vs(4);
+ cout << "Space for " << vs.size() << " values." << endl;
+ int vNumber = 0;
+ for (std::vector<URealUncorr>::iterator it = vs.begin();
+ it != vs.end(); ++it, ++vNumber)
+ { // do all tests.
+ vs[vNumber] = *it;
+ cout << "vs " << vNumber << ": " << *it << ' ';
+ istringstream myIstream(line); // " 1.2 +/- 0.1 ";
+ // Read value and deduce if int or real, and implied uncertainty.
+ // 1, 10, 100, 1000 imply exact integer.
+ // 100. implies 100.0 +/- 0.5
+ // 100.0 +/- 5.0 , 100 +/- 50 can only be input with explicit +/-
+ // 100.0 implies 100.00 +/- 0.05
+ // 1.0 & 1.1 implies +/- 0.05
+ // 1.10 & 1.23 implies +/- 0.005
+ // Can't fractional part as int because leading zero is significant.
+ // Can read first part before . as an int cos leading zeros carry no info.
+
+ int avail = myIstream.rdbuf()->in_avail();
+ // cout << " (" << avail << ") ";
+ if (avail == 0)
+ {
+ cerr << "No input!" << endl;
+ }
+ }
+}
+
+// bool operator<(const MyInt& x) const { return _value < x._value; }
+// bool operator==(const MyInt& x) const { return _value == x._value; }
+
+
+------ Build started: Project: Quan1, Configuration: Debug Win32 ------
+ Running 4 test cases...
+ Platform: Win32
+ Compiler: Microsoft Visual C++ version 10.0
+ STL : Dinkumware standard library version 520
+ Boost : 1.49.0
+ Quan1 test: TestQuan1.cpp at "Wed Jan 18 12:44:01 2012", MSVC version 160040219.
+ Quan1 Test output to Quan1Out.txt Wed Jan 18 12:44:01 2012
+ Quan1 input from Quan1In.txt Wed Jan 18 12:44:01 2012
+ top of lower 1.1 = 1.2
+ bottom of higher 1.1 = 1
+ sqrt_sumsquares sds = 0.141421
+ Difference of values in max sds between 1.10 +/-0.2 and 1.10 +/-0.2 == 0
+ Difference in sds between 1.10 +/-0.2 and 1.10 +/-0.2 == 0
+ Difference in sds between 1.40 +/-0.2 and 1.10 +/-0.2 == 2.12132
+ Difference in sds between 1.60 +/-0.2 and 1.10 +/-0.2 == 3.53553
+ Means 1.10 +/-0.2 1.40 +/-0.2, Difference of means is 0.30 +/-0.3
+ SDs 0.1 0.1
+ hypot sds 0.141421
+ Degrees of freedom 1 1
+ Standard errors 0.01 0.01, mean se 0.01 sqrt() 0.141421
+ Variances 0.01 0.01
+ variance/df 0.01 0.01
+ df top 0.0004
+ df bot 0.0002
+ df 2
+ sqrt(varlln + varhhn) 0.141421
+ Student's t 2.12132, df 2
+ l == h
+ (less<double>(1.2, 3.4 ))
+ Test member predicate function 1.10 +/-0.2 < 1.10 +/-0.2
+ (lessUnc(l, h)) l ~= h
+ l 1.10 +/-0.2 ~= h 1.10 +/-0.2
+ ll 1.10 +/-0.2 != hh 1.40 +/-0.2
+ l 1.10 +/-0.2 ~= h 1.10 +/-0.2
+ ll 1.10 +/-0.2 ~= hh 1.40 +/-0.2
+ Testing static memberfunction predicate lessU<isCorrelated>
+ 1.10 +/-0.2 is < 1.40 +/-0.2
+ lc < hc
+ 1.10 +/-0.2 is < 1.40 +/-0.2
+ lessU 1.1 1.2 >= 1 1.14142 1.1 0.141421 0.2
+ lessU 1.1 1.2 < 1.3 1.44142 1.4 0.141421 -0.1
+ lessU 1 1 < 2 2 2 0 -1
+ lessU 1.1 1.2 < 1.3 1.44142 1.4 0.141421 -0.1
+ lessU 1.1 1.3 < 1.2 1.48284 1.4 0.282843 0.1
+ lessU 1.1 1.3 < 1.4 1.68284 1.6 0.282843 -0.1
+ lessU 0 0 < 1.3 1.4 1.4 0.1 -1.3
+ lessU 1.1 1.2 < 99 99.1 99 0.1 -97.8
+ 1.10 +/-0.2 is << 1.40 +/-0.2
+ 1.10 +/-0.2 is << 1.60 +/-0.2
+ 0. < 1.40 +/-0.2
+ 1.10 +/-0.2 is < 99. +/-0
+ 1.10 +/-0.2 is <= 99. +/-0
+ 1.10 +/-0.2 is ~= 1.10 +/-0.2
+ Space reserved for 20 values.
+ is.eof() == true after 1.1000 +/-0.001(no unit).
+ is.eof() == true after 0.9700 +/-0.005(no unit).
+ 6 values, with expected uncertainty 0.0500 +/-0.01, on 3 lines.
+ 6.620
+ 6 Uncertain Values:
+ Value #1 1.2500 +/-0.003
+ Value #2 1.20 +/-0.03
+ Value #3 1.10 +/-0.03
+ Value #4 1.1000 +/-0.001
+ Value #5 1.00 +/-0.03
+ Value #6 0.9700 +/-0.005
+ mean = 1.103 +/-0.007
+
+
+ plusMinus
+ Sorted Meas vector using default operator<.
+ 0.97 # 6, 1 # 3, 1.1 # 1, 1.1 # 4, 1.2 # 2, 1.25 # 5,
+ Sorted by order using static member functor Meas::precedes.
+ 1.1 # 1, 1.2 # 2, 1 # 3, 1.1 # 4, 1.25 # 5, 0.97 # 6,
+
+ plusMinus
+ 1.2500 +/-0.003
+ Sorted by value using static member functor Meas::less.
+ 0.97 # 6, 1 # 3, 1.1 # 1, 1.1 # 4, 1.2 # 2, 1.25 # 5,
+
+ Sorted by order using static member functor Meas::precedes.
+ 1.1 # 1, 1.2 # 2, 1 # 3, 1.1 # 4, 1.25 # 5, 0.97 # 6,
+
+ Sorted by uncertain value using static member functor Meas::lessU.
+ 0.97 # 6, 1 # 3, 1.1 # 1, 1.1 # 4, 1.2 # 2, 1.25 # 5,
+
+ Sorted by uncertain value using static member functor Meas::lessU2.
+ 0.97 # 6, 1 # 3, 1.1 # 1, 1.1 # 4, 1.2 # 2, 1.25 # 5,
+
+ Sorted using functor lessAbsM.
+ 0.97 # 6, 1 # 3, 1.1 # 1, 1.1 # 4, 1.2 # 2, 1.25 # 5,
+
+
+ TestQuan1.cpp ended Wed Jan 18 12:44:01 2012
+ lessU 1 1.0125 >= 0.9675 0.980248 0.97 0.0127475 0.045
+ lessU 1 1.0125 >= 0.9675 0.980248 0.97 0.0127475 0.045
+ lessU 1.1 1.1125 >= 0.9675 0.980248 0.97 0.0127475 0.145
+ lessU 1.1 1.1125 >= 0.9875 1.00518 1 0.0176777 0.125
+ lessU 1.1 1.1005 >= 0.9675 0.97005 0.97 0.00254951 0.133
+ lessU 1.1 1.1005 >= 1.0875 1.10001 1.1 0.01251 0.013
+ lessU 1.2 1.2125 >= 0.9675 0.980248 0.97 0.0127475 0.245
+ lessU 1.2 1.2125 >= 1.0995 1.11201 1.1 0.01251 0.113
+ lessU 1.25 1.25125 >= 0.9675 0.970295 0.97 0.00279509 0.28375
+ lessU 1.25 1.25125 >= 1.1875 1.20006 1.2 0.0125623 0.06375
+ MU #2 1.2 1.2 >= 1.1 1.1 #1 1.1
+ MU #2 1.2 1.2 >= 1.1 1.1 #1 1.1
+ MU #3 1 1 < 1.1 1.1 #1 1.1
+ MU #1 1.1 1.1 >= 1 1 #3 1
+ MU #4 1.1 1.1 >= 1 1 #3 1
+ MU #4 1.1 1.1 < 1.2 1.2 #2 1.2
+ MU #2 1.2 1.2 >= 1.1 1.1 #4 1.1
+ MU #4 1.1 1.1 >= 1.1 1.1 #1 1.1
+ MU #5 1.25 1.25 >= 1 1 #3 1
+ MU #5 1.25 1.25 >= 1.2 1.2 #2 1.2
+ MU #6 0.97 0.97 < 1 1 #3 1
+ MU #3 1 1 >= 0.97 0.97 #6 0.97
+ U2 #3 1 1 >= 0.97 0.97 #6 0.97
+ U2 #3 1 1 >= 0.97 0.97 #6 0.97
+ U2 #1 1.1 1.1 >= 0.97 0.97 #6 0.97
+ U2 #1 1.1 1.1 >= 1 1 #3 1
+ U2 #4 1.1 1.1 >= 0.97 0.97 #6 0.97
+ U2 #4 1.1 1.1 >= 1.1 1.1 #1 1.1
+ U2 #2 1.2 1.2 >= 0.97 0.97 #6 0.97
+ U2 #2 1.2 1.2 >= 1.1 1.1 #4 1.1
+ U2 #5 1.25 1.25 >= 0.97 0.97 #6 0.97
+ U2 #5 1.25 1.25 >= 1.2 1.2 #2 1.2
+
+ *** No errors detected
+========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
+
+
+
+*/
\ No newline at end of file

Added: sandbox/SOC/2007/quan/libs/quan/test/test_rounding.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/libs/quan/test/test_rounding.cpp 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,1432 @@
+/*!
+ \file
+ \brief Tests of Common rounding.
+ \details
+ http://www.diycalculator.com/popup-m-round.shtml#A3
+ all rounding types, including round-to-half and asymmetric and symmetric versions.\n
+ http://www.chem1.com/acad/webtext/pre/mm3.html
+ "The purpose in rounding off is to avoid expressing a value to a greater degree of precision
+ than is consistent with the uncertainty in the measurement."\n
+ "Observed values should be rounded off to the number of digits
+ that most accurately conveys the uncertainty in the measurement."
+ \date Oct 09, May 12
+ \author Paul A. Bristow
+*/
+
+// \file test_rounding_cout.hpp
+
+// Copyright Paul A. Bristow 2009, 2012.
+
+// Use, modification and distribution are subject to 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) // Boost.Test
+
+#define BOOST_TEST_MAIN
+// #define BOOST_LIB_DIAGNOSTIC "on" // Report Boost.Test library file details.
+
+#include <boost/static_assert.hpp>
+
+#include <boost/test/unit_test.hpp>
+ using boost::unit_test::test_suite;
+ using boost::unit_test::unit_test_log;
+
+using boost::unit_test_framework::unit_test_log;
+using boost::unit_test_framework::log_level;
+
+#include <boost/quan/rounding.hpp>
+
+#include <iostream>
+ using std::cout;
+ using std::cerr;
+ using std::cin;
+ using std::endl;
+ using std::ends;
+ using std::dec;
+ using std::hex;
+ using std::fixed;
+ using std::left;
+ using std::right;
+ using std::showpoint;
+ using std::defaultfloat;
+ using std::scientific;
+ using std::boolalpha;
+ using std::showpos;
+ using std::noshowpos;
+
+#include <iomanip>
+ using std::setprecision;
+ using std::setw;
+#include <string>
+ using std::string;
+
+#include <fstream> // for fstream
+ using std::fstream;
+ using std::ofstream;
+
+#include <sstream> // stream
+ using std::ostringstream;
+ using std::string;
+ using std::basic_string;
+ using std::ios_base;
+
+#include <limits>
+ using std::numeric_limits;
+
+BOOST_STATIC_ASSERT (std::numeric_limits<double>::is_iec559); // Assume IEEE 754 ONLY.
+// _STATIC_ASSERT (numeric_limits<double>::is_iec559); // and MS STATIC assert.
+
+ // const unsigned int maxdigits10 = 2 + std::numeric_limits<double>::digits * 3010/10000;
+ const double eps = std::numeric_limits<double>::epsilon();
+ const int digits10 = std::numeric_limits<double>::digits10;
+
+ const double tol = 0.001; // Fractional tolerance for BOOST_CHECK_CLOSE_FRACTION.
+
+BOOST_AUTO_TEST_CASE(round_test_0)
+{
+ //BOOST_CHECK_EQUAL(round_ms(12345, 1), "12345."); // 3 significant digits, so rounder digit is '8', and m is +1
+}
+
+BOOST_AUTO_TEST_CASE(round_test_1)
+{ // Round to cout tests.
+
+ string message("Round test: " __FILE__ );
+#ifdef __TIMESTAMP__
+ message += " at " BOOST_STRINGIZE(__TIMESTAMP__);
+#endif
+#ifdef _MSC_FULL_VER
+ message += ", MSVC version " BOOST_STRINGIZE(_MSC_FULL_VER) ".";
+#else
+ message += "."
+#endif
+
+ BOOST_MESSAGE(message);
+ BOOST_MESSAGE("double maxdigits10 is " << maxdigits10);
+ cout << "std::numeric_limits<double>::max_exponent = " << std::numeric_limits<double>::max_exponent
+ << ", \nstd::numeric_limits<double>::max_exponent10 = " << std::numeric_limits<double>::max_exponent10
+ << ",\nstd::numeric_limits<double>::max_exponent10 -1 = "<< std::numeric_limits<double>::max_exponent10 -1 << ". " << endl;
+ // std::numeric_limits<double>::max_exponent = 1024,
+ // std::numeric_limits<double>::max_exponent10 = 308,
+ // std::numeric_limits<double>::max_exponent10 -1 = 307.
+#ifdef _MSC_VER
+ BOOST_CHECK_EQUAL(maxdigits10, 17U);
+#endif
+
+ // Experiments to see if a special meaning can be assigned to BOTH fixed and scientific.
+ // BUT the std::hex display option added with TR1
+ // means CANNOT use this mechanism.
+ // #define _IOShexfloat 0x3000 // added with TR1.
+ // Last top Bit 15 also appears used, so MUST use uncflags for controlling scaling etc.
+
+ //std::ios_base::fmtflags fs = cout.flags();
+ //cout << hex << "cout.flags() " << (cout.flags() & std::ios_base::floatfield) << endl;
+ //cout << "std::ios::fixed "<< std::ios::fixed << fixed << endl;
+ //cout << hex << "cout.flags() " << (cout.flags() & std::ios_base::floatfield) << endl;
+ //cout << "std::ios::scientific "<< std::ios::scientific << scientific << endl;
+ //cout << hex << "cout.flags() " << (cout.flags() & std::ios_base::floatfield) << endl;
+
+ //cout.setf(std::ios::fixed | std::ios::scientific, std::ios_base::floatfield);
+ //cout.setf(std::ios::fixed | std::ios::scientific);
+ //cout << hex << "cout.flags() = " << (cout.flags() & std::ios_base::floatfield) << endl;
+ // so need a extra 'special' manipulator to set BOTH scientific AND fixed.
+} // BOOST_AUTO_TEST_CASE(round_test_1)
+
+
+
+BOOST_AUTO_TEST_CASE(round_f_test)
+{
+ // Removed as assume can do scaling with Boost,Units autoscaling.
+ //{ // Test unc scaling to scientific and engineering powers.
+ // scaled = true;
+ // BOOST_CHECK_EQUAL(round_f(123.4567, 3), "123."); // No trailing space.
+ // BOOST_CHECK_EQUAL(round_f(1234.567, 3), "1.23 k");
+ // BOOST_CHECK_EQUAL(round_f(12345678.9, 3), "12.3 M");
+ // BOOST_CHECK_EQUAL(round_f(123456789., 4), "123.5 M");
+ // BOOST_CHECK_EQUAL(round_f(1234567890., 6), "1.23457 G");
+ // scaled = false;
+ //}
+ { // Test round_f.
+ // round_f is fixed format.
+ double v = 1.23456; // Value to test rounded output.
+ BOOST_CHECK_EQUAL(round_f(v, 0), ""); // With message "Trying to output zero significant digits!".
+ BOOST_CHECK_EQUAL(round_f(v, -1), ""); // With message "Trying to output -1 significant digits!".
+ BOOST_CHECK_EQUAL(round_f(v, 1), "1."); //
+ BOOST_CHECK_EQUAL(round_f(v, 2), "1.2"); //
+ BOOST_CHECK_EQUAL(round_f(v, 3), "1.23"); //
+ BOOST_CHECK_EQUAL(round_f(v, 4), "1.235"); //
+ BOOST_CHECK_EQUAL(round_f(v, 5), "1.2346"); //
+ BOOST_CHECK_EQUAL(round_f(v, 6), "1.23456"); //
+ BOOST_CHECK_EQUAL(round_f(v, 7), "1.234560"); //
+ BOOST_CHECK_EQUAL(round_f(v, 8), "1.2345600"); //
+ BOOST_CHECK_EQUAL(round_f(v, 9), "1.23456000"); //
+ BOOST_CHECK_EQUAL(round_f(v, 10), "1.234560000"); //
+ BOOST_CHECK_EQUAL(round_f(v, 11), "1.2345600000"); //
+ BOOST_CHECK_EQUAL(round_f(v, 12), "1.23456000000"); //
+ BOOST_CHECK_EQUAL(round_f(v, 13), "1.234560000000"); //
+ BOOST_CHECK_EQUAL(round_f(v, 14), "1.2345600000000"); // Maximum significant digits -1
+ BOOST_CHECK_EQUAL(round_f(v, 15), "1.23456000000000"); //
+ // Message is "Maximum significant digits is 15" - and several repeats.
+ BOOST_CHECK_EQUAL(round_f(v, 16), "1.23456000000000"); // Maximum significant digits is 15
+ BOOST_CHECK_EQUAL(round_f(v, 17), "1.23456000000000"); // Maximum significant digits is 15
+ BOOST_CHECK_EQUAL(round_f(v, std::numeric_limits<double>::digits10), "1.23456000000000"); //
+ BOOST_CHECK_EQUAL(round_f(v, maxdigits10), "1.23456000000000"); // Maximum significant digits is 15 (should be std::numeric_limits<double>::maxdigits10).
+
+ v = 1.23456789012345678901234567890; // Check that all the digits are used, and rounded at digit 15
+ BOOST_CHECK_EQUAL(round_f(v, maxdigits10), "1.23456789012346"); // Maximum significant digits is 15 (should be std::numeric_limits<double>::maxdigits10).
+
+ v = 0.12345678901234567890; // Value < unity.
+ BOOST_CHECK_EQUAL(round_f(v, 1), "0.1"); //
+ BOOST_CHECK_EQUAL(round_f(v, 2), "0.12"); //
+ BOOST_CHECK_EQUAL(round_f(v, 3), "0.123"); //
+ BOOST_CHECK_EQUAL(round_f(v, digits10-10), "0.12346"); // 5
+ BOOST_CHECK_EQUAL(round_f(v, 13), "0.1234567890123"); // 13
+ BOOST_CHECK_EQUAL(round_f(v, digits10 -2), "0.1234567890123"); // 13
+ BOOST_CHECK_EQUAL(round_f(v, 14), "0.12345678901235"); // 14
+ BOOST_CHECK_EQUAL(round_f(v, digits10 -1), "0.12345678901235"); // 14
+ BOOST_CHECK_EQUAL(round_f(v, maxdigits10), "0.123456789012346"); // Maximum significant digits is 15 (should be std::numeric_limits<double>::maxdigits10).
+
+ v = 0.0012345678901234567890; // Value much less than unity.
+ BOOST_CHECK_EQUAL(round_f(v, 1), "0.001"); //
+ BOOST_CHECK_EQUAL(round_f(v, 2), "0.0012"); //
+ BOOST_CHECK_EQUAL(round_f(v, 3), "0.00123"); //
+ BOOST_CHECK_EQUAL(round_f(v, 4), "0.001235"); //
+ BOOST_CHECK_EQUAL(round_f(v, 10), "0.001234567890"); //
+ BOOST_CHECK_EQUAL(round_f(v, 11), "0.0012345678901"); //
+ BOOST_CHECK_EQUAL(round_f(v, 12), "0.00123456789012"); //
+ BOOST_CHECK_EQUAL(round_f(v, 13), "0.001234567890123"); //
+ BOOST_CHECK_EQUAL(round_f(v, 14), "0.0012345678901235"); //
+ BOOST_CHECK_EQUAL(round_f(v, digits10), "0.00123456789012346"); //
+ BOOST_CHECK_EQUAL(round_f(v, maxdigits10), "0.00123456789012346"); //
+
+ v = 12345678901234567890.0; // Value > max_digits10 digits.
+ BOOST_CHECK_EQUAL(round_f(v, 4), "12350000000000000000.");
+ BOOST_CHECK_EQUAL(round_f(v, 10), "12345678900000000000.");
+ BOOST_CHECK_EQUAL(round_f(v, maxdigits10), "12345678901234600000.");
+
+ v = 0.0000000012345678901234567890; // Value < max_digits10 digits.
+ BOOST_CHECK_EQUAL(round_f(v, 4), "0.000000001235"); //
+
+ // Value max and min.
+ v = (std::numeric_limits<double>::max)(); // 1.797693134862316e+308
+ BOOST_CHECK_EQUAL(round_f(v, 4), "179800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000."); //
+ v = (std::numeric_limits<double>::min)();// 2.2250738585072014e-308
+ BOOST_CHECK_EQUAL(round_f(v, 4), "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002225"); //
+ }
+} //BOOST_AUTO_TEST_CASE(round_f_test)
+
+
+BOOST_AUTO_TEST_CASE(round_e_test) // Test round_e.
+{ // round_e is scientific or exponential format.
+ {
+ double d = 1.1234012340123401234; // No carry examples.
+
+ BOOST_CHECK_EQUAL(round_e(d, 1), "1.");
+ BOOST_CHECK_EQUAL(round_e(d, 2), "1.1");
+ BOOST_CHECK_EQUAL(round_e(d, 3), "1.12");
+ BOOST_CHECK_EQUAL(round_e(d, 4), "1.123"); // 4 sigdigits.
+ BOOST_CHECK_EQUAL(round_e(d, 5), "1.1234"); // 5 sigdigits.
+ BOOST_CHECK_EQUAL(round_e(d, 6), "1.12340"); //6 sigdigits.
+ BOOST_CHECK_EQUAL(round_e(d, digits10-1), "1.1234012340123"); // 14 sigdigits.
+ BOOST_CHECK_EQUAL(round_e(d, digits10), "1.12340123401234"); // 15 sigdigits.
+ BOOST_CHECK_EQUAL(round_e(d, maxdigits10), "1.12340123401234"); // 15 sigdigits, because reached digits10.
+ BOOST_CHECK_EQUAL(round_e(d, maxdigits10+1), "1.12340123401234"); // 15 sigdigits, because reached digits10.
+ BOOST_CHECK_EQUAL(round_e(d, maxdigits10+2), "1.12340123401234"); // 15 sigdigits, because reached digits10.
+ }
+
+ {
+ double d = 1.12345678901234567890; //
+
+ //cout << "round_e(d, 1); " << round_e(d, 1); // 1.
+ //cout << "round_e(d, 2); " << round_e(d, 2); // 1.1
+ //cout << "round_e(d, 3); " << round_e(d, 3); // 1.12
+ //cout << "round_e(d, 4); "<< round_e(d, 4); // 1.123
+ //cout << "round_e(d, 5); "<< round_e(d, 5); // 1.1234
+ //cout << "round_e(d, 6); "<< round_e(d, 6); // 1.12340
+ //cout << "round_e(d, digits10); "<< round_e(d, digits10); //
+ //cout << "round_e(d, digits10); "<< round_e(d, maxdigits10); //
+
+ BOOST_CHECK_EQUAL(round_e(d, 1), "1."); // 1 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 2), "1.1"); // 2 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 3), "1.12"); // 3 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 4), "1.123"); // 4 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 5), "1.1235"); // 5 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 6), "1.12346"); // 6 digits.
+
+ BOOST_CHECK_EQUAL(round_e(d, 11), "1.1234567890"); // 11 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 12), "1.12345678901"); // 12 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 13), "1.123456789012"); // 13 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 14), "1.1234567890123"); // 14 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 15), "1.12345678901235"); // 15 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 16), "1.12345678901235"); // 15 digits, because reached digits10.
+ BOOST_CHECK_EQUAL(round_e(d, 17), "1.12345678901235"); // 15 digits, because reached digits10.
+ BOOST_CHECK_EQUAL(round_e(d, 18), "1.12345678901235"); // 15 digits, because reached digits10.
+ }
+ {
+ double d = 0.99999999999999999; // Round to before decimal point.
+ // cout << setprecision(4) << showpoint << d << endl; // 1.000
+ BOOST_CHECK_EQUAL(round_e(d, 1), "1."); // 1 digit.
+ BOOST_CHECK_EQUAL(round_e(d, 2), "1.0"); // 2 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 3), "1.00"); // 3 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 4), "1.000"); // 4 digits.
+ // ...
+ BOOST_CHECK_EQUAL(round_e(d, 15), "1.00000000000000"); // 15 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 16), "1.00000000000000"); // 15 digits, because reached digits10.
+ BOOST_CHECK_EQUAL(round_e(d, 17), "1.00000000000000"); // 15 digits, because reached digits10.
+ BOOST_CHECK_EQUAL(round_e(d, 18), "1.00000000000000"); // 15 digits, because reached digits10.
+ }
+
+ {
+ double d = 19.999999999999999; // Actually 2.00000000000000
+ BOOST_CHECK_EQUAL(round_e(d, 1), "2.e1"); // 1 digit.
+ BOOST_CHECK_EQUAL(round_e(d, 2), "2.0e1"); // 2 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 3), "2.00e1"); // 3 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 4), "2.000e1"); // 4 digits.
+ //...
+ BOOST_CHECK_EQUAL(round_e(d, 15), "2.00000000000000e1"); // 15 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 16), "2.00000000000000e1"); // 15 digits, because reached digits10.
+ BOOST_CHECK_EQUAL(round_e(d, 17), "2.00000000000000e1"); // 15 digits, because reached digits10.
+ BOOST_CHECK_EQUAL(round_e(d, 18), "2.00000000000000e1"); // 15 digits, because reached digits10.
+ }
+ {
+ double d = 19.99; // Roundable.
+ BOOST_CHECK_EQUAL(round_e(d, 1), "2.e1"); // 1 digit.
+ BOOST_CHECK_EQUAL(round_e(d, 2), "2.0e1"); // 2 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 3), "2.00e1"); // 3 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 4), "1.999e1"); // 4 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 5), "1.9990e1"); // 5 digits, last is trailing significant zero.
+ //...
+ BOOST_CHECK_EQUAL(round_e(d, 15), "1.99900000000000e1"); // 15 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 16), "1.99900000000000e1"); // 15 digits, because reached digits10.
+ BOOST_CHECK_EQUAL(round_e(d, 17), "1.99900000000000e1"); // 15 digits, because reached digits10.
+ BOOST_CHECK_EQUAL(round_e(d, 18), "1.99900000000000e1"); // 15 digits, because reached digits10.
+ }
+ { // Positive exponent.
+ double d = 9.9e+2; // 990
+ //cout << setprecision(1) << fixed << d << endl; // 990.0
+ //cout << setprecision(1) << scientific << d << endl; // 9.9e+002
+ //cout << setprecision(0) << scientific << d << endl; // 9.9e+002
+ BOOST_CHECK_EQUAL(round_e(d, 1), "1.e3"); // 1 digit, rounded.
+ BOOST_CHECK_EQUAL(round_e(d, 2), "9.9e2"); // 2 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 3), "9.90e2"); // 3 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 4), "9.900e2"); // 4 digits.
+ }
+
+ { // Big positive exponent.
+ double d = 9.9e+20; // 990
+ //cout << setprecision(1) << fixed << d << endl; // 990000000000000000000.0
+ //cout << setprecision(1) << scientific << d << endl; // 9.9e+020
+ //cout << setprecision(0) << scientific << d << endl; // 9.9e+020
+ BOOST_CHECK_EQUAL(round_e(d, 1), "1.e21"); // 1 digit, rounded.
+ BOOST_CHECK_EQUAL(round_e(d, 2), "9.9e20"); // 2 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 3), "9.90e20"); // 3 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 4), "9.900e20"); // 4 digits.
+ }
+
+ { // Very big positive exponent.
+ double d = 9.9e+123; //
+ //cout << setprecision(1) << fixed << d << endl; // 990000000000000000000.0
+ //cout << setprecision(1) << scientific << d << endl; // 9.9e+020
+ //cout << setprecision(0) << scientific << d << endl; // 9.9e+020
+ BOOST_CHECK_EQUAL(round_e(d, 1), "1.e124"); // 1 digit, rounded.
+ BOOST_CHECK_EQUAL(round_e(d, 2), "9.9e123"); // 2 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 3), "9.90e123"); // 3 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 4), "9.900e123"); // 4 digits.
+ }
+
+ { // Negative exponent.
+ double d = 9.9e-2;
+ //cout << setprecision(1) << fixed << d << endl; // 0.1
+ //cout << setprecision(1) << scientific << d << endl; // 9.9e-002
+ BOOST_CHECK_EQUAL(round_e(d, 1), "1.e-1"); // 1 digit, rounded.
+ BOOST_CHECK_EQUAL(round_e(d, 2), "9.9e-2"); // 2 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 3), "9.90e-2"); // 3 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 4), "9.900e-2"); // 4 digits.
+ }
+
+ { // Big negative exponent.
+ double d = 9.9e-20;
+ //cout << setprecision(1) << fixed << d << endl; // 0.1
+ //cout << setprecision(1) << scientific << d << endl; // 9.9e-002
+ BOOST_CHECK_EQUAL(round_e(d, 1), "1.e-19"); // 1 digit, rounded.
+ BOOST_CHECK_EQUAL(round_e(d, 2), "9.9e-20"); // 2 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 3), "9.90e-20"); // 3 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 4), "9.900e-20"); // 4 digits.
+ }
+ { // Very big negative exponent.
+ double d = 9.9e-234;
+ //cout << setprecision(1) << fixed << d << endl; // 0.1
+ //cout << setprecision(1) << scientific << d << endl; // 9.9e-002
+ BOOST_CHECK_EQUAL(round_e(d, 1), "1.e-233"); // 1 digit, rounded.
+ BOOST_CHECK_EQUAL(round_e(d, 2), "9.9e-234"); // 2 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 3), "9.90e-234"); // 3 digits.
+ BOOST_CHECK_EQUAL(round_e(d, 4), "9.900e-234"); // 4 digits.
+ }
+ { // Negative values.
+ double d = -1.;
+ BOOST_CHECK_EQUAL(round_e(d, 1), "-1."); // 1 digit, not rounded.
+ BOOST_CHECK_EQUAL(round_e(d, 2), "-1.0"); // 2 digit, not rounded.
+ BOOST_CHECK_EQUAL(round_e(d, 3), "-1.00"); // 2 digit, not rounded.
+ }
+
+ { // Problematic rounding.
+ // 1.5 is stored as 1.49999999999999, but should round up to 1.5, not down to 1.4.
+ double d = 1.5;
+ BOOST_CHECK_EQUAL(round_e(d, 1), "2."); // 1 digit, not rounded.
+ BOOST_CHECK_EQUAL(round_e(d, 2), "1.5"); // 2 digit, not rounded.
+ BOOST_CHECK_EQUAL(round_e(d, 3), "1.50"); // 2 digit, not rounded.
+ }
+
+ { // Misc
+ double d = 1.2945678901234567890e6;
+ BOOST_CHECK_EQUAL(round_e(d, 1), "1.e6");
+ BOOST_CHECK_EQUAL(round_e(d, 2), "1.3e6");
+ BOOST_CHECK_EQUAL(round_e(d, 3), "1.29e6");
+ BOOST_CHECK_EQUAL(round_e(d, 4), "1.295e6");
+ BOOST_CHECK_EQUAL(round_e(d, 11), "1.2945678901e6"); // 11 sigdigits.
+ BOOST_CHECK_EQUAL(round_e(d, 12), "1.29456789012e6"); // 12 sigdigits.
+ BOOST_CHECK_EQUAL(round_e(d, 13), "1.294567890123e6"); // 13 sigdigits.
+ BOOST_CHECK_EQUAL(round_e(d, 14), "1.2945678901235e6"); // 14 sigdigits.
+ BOOST_CHECK_EQUAL(round_e(d, 15), "1.29456789012346e6"); // 15 sigdigits.
+ BOOST_CHECK_EQUAL(round_e(d, 16), "1.29456789012346e6"); // 15 sigdigits, because reached digits10.
+ BOOST_CHECK_EQUAL(round_e(d, 17), "1.29456789012346e6"); // 15 sigdigits, because reached digits10.
+ BOOST_CHECK_EQUAL(round_e(d, 18), "1.29456789012346e6"); // 15 sigdigits, because reached digits10.
+
+ d = 987.654; // 9.87654e2
+
+ BOOST_CHECK_EQUAL(round_e(d, 1), "1.e3");
+ BOOST_CHECK_EQUAL(round_e(d, 2), "9.9e2");
+ BOOST_CHECK_EQUAL(round_e(d, 3), "9.88e2");
+ BOOST_CHECK_EQUAL(round_e(d, 4), "9.877e2");
+ BOOST_CHECK_EQUAL(round_e(d, 5), "9.8765e2");
+ BOOST_CHECK_EQUAL(round_e(d, 6), "9.87654e2");
+ BOOST_CHECK_EQUAL(round_e(d, 7), "9.876540e2"); // 11 sigdigits.
+ BOOST_CHECK_EQUAL(round_e(d, 11), "9.8765400000e2"); // 11 sigdigits.
+ BOOST_CHECK_EQUAL(round_e(d, 12), "9.87654000000e2"); // 12 sigdigits.
+ BOOST_CHECK_EQUAL(round_e(d, 13), "9.876540000000e2"); // 13 sigdigits.
+ BOOST_CHECK_EQUAL(round_e(d, 14), "9.8765400000000e2"); // 14 sigdigits.
+ BOOST_CHECK_EQUAL(round_e(d, 15), "9.87654000000000e2"); // 15 sigdigits.
+ BOOST_CHECK_EQUAL(round_e(d, 16), "9.87654000000000e2"); // 15 sigdigits, because reached digits10.
+ BOOST_CHECK_EQUAL(round_e(d, 17), "9.87654000000000e2"); // 15 sigdigits, because reached digits10.
+ BOOST_CHECK_EQUAL(round_e(d, 18), "9.87654000000000e2"); // 15 sigdigits, because reached digits10.
+
+
+ d = 0.0987654; // 9.87654e-2
+
+ BOOST_CHECK_EQUAL(round_e(d, 1), "1.e-1");
+ BOOST_CHECK_EQUAL(round_e(d, 2), "9.9e-2");
+ BOOST_CHECK_EQUAL(round_e(d, 3), "9.88e-2");
+ BOOST_CHECK_EQUAL(round_e(d, 4), "9.877e-2");
+ BOOST_CHECK_EQUAL(round_e(d, 5), "9.8765e-2");
+ BOOST_CHECK_EQUAL(round_e(d, 6), "9.87654e-2");
+ BOOST_CHECK_EQUAL(round_e(d, 7), "9.876540e-2"); // 7 sigdigits.
+ BOOST_CHECK_EQUAL(round_e(d, 11), "9.8765400000e-2"); // 11 sigdigits.
+ BOOST_CHECK_EQUAL(round_e(d, 12), "9.87654000000e-2"); // 12 sigdigits.
+ BOOST_CHECK_EQUAL(round_e(d, 13), "9.876540000000e-2"); // 13 sigdigits.
+ BOOST_CHECK_EQUAL(round_e(d, 14), "9.8765400000000e-2"); // 14 sigdigits.
+ BOOST_CHECK_EQUAL(round_e(d, 15), "9.87654000000000e-2"); // 15 sigdigits.
+ BOOST_CHECK_EQUAL(round_e(d, 16), "9.87654000000000e-2"); // 15 sigdigits, because reached digits10.
+ BOOST_CHECK_EQUAL(round_e(d, 17), "9.87654000000000e-2"); // 15 sigdigits, because reached digits10.
+ BOOST_CHECK_EQUAL(round_e(d, 18), "9.87654000000000e-2"); // 15 sigdigits, because reached digits10.
+ }
+
+ { // Non-finites.
+ double d = std::numeric_limits<double>::quiet_NaN();
+ BOOST_CHECK_EQUAL(round_e(d, 1), "NaN");
+ BOOST_CHECK_EQUAL(round_e(-d, 1), "-NaN");
+
+ d = std::numeric_limits<double>::infinity();
+ BOOST_CHECK_EQUAL(round_e(d, 1), "Inf");
+ BOOST_CHECK_EQUAL(round_e(-d, 1), "-Inf");
+ }
+} // BOOST_AUTO_TEST_CASE(round_e_test)
+
+BOOST_AUTO_TEST_CASE(cdf_quantile_test)
+ { // Test the calculation of CDF and quantiles for triangular and uniform distributions.
+ static const double sqrt_6 = 2.4494897427831780981972840747058913919659474804966; // sqrt(6)
+
+ boost::math::triangular tdist(-sqrt_6, 0., +sqrt_6); // Wimmer page 23, below eq 6.
+ double alpha = 0.005;
+ double qlo = quantile(complement(tdist, alpha));
+ double qhi = quantile(tdist, alpha);
+ //cout << "quantile(complement(tdist, alpha)); " << qlo << ", quantile(tdist, alpha) " << qhi << endl;
+ // quantile(complement(tdist, alpha)); 2.20454, quantile(tdist, alpha) -2.20454
+ //cout << "cdf( quantile(complement(tdist, alpha)) = "<< cdf_tri(qlo) << ", cdf(quantile(tdist, alpha) = " << cdf_tri(qhi) << endl;
+ // cdf( quantile(complement(tdist, alpha)) = 0.995, cdf(quantile(tdist, alpha) = 0.005
+ BOOST_CHECK_CLOSE_FRACTION(cdf_tri(qhi), alpha, 0.001);
+ BOOST_CHECK_CLOSE_FRACTION(cdf_tri(qlo), 1. - alpha, 0.001);
+
+ double q01l = quantile_tri(1. - alpha);
+ double q01h = quantile_tri(alpha);
+
+ //cout << "quantile_tri(1. - alpha) " << q01l << ", quantile_tri(alpha); " << q01h << endl;
+ // quantile_tri(1. - alpha) 2.20454, quantile_tri(alpha); -2.20454
+
+ double c01h = cdf_tri(q01h);
+ BOOST_CHECK_CLOSE_FRACTION(c01h, alpha, 0.02); // Fails with 0.01, OK with 0.02
+ // difference{0.292893} between c01h{0.0070710678118655057} and alpha{0.01} exceeds 0.01
+
+ double c01l = cdf_tri(q01l);
+ BOOST_CHECK_CLOSE_FRACTION(c01l, 1. - alpha, 0.005); // OK at 0.005
+ //cout << "cdf_tri(quantile_tri(alpha)) " << c01l << ",cdf_tri(quantile_tri(1. - alpha)) " << c01h << endl;
+ // cdf_tri(quantile_tri(alpha)) 0.995,cdf_tri(quantile_tri(1. - alpha)) 0.005
+ BOOST_CHECK_EQUAL(cdf_tri(-3.), 0); // check > sqrt_6 limits.
+ BOOST_CHECK_EQUAL(cdf_tri(+3.), 1.);
+
+ boost::math::uniform udist(-sqrt_3, +sqrt_3); // Wimmer page 3, below eq 5.
+ // Loop back tests.
+ //cout << "loopback boost::math cdf(z) "<< endl;
+ for (double d = -2.4; d < +2.4; d += 0.2)
+ {
+ // cout << d << ' '<< cdf(tdist, d) << ' ' << quantile(tdist, cdf(tdist, d)) << ' '<< d - quantile(tdist, cdf(tdist, d)) << endl;
+ //BOOST_CHECK_CLOSE_FRACTION(d, quantile(tdist, cdf(tdist, d)), 0.01); fails for d near zero
+ BOOST_CHECK_SMALL(d - quantile(tdist, cdf(tdist, d)), 100 * eps);
+ }
+
+ //cout << "loopback boost::math quantile(alpha))" << endl;
+ for (double a = 0.; a <= 1.; a += 0.1)
+ {
+ //cout << a << ' ' << quantile(tdist, a) << ' ' << cdf(tdist, quantile(tdist, a)) << ' ' << a - cdf(tdist, quantile(tdist, a)) << endl;
+ BOOST_CHECK_CLOSE_FRACTION(a, cdf(tdist, quantile(tdist, a)), 0.01);
+ }
+
+ //cout << "loopback triangular cdf(z)" << endl;
+ for (double d = -2.4; d < +2.4; d += 0.2)
+ {
+ //cout << d << ' '<< cdf_tri(d) << ' ' << quantile_tri(cdf_tri(tdist, d)) << ' '<< d - quantile_tri(cdf_tri(tdist, d)) << endl;
+ //BOOST_CHECK_CLOSE_FRACTION(d, quantile_tri(cdf(tdist, d)), 0.01); // fails d near zero
+ BOOST_CHECK_SMALL(d - quantile_tri(cdf(tdist, d)), 100 * eps);
+ }
+
+ //cout << "loopback triangular quantile" << endl;
+ for (double a = 0.; a <= 1.; a += 0.1)
+ {
+ //cout << a << ' ' << quantile_tri(a) << ' ' << cdf_tri(quantile_tri(a)) << ' ' << a - cdf_tri(quantile_tri(a)) << endl;
+ BOOST_CHECK_CLOSE_FRACTION(a, cdf_tri(quantile_tri(a)), 0.01);
+ }
+ //cout << "loopback uniform quantile" << endl;
+ for (double a = 0.; a <= 1.; a += 0.1)
+ {
+ //cout << a << ' ' << quantile_uni(a) << ' ' << cdf_uni(quantile_uni(a)) << ' ' << a - cdf_uni(quantile_uni(a)) << endl;
+ BOOST_CHECK_CLOSE_FRACTION(a, cdf_uni(quantile_uni(a)), 0.01);
+ }
+ //cout << "loopback uniform cdf_uni(z)" << endl;
+ for (double d = -sqrt_3; d < +sqrt_3; d += 0.2)
+ {
+ //cout << d << ' '<< cdf(d) << ' ' << quantile_tri(cdf(tdist, d)) << ' '<< d - quantile_tri(cdf(tdist, d)) << endl;
+ //BOOST_CHECK_CLOSE_FRACTION(d, quantile_tri(cdf(tdist, d)), 0.01); // fails d near zero
+ BOOST_CHECK_SMALL(d - quantile_uni(cdf(udist, d)), 100 * eps);
+ }
+ // Compare Wimmer and Boost::math uniform cdf
+ for (double d = -sqrt_3; d < +sqrt_3; d += 0.2)
+ {
+ BOOST_CHECK_SMALL((cdf_uni(d) - cdf(udist, d)), 100 * eps);
+ }
+ // Compare Wimmer and Boost::math uniform quant
+ for (double a = 0.; a <= 1.; a += 0.1)
+ {
+ BOOST_CHECK_SMALL((quantile_uni(a) - quantile(udist, a)), 100 * eps);
+ }
+ } // BOOST_AUTO_TEST_CASE(cdf_quantile_test)
+
+BOOST_AUTO_TEST_CASE(round_ms_test)
+{ // Test round_ms function.
+ //template<typename = FPT> std::string round_ms(FPT v, signed int m); // Round v to digit m.
+
+ double v = (std::numeric_limits<double>::max)();
+ BOOST_CHECK_EQUAL(round_ms(v, std::numeric_limits<double>::max_exponent10), "0."); // 1.797693134862316 and 308
+ BOOST_CHECK_EQUAL(round_ms(-v, std::numeric_limits<double>::max_exponent10), "0."); // -1.797693134862316 and 308
+ BOOST_CHECK_EQUAL(round_ms(v, std::numeric_limits<double>::max_exponent10 -1), "200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000."); // -1.797693134862316 and 307
+ BOOST_CHECK_EQUAL(round_ms(-v, std::numeric_limits<double>::max_exponent10 -1), "-200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000."); // -1.797693134862316 and 307
+
+ BOOST_CHECK_EQUAL(round_ms(v, 308), "0."); // 1.797693134862316 and 308
+ BOOST_CHECK_EQUAL(round_ms(-v, 308), "0."); // -1.797693134862316 and 308
+ BOOST_CHECK_EQUAL(round_ms(v, 307), "200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000."); // -1.797693134862316 and 308
+ BOOST_CHECK_EQUAL(round_ms(-v, 307), "-200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000."); // -1.797693134862316 and 308
+
+ v = (std::numeric_limits<double>::min)();
+ // cout <<setprecision (17) << v << endl; // 2.2250738585072014e-308
+ BOOST_CHECK_EQUAL(round_ms(v, std::numeric_limits<double>::min_exponent10), "0."); // 2.22507385850720 and -308
+ BOOST_CHECK_EQUAL(round_ms(v, std::numeric_limits<double>::min_exponent10+1), "0."); // 2.22507385850720 and -307 ?? is 0. expected?
+ BOOST_CHECK_EQUAL(round_ms(v, std::numeric_limits<double>::min_exponent10+2), "0."); // 2.22507385850720 and -306 ?? is 0. expected?
+
+ // Zero (positive).
+ BOOST_CHECK_EQUAL(round_ms(0., 0), "0."); //
+ BOOST_CHECK_EQUAL(round_ms(0., +1), "0."); //
+ BOOST_CHECK_EQUAL(round_ms(0., -1), "0."); //
+ BOOST_CHECK_EQUAL(round_ms(0., +2), "0."); //
+ BOOST_CHECK_EQUAL(round_ms(0., -2), "0.0"); //
+ BOOST_CHECK_EQUAL(round_ms(0., -3), "0.00"); //
+ // Zero (negative).
+ BOOST_CHECK_EQUAL(round_ms(-0., +2), "0."); //
+ BOOST_CHECK_EQUAL(round_ms(-0., +1), "0."); //
+ BOOST_CHECK_EQUAL(round_ms(-0., 0), "0."); //
+ BOOST_CHECK_EQUAL(round_ms(-0., -1), "-0."); //
+ BOOST_CHECK_EQUAL(round_ms(-0., -3), "-0.00"); //
+ BOOST_CHECK_EQUAL(round_ms(-3278.35876, -3), "-3278.36"); //
+
+ // Infinity plus and minus.
+ BOOST_CHECK_EQUAL(round_ms(+std::numeric_limits<double>::infinity(), +2), "inf");
+ BOOST_CHECK_EQUAL(round_ms(-std::numeric_limits<double>::infinity(), +1), "-inf");
+ // NaN, note sign bit of NaN is recognized.
+ BOOST_CHECK_EQUAL(round_ms(+std::numeric_limits<double>::quiet_NaN(), +2), "NaN");
+ BOOST_CHECK_EQUAL(round_ms(-std::numeric_limits<double>::quiet_NaN(), +1), "-NaN");
+
+ BOOST_CHECK_EQUAL(round_ms(123.45678901234567890, -2),"123.5") ; //
+ // Wimmer example 2 page 1660
+ BOOST_CHECK_EQUAL(round_ms(3278.35876, -3), "3278.36"); //
+ BOOST_CHECK_EQUAL(round_ms(159.21, +1), "200."); //
+ BOOST_CHECK_EQUAL(round_ms(1121.85, +3), "0."); //
+ // Some more examples.
+ BOOST_CHECK_EQUAL(round_ms(1111.1111, +3), "0."); //
+ BOOST_CHECK_EQUAL(round_ms(1111.1111, +2), "1000."); //
+ BOOST_CHECK_EQUAL(round_ms(1111.1111, +1), "1100."); //
+ BOOST_CHECK_EQUAL(round_ms(1111.1111, +0), "1110."); //
+ BOOST_CHECK_EQUAL(round_ms(1111.1111, -1), "1111."); //
+ BOOST_CHECK_EQUAL(round_ms(1111.1111, -2), "1111.1"); //
+ BOOST_CHECK_EQUAL(round_ms(1111.1111, -3), "1111.11"); //
+
+ BOOST_CHECK_EQUAL(round_ms(9999.9999, +4), "0."); //
+ BOOST_CHECK_EQUAL(round_ms(9999.9999, +3), "0."); //
+ BOOST_CHECK_EQUAL(round_ms(9999.9999, +2), "10000."); //
+ BOOST_CHECK_EQUAL(round_ms(9999.9999, +1), "10000."); //
+ BOOST_CHECK_EQUAL(round_ms(9999.9999, +0), "10000."); //
+ BOOST_CHECK_EQUAL(round_ms(9999.9999, -1), "10000."); //
+ BOOST_CHECK_EQUAL(round_ms(9999.9999, -2), "10000.0"); //
+ BOOST_CHECK_EQUAL(round_ms(9999.9999, -3), "10000.00"); //
+ BOOST_CHECK_EQUAL(round_ms(9999.9999, -4), "10000.000"); //
+ BOOST_CHECK_EQUAL(round_ms(9999.9999, -5), "9999.9999"); //
+
+ BOOST_CHECK_EQUAL(round_ms(1703.12345679, -7), "1703.123457"); // David A. Pimentel 6 digits after decimal point example 2 (so m = -7).
+
+ BOOST_CHECK_EQUAL(round_ms(0.152, -3), "0.15");
+ BOOST_CHECK_EQUAL(round_ms(0.155, -3), "0.16");
+ BOOST_CHECK_EQUAL(round_ms(0.159, -3), "0.16");
+ // With option to use shorter form with no zero preceeding decimal point.
+ //BOOST_CHECK_EQUAL(round_ms(0.152, -3), ".15");
+ //BOOST_CHECK_EQUAL(round_ms(0.155, -3), ".16");
+ //BOOST_CHECK_EQUAL(round_ms(0.159, -3), ".16");
+
+ BOOST_CHECK_EQUAL(round_ms(0.159, 0), "0.");
+ BOOST_CHECK_EQUAL(round_ms(0.159, -1), "0.");
+ BOOST_CHECK_EQUAL(round_ms(0.159, -2), "0.2");
+ BOOST_CHECK_EQUAL(round_ms(0.159, -3), "0.16");
+ BOOST_CHECK_EQUAL(round_ms(0.159, -4), "0.159");
+
+ BOOST_CHECK_EQUAL(round_ms(0.01234567, -2), "0.");
+ BOOST_CHECK_EQUAL(round_ms(0.01234567, -3), "0.01");
+ BOOST_CHECK_EQUAL(round_ms(0.01234567, -4), "0.012");
+ BOOST_CHECK_EQUAL(round_ms(0.0001234567, -6), "0.00012");
+
+ // Examples from http://www.chem1.com/acad/webtext/pre/mm3.html
+ BOOST_CHECK_EQUAL(round_ms(34.216, -2), "34.2"); // 3 significant digits, so rounder digit is '1', and m is -2
+ BOOST_CHECK_EQUAL(round_ms(6.252, -2), "6.3"); // 2 significant digits, so rounder digit is '5', and m is -2
+ BOOST_CHECK_EQUAL(round_ms(39.99, -2), "40.0"); // 3 significant digits, so rounder digit is '9', and m is -2
+ BOOST_CHECK_EQUAL(round_ms(85381., 1), "85400."); // 3 significant digits, so rounder digit is '8', and m is +1
+ BOOST_CHECK_EQUAL(round_ms(0.04597, -5), "0.0460"); // 3 significant digits, so rounder digit is '7', and m is -5
+
+ BOOST_CHECK_EQUAL(round_ms(1.23, -2),"1.2"); // round to -1, so m = -2 round down, no carry
+ BOOST_CHECK_EQUAL(round_ms(1.25, -2),"1.3"); // round -1, so m = -2, round up no carry.
+ BOOST_CHECK_EQUAL(round_ms(1.95, -2),"2.0"); // round -1, so m = -2, round up, and carry.
+
+ // Some very large values.
+ BOOST_CHECK_EQUAL(round_ms(1.95e+6, +2),"1950000."); //
+ BOOST_CHECK_EQUAL(round_ms(1.95e+9, +2),"1950000000."); //
+ BOOST_CHECK_EQUAL(round_ms(1.95e+12, +2),"1950000000000."); //
+ BOOST_CHECK_EQUAL(round_ms(1.95e+15, +2),"1950000000000000."); //
+ BOOST_CHECK_EQUAL(round_ms(1.95e+18, +2),"1950000000000000000."); //
+ BOOST_CHECK_EQUAL(round_ms(1.95e+24, +2),"1950000000000000000000000."); //
+ // numeric_limits<double>::max() = 1.797693134862316 E 308
+ BOOST_CHECK_EQUAL(round_ms(numeric_limits<double>::max(), 305),"180000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000."); //
+ BOOST_CHECK_EQUAL(round_ms(numeric_limits<double>::min(), -307),"0.");
+
+ // Some small values.
+ BOOST_CHECK_EQUAL(round_ms(1.95e-6, -8),"0.0000020");
+ BOOST_CHECK_EQUAL(round_ms(-1.95e-6, -8),"-0.0000020");
+ BOOST_CHECK_EQUAL(round_ms(-1.95e-12, -14),"-0.0000000000020");
+} // BOOST_AUTO_TEST_CASE(round_ms_test)
+
+BOOST_AUTO_TEST_CASE(Wimmer_3)
+{ // Test by comparion with Wimmer example 3, page 1660.
+ // Calculate confidence interval.
+ //std::pair<double, double> conf_interval(double value, double unc, double df, double alpha);
+ std::pair<double, double> p(97.8725, 157.7975);
+ // cout << p << endl; // <97.8725, 157.798>
+ p = conf_interval(127.835, 15.287); // Default to 1 degree of freedom, alpha 0.05, 95% confidence & gaussian.
+ BOOST_CHECK_CLOSE_FRACTION(p.first, 97.8725, tol);
+ BOOST_CHECK_CLOSE_FRACTION(p.second, 157.798, tol); //
+ // 2nd example for 99%, alpha = 0.01:
+ p = conf_interval(127.835, 15.287, 1., 0.01); // 99% confidence.
+ BOOST_CHECK_CLOSE_FRACTION(p.first, 88.4583, tol);
+ BOOST_CHECK_CLOSE_FRACTION(p.second, 167.2117, tol); //
+ // End Test by comparion with Wimmer example 3, page 1660.
+} // BOOST_AUTO_TEST_CASE(Wimmer_3)
+
+BOOST_AUTO_TEST_CASE(Wimmer_4)
+{ // Wimmer example 4 - more than one measurement.
+ // std::pair<double, double> conf_interval(double mean, double unc, double df = 1., double alpha = 0.05, distribution_type distrib = gaussian)
+ // Uncertainty 1.215349 given is now sigma/sqrt(N or df),
+ // so need to multiply by sqrt(2).
+ std::pair<double, double> p;
+ p = conf_interval(13.8049, 1.215349 * sqrt(2.), 2, 0.05, gaussian); // 95% confidence, and default gaussian.
+ BOOST_CHECK_CLOSE_FRACTION(p.first, 11.42281596, tol);
+ BOOST_CHECK_CLOSE_FRACTION(p.second, 16.18698404, tol);
+ p = conf_interval(13.8049, 1.215349 * sqrt(2.), 2); // 95% confidence, and default gaussian.
+ BOOST_CHECK_CLOSE_FRACTION(p.first, 11.42281596, tol);
+ BOOST_CHECK_CLOSE_FRACTION(p.second, 16.18698404, tol);
+// Similarly for
+ p = conf_interval(13.8049, 1.215349 * sqrt(2.), 2, 0.01); // df =2, 99% confidence, and default gaussian.
+ BOOST_CHECK_CLOSE_FRACTION(p.first, 10.67416098, tol);
+ BOOST_CHECK_CLOSE_FRACTION(p.second, 16.93563902, tol); //
+ // End Wimmer example 4
+} // BOOST_AUTO_TEST_CASE(Wimmer_4)
+
+BOOST_AUTO_TEST_CASE(Wimmer_5_1)
+{ // Wimmer example 5(i) e = 0.01
+ //int round_m(double epsilon, double unc, unsigned int sigdigits, distribution_type t);
+
+ // Mean is 127.835, and standard deviation sigma is 15.287.
+ double sigma = 15.287;
+ // Round sigma to 2 significant decimal digits.
+ double sigma_star = round_sig(sigma, 2); // 2 for ISO rule.
+ BOOST_CHECK_CLOSE_FRACTION(sigma_star, 15., tol); // Sigma rounded.
+
+ double epsilon = 0.01; // Allow 1% loss from rounding.
+ int m = round_m(epsilon, sigma, 2U, gaussian); // Calculate rounding digit, using sigma.
+ BOOST_CHECK_EQUAL(m, -1); // Rounding digit is 1st after decimal point, 0.d.
+ // Repeat using defaults.
+ m = round_m(epsilon, sigma); // Calculate rounding digit, using sigma.
+ BOOST_CHECK_EQUAL(m, -1); // Rounding digit is 1st after decimal point, 0.d.
+
+ double g = gamma(sigma_star, sigma);
+ BOOST_CHECK_CLOSE_FRACTION(g, 0.98123, tol); // Check gamma = 0.98123 given.
+
+ double d = delta(epsilon, g, gaussian);
+ BOOST_CHECK_CLOSE_FRACTION(d, 0.0537, tol); // Wimmer only quotes 0.05.
+ d = 0.05 * sigma_star / (5 * g); // Round as Wimmer to 0.05
+ double md = log10(d);
+ BOOST_CHECK_CLOSE_FRACTION(md, -0.815, tol);
+ BOOST_CHECK_CLOSE_FRACTION(floor(md), -1, tol); // m = -1, so rounding digit is 0.d.
+ // Using full accuracy 0.0537 also gives m = -1 as calculated by round_m above.
+
+ double x = 127.835; // Value to be rounded using m = -1.
+ BOOST_CHECK_EQUAL(round_ms(x, m),"128."); // Round mean to a string.
+ BOOST_CHECK_EQUAL(round_ms(x, round_m(0.01, 15.287, 2U, gaussian)),"128.");
+
+// void out_value_df_limits(double mean, double unc, int degfree = 1, std::ostream& os = cout)
+ ostringstream oss;
+ out_value_df_limits(127.835, 15.287, 1, oss);
+ // out_value_df_limits(123.835, 15.287); 128. +/- 15 <97.9, 157.8>
+ // cout << oss.str() << endl;
+ BOOST_CHECK_EQUAL(oss.str(), "128. +/- 15 <97.9, 157.8>");
+} // BOOST_AUTO_TEST_CASE(Wimmer_5_1)
+
+ BOOST_AUTO_TEST_CASE(Wimmer_5_2)
+ { // Wimmer example 5(ii)
+
+ double sigma = 0.0232;
+ double sigma_star = round_sig(sigma, 1); // Why only one significant digit for rounding?
+ BOOST_CHECK_CLOSE_FRACTION(sigma_star, 0.02, tol);
+
+ double g = gamma(sigma_star, sigma);
+ BOOST_CHECK_CLOSE_FRACTION(g, 0.86207, tol); // Check gamma = 0.86207 given.
+
+ // Wimmer says epsilon = 0.04 will fails from table 1.
+ // Epsilon 0.05 (95%) gamma_0.05 is 0.90175 which is > 0.86207,
+ // Epsilon 0.1 (90%) gamma_0.1 is 0.81271 which is < 0.86207 so OK.
+ double epsilon = 0.001; // Expect to fail if only use one digit for rounding sigma.
+ int m = round_m(epsilon, sigma); // Calculate rounding digit, using sigma.
+ BOOST_CHECK_EQUAL(m, -9999);
+ // Message: Cannot return a rounding m because epsilon 0.001 is too small!
+ epsilon = 0.1; // Should be OK.
+ m = round_m(epsilon, sigma); // Calculate rounding digit, using sigma.
+ BOOST_CHECK_EQUAL(m, -3);
+
+ double x = 1.23875; // Final part of example.
+ epsilon = 0.1; // Should be OK.
+ string s = round_ms(x, m);
+ BOOST_CHECK_EQUAL(s, "1.24");
+ std::pair<double, double> ci =
+ conf_interval(x, sigma_star, 1., 0.05);
+ //cout << "conf_interval(x, sigma, 1., 0.05);" << ci << endl;
+ BOOST_CHECK_CLOSE_FRACTION(ci.first, 1.2008, tol * 2); // 1.1995
+ BOOST_CHECK_CLOSE_FRACTION(ci.second, 1.2792, tol); // 1.27795
+ // Not sure why this isn't exactly same as Wimmer.
+ }
+
+BOOST_AUTO_TEST_CASE(round_ue_test)
+{ // Test using round_ue
+ // Round using value and uncertainty (and controlling sigdigits of uncertainty).
+ // std::string round_ue(double v, double unc, double epsilon = 0.01, unsigned int sigdigits = 2U)
+ BOOST_CHECK_EQUAL(round_ue(127.835, 15.287, 0.01, 2U),"128."); // explicit 2 uncertain digits.
+ BOOST_CHECK_EQUAL(round_ue(127.835, 15.287, 0.01),"128."); // Default unc sigdigit (2)s.
+ BOOST_CHECK_EQUAL(round_ue(127.835, 15.287),"128."); // Default unc sigdigits and default epsilon.
+
+ // Wimmer example 5(i b) e = 0.04
+ BOOST_CHECK_EQUAL(round_ue(127.835, 15.287, 0.04),"130."); // Increase e to 0.04 to allow more rounding loss.
+ // Wimmer example 5(ii a) e = 0.05 fails.
+ //BOOST_CHECK_NE(round_ue(1.23875, 0.0232, 0.05, 1U),"1.24"); // Fails correctly with message:
+ // Epsilon 0.05 is too small for gamma rounded/unrounded ratio 0.862069
+ // Cannot return a rounding m because epsilon is too small!
+ // Wimmer example 5(ii b) e = 0.1
+ BOOST_CHECK_EQUAL(round_ue(1.23875, 0.0232, 0.1, 1U),"1.24"); //
+
+ { // Wimmer example 6 - case (ii) known confidence interval estimate for sigma.
+
+ // P{lo_sigma < sigma < hi_sigma} = 1 - phi
+
+ // So we know 0.98 confidence interval for unc (sigma) is <5.67, 5.82>.
+ // phi = 1- 0.98 = 0.02
+ // unc conf phi = 0.02, round conf eps = 0.05, combined eta = eps - phi = 0.05 - 0.02 = 0.03.
+ double nu = 0.03;
+
+ std::pair<double, double> u(5.67, 5.82); // Known sigma 0.98 confidence interval estimate.
+ // and gamma = 5.67/5.82 = 0.97423
+ //cout << "uncs ratio " << gamma(5.67, 5.82) << endl; // uncs ratio 0.974227
+ BOOST_CHECK_CLOSE_FRACTION(gamma(5.67, 5.82), 0.97423, tol); // unc ratio.
+ // cout << "delta " << delta(nu, gamma(5.67, 5.82)) << endl; // delta 0.261833
+ BOOST_CHECK_CLOSE_FRACTION(delta(nu, gamma(5.67, 5.82)), 0.26, tol*10); // delta = 0.26
+ // cout << log10(0.26 * 5.82 /5) << endl; // expect -0.519074
+ BOOST_CHECK_CLOSE_FRACTION(log10(0.26 * 5.82 / 5), -0.519, tol);
+ // m < -0.519 so rounding x.
+ int m = static_cast<int>(floor(-0.519));
+ //cout << "floor(-0.519) " << m << endl; // floor(-0.519) -1
+ BOOST_CHECK_EQUAL(m, -1);
+ double x = 56.387; // Measured value.
+ BOOST_CHECK_EQUAL(round_ms(x, m), "56."); // Rounded measured value.
+ double x_star = 56.; // Rounded mean x.
+
+ double alpha = 0.05; // 95% confidence, for 0.05_proper (1-alpha) = 0.95 confidence interval.
+ using boost::math::normal;
+ normal dist; // Normal distribution with zero mean and unit standard deviation.
+ //double t1 = quantile(dist, alpha / 2);
+ //cout << t1 << endl; // = -1.95996 so can use
+ double t = quantile(complement(dist, alpha /2 ));
+ // cout << t << endl; // 1.95996 for 0.05
+ BOOST_CHECK_CLOSE_FRACTION(t, 1.95996, tol);
+ // Wimmer rounds to t = 1.96; but tests pass OK with either value.
+
+ std::pair<double, double> p; // Confidence interval.
+ p.first = x_star - 5.67 * t; // lower.
+ p.second = x_star + 5.67 * t; // higher.
+ // cout << p << endl; // <44.887, 67.113>
+ BOOST_CHECK_CLOSE_FRACTION(p.first, 44.8868, tol); // Wimmer values.
+ BOOST_CHECK_CLOSE_FRACTION(p.second, 67.1132, tol);
+
+ // Wimmer second example using tighter alpha.
+ x_star = 56.; // Rounded mean.
+ alpha = 0.01; // 99% confidence for 0.05 proper 0.99 confidence interval estimate.
+ normal dist01; // Normal distribution with zero mean and unit standard deviation.
+ t = quantile(complement(dist01, alpha / 2));
+ // cout << t << endl; // 1.95996
+ // Confidence interval.
+ p.first = x_star - 5.67 * t;
+ p.second = x_star + 5.67 * t;
+ // cout << "Alpha 0.01 " << p << endl; // Alpha 0.01 <41.395, 70.605>
+ BOOST_CHECK_CLOSE_FRACTION(p.first, 41.391, tol);
+ BOOST_CHECK_CLOSE_FRACTION(p.second, 70.6059, tol);
+ // Note this 0.995 confidence requirement means that the interval is wider.
+ }//End Wimmer example 6 - case (ii) known confidence interval estimate for sigma.
+
+ { // Wimmer p 1662, example 7 - Repeated measurements with known variance.
+ using namespace boost::math;
+ int n = 10; // number of measurements is 10.
+ double x = 87.93911210729208; // Mean of 10 measurements.
+ double variance = 0.5; // known variance sigma^2 is 0.5.
+ double sigma = sqrt(variance); // and known variance sigma^2 is 0.5.
+ double sigma_star = sigma / sqrt(static_cast<double>(n)); // Why divide by sqrt(10)?
+ BOOST_CHECK_CLOSE_FRACTION(sigma_star, 0.223606797, tol/10.);
+ double sigma_rounded = round_sig(sigma_star, 1); // Round to 1 sig digit to get 0.2.
+ // cout << "unc_rounded " << unc_rounded << endl; // unc_rounded 0.2
+ BOOST_CHECK_CLOSE_FRACTION(sigma_rounded, 0.2, tol); //
+ BOOST_CHECK_EQUAL(sigma_rounded, 0.2); // unc 0.1 properly rounded.
+ ostringstream oss;
+ oss << setprecision(3) << sigma_rounded; // expect 0.2 whatever precision (< digits10)
+ BOOST_CHECK_EQUAL(oss.str(), "0.2"); // sigma 0.1_properly rounded.
+
+ double gam = sigma_rounded / sigma_star; // 0.2 / 0.223606797 = 0.89442
+ BOOST_CHECK_CLOSE_FRACTION(gam, 0.89442, tol);
+ // Using eq 24 gives delta(0.1, 0.89442, max) = 0.43
+ double del = delta(0.1, gam); // eps = 0.1 for mere 90% confidence.
+ BOOST_CHECK_CLOSE_FRACTION(del, 0.43, 0.05);
+ // According to eq 12, m < -1.716,
+ // so we ought to round x mean to order m = -2, (rounding digit is 0.0d)
+ // to get the 0.1 properly-rounded result of format dd.d,
+ // and the 0.1-proper (1-alpha) confidence interval estimate for mean,
+ // for alpha = 0.01,
+ // confidence interval is 87.9 +/- 0.2 and (87.3848, 88.4152).
+
+ double r = log10(del * sigma_rounded / (5 * gam));
+ //cout << "r = " << r << endl; // r = -1.71409
+ BOOST_CHECK_CLOSE_FRACTION(r, -1.716, tol *5 );
+ int m = static_cast<int>(floor(log10(del * sigma_rounded / (5 * gam)))); // Wimmer eq 12 p 1661.
+ BOOST_CHECK_EQUAL(m, -2);
+ // Expect mean 87.9 +/- 0.2
+ BOOST_CHECK_EQUAL(round_ms(x, m), "87.9"); // 0.1 properly rounded.
+ // Have already got unc_rounded so display "+/- 0.2".
+ double rounded_x = 87.9;
+
+ // Estimate confidence interval.
+ double alpha = 0.01;
+ //boost::math::normal dist(rounded_x, variance/(n-1));
+ //double t = quantile(complement(dist, alpha/2));
+ //cout << "quantile(complement(dist, alpha/2)); = " << t << endl; // for 0.1 = 1.64485, 0.01 2.57583
+ // This should be the upper limit.
+ // quantile(complement(dist, alpha/2)); = 88.1213
+ // dist(x, variance/n); gives quantile(complement(dist, alpha/2)); = 88.0679
+ // dist(rounded_x, variance/n); gives quantile(complement(dist, alpha/2)); = 88.0288
+ // dist(rounded_x, variance/(n-1)); gives quantile(complement(dist, alpha/2)); = 88.0431
+ // So none of these are quite right - expect upper = 88.4152
+
+ normal dist01;
+ double t = quantile(complement(dist01, alpha/2));
+ std::pair<double, double> p; // Confidence interval.
+ // Note use of rounded values to get exactly the same result as Wimmer.
+ p.first = rounded_x - sigma_rounded * t;
+ p.second = rounded_x + sigma_rounded * t;
+ // cout << "lower " << p.first << ", upper " << p.second << endl; // lower 87.3848, upper 88.4152
+ BOOST_CHECK_CLOSE_FRACTION(p.first, 87.3848, tol); // These confidence intervals are given.
+ BOOST_CHECK_CLOSE_FRACTION(p.second, 88.4152, tol);
+
+ // So in summary:
+ // void out_value_limits(double mean, double unc, std::pair<double, double> ci, int m, std::ostream& os = cout);
+ // std::cout << "out_value_limits(x, sigma_star, p, m, std::cout); ";
+ // out_value_limits(x, sigma_star, p, m, std::cout);
+ // std::cout << std::endl;
+ // out_value_limits(x, sigma_star, p, m, std::cout); 87.9 +/- 0.22 <87.38, 88.42>
+
+ alpha = 0.1; // 90% confidence for mean.
+ t = quantile(complement(dist01, alpha / 2));
+ //cout << t << endl; // 1.64485
+ p.first = rounded_x - sigma_star * t;
+ p.second = rounded_x + sigma_star * t;
+ // cout << "Alpha 0.1 " << p << endl; // Alpha 0.1 <87.5322, 88.2678>
+ BOOST_CHECK_CLOSE_FRACTION(p.first, 87.573, tol); // These confidence intervals not given,
+ BOOST_CHECK_CLOSE_FRACTION(p.second, 88.27, tol); // but they look plausible.
+
+ alpha = 0.05; // 95% confidence for mean (not given by Wimmer).
+ t = quantile(complement(dist01, alpha / 2));
+ // cout << t << endl; // 1.95996
+ p.first = rounded_x - sigma_star * t;
+ p.second = rounded_x + sigma_star * t;
+ //cout << "Alpha 0.05 " << p << endl; // 87.5009 == 87.5 // 88.3774 == 88.3 rounded.
+ // Alpha 0.05 <87.4617, 88.3383>
+ BOOST_CHECK_CLOSE_FRACTION(p.first, 87.3848, tol);
+ BOOST_CHECK_CLOSE_FRACTION(p.second, 88.4152, tol);
+ BOOST_CHECK_EQUAL(round_ms(p.first, m), "87.5"); // 0.1 properly rounded.
+ BOOST_CHECK_EQUAL(round_ms(p.second, m), "88.3"); // 0.1 properly rounded.
+
+ alpha = 0.01; // 99% confidence for mean (Wimmer).
+ t = quantile(complement(dist01, alpha / 2));
+ // cout << t << endl; // 2.57583
+ p.first = rounded_x - sigma_star * t;
+ p.second = rounded_x + sigma_star * t;
+ // cout << "Alpha 0.01 " << p << endl;// 87.3631 == 87.3, 88.5151 == 88.5
+ // Alpha 0.01 <87.324, 88.476>
+ BOOST_CHECK_CLOSE_FRACTION(p.first, 87.3848, tol); // but Wimmer gives 87.3848 not 88.5151.
+ BOOST_CHECK_CLOSE_FRACTION(p.second, 88.4152, tol); // but Wimmer gives 88.4152 not 88.5151.
+ BOOST_CHECK_EQUAL(round_ms(p.first, m), "87.3"); // 0.1_properly rounded.
+ BOOST_CHECK_EQUAL(round_ms(p.second, m), "88.5"); // 0.1_properly rounded.
+ //cout << "Mean " << x << " == " << round_ms(x, m) << " +/- " << sigma_rounded
+ // << " <" << round_ms(p.first, m) << ", " << round_ms(p.second, m) << ">" << endl;
+ //Mean 87.9391 == 87.9 +/- 0.2 <87.3, 88.5>
+
+ }// End Wimmer p 1662, example 7 - Repeated measurements with known variance.
+} // BOOST_AUTO_TEST_CASE(round_m_test)
+
+BOOST_AUTO_TEST_CASE(Wimmer_triangular_test)
+{ // Wimmer Triangular distribution example 3, page 27.
+ double x = 127.835;
+ double unc = 15.287;
+ double unc_rounded = round_sig(unc, 2); // round to 2 sig digit - ISO rule.
+ // cout << "unc_rounded " << unc_rounded << endl; // unc_rounded 15
+ BOOST_CHECK_CLOSE_FRACTION(unc_rounded, 15., 0.01);
+ ostringstream oss;
+ oss << setprecision(3) << unc_rounded; // expect 0.2 whatever precision (< digits10)
+ BOOST_CHECK_EQUAL(oss.str(), "15"); // unc 15. properly rounded.
+ double gam = unc_rounded / unc;
+ BOOST_CHECK_CLOSE_FRACTION(gam, 0.98123, 0.01);
+ // double delta(double epsilon, double gamma, distribution_type distrib = normal);
+ double del = delta(0.01, gam, triangular); // eps = 0.01 for high 99% confidence.
+ BOOST_CHECK_CLOSE_FRACTION(del, 0.0561, 0.01);
+
+ int m = round_m(0.01, unc, 2, triangular);
+ BOOST_CHECK_EQUAL(m, -1);
+ BOOST_CHECK_EQUAL(round_ms(x, m), "128.");
+ // ostringstream oss2; // Maybe quicker to construct a new string than erase old one?
+ oss.clear(); // Clears only clear stream fail or error bits!
+ oss.str(""); // Erases the previous str (oss.str().erase() does NOT change std::string - because it only acts on a copy C string?)
+ oss << setprecision(3) << unc_rounded; // expect 15 whatever precision (< digits10)
+ BOOST_CHECK_EQUAL(oss.str(), "15"); // unc 15. properly rounded.
+ std::pair<double, double> ci;
+ //std::pair<double, double> conf_interval(double value, double unc, double df = 1., double alpha = 0.05, distribution_type distrib);
+ // value should be the rounded value 130, not the 'exact' double value 127.835.
+ // unc should also be the rounded value, 15, not the 'exact' double value 15.287.
+ // I don't understand the logic of calculating the confidence intervals with rounded data?
+ using boost::lexical_cast;
+ double vr = lexical_cast<double>(round_ms(x, m)); // = 128.
+ ci = conf_interval(vr, unc_rounded, 1, 0.05, triangular); // alpha = 0.05, example 3 1st 0.01-proper 0.95 confidence interval <99.5, 156.5>.
+ // cout << "conf_interval(vr, unc, 1, 0.05, triangular); " << ci << endl;
+ // conf_interval(vr, unc, 1, 0.05, triangular); <99.4735, 156.527>
+ BOOST_CHECK_CLOSE_FRACTION(ci.first, 99.5, tol); // 98.9
+ BOOST_CHECK_CLOSE_FRACTION(ci.second, 156.5, tol); // 157.1
+
+ // Round confidence intervals to 1 decimal digit
+ //double cilo = lexical_cast<double>(round_ms(ci.first, m-1)); // = 98.9
+ //cout << "ci lo " << cilo << endl; // ci lo 99.5
+ //double cihi = lexical_cast<double>(round_ms(ci.second, m-1)); // = 156.5
+ //cout << "ci hi " << cihi << endl; // ci hi 156.5
+
+ //out_confidence_interval(ci, m, cout); // <99.5, 157>
+ //cout << endl;
+
+ oss.clear(); // Clears only clear stream fail or error bits!
+ oss.str(""); // Erases the previous str (oss.str().erase() does NOT change std::string - because it only acts on a copy C string?)
+ out_confidence_interval(ci, m, oss); // <99.5, 157>
+ BOOST_CHECK_EQUAL(oss.str(), "<99.5, 157>");
+
+ //out_value_limits(x, unc, ci, m); // 128. +/- 15 <99.5, 156.5>
+ //cout << endl;
+ oss.clear(); // Clears only clear stream fail or error bits!
+ oss.str(""); // Erases the previous str (oss.str().erase() does NOT change std::string - because it only acts on a copy C string?)
+ out_value_limits(x, unc, ci, m, oss); // 128. +/- 15 <99.5, 156.5>
+ BOOST_CHECK_EQUAL(oss.str(), "128. +/- 15 <99.5, 156.5>");
+
+ // Now for 2nd example, consider eps = 0.05 - only 95% rather than 99% confidence of rounding loss.
+ del = delta(0.05, gam, triangular); // eps = 0.05 for lower 95% confidence.
+ BOOST_CHECK_CLOSE_FRACTION(del, 0.4931, tol);
+ m = round_m(0.05, unc, 2, triangular);
+ BOOST_CHECK_EQUAL(m, 0); // round to order m == 0
+ BOOST_CHECK_EQUAL(round_ms(x, m), "130.");
+ // Show confidence intervals for various alpha, 0.01 to 0.1:
+ ci = conf_interval(x, unc, 1, 0.01, triangular);
+ //cout << "conf_interval(x, unc, 1, 0.01, triangular); " << ci << endl;
+ oss.clear(); // Clears only clear stream fail or error bits!
+ oss.str(""); // Erases the previous str (oss.str().erase() does NOT change std::string - because it only acts on a copy C string?)
+ oss << setprecision(6) << ci;
+ BOOST_CHECK_EQUAL(oss.str(), "<94.1342, 161.536>");
+
+ ci = conf_interval(x, unc, 1, 0.02, triangular);
+ //cout << "conf_interval(x, unc, 1, 0.02, triangular); " << ci << endl;
+ oss.clear(); // Clears only clear stream fail or error bits!
+ oss.str(""); // Erases the previous str (oss.str().erase() does NOT change std::string - because it only acts on a copy C string?)
+ oss << setprecision(6) << ci;
+ BOOST_CHECK_EQUAL(oss.str(), "<95.6852, 159.985>");
+
+ ci = conf_interval(x, unc, 1, 0.05, triangular);
+ //cout << "conf_interval(x, unc, 1, 0.05, triangular); " << ci << endl;
+ oss.clear(); // Clears only clear stream fail or error bits!
+ oss.str(""); // Erases the previous str (oss.str().erase() does NOT change std::string - because it only acts on a copy C string?)
+ oss << setprecision(6) << ci;
+ BOOST_CHECK_EQUAL(oss.str(), "<98.7627, 156.907>");
+
+ ci = conf_interval(x, unc, 1, 0.1, triangular);
+ //cout << "conf_interval(x, unc, 1, 0.1, triangular); " << ci << endl;
+ oss.clear(); // Clears only clear stream fail or error bits!
+ oss.str(""); // Erases the previous str (oss.str().erase() does NOT change std::string - because it only acts on a copy C string?)
+ oss << setprecision(6) << ci;
+ BOOST_CHECK_EQUAL(oss.str(), "<102.231, 153.439>");
+
+ //conf_interval(x, unc, 1, 0.01, triangular); <94.1342, 161.536>
+ //conf_interval(x, unc, 1, 0.02, triangular); <95.6852, 159.985>
+ //conf_interval(x, unc, 1, 0.05, triangular); <98.7627, 156.907>
+ //conf_interval(x, unc, 1, 0.1, triangular); <102.231, 153.439>
+ // Showing significantly wider interval as require less confidence (1-alpha) from 99% down to 90%.
+
+ // Check with Wimmer 0.05 proper 0.95 confidence interval is <101.5, 158.5>
+ vr = lexical_cast<double>(round_ms(x, m));
+ ci = conf_interval(vr, unc_rounded, 1, 0.05, triangular);
+ BOOST_CHECK_CLOSE_FRACTION(ci.first, 101.5, tol);
+ BOOST_CHECK_CLOSE_FRACTION(ci.second, 158.5, tol);
+} // BOOST_AUTO_TEST_CASE(Wimmer_triangular_test)
+
+BOOST_AUTO_TEST_CASE(Wimmer_uniform_test)
+{ // Wimmer Uniform distribution - no example but use same data as triangular.
+ //cout << "Uniform distribution " << endl;
+ double x = 127.835;
+ double unc = 15.287;
+ double unc_rounded = round_sig(unc, 2); // round to 2 sig digit - why?
+ // cout << "unc_rounded " << unc_rounded << endl; // 15
+ BOOST_CHECK_CLOSE_FRACTION(unc_rounded, 15., tol);
+ ostringstream oss;
+ oss << setprecision(3) << unc_rounded; // expect 0.2 whatever precision (< digits10)
+ BOOST_CHECK_EQUAL(oss.str(), "15"); // unc 15. properly rounded.
+ double gam = unc_rounded / unc;
+ BOOST_CHECK_CLOSE_FRACTION(gam, 0.98123, 0.01);
+ // double delta(double epsilon, double gamma, distribution_type distrib = normal);
+ // Compare all deltas for the three distributions.
+ BOOST_CHECK_CLOSE_FRACTION(delta(0.01, gam), 0.053705908361491229, 0.01);
+ BOOST_CHECK_CLOSE_FRACTION(delta(0.01, gam, triangular), 0.056070697653393911, 0.01);
+ BOOST_CHECK_CLOSE_FRACTION(delta(0.01, gam, uniform), -1, 0.01);
+ // cout << "delta(0.01, gam, gaussian) = " << delta(0.01, gam) << ' ' << delta(0.01, gam, triangular) << ' ' << delta(0.01, gam, uniform) << endl;
+ // "Epsilon 0.01 is too small for gamma rounded/unrounded ratio 0.98122587819716089, threshold is 0.98999999999999999for uniform distribution."
+ double del = delta(0.01, gam, uniform); // eps = 0.01 for high 99% confidence.
+ BOOST_CHECK_CLOSE_FRACTION(del, -1., 0.01); // but is too high, so return -1
+ // "Epsilon 0.01 is too small for gamma rounded/unrounded ratio 0.981226, threshold is 0.99."
+ del = delta(0.04, gam, uniform); // eps = 0.01 for not so high 96% confidence.
+ BOOST_CHECK_CLOSE_FRACTION(del, 0.106046331775506, tol);
+ int m = round_m(0.04, unc, 2, uniform);
+ BOOST_CHECK_EQUAL(m, -1);
+ BOOST_CHECK_EQUAL(round_ms(x, m), "128.");
+ // ostringstream oss2; // Maybe quicker to construct a new string than erase old one?
+ oss.clear(); // Clears only clear stream fail or error bits!
+ oss.str(""); // Erases the previous str (oss.str().erase() does NOT change std::string - because it only acts on a copy C string?)
+ oss << setprecision(3) << unc_rounded; // expect 15 whatever precision (< digits10)
+ BOOST_CHECK_EQUAL(oss.str(), "15"); // unc 15. properly rounded.
+ //std::pair<double, double> conf_interval(double value, double unc, double df = 1., double alpha = 0.05, distribution_type distrib);
+ // value should be the rounded value 130, not the 'exact' double value 127.835.
+ // unc should also be the rounded value, 15, not the 'exact' double value 15.287.
+ // I don't understand the logic of calculating the confidence intervals with rounded data?
+ using boost::lexical_cast;
+ double vr = lexical_cast<double>(round_ms(x, m)); // = 128.
+ std::pair<double, double> ci = conf_interval(vr, unc_rounded, 1, 0.05, uniform); // alpha = 0.05, example 3b 1st 0.04-proper 0.95 confidence interval <99.5, 156.5>.
+ //cout << "conf_interval(vr, unc, 1, 0.05, uniform); " << ci << endl;
+ // conf_interval(vr, unc, 1, 0.05, uniform); <103.318, 152.682>
+ {
+ std::ostringstream os;
+ os << ci;
+ BOOST_CHECK_EQUAL(os.str(), "<103.318, 152.682>");
+ }
+ BOOST_CHECK_CLOSE_FRACTION(ci.first, 103.32, tol); //
+ BOOST_CHECK_CLOSE_FRACTION(ci.second, 152.68, tol); //
+ //cout << "out_value_limits(x, unc, ci, m) = " ;
+ //out_value_limits(x, unc, ci, m);
+ //cout << endl; //
+ // out_value_limits(x, unc, ci, m) = 128. +/- 15 <103.3, 152.7>
+ {
+ std::ostringstream os;
+ out_value_limits(x, unc, ci, m, os); // Output value, uncertainty and confidence limits.
+ BOOST_CHECK_EQUAL(os.str(), "128. +/- 15 <103.3, 152.7>");
+ // Need also degrees of freedom.
+
+ }
+} // BOOST_AUTO_TEST_CASE(Wimmer_uniform_test)
+
+BOOST_AUTO_TEST_CASE(Sephton_C_rounding_test)
+{ // Sephton's example of counter-intuitive C/C++ rounding.
+ double d = 0.15;
+ //cout << setprecision(17) << "0.15 precision 17 is " << d << endl; // Double is 0.14999999999999999
+ //cout << setprecision(1) << "0.15 precision 1 is " << d << endl; // 0.15 precision 1 is 0.1
+ // so internally stored value is nearer to 1., so rounds down to 0.1, perhaps to viewers' surprise!
+ BOOST_CHECK_EQUAL(round_e(d, 0),""); // No significant digits! might decide to throw an exception?
+ BOOST_CHECK_EQUAL(round_e(d, 1),"2.e-1"); // 1 significant digit.
+ BOOST_CHECK_EQUAL(round_e(d, 2),"1.5e-1");
+ BOOST_CHECK_EQUAL(round_e(d, 3),"1.50e-1");
+ BOOST_CHECK_EQUAL(round_e(d, 4),"1.500e-1");
+
+ d = 1.25; //
+ //cout << setprecision(17) << "1.25 precision 17 is " << d << endl; // Double is
+ //cout << setprecision(2) << "1.25 precision 2 is " << d << endl; // 1.25 precision 2 is 1.3
+ //cout << "printf(""%.1f"", 1.25); = "; printf("%.1f\n", 1.25); cout << endl; // printf(%.1f, 1.25); = 1.3
+ d = 0.15; // Sephton's pathological example showing that
+ // output digit string is 'correct' (0.15) for precision(numeric_limits<double>::digits10)
+ // and this rounds to 0.2, as expected.
+ // Imprecision 0.14999999999999999 only appears at numeric_limits<double>::maxdigits10.
+ // So by starting with the digit10 precision string, we should never get the unexpected
+ // and unwanted rounding down to 0.1.
+ for (int i = 1; i <= maxdigits10; i++)
+ {
+ //cout << i << ' ' << showpoint << setprecision(i) << d << ' ' << round_e(d, i) << endl;
+ //1 0.1 2.e-001
+ //2 0.15 1.5e-001
+ //3 0.150 1.50e-001
+ //4 0.1500 1.500e-001
+ //5 0.15000 1.5000e-001
+ //6 0.150000 1.50000e-001
+ //7 0.1500000 1.500000e-001
+ //8 0.15000000 1.5000000e-001
+ //9 0.150000000 1.50000000e-001
+ //10 0.1500000000 1.500000000e-001
+ //11 0.15000000000 1.5000000000e-001
+ //12 0.150000000000 1.50000000000e-001
+ //13 0.1500000000000 1.500000000000e-001
+ //14 0.15000000000000 1.5000000000000e-001
+ //15 0.150000000000000 1.50000000000000e-001
+ //16 0.1500000000000000 1.50000000000000e-001
+ //17 0.14999999999999999 1.50000000000000e-001
+ }
+} // BOOST_AUTO_TEST_CASE(Sephton_C_rounding_test) Sephton's example of counter-intuitive C/C++ rounding.
+
+ BOOST_AUTO_TEST_CASE(round_n_test) // Round number v *at* d th decimal place.
+ {
+ // Test round_1.
+ BOOST_CHECK_CLOSE_FRACTION(round_1(0.52), 0.5, 2 * eps);
+ BOOST_CHECK_CLOSE_FRACTION(round_1(0.55), 0.6, 2 * eps);
+ BOOST_CHECK_CLOSE_FRACTION(round_1(0.59), 0.6, 2 * eps);
+
+ // Test round_2.
+ BOOST_CHECK_CLOSE_FRACTION(round_2(0.152), 0.15, 2 * eps);
+ BOOST_CHECK_CLOSE_FRACTION(round_2(0.155), 0.16, 2 * eps);
+ BOOST_CHECK_CLOSE_FRACTION(round_2(0.159), 0.16, 2 * eps);
+
+ // Test round_3.
+ BOOST_CHECK_CLOSE_FRACTION(round_3(0.1552), 0.155, 2 * eps);
+ BOOST_CHECK_CLOSE_FRACTION(round_3(0.1555), 0.156, 2 * eps);
+ BOOST_CHECK_CLOSE_FRACTION(round_3(0.1559), 0.156, 2 * eps);
+
+ // Test round_n.
+ BOOST_CHECK_CLOSE_FRACTION(round_to_n(0.159, 1), 0.2, 2 * eps);
+ BOOST_CHECK_CLOSE_FRACTION(round_to_n(0.159, 2), 0.16, 2 * eps);
+ BOOST_CHECK_CLOSE_FRACTION(round_to_n(0.159, 3), 0.159, 2 * eps);
+
+ // Test round_sig. v rounded to n significant decimal digits.
+ BOOST_CHECK_CLOSE_FRACTION(round_sig(1703.12345679, 6), 1703.12, 2 * eps); // David A. Pimentel 6 significant digits example 1.
+ BOOST_CHECK_CLOSE_FRACTION(round_nth(1703.12345679, 6), 1703.123457, 2 * eps); // David A. Pimentel 6 digits after decimal point example 2.
+
+ // Value 15.284.
+ BOOST_CHECK_CLOSE_FRACTION(round_sig(15.284, 0), 0., 2 * eps); // By definition, zero significant digits returns zero.
+ BOOST_CHECK_CLOSE_FRACTION(round_sig(15.284, 1), 20., 2 * eps); // Expect rounded up to 20.
+ BOOST_CHECK_CLOSE_FRACTION(round_sig(15.284, 2), 15., 2 * eps); // Expect rounded to 15.
+ BOOST_CHECK_CLOSE_FRACTION(round_sig(15.284, 3), 15.3, 2 * eps); // Round up .28 to .3.
+ BOOST_CHECK_CLOSE_FRACTION(round_sig(15.284, 4), 15.28, 2 * eps); // Round .284 to .28.
+ BOOST_CHECK_CLOSE_FRACTION(round_sig(15.284, 5), 15.284, 2 * eps); // Unchanged.
+ BOOST_CHECK_CLOSE_FRACTION(round_sig(15.284, 5), 15.2840, 2 * eps); // Unchanged but with one trailing zero.
+
+ // Quite big values, but not more than digits10.
+ BOOST_CHECK_CLOSE_FRACTION(round_sig(123456.789, 0), 0., 2 * eps);
+ BOOST_CHECK_CLOSE_FRACTION(round_sig(123456.789, 1), 100000., 2 * eps);
+ BOOST_CHECK_CLOSE_FRACTION(round_sig(123456.789, 2), 120000., 2 * eps);
+ BOOST_CHECK_CLOSE_FRACTION(round_sig(123456.789, 3), 123000, 2 * eps);
+ BOOST_CHECK_CLOSE_FRACTION(round_sig(123456.789, 4), 123500., 2 * eps);
+ BOOST_CHECK_CLOSE_FRACTION(round_sig(123456.789, 5), 123460.0, 2 * eps);
+ BOOST_CHECK_CLOSE_FRACTION(round_sig(123456.789, 6), 123457.0, 2 * eps);
+ BOOST_CHECK_CLOSE_FRACTION(round_sig(123456.789, 7), 123456.8, 2 * eps);
+ BOOST_CHECK_CLOSE_FRACTION(round_sig(123456.789, 8), 123456.79, 2 * eps);
+ BOOST_CHECK_CLOSE_FRACTION(round_sig(123456.789, 9), 123456.789, 2 * eps);
+
+ BOOST_CHECK_CLOSE_FRACTION(round_sig(15.287, 2), 15., 2 * eps);
+ // Wimmer rounding examples, p 1659, 1 significant digit rounding.
+ BOOST_CHECK_CLOSE_FRACTION(round_sig(127.37, 1), 100., 2 * eps);
+ BOOST_CHECK_CLOSE_FRACTION(round_sig(0.0983, 1), 0.1, 2 * eps);
+ BOOST_CHECK_CLOSE_FRACTION(round_sig(52.83, 1), 50., 2 * eps);
+ // Wimmer rounding examples, p 1660, 3 significant digit rounding.
+ BOOST_CHECK_CLOSE_FRACTION(round_sig(1582.738, 3), 1580., 2 * eps);
+ BOOST_CHECK_CLOSE_FRACTION(round_sig(985.438, 3), 985., 2 * eps);
+ BOOST_CHECK_CLOSE_FRACTION(round_sig(0.00987624, 3), 0.00988, 2 * eps);
+
+ //cout << round(15.287) << ' ' << round(15.287)/15.287 << endl; // 0.981226
+ //cout << round(15.587) << endl;
+ //cout << round(15.1f) << endl;
+ } // BOOST_AUTO_TEST_CASE(round_n_test)
+
+
+ BOOST_AUTO_TEST_CASE(Wimmer_delta)
+ {
+ //double d0 = delta(0.01, 15./15.287);
+ //double d1 = delta(0.01, 0.98123);
+ //double d2 = delta(0.04, 0.98123);
+ //double d3 = delta(0.005, 0.99736);
+ //double d4 = delta(0.1, 0.89442);
+ //cout << d1 << endl; // 0.053779
+ //cout << d2 << endl; // 0.352144
+ //cout << d3 << endl; // 0.12
+ //cout << d4 << endl; // 0.431895
+
+ //double d5 = delta(0.05, 0.86207);
+ // Epsilon 0.05 is too small for gamma rounded/unrounded ratio 0.86207
+
+ //cout << d5 << endl; // -1.#IND
+
+ // Values in Table 1 Threshold value of gamma rounded for epsilon.
+ // If gamma rounded ratio > threshold, cannot get epsilon-properly rounded result.
+ //double d005 = delta(0.005, 0.98972); // fails.
+ //double d005p = delta(0.005, 0.99871); // is OK
+ //double d01 = delta(0.01, 0.97954);
+ //double d02 = delta(0.02, 0.95951);
+ //double d03 = delta(0.03, 0.93987);
+ //double d04 = delta(0.04, 0.92063);
+ //double d05 = delta(0.05, 0.90175);
+ //double d1 = delta(0.1, 0.81271);
+ //Epsilon 0.05 is too small for gamma rounded/unrounded ratio 0.86207
+ //Epsilon 0.005 is too small for gamma rounded/unrounded ratio 0.98972
+ //Epsilon 0.01 is too small for gamma rounded/unrounded ratio 0.97954
+ //Epsilon 0.02 is too small for gamma rounded/unrounded ratio 0.95951
+ //Epsilon 0.03 is too small for gamma rounded/unrounded ratio 0.93987
+ //Epsilon 0.04 is too small for gamma rounded/unrounded ratio 0.92063
+ //Epsilon 0.05 is too small for gamma rounded/unrounded ratio 0.90175
+ //Epsilon 0.1 is too small for gamma rounded/unrounded ratio 0.81271
+
+
+ //cout << d005p << endl;
+ //cout << d005 << endl;
+ //cout << d01 << endl;
+ //cout << d02 << endl;
+ //cout << d03 << endl;
+ //cout << d04 << endl;
+ //cout << d05 << endl;
+ //cout << d1 << endl;
+
+ // Wimmer et al claim "equation 24 approximation error is less than 0.0123 for epsilon 0.005 to 0.1".
+ // Check that this is true for these examples from the text.
+ // Perhaps should be abs (difference) < 0.0123 ?
+ BOOST_CHECK((delta(0.01, 0.98123) - 0.05) < 0.0123);
+ BOOST_CHECK((delta(0.04, 0.98123) - 0.35) < 0.0123);
+ BOOST_CHECK((delta(0.005, 0.99736) - 0.12) < 0.0123);
+ BOOST_CHECK((delta(0.1, 0.89442) - 0.43) < 0.0123);
+} // BOOST_AUTO_TEST_CASE(Wimmer_delta)
+
+BOOST_AUTO_TEST_CASE(Wimmer_gamma_test) // Test Wimmer gamma = rounded /unrounded
+{
+ BOOST_CHECK_CLOSE_FRACTION(gamma(1.8, 1.8457), 0.97524, 0.01);
+} // BOOST_AUTO_TEST_CASE(Wimmer_gamma_test)
+
+BOOST_AUTO_TEST_CASE(round_m_test2)
+{
+ ostringstream oss;
+ double u = 15.287;
+ //cout << round_1(u) << ' ' << round_2(u) << ' ' << round_3(u) << ' ' << round_nth(u, 4) << endl;
+ // 15.3 15.29 15.287 15.287
+ oss << round_1(u);
+ BOOST_CHECK_EQUAL(oss.str(), "15.3");
+ oss.str(""); oss.clear();
+
+ double t = 0.15; // printf unwanted round down case.
+ // cout << round_1(t) << ' ' << round_2(t) << ' ' << round_3(t) << ' ' << round_nth(t, 4) << endl;
+ // 0.2 0.15 0.15 0.15
+ // Note the desired 0.2! Using this rounding algorithm, unlike printf 0.1.
+ // 0.2 0.15 0.15 0.15
+ oss << round_1(t);
+ BOOST_CHECK_EQUAL(oss.str(), "0.2");
+ oss.str(""); oss.clear();
+ oss << round_2(t);
+ BOOST_CHECK_EQUAL(oss.str(), "0.15");
+ oss.str(""); oss.clear();
+ oss << round_nth(t, 1);
+ BOOST_CHECK_EQUAL(oss.str(), "0.2");
+
+ BOOST_CHECK_EQUAL(round_m(0.01, 15.287, 2U), -1); // Example 5 (i a), page 1662.
+ BOOST_CHECK_EQUAL(round_m(0.04, 15.287, 2U), 0); // Example 5 (i b)
+ BOOST_CHECK_NE(round_m(0.05, 0.0232, 1U), -3); // Example 5 (ii a) epsilon <= 0.05 should fail, and does.
+ // Cannot return a rounding m because epsilon 0.05 is too small!
+ BOOST_CHECK_EQUAL(round_m(0.1, 0.0232, 1U), -3); // Example 5 (ii b), should pass.
+
+ // 0.053779018871944452 and 0.05
+ BOOST_CHECK_EQUAL(round_e(0.0000000012345678901234567, 1),"1.e-9"); // round 1 sig digit.
+ //BOOST_CHECK_EQUAL(round(0.12345678901234567, 0),"1."); // round 0 - at decimal
+ //BOOST_CHECK_EQUAL(round(1.2345678901234567, 0),"1."); // round 0 - at decimal
+ //BOOST_CHECK_EQUAL(round(123456789.01234567, 0),"1."); // round 0 - at decimal
+ //BOOST_CHECK_EQUAL(round(12345678901234567., 0),"1."); // round 0 - at decimal
+ //BOOST_CHECK_EQUAL(round(12345678901234567890123456789., 0),"1."); // round 0 - at decimal
+
+ //double d = 1.2945678901234567890;
+ //cout << scientific << setprecision(0) << d << endl; //default 6
+ //cout << scientific << setprecision(1) << d << endl; // 1.2
+ //cout << scientific << setprecision(2) << d << endl; // 1.23
+ //cout << scientific << setprecision(3) << d << endl; // 1.235
+ //cout << scientific << setprecision(15) << d << endl; // 1.294567890123457e+000
+ //cout << scientific << setprecision(16) << d << endl; // 1.2945678901234567e+000
+ //cout << scientific << setprecision(17) << d << endl; // 1.29456789012345670e+000
+ //cout << scientific << setprecision(18) << d << endl; // 1.294567890123456700e+000
+} // BOOST_AUTO_TEST_CASE(round_m_test)
+
+// cout << endl;
+
+/*
+
+------ Build started: Project: test_rounding, Configuration: Debug Win32 ------
+Build started 04-May-2012 18:12:45.
+InitializeBuildStatus:
+ Creating "Debug\test_rounding.unsuccessfulbuild" because "AlwaysCreate" was specified.
+ClCompile:
+ test_rounding.cpp
+ManifestResourceCompile:
+ All outputs are up-to-date.
+Manifest:
+ All outputs are up-to-date.
+LinkEmbedManifest:
+ All outputs are up-to-date.
+ test_rounding.vcxproj -> J:\Cpp\quan\MSVC\Debug\test_rounding.exe
+CustomBuildStep:
+ Description: Autorun "J:\Cpp\quan\MSVC\Debug\\test_rounding.exe"
+ Running 17 test cases...
+ Platform: Win32
+ Compiler: Microsoft Visual C++ version 10.0
+ STL : Dinkumware standard library version 520
+ Boost : 1.50.0
+ Round test: ..\libs\quan\test\test_rounding.cpp at "Fri May 4 18:12:45 2012", MSVC version 160040219.
+ double maxdigits10 is 17
+ std::numeric_limits<double>::max_exponent = 1024,
+ std::numeric_limits<double>::max_exponent10 = 308,
+ std::numeric_limits<double>::max_exponent10 -1 = 307.
+ Trying to output zero significant digits!
+ Trying to output -1 significant digits!
+ Maximum significant digits is 15
+ Maximum significant digits is 15
+ Maximum significant digits is 15
+ Maximum significant digits is 15
+ Maximum significant digits is 15
+ Maximum significant digits is 15
+ Maximum significant digits is 15
+ Epsilon 0.001 is too small for gamma rounded/unrounded ratio 0.991379, threshold is -0.00666462 for gaussian distribution.
+ Cannot compute a rounding m because epsilon 0.001 is too small!
+ Epsilon 0.01 is too small for gamma rounded/unrounded ratio 0.981226, threshold is 0.99 for uniform distribution.
+ Epsilon 0.01 is too small for gamma rounded/unrounded ratio 0.981226, threshold is 0.99 for uniform distribution.
+ Trying to display 0 significant decimal digits!
+ Cannot return a rounding m because epsilon 0.05 is too small!
+
+ Test suite "Master Test Suite" passed with:
+ 544 assertions out of 544 passed
+ 17 test cases out of 17 passed
+
+ Test case "round_test_1" passed with:
+ 1 assertion out of 1 passed
+
+ Test case "round_f_test" passed with:
+ 48 assertions out of 48 passed
+
+ Test case "round_e_test" passed with:
+ 126 assertions out of 126 passed
+
+ Test case "cdf_quantile_test" passed with:
+ 134 assertions out of 134 passed
+
+ Test case "round_ms_test" passed with:
+ 80 assertions out of 80 passed
+
+ Test case "Wimmer_3" passed with:
+ 4 assertions out of 4 passed
+
+ Test case "Wimmer_4" passed with:
+ 6 assertions out of 6 passed
+
+ Test case "Wimmer_5_1" passed with:
+ 10 assertions out of 10 passed
+
+ Test case "Wimmer_5_2" passed with:
+ 7 assertions out of 7 passed
+
+ Test case "round_ue_test" passed with:
+ 36 assertions out of 36 passed
+
+ Test case "Wimmer_triangular_test" passed with:
+ 20 assertions out of 20 passed
+
+ Test case "Wimmer_uniform_test" passed with:
+ 15 assertions out of 15 passed
+
+ Test case "Sephton_C_rounding_test" passed with:
+ 5 assertions out of 5 passed
+
+ Test case "round_n_test" passed with:
+ 38 assertions out of 38 passed
+
+ Test case "Wimmer_delta" passed with:
+ 4 assertions out of 4 passed
+
+ Test case "Wimmer_gamma_test" passed with:
+ 1 assertion out of 1 passed
+
+ Test case "round_m_test2" passed with:
+ 9 assertions out of 9 passed
+
+FinalizeBuildStatus:
+ Deleting file "Debug\test_rounding.unsuccessfulbuild".
+ Touching "Debug\test_rounding.lastbuildstate".
+
+Build succeeded.
+
+Time Elapsed 00:00:04.20
+========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
+
+
+*/
+

Added: sandbox/SOC/2007/quan/libs/quan/test/unc_tests.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/quan/libs/quan/test/unc_tests.cpp 2012-10-05 10:48:15 EDT (Fri, 05 Oct 2012)
@@ -0,0 +1,1766 @@
+/*!
+ \file
+ \brief Testing uncertain classes using Boost Test Tool.
+ \details Class for simple Propagation of Uncertainties
+ according to a pure Gaussian model.
+*/
+
+// Use, modification and distribution are subject to 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)
+// Copyright Paul A. Bristow 1998, 2012.
+
+// unc_tests.cpp
+
+#ifdef _MSC_VER
+# pragma warning(disable: 4702) // unreachable code
+# pragma warning(disable: 4511) // copy constructor could not be generated.
+# pragma warning(disable: 4512) // assignment operator could not be generated.
+# pragma warning(disable: 4521) // alignment of a member was sensitive to packing.
+# pragma warning(disable: 4100) // unreferenced formal parameter.
+# pragma warning(disable: 4701) // local variable may be used without having been initialized.
+# pragma warning(disable: 4121) // alignment of a member was sensitive to packing.
+# pragma warning(disable: 4127) // conditional expression is constant.
+#endif
+
+// #define UNC_TRACE // Diagnostic output.
+
+#define BOOST_TEST_MAIN // Required for int test_main() (must come FIRST).
+//#define BOOST_LIB_DIAGNOSTIC "on"// Show library file details.
+// Linking to lib file: libboost_unit_test_framework-vc100-mt-s-1_49.lib
+
+#include <boost/config.hpp>
+#include <boost/cstdlib.hpp> // needed for boost::exit_failure;
+
+#include <boost/test/unit_test.hpp> // Enhanced for unit_test framework autolink,
+#include <boost/test/floating_point_comparison.hpp> // Extra test tool for FP comparison.
+ using boost::unit_test::test_suite;
+ using boost::unit_test::unit_test_log;
+
+// Classes for simple propagation of Uncertainties according to a pure Gaussian model.
+
+#include <cmath> // for <math.h>
+#include <iostream>
+ using std::ostream;
+ using std::cout;
+ using std::ios_base;
+ using std::ends;
+ using std::endl;
+ using std::ios_base;
+ using std::hex;
+ using std::oct;
+ using std::dec;
+ using std::boolalpha;
+ using std::getline;
+ using std::skipws;
+ using std::noskipws;
+ using std::uppercase;
+ using std::showbase;
+ using std::showpos;
+ using std::left;
+ using std::right;
+ using std::internal; // Initial default - neither left, right nor internal.
+#include <iomanip> // for <iomanip.h> for setw, setprecision ...
+ using std::setfill;
+#include <fstream> // for <fstream.h> for filing.
+ using std::ofstream;
+ using std::ifstream;
+#include <string> // for C++ Std strings
+ using std::basic_string;
+ using std::string;
+#include <sstream> // for o & istringstream
+ using std::istringstream;
+ using std::ostringstream;
+ using std::stringstream;
+#include <limits>
+ using std::numeric_limits;
+
+#include <boost/quan/xiostream.hpp> // extra iostream manipulators like noshowbase
+ using std::lowercase;
+ using std::defaultfloat; // Initial default - neither scientific nor fixed.
+ using std::nofixed;
+ using std::noscientific;
+ using std::noadjust;
+ using std::hexbase;
+
+#include <boost/quan/unc.hpp> // Declaration of Uncertain Classes.
+
+// Files made global to avoid nasty memory leak, and loop to end of memory.
+const char testInputFilename[] = "unc_test_input.txt"; // Input for tests (fin).
+ifstream fin(testInputFilename, ios_base::in);
+const char outFilename[] = "unc_test_output.txt"; // output from tests (fout).
+ofstream fout(outFilename, ios_base::out); // Use default ios_base::overwrite/replace.
+// const char logFilename[] = "unc_log.txt"; // // Boost test log (usual to send to cout).
+// ofstream lout(logFilename, ios_base::out); // Use default overwrite/ iso::replace.
+const char diagFilename[] = "unc_diag.txt"; // diagnostic log diverted from cerr (dout).
+ ofstream dout(diagFilename, ios_base::out); // Use default overwrite/ iso::replace.
+//const char testLogFilename[] = "unc_test.log"; // Not used yet.
+
+// typedef basic_string <char>::size_type size_type;
+// using basic_string <char>::size_type;
+
+// toString concept works for some purposes,
+// but is flawed to combine several manipulators and it needs setUncDefaults.
+// Check using manips output expected string result, for example:
+// CHECK(hex << showbase << setw(10) << i, " 0xf")
+// CHECK(scientific << setw(20) << d, " 1.234568e+001");
+// Note: sets uncertain defaults (& oss has ios defaults too).
+// BUT CHECK cannot check the number of chars output using unc_print "used",
+// so use CHECK_USED for this.
+
+#define CHECK(manips, result)\
+{\
+ ostringstream oss;\
+ setUncDefaults(oss);\
+ oss << manips;\
+ BOOST_CHECK_EQUAL(oss.str(), result);\
+}// #define CHECK(manips, result)
+// BOOST_CHECK_EQUAL(oss.str().length(), strlen(result));\
+// Temporarily removed because causes too much clutter in log.
+// Anyway. if strings are same, then length check is superfluous.
+
+// Also check that the unc used count was correct.
+#define CHECK_USED(manips, result)\
+{\
+ typedef basic_string <char>::size_type size_type;\
+ ostringstream oss;\
+ setUncDefaults(oss);\
+ oss << manips;\
+ BOOST_CHECK_EQUAL(oss.str(), result);\
+}
+// BOOST_CHECK_EQUAL(oss.str().length(), static_cast<size_type>(oss.iword(usedIndex)));\
+// Was temporarily removed because causes too much clutter in log.
+
+// Compare results of reading string into a uncun, for example 1.2 +/-0.01 (8)
+// with all elements of uncun type.
+#define CHECK_IN(in_string, mean, sd, df, ty)\
+{\
+ uncun r;\
+ std::istringstream iss(in_string);\
+ setUncDefaults(iss);\
+ iss >> r;\
+ BOOST_CHECK_CLOSE_FRACTION(r.value(), mean, numeric_limits<double>::epsilon());\
+ BOOST_CHECK_CLOSE_FRACTION(r.std_dev(), sd, numeric_limits<float>::epsilon());\
+ BOOST_CHECK_EQUAL(r.deg_free(), df);\
+ BOOST_CHECK_EQUAL(r.types(), ty);\
+ showUncTypes(r.types());\
+} // #define CHECK_IN(in, value, sd, df, types)
+
+// CHECK_OUT_IN Output via manips, and read back in, check is same.
+#define CHECK_OUT_IN(manips, result, value, sd, df, types)\
+{\
+ typedef basic_string <char>::size_type size_type;\
+ stringstream ss;\
+ setUncDefaults(ss);\
+ ss << manips;\
+ BOOST_CHECK_EQUAL(ss.str(), result);\
+ BOOST_CHECK_EQUAL(ss.str().length(), static_cast<size_type>(ss.iword(usedIndex)));\
+ uncun r;\
+ ss >> r;\
+ BOOST_CHECK_CLOSE_FRACTION(r.value(), value, numeric_limits<double>::epsilon());\
+ BOOST_CHECK_CLOSE_FRACTION(r.std_dev(), sd, numeric_limits<float>::epsilon());\
+ BOOST_CHECK_EQUAL(r.deg_free(), df);\
+ BOOST_CHECK_EQUAL(r.types(), types);\
+}// #define CHECK_OUT_IN(manips, result)
+
+// Integrity check on iword begin and end no longer needed in CHECK.
+// BOOST_CHECK_EQUAL(oss.iword(topIndex), indexID);\
+// BOOST_CHECK_EQUAL(oss.iword(0), indexID);\
+// BOOST_CHECK_EQUAL(oss.iword(topIndex), indexID);\
+// BOOST_CHECK_EQUAL(oss.iword(0), indexID);\
+
+// This test case is automatically registered by using BOOST_AUTO_TEST_CASE.
+ using std::istream;
+ using std::ostream;
+ using std::ios_base;
+ using std::char_traits;
+ using std::cout;
+ using std::cerr;
+ using std::cin;
+ using std::endl;
+ using std::flush;
+ using std::ws;
+ using std::streamsize;
+ using std::boolalpha;
+ using std::dec;
+ using std::hex;
+ using std::showbase;
+ using std::fixed;
+ using std::scientific;
+ using std::right;
+ using std::showpos;
+ using std::noshowpos;
+ using std::noshowbase;
+ using std::noshowpoint;
+ using std::showpoint;
+
+ using std::setprecision;
+ using std::setw;
+ using std::resetiosflags;
+
+
+BOOST_AUTO_TEST_CASE(unc_test_basic)
+{ // Uncertain Class tests.
+ boost::unit_test::unit_test_log.set_threshold_level( boost::unit_test::log_messages);
+
+ string message("Round to cout test: " __FILE__ );
+#ifdef __TIMESTAMP__
+ message += " at " BOOST_STRINGIZE(__TIMESTAMP__);
+#endif
+#ifdef _MSC_FULL_VER
+ message += ", MSVC version " BOOST_STRINGIZE(_MSC_FULL_VER) ".";
+#else
+ message += "."
+#endif
+ BOOST_MESSAGE(message);
+
+ // BOOST_CHECK(zeroIndex == indexID); // Should pass?
+
+
+ // BOOST_CHECK(lout.is_open());
+ // unc_tests.cpp(235): info: check lout.is_open() passed
+ // unit_test_log.set_stream(lout); // Switch to log file.
+ // BOOST_TEST_MESSAGE(message);
+
+ BOOST_CHECK(numeric_limits<double>::is_iec559 == true); // IEC559/IEEE754 floating point.
+
+ // Change log level to record warnings & errors.
+ // unit_test_log.set_log_threshold(boost::unit_test::log_successful_tests);
+ unit_test_log.set_threshold_level(boost::unit_test::log_all_errors);
+ //unit_test_log::instance().set_threshold_level(test_suite);
+ //unit_test_log::instance().set_threshold_level(messages); // user messages
+ // Prepare to send log to a file instead of cout.
+
+ cout << "\x0F1 Uncertain Class Test output to " << outFilename << ' '
+ << __FILE__ << ' ' << __TIMESTAMP__ << endl;
+ // +- symbol on screen cout = dec 177, hex F1 but shows ~n in files?
+ // BUT is messy because in file codeset +- symbol \x0B1 176!
+
+ BOOST_CHECK(fout.is_open());
+ // Test output to file ...
+ fout << "Test Output from " << __FILE__ << " " << __TIMESTAMP__"\n" << endl;
+
+ // Test diagnostic output to file ...
+ //BOOST_CHECK(lout.is_open());
+ //lout << "Unc " << logFilename << " opened." << endl;
+ BOOST_CHECK(dout.is_open());
+ dout << "Unc Diagnostics logged to " << diagFilename << " from " << __FILE__ << " " << __TIMESTAMP__"\n"<< endl;
+ cout << "Unc Diagnostics logged to " << diagFilename << endl; // \x0F1 on screen but ~n in files.
+ cerr.rdbuf(dout.rdbuf()); // cerr = dout; // Switch cerr to diagnostic log.
+ // dout << "Diagnostic cerr from " << __FILE__ << " " << __TIMESTAMP__"\n" << endl;
+ cerr << "\x0B1 \x0B5 Diagnostic cerr from " << __FILE__ << " " << __TIMESTAMP__"\n" << endl;
+ // Greek mu is \x0B5 for files, degree symbol is \x0B0
+ // BOOST_CHECK(fin.is_open()); // No input yet?
+
+ BOOST_MESSAGE("Uncertain Class tests log. " << " Expected Was Expected");
+
+ // cout.fill('0'); // to get trailing zeros.
+ // cout << fixed << setprecision(17) << 12.34 << automatic << endl; // 12.34000000000000000
+ // gives 17 digits (2 digits plus 15 trailing zeros AFTER decimal point).
+
+ //________________________________________________________________________________________________________________________________
+ {
+ // Some floating point comparison examples, with two tolerances, just wide enough, and too tight.
+ double fp1 = 1.;
+ double fp2 = 1.00001;
+ BOOST_CHECK_CLOSE(fp1, fp2, 0.00100001); // Wide tolerance info: test fp1 ~= fp2 passed.
+ // difference between fp1{1} and fp2{1.00001} exceeds 0.001% (0.00001 * 100 = 0.001%)
+ // Note that BOOST_CHECK_CLOSE(fp1, fp2, 0.001); // just fails, but 0.001000001 passes.
+
+ // BOOST_CHECK_CLOSE(fp1, fp2, 0.0000000001); // Tight tolerance so should fail [1 !~= 1.00001 (+/-1e-010)].
+ // error in "call_test_main": difference between fp1{1} and fp2{1.00001} exceeds 1e-010%
+ }
+
+ setUncDefaults(fout); // Should set the indexID values too.
+ long& zeroid = fout.iword(zeroIndex);
+ long& topid = fout.iword(topIndex);
+ BOOST_CHECK_EQUAL(zeroid, indexID); // Check iword init at bottom OK,
+ BOOST_CHECK_EQUAL(topid, indexID); // Check iword init at bottom OK,
+ BOOST_CHECK_EQUAL(fout.iword(zeroIndex), indexID); // Check iword init at bottom OK,
+ BOOST_CHECK_EQUAL(fout.iword(topIndex), indexID);// and at top too.
+ long& uncFlags = fout.iword(uncFlagsIndex);
+
+ setUncDefaults(dout); // Should set the indexID values too.
+ zeroid = dout.iword(zeroIndex);
+ topid = dout.iword(topIndex);
+ BOOST_CHECK_EQUAL(zeroid, indexID); // Check iword init at bottom OK,
+ BOOST_CHECK_EQUAL(topid, indexID);// & at top too.
+
+ setUncDefaults(std::cout);
+
+ // Check initial ios flags, precision, fill, width.
+ // Expect IOS flags: skipwhite dec, precision 6, fill ' '
+ std::streamsize originalWidth = fout.width(); // Not useful to restore.
+ BOOST_CHECK_EQUAL(fout.width(), 0); // std default precision.
+ std::streamsize originalPrecision = fout.precision(); // Default precision is 6.
+ BOOST_CHECK_EQUAL(fout.precision(), 6); // std default precision is 6.
+ long originalFlags = fout.flags(); // hex 201 == skipwhite dec.
+ BOOST_CHECK_EQUAL(fout.flags(), 0x201);
+ BOOST_CHECK_EQUAL(fout.flags(), std::ios_base::skipws | std::ios_base::dec);
+ BOOST_CHECK_EQUAL(fout.fill(), ' '); // fill char is space.
+ BOOST_CHECK_EQUAL(fout.flags() & ios_base::floatfield, 0);
+ BOOST_CHECK_EQUAL(fout.flags() & ios_base::adjustfield, 0);
+ BOOST_CHECK_EQUAL(fout.flags() & ios_base::adjustfield, (int)!(ios_base::left | ios_base::right | ios_base::internal));
+ BOOST_CHECK_EQUAL(fout.flags() & ios_base::showbase, 0); // no showbase.
+ BOOST_CHECK_EQUAL(fout.flags() & ios_base::boolalpha, 0); // no boolapha.
+
+ // Basic checks on re-initialisation of ios and unc using.
+ void setiosDefaults(ostream&); // &
+ void setUncDefaults(ios_base&);
+
+ ostringstream oss;
+ std::ios_base::fmtflags init_flags = oss.flags();
+ //outFmtFlags(init_flags); // Default flags after initializing stream: skipws & dec.
+ setUncDefaults(oss);
+ long init_uflags = uFlags(oss);
+ oss.flags(~init_flags); // Alter all the flags.
+ //outFmtFlags(oss.flags()); // Show altered flags.
+ //outFmtFlags(0xFFFFFF); // Show all flags.
+ oss.precision(99);
+ BOOST_CHECK_EQUAL(oss.precision(), 99);
+ oss.fill('*');
+ BOOST_CHECK_EQUAL(oss.fill(), '*');
+
+ //setuFlags(oss,0xFFFFFFFF);
+ //showUncFlags(oss);
+ // Restore as initialised.
+ setiosDefaults(oss);
+ setUncDefaults(oss);
+ //outFmtFlags(oss.flags());
+ //outUncFlags(oss);
+ BOOST_CHECK_EQUAL(oss.rdstate(), ios_base::goodbit);
+ BOOST_CHECK_EQUAL(init_flags, oss.flags()); // Check now same as when initialised = skipws & dec.
+ BOOST_CHECK_EQUAL(oss.precision(), 6);
+ BOOST_CHECK_EQUAL(oss.fill(), ' ');
+ BOOST_CHECK_EQUAL(oss.width(), 0);
+ BOOST_CHECK_EQUAL(uFlags(oss), init_uflags);
+ BOOST_CHECK_EQUAL(oss.iword(uncFlagsIndex), 0);
+ BOOST_CHECK_EQUAL(oss.iword(sigDigitsIndex), 3);
+ BOOST_CHECK_EQUAL(oss.iword(uncWidthIndex), 10);
+ BOOST_CHECK_EQUAL(oss.iword(scaleIndex), 0);
+ BOOST_CHECK_EQUAL(oss.iword(setUncSigDigitsIndex), 2);// Default 2 sig digits.
+
+ extern const long indexID; // random id to check init OK.
+ BOOST_CHECK_EQUAL(oss.iword(zeroIndex), indexID);
+ BOOST_CHECK_EQUAL(oss.iword(topIndex), indexID);
+
+ std::streamsize w = cerr.width(6); // Set a width of 6.
+ BOOST_CHECK_EQUAL(cerr.width(), 6); // Confirm has been set to 6.
+ cerr << endl; // Does NOT 'Use' width.
+ BOOST_CHECK_EQUAL(cerr.width(), 6); // Confirm is STILL 6.
+ cerr << '\t' << endl; // (\a shows as small square) Does 'Use' width, like << "use" or << 99
+ BOOST_CHECK_EQUAL(cerr.width(), 0);// Check width has been reset to zero.
+ } // BOOST_AUTO_TEST_CASE(unc_test_basic)
+
+//#define CPP_TESTS
+#ifdef CPP_TESTS
+BOOST_AUTO_TEST_CASE(unc_test_stdio)
+{ // Examples of C++ std integer output.
+ int i1 = 1;
+ CHECK(i1, "1");
+ CHECK(noshowpoint << i1, "1"); // Explicit NOshowpoint
+ CHECK(showpoint << i1, "1"); // Never show point if value is integer!
+
+ int i1234 = 1234;
+ CHECK(i1234, "1234");
+ CHECK(noshowpoint << i1234, "1234"); // Normal
+ CHECK(showpoint << i1234, "1234"); // NOT "1234." Doesn't show point if integer!
+ CHECK(showpos << i1234, "+1234"); // Shows +
+
+ int m1 = -1; // negative variable.
+ CHECK(m1, "-1"); // negative constant.
+ CHECK(hex << m1, "ffffffff"); //
+ int m1234 = -1234;
+ CHECK(m1234, "-1234"); // plain negative
+ CHECK(noshowpoint << m1234, "-1234"); // Normal
+ CHECK(showpoint << m1234, "-1234"); // NOT "-1234." Doesn't show point if integer!
+ CHECK(showpos << m1234, "-1234"); // Makes no difference - always show - sign.
+ CHECK(noshowpos << m1234, "-1234"); // Makes no difference - always show - sign.
+
+ int i = 15;
+ CHECK(hex << showbase << setw(5) << i, " 0xf"); // 2 spaces + 3 digit chars.
+ CHECK(hex << noshowbase << setw(5) << i, " f"); // 4 spaces + 1 digit char .
+ CHECK(hex << left << noshowbase << setw(5) << i, "f "); // 1 digit char + 4 fill spaces.
+ CHECK(right << dec << noshowbase << setw(5) << i, " 15"); // 1 digit char + 3 fill spaces.
+ CHECK(setfill('~') << left << dec << noshowbase << setw(5) << i, "15~~~"); // 3 ~ & 1 digit char.
+ CHECK(setfill('~') << right << dec << noshowbase << setw(5) << i, "~~~15"); // 1 digit char + 3 ~.
+
+ // Check some examples of built-in double output.
+
+ double zero = 0.;
+ double one = 1.;
+ double minus1 = -1.;
+ double point1 = 0.1;
+
+ CHECK(zero, "0"); // normal defaults, width = 1
+ CHECK(showpos << zero, "+0"); // normal defaults, width = 1
+ CHECK(setprecision(0) << zero, "0"); // NO decimal point.
+ // Check use of showpos and showpoint.
+ CHECK(fixed << showpos << showpoint << zero, "+0.000000"); // 1+6 zeros - no precision set, so defaults to 6.
+ CHECK(showpoint << setprecision(1) << zero, "0.0"); // normal defaults, width = 7
+ CHECK(showpoint << showpos << setprecision(0) << zero, "+0.000000"); // 6 zeros
+ CHECK(showpoint << showpos << setprecision(1) << zero, "+0.0"); // normal defaults, width = 1
+ CHECK(showpoint << showpos << setprecision(-1) << zero, "+0.000000"); // 6 zeros
+ CHECK(showpoint << showpos << setprecision(6) << zero, "+0.000000"); // 6 zeros
+ // So setprecision(0) means precision(6) if normal unless fixed when
+ CHECK(fixed << showpoint << setfill('~') << setprecision(0) << zero, "0."); // width = 2
+ CHECK(fixed << showpos << showpoint << setfill('~') << setprecision(0) << zero, "+0."); // width = 2
+ CHECK(fixed << showpos << showpoint << setprecision(0) << zero, "+0."); // width = 3
+ CHECK(fixed << showpos << showpoint << setprecision(1) << zero, "+0.0"); // width = 4
+ CHECK(fixed << showpos << showpoint << setprecision(2) << zero, "+0.00"); // width = 5
+ CHECK(fixed << showpos << showpoint << setprecision(3) << zero, "+0.000"); // width = 6
+
+ CHECK(fixed << setprecision(0) << zero, "0"); // width = 1
+ CHECK(fixed << showpoint << setprecision(0) << zero, "0."); // width = 2
+ CHECK(fixed << showpoint << setprecision(1) << zero, "0.0"); // width = 3
+ CHECK(fixed << showpoint << setprecision(2) << zero, "0.00"); // width = 4
+ CHECK(fixed << showpoint << setprecision(3) << zero, "0.000"); // width = 5
+
+ CHECK(one, "1"); // normal defaults, width = 1
+ CHECK(showpoint << one, "1.00000"); // Same as above, using default precision(6)
+ // << showpoint means that precision is used.
+ CHECK(left << showpoint << setfill('~') << setprecision(6) << one, "1.00000"); // width = 7
+ CHECK(left << showpoint << setfill('~') << setprecision(1) << one, "1."); // width = 7
+ CHECK(left << showpoint << setfill('~') << setprecision(0) << one, "1.00000"); // NOT "1."
+ // So conclude that precision(0) means default is used.
+ // Show how precision controls if width is not set & show that no fill char ~ are used):
+ CHECK(left << fixed << showpoint << setprecision(4) << one, "1.0000"); // width = 6
+ CHECK(left << fixed << showpoint << setfill('~') << setprecision(6) << one, "1.000000"); // width = 8
+ CHECK(left << fixed << showpoint << setfill('~') << setprecision(5) << one, "1.00000"); // width = 7
+ CHECK(left << fixed << showpoint << setfill('~') << setprecision(4) << one, "1.0000"); // width = 6
+ CHECK(left << fixed << showpoint << setfill('~') << setprecision(3) << one, "1.000"); // width = 5
+ CHECK(left << fixed << showpoint << setfill('~') << setprecision(2) << one, "1.00"); // width = 4
+ CHECK(left << fixed << showpoint << setfill('~') << setprecision(1) << one, "1.0"); // width = 3
+ CHECK(left << fixed << showpoint << setfill('~') << setprecision(0) << one, "1."); // width = 2
+ CHECK(left << showpoint << setfill('~') << setprecision(0) << one, "1.00000"); // width = 6 + 1 .
+
+ CHECK(fixed << showpoint << setprecision(0) << minus1, "-1."); // width = 3 if value >= 1, precision(0) then 1 digit.
+ CHECK(fixed << showpoint << setprecision(1) << minus1, "-1.0"); // width = 4
+ CHECK(fixed << showpoint << setprecision(2) << minus1, "-1.00"); // width = 5
+ CHECK(fixed << showpoint << setprecision(3) << minus1, "-1.000"); // width = 6
+
+ CHECK(fixed << showpoint << setprecision(0) << point1, "0."); // width = 2 - else if value < 1. then NO precision!
+ CHECK(fixed << showpoint << setprecision(1) << point1, "0.1"); // width = 3
+ CHECK(fixed << showpoint << setprecision(2) << point1, "0.10"); // width = 4
+ CHECK(fixed << showpoint << setprecision(3) << point1, "0.100"); // width = 5
+
+ double big = 123456.;
+ CHECK(big, "123456"); // default 'normal' is not fixed, nor showpoint, nor scientific.
+ // Nicholai M Josuttis, The C++ Standard Library, ISBN 0 201 37926 0, page 624
+ CHECK(showpoint << big, "123456."); // Add single . point.
+ CHECK(showpoint << setprecision(0) << big, "123456."); // Same as no setprecision
+ CHECK(showpoint << setprecision(1) << big, "1.e+005"); // Cuts down to 1 decimal place and goes exp.
+ CHECK(showpoint << setprecision(2) << big, "1.2e+005"); // Cuts down to 1+1 decimal place and goes exp.
+ CHECK(showpoint << setprecision(3) << big, "1.23e+005"); // Cuts down to 1+2 decimal place and goes exp.
+ CHECK(showpoint << setprecision(4) << big, "1.235e+005"); // Rounds to 1+3 decimal place and goes exp.
+ CHECK(showpoint << setprecision(5) << big, "1.2346e+005"); // Rounds to 1+4 decimal place and goes exp.
+ CHECK(showpoint << setprecision(6) << big, "123456."); // Using default 6 for setprecision(6).
+ CHECK(showpoint << big, "123456."); // Same as using default setprecision(6).
+ CHECK(showpoint << setprecision(7) << big, "123456.0"); // Precision digits (7) in integral & fractional part.
+ CHECK(showpoint << setprecision(17) << big, "123456.00000000000"); // Max 64-bit double setprecision, 18 digits
+
+ // If fixed then precision sets the number of digits in the FRACTIONAL part.
+ CHECK(fixed << showpoint << setprecision(0) << big, "123456."); //
+ CHECK(fixed << showpoint << setprecision(1) << big, "123456.0"); //
+ CHECK(fixed << showpoint << setprecision(2) << big, "123456.00"); //
+ CHECK(fixed << showpoint << setprecision(3) << big, "123456.000"); //
+
+ double fourDigits = 1234.;
+ CHECK(fourDigits, "1234"); // default 'normal' aka 'automatic' is not fixed, nor scientific, nor showpoint, nor showpos.
+ // Nicholai M Josuttis, The C++ Standard Library, ISBN 0 201 37926 0, page 624
+ CHECK(showpoint << fourDigits, "1234.00"); // Add single . point.
+ CHECK(showpoint << setprecision(0) << fourDigits, "1234.00"); // Same as no setprecision
+ CHECK(showpoint << setprecision(1) << fourDigits, "1.e+003"); // Cuts down to 1 decimal place and goes exp.
+ CHECK(showpoint << setprecision(2) << fourDigits, "1.2e+003"); // Cuts down to 1+1 decimal place and goes exp.
+ CHECK(showpoint << setprecision(3) << fourDigits, "1.23e+003"); // Cuts down to 1+2 decimal place and goes exp.
+ CHECK(showpoint << setprecision(4) << fourDigits, "1234."); // Rounds to 1+3 decimal place.
+ CHECK(showpoint << setprecision(5) << fourDigits, "1234.0"); // Rounds to 1+4 decimal place.
+ CHECK(showpoint << setprecision(6) << fourDigits, "1234.00"); // Using default 6 for setprecision(6).
+ CHECK(showpoint << fourDigits, "1234.00"); // Same as using default setprecision(6).
+ CHECK(showpoint << setprecision(7) << fourDigits, "1234.000"); // Precision digits (7) in integral & fractional part.
+ CHECK(showpoint << setprecision(17) << fourDigits, "1234.0000000000000"); // Max 64-bit double setprecision, 18 digits
+
+ // If fixed then precision sets the number of digits in the FRACTIONAL part.
+ CHECK(fixed << showpoint << setprecision(0) << fourDigits, "1234."); //
+ CHECK(fixed << showpoint << setprecision(1) << fourDigits, "1234.0"); //
+ CHECK(fixed << showpoint << setprecision(2) << fourDigits, "1234.00"); //
+ CHECK(fixed << showpoint << setprecision(3) << fourDigits, "1234.000"); //
+
+ // Using fixed, showpoint and setprecision to show significant digits, including decimal point and trailing zeros.
+ double twelve34 = 12.34;
+ CHECK(twelve34, "12.34");
+ CHECK(fixed << showpoint << setprecision(0) << twelve34, "12.");
+ CHECK(fixed << showpoint << setprecision(1) << twelve34, "12.3");
+ CHECK(fixed << showpoint << setprecision(2) << twelve34, "12.34");
+ CHECK(fixed << showpoint << setprecision(3) << twelve34, "12.340"); // Adds trailing zero(s)
+ CHECK(fixed << showpoint << setprecision(4) << twelve34, "12.3400");
+ CHECK(fixed << showpoint << setprecision(5) << twelve34, "12.34000");
+
+ // fill NOT used unless width is set.
+ // Forcing + sign with showpos
+ CHECK(left << fixed << showpos << showpoint << setfill('0') << setprecision(0) << one, "+1."); // width = 3
+ CHECK(left << fixed << showpoint << setfill('0') << setprecision(0) << minus1, "-1."); // width = 3
+
+ // fill NOT used unless width is set using setw().
+ CHECK(left << fixed << showpoint << setfill('~') << setprecision(4) << one, "1.0000"); // no set width, 4 zeros after.
+ // Using setfill and showpoint (and setw) to show trailing zeros.
+ CHECK(left << fixed << showpoint << setfill('0') << setprecision(4) << setw(8) << one, "1.000000"); // 2 extra fill zeros.
+ CHECK(left << fixed << showpoint << setfill('~') << setprecision(4) << setw(8) << one, "1.0000~~"); // 2 extra fill ~.
+ CHECK(left << fixed << showpoint << setfill('~') << setprecision(4) << setw(7) << one, "1.0000~"); // 1 extra fill ~
+ CHECK(left << fixed << showpoint << setfill('~') << setprecision(4) << setw(6) << one, "1.0000"); // width has no effect.
+ CHECK(left << fixed << showpoint << setfill('~') << setprecision(4) << setw(5) << one, "1.0000"); // NO fill.
+ CHECK(left << fixed << showpoint << setfill('~') << setprecision(3) << setw(4) << one, "1.000");
+ CHECK(left << fixed << showpoint << setfill('~') << setprecision(2) << setw(3) << one, "1.00");
+ CHECK(left << fixed << showpoint << setfill('~') << setprecision(1) << setw(3) << one, "1.0");
+ CHECK(left << fixed << showpoint << setfill('~') << setprecision(1) << setw(1) << one, "1.0"); // want 1.
+ CHECK(left << fixed << showpoint << setfill('~') << setprecision(1) << setw(2) << zero , "0.0"); // want 0.
+ CHECK(left << fixed << showpoint << setfill('~') << setprecision(1) << setw(1) << zero , "0.0"); // 0.0
+ CHECK(left << fixed << noshowpoint << setfill('~') << setprecision(1) << setw(1) << zero , "0.0");
+ CHECK(left << fixed << noshowpoint << setfill('~') << setprecision(0) << setw(1) << zero , "0");
+ CHECK(left << fixed << showpoint << setfill('~') << setprecision(0) << setw(1) << zero , "0.");
+ CHECK(left << fixed << showpoint << setfill('~') << setprecision(0) << setw(0) << zero , "0."); // setw(0) undefined?
+ CHECK(left << fixed << showpoint << setfill('~') << setprecision(-1) << one, "1.000000"); // precision < 0 means default = 6
+
+ double d = 1.234567890;
+ CHECK(setw(20) << d, " 1.23457"); // precision 6, width 20 is 13 spaces + 7 chars.
+ CHECK(fixed << setw(20) << d, " 1.234568"); // width 20 is 12 spaces + 8 chars.
+ CHECK(fixed << setw(20) << d, " 1.234568"); // width 20 is 13 spaces + 8 chars.
+ CHECK(scientific << setw(20) << d, " 1.234568e+000"); // width 20 is 7 spaces + 13 chars.
+ CHECK(scientific << d, "1.234568e+000"); // width reverts automatically to 0.
+ CHECK(scientific << setw(20) << right << d, " 1.234568e+000"); // width 20 is 7 spaces + 13 chars.
+ CHECK(scientific << setw(20) << left << d, "1.234568e+000 "); // width 20 is 7 spaces + 13 chars.
+ CHECK(scientific << setw(20) << internal << d, " 1.234568e+000"); // width 20 is 7 spaces + 13 chars.
+ CHECK(scientific << setw(20) << showpos << internal << d, "+ 1.234568e+000"); // width 20 is 7 spaces + 13 chars.
+ CHECK(scientific << setw(20) << showpos << internal << setfill('0') << d, "+0000001.234568e+000"); // width 20 is 6 zero fills, 0 spaces + 14 chars.
+ CHECK(scientific << setw(20) << showpos << internal << setfill('*') << d, "+******1.234568e+000"); // width 20 is 6 * fills, 0 spaces + 14 chars.
+ CHECK(scientific << setw(20) << showpos << d, " +1.234568e+000"); // width 20 is 6 spaces + 14 chars.
+ CHECK(scientific << setw(20) << showpos << left << d, "+1.234568e+000 "); // width 20 is 14 chars + 6 spaces.
+ CHECK(scientific << setw(20) << noshowpos << setfill('~') << d, "~~~~~~~1.234568e+000"); // Combine scientific with fill
+ CHECK(scientific << setw(20) << noshowpos << right << setfill('~') << d, "~~~~~~~1.234568e+000"); // Combine scientific with fill
+ CHECK(scientific << setw(20) << noshowpos << internal << setfill('~') << d, "~~~~~~~1.234568e+000"); // Combine scientific with fill
+ CHECK(scientific << setw(20) << noshowpos << left << setfill('~') << d, "1.234568e+000~~~~~~~"); // Combine scientific with fill
+
+ // Padding with fill char.
+ CHECK(setw(0) << setfill('~') << i, "15"); // width(0) so no fill.
+ CHECK(setw(1) << setfill('~') << i, "15"); // width(1) so no room for fill.
+ CHECK(setw(2) << setfill('~') << i, "15"); // width(1) so no room for fill.
+ CHECK(setw(3) << setfill('~') << i, "~15"); // width(1) so 1 fill.
+ CHECK(setw(5) << setfill('~') << i, "~~~15"); // width 5 is 3 fill + 2 digits.
+ CHECK(setw(5) << setfill('~') << right << i, "~~~15"); // width 5 is 3 fill + 2 digits.
+ CHECK(setw(5) << setfill('~') << internal << i, "~~~15"); // width 5 is 3 fill + 2 digits.
+ CHECK(setw(5) << setfill('~') << left << i, "15~~~"); // width 5 is 2 digits + 3 fill.
+ CHECK(setw(5) << setfill('~') << noadjust << i, "~~~15"); // width 5 is 3 fill + 2 digits.
+ CHECK(setw(5) << setfill('~') << left << i, "15~~~"); // width 5 is 2 digits + 3 fill.
+ CHECK(setfill(' ') << i, "15"); // width goes back to 0 each time.
+
+ // Extra multiple manipulators: spaces, tabs and chars.
+ CHECK(spaces(5), " ");
+ CHECK(tabs(5), "\t""\t""\t""\t""\t");
+ CHECK(stars(5), "*****");
+ CHECK(chars(5, '~'), "~~~~~");
+ CHECK(chars(5, ' '), " ");
+} // BOOST_AUTO_TEST_CASE(unc_test_stdio)
+#endif // CPP_TESTS
+
+BOOST_AUTO_TEST_CASE(unc_test_std_rounding)
+{ // Show 'C++ Standard' rounding of 9.95 and precision(6) is NOT "10."
+ {
+ // Repeated with unc types later.
+ double nine95 = 9.95;
+ double nine94 = 9.94;
+ double nine96 = 9.96;
+ CHECK(nine95, "9.95"); // Should NOT round up to 10 - default precision is 6.
+ CHECK(nine94, "9.94"); // Should NOT down up to 9.9
+ CHECK(nine96, "9.96"); // Should NOT round up to 10.
+
+ CHECK(setprecision(2) << nine95, "9.9"); // Should round up to 10.
+ CHECK(setprecision(2) << nine94, "9.9"); // Should down up to 9.9 .
+ CHECK(setprecision(2) << nine96, "10"); // Should round up to 10 .
+ CHECK(showpoint << setprecision(2) << nine96, "10."); // Should round up to 10.
+ CHECK(fixed << noshowpoint << setprecision(2) << nine95, "9.95");
+ CHECK(fixed << showpoint << setprecision(2) << nine95, "9.95");
+ }
+ { // Similar checks for unc type.
+ uncun nine94(9.94, 0.1f); //
+ uncun nine95B(_nextafter(9.95, numeric_limits<double>::min()), 0.1f); // Just below 9.95.
+ uncun nine95(9.95, 0.1f); // Nearest representable to 9.95.
+ uncun nine95A(_nextafter(9.95, numeric_limits<double>::max()), 0.1f); // Just after 9.95.
+ uncun nine96(9.96, 0.1f); //
+ CHECK(nine94, "9.94"); // Should round down up to 9.94.
+ CHECK(nine95B, "9.95"); // Should NOT round up to 10.
+ CHECK(nine95, "9.95"); // Should NOT round up to 10.
+ CHECK(nine95A, "9.95"); // Should NOT round up to 10.
+ CHECK(nine96, "9.96"); // Should NOT round up to 10.
+ }
+}// BOOST_AUTO_TEST_CASE(unc_test_std_rounding)
+
+
+ BOOST_AUTO_TEST_CASE(unc_test_zeros)
+ { // Uncertain reals - constructor and get/set functions.
+ { // (Start a new scope for all uncs to allow reuse of names like one23...)
+ uncun zd(0); // Integer Zero, using constructor from int zero.
+ unsigned short f = zd.uncFlags();
+ BOOST_CHECK(zd.types() & VALUE_ZERO); // Should be flagged as zero.
+ BOOST_CHECK(zd.types() & VALUE_EXACT); // Should be flagged as exact because sd == 0.
+ BOOST_CHECK(zd.types() & VALUE_INTEGER); // and integer.
+ CHECK(zd, "0"); // Expect just 0 because is exact integer zero.
+
+ uncun u0(0.); // Construct from double zero (default unc, df, & flags)
+ BOOST_CHECK_EQUAL(u0.value(), 0.);
+ BOOST_CHECK_EQUAL(u0.std_dev(), 0.f);
+ BOOST_CHECK_EQUAL(u0.deg_free(), 1);
+ BOOST_CHECK(u0.types() & VALUE_ZERO); // Should still be flagged as zero.
+ CHECK(u0, "0"); // Expect 0 because is exact and isInteger zero because zero uncertainty.
+
+ }
+ {
+ uncun u0(0, 0); // Exact Zero, using constructor from int zero.
+ //BOOST_CHECK(u0.types() & VALUE_ZERO);
+ //BOOST_CHECK((u0.types() & VALUE_INTEGER)); //
+
+ u0.std_dev(0.01f); // Zero, but add known uncertainty.
+ BOOST_CHECK_EQUAL(u0.std_dev(), 0.01f);
+ BOOST_CHECK(u0.types() & VALUE_ZERO);
+ BOOST_CHECK(!(u0.types() & VALUE_INTEGER)); // No longer exact,
+ BOOST_CHECK((u0.types() & UNC_KNOWN)); // but unc is known.
+ CHECK_USED(plusminus << u0, "0.000 +/-0.010"); // So now show added uncertainty.
+
+ u0.std_dev(0.1f); // Increase std deviation.
+ BOOST_CHECK(u0.types() & VALUE_ZERO); // Should still be flagged as zero.
+ BOOST_CHECK(!(u0.types() & VALUE_INTEGER)); // Made uncertain, so no longer exact.
+ CHECK_USED(u0, "0.00"); // So now add decimal point.
+ CHECK_USED(plusminus << u0, "0.00 +/-0.10"); // So now show increased uncertainty.
+
+ u0.std_dev(1.f); // Increase std deviation more.
+ BOOST_CHECK(u0.types() & VALUE_ZERO); // Should still be flagged as zero.
+ BOOST_CHECK(!(u0.types() & VALUE_INTEGER)); // Made uncertain so no longer exact.
+ CHECK_USED(u0, "0.0"); // Add decimal point.
+ CHECK_USED(plusminus << u0, "0.0 +/-1.0"); // Add uncertainty.
+
+ uncun z(0); // Exact Zero, using constructor from integer.
+ BOOST_CHECK_EQUAL(z.value(), 0.); // value
+ BOOST_CHECK_EQUAL(z.std_dev(), 0.f);// std_dev
+ BOOST_CHECK_EQUAL(z.deg_free(), 1); // deg_free
+ BOOST_CHECK(z.types() & VALUE_ZERO); // Is zero.
+ BOOST_CHECK(z.types() & VALUE_INTEGER); // Is integer.
+ CHECK_USED(z, "0"); // Exact zero.
+ CHECK_USED(setw(0) << z, "0"); // Exact zero, default width.
+ CHECK_USED(setw(1) << z, "0"); // Tight fit.
+ CHECK_USED(setw(2) << z, " 0"); // no adjust == right justify
+ CHECK_USED(left << setw(2) << z, "0 "); // Just 1 pad.
+ CHECK_USED(left << setw(3) << z, "0 "); // 2 pads.
+ CHECK_USED(left << setw(4) << z, "0 "); // 1 digit plus 3 pad.
+ CHECK_USED(left << setw(4) << z, "0 "); // 1 digit plus 3 pad, left == default.
+ CHECK_USED(right << setw(4) << z, " 0"); // right so 3 pad plus 1 digit.
+ }
+ } // BOOST_AUTO_TEST_CASE(unc_test_zeros)
+
+ BOOST_AUTO_TEST_CASE(unc_test_unity)
+ {
+ uncun unity(1); // Exact unity constructed from integer.
+ BOOST_CHECK(unity.types() & VALUE_INTEGER); // Check IS recognised as integer.
+ CHECK_USED(unity, "1"); // No decimal point for integer.
+// CHECK_USED(showpoint << unity, "1."); // DO show decimal point for integer value but only if showpoint.
+// But this would imply all the setprecision (6) trailing zeros! showpoint is MAD!
+ BOOST_CHECK(unity.types() & VALUE_EXACT); // And is exact (sd == 0).
+ CHECK_USED(plusminus << unity, "1"); // Do NOT show +/-0 for integer value.
+
+ unity.types(VALUE_INTEGER); // Clear integer flag.
+ BOOST_CHECK((unity.types() & VALUE_INTEGER) == false); // Check integer flag has been cleared.
+ BOOST_CHECK(unity.types() & VALUE_EXACT); // Check is still exact (sd == 0).
+
+ CHECK_USED(unity, "1."); // Should have decimal point because sd == 0,
+ // so exact (but no longer integer).
+ CHECK_USED(showpoint << unity, "1."); // Regardless of showpoint or not.
+
+ CHECK_USED(plusminus << unity, "1. +/-0"); // Do show +/-0 for exact value (no longer integer).
+ // Show "+/-0" if requested for real exact, for example: "2.54 +/-0".
+ // But NOT for integer, so, for example, just "1" and never "1 +/-0".
+
+ uncun ud(1., 0.f); // Exact Unity from double.
+ BOOST_CHECK(!(ud.types() & VALUE_ZERO)); // Should NOT be flagged as zero.
+ BOOST_CHECK(ud.types() & VALUE_EXACT); // Should be flagged as zero.
+ BOOST_CHECK(!(ud.types() & VALUE_INTEGER)); // but NOT integer.
+
+ uncun negud(-1., 0.f); // Exact Minus negative Unity from double.
+ BOOST_CHECK(!(negud.types() & VALUE_ZERO)); // Should NOT be flagged as zero.
+ BOOST_CHECK(negud.types() & VALUE_EXACT); // Should be flagged as zero.
+ uncun u0(0.);
+ u0.std_dev(0.001f);
+ CHECK_USED(u0, "0.0000");
+ u0.std_dev(0.0001f);
+ CHECK_USED(u0, "0.00000"); //
+ u0.std_dev(0.00001f);
+ CHECK_USED(u0, "0.000000"); //
+ u0.std_dev(0.000001f);
+ CHECK_USED(u0, "0.0000000"); //
+ u0.std_dev(0.000000000000001f);
+ CHECK_USED(u0,"0.00000000000000"); // All 15 guaranteed decimal digits.
+ u0.std_dev(0.0000000000000001f);
+ CHECK_USED(u0, "0.00000000000000"); // All 17 significant decimal digits.
+ uncun exact(1., 1.f, 2, VALUE_EXACT); // Exact Unity from double with sd and df.
+ // This should signal a conflict in the constructor!
+ BOOST_CHECK(exact.types() & VALUE_EXACT); // Should still be flagged as exact.
+ BOOST_CHECK_EQUAL(exact.value(), 1.); // value
+ BOOST_CHECK_EQUAL(exact.std_dev(), 0.f);// StdDeviation should be over-ridden by VALUE_EXACT.
+ // "Value 1 flagged as exact, but uncertainty 1 is not zero!"
+ BOOST_CHECK_EQUAL(exact.deg_free(), 0); // deg_free should be overwritten by VALUE_EXACT.
+ // "Value 1 flagged as exact, but degfree 2 is not zero!"
+
+ uncun iminus1(-1); // Exact minus 1 from integer -1 value.
+ BOOST_CHECK(iminus1.types() & VALUE_INTEGER); // Check IS recognised as integer.
+ BOOST_CHECK(iminus1.types() & VALUE_EXACT); // Check IS recognised as integer.
+ BOOST_CHECK(iminus1.types() & UNC_NOPLUS); // Check IS recognised as no > 0.
+ uncun iminus10(-10); // Exact minus 10 from integer -1 value.
+ BOOST_CHECK(iminus10.types() & VALUE_INTEGER); // Check IS recognised as integer.
+ BOOST_CHECK(iminus10.types() & UNC_NOPLUS); // Check IS recognised as not > 0.
+ BOOST_CHECK(iminus10.types() & UNC_NOMINUS); // Check IS recognised as not < 0.
+ CHECK_USED(iminus10, "-10"); // Must be negative integer.
+
+ uncun uminus1(-1.); // NOT Exact minus 1 from double -1. value.
+ BOOST_CHECK(!(uminus1.types() & VALUE_INTEGER)); // Check IS recognised as integer.
+ CHECK_USED(uminus1, "-1."); // Must be negative double, not integer.
+ // These fail separating 1 and .
+ //CHECK_USED(left << setw(10) << uminus1, "-1. "); //
+ //CHECK_USED(right << setw(10) << uminus1, " -1."); //
+
+ } // BOOST_AUTO_TEST_CASE(unc_test_unity)
+
+ BOOST_AUTO_TEST_CASE(unc_test_1234)
+ {
+ int t = 12;
+ uncun twelveI(t); // Exact 12 from integer variable.
+ BOOST_CHECK(twelveI.types() & VALUE_INTEGER); // Check IS integer from variable.
+ CHECK_USED(twelveI, "12"); // no . because integer.
+// CHECK_USED(noplusminus << showpoint << twelveI, "12."); // Show decimal point for integer value only if showpoint.
+ CHECK_USED(plusminus << twelveI, "12"); // Do NOT show +/-0 for integer value.
+ twelveI.types(VALUE_INTEGER); // Clear integer flag.
+ BOOST_CHECK(!(twelveI.types() & VALUE_INTEGER)); // Check integer flag has cleared.
+ CHECK_USED(twelveI, "12."); // Should have decimal point because sd = 0 so should be exact like 2.54.
+
+ uncun twelve3(12.3, 0.026f); // Explicit sd.
+ CHECK_USED(noplusminus << twelve3, "12.30"); // OK
+ CHECK_USED(plusminus << twelve3, "12.30 +/-0.026");
+ //CHECK_OUT_IN(plusminus << twelve3, "12.30 +/-0.05", 12.3, 0.025f, 0, (UNC_KNOWN | UNC_QUAN_DECIMAL | UNC_EXPLICIT) ));
+
+ uncun imax(numeric_limits<int>::max()); // Exact int max 2147483647.
+ BOOST_CHECK(imax.types() & VALUE_INTEGER); // Check IS integer from argument.
+ CHECK_USED(imax, "2147483647"); // no . because integer.
+
+ uncun imin(numeric_limits<int>::min()); // Exact int min -2147483648.
+ BOOST_CHECK(imin.types() & VALUE_INTEGER); // Check IS integer from argument.
+ CHECK_USED(imin, "-2147483648"); // no . because integer.
+ uncun twelvede(1234.); // double from double variable, default stddev, so implicitly exact.
+ BOOST_CHECK(!(twelvede.types() & VALUE_INTEGER)); // Check is NOT integer from variable.
+ BOOST_CHECK((twelvede.types() & VALUE_EXACT)); // Check IS flagged as exact.
+ CHECK_USED(twelvede, "1234."); // . because from double, even though exact. // 1.234 no trailing zeros.
+ } // BOOST_AUTO_TEST_CASE(unc_test_1234)
+
+ BOOST_AUTO_TEST_CASE(unc_test_exact)
+ { // Exact values
+ // 1. inch Autoscaled SI 25. +/- 13. millimeter or 25. mm
+ // 1.0 inch Autoscaled SI 25.4 +/- 1.3 millimeter or 25.4 mm
+ // 1.00 Autoscaled SI 25.4 +/- 0.13 millimeter or 25.4 mm
+ // 1.000 Autoscaled SI 25.400 +/- 0.013 millimeter or 25.400 mm
+
+ uncun inch_in_cm(2.54); // Exact, with decimal fraction part, implicitly created from double.
+ BOOST_CHECK((inch_in_cm.types() & VALUE_EXACT)); // Check is known to be exact.
+
+ CHECK_USED(inch_in_cm, "2.54"); // No trailing zeros, because exact.
+ // Trailing zeros would imply an uncertainty.
+
+ inch_in_cm.setUncTypes(inch_in_cm.types() & ~VALUE_EXACT); // Flag as NOT exact.
+ BOOST_CHECK(!(inch_in_cm.types() & VALUE_EXACT)); // Check exact flag has cleared.
+ CHECK_USED(inch_in_cm, "2.54000000000000"); // Max trailing zeros, because sd still == 0.F.
+
+ inch_in_cm.std_dev(0.0012f); // Add some uncertainty.
+ BOOST_CHECK(!(inch_in_cm.types() & VALUE_EXACT)); // Check still NOT exact.
+ CHECK_USED(inch_in_cm, "2.540"); // One trailing zeros because std dev specified 0.012f.
+ inch_in_cm.types(VALUE_EXACT); // Make Exact - Explicitly. - Doesn't work
+ inch_in_cm.std_dev(0.f); // No uncertainty.
+ BOOST_CHECK((inch_in_cm.types() & VALUE_EXACT)); // Check is now known to be exact.
+ CHECK_USED(inch_in_cm, "2.54"); // Explicitly exact, so no trailing zeros.
+} // BOOST_AUTO_TEST_CASE(unc_test_exact)
+
+
+ BOOST_AUTO_TEST_CASE(unc_test_12345)
+ {
+ uncun one234(1234.321, 1000.f); // double from double variable, but NOT exact.
+ BOOST_CHECK(!(one234.types() & VALUE_INTEGER)); // Check NOT integer from variable.
+ BOOST_CHECK(!(one234.types() & VALUE_EXACT)); // Check is NOT flagged as exact.
+ CHECK_USED(one234, "1200."); // Rounded to zero before decimal point shows uncertainty.)
+ one234.std_dev(100.f);
+ CHECK_USED(one234, "1230."); // No trailing zeros show implicit uncertainty.
+ one234.std_dev(10.f);
+ CHECK_USED(one234, "1234."); // because from double and not exact, fractional decimals show uncertainty.
+ one234.std_dev(1.f);
+ CHECK_USED(one234, "1234.3"); // because from double and not exact, fractional decimals show uncertainty.
+ one234.std_dev(0.1f);
+ CHECK_USED(one234, "1234.32"); // because from double and not exact, fractional decimals show uncertainty.
+ one234.std_dev(0.01f);
+ CHECK_USED(one234, "1234.321"); // because from double and not exact, trailing zero shows uncertainty.
+
+ uncun twelve34(12.34, 0.10f); // double from double variable, but NOT exact.
+ BOOST_CHECK(!(twelve34.types() & VALUE_INTEGER)); // Check NOT integer from variable.
+ BOOST_CHECK(!(twelve34.types() & VALUE_EXACT)); // Check is flagged NOT exact.
+ CHECK_USED(twelve34, "12.34"); // because from double and not exact, trailing zeros show uncertainty.
+ twelve34.std_dev(0.01f);
+ CHECK_USED(twelve34, "12.340"); // trailing zeros show uncertainty.
+ twelve34.std_dev(0.001f);
+ CHECK_USED(twelve34, "12.3400"); // trailing zeros show uncertainty.
+ twelve34.std_dev(0.0001f);
+ CHECK_USED(twelve34, "12.34000"); // trailing zeros show uncertainty.
+ twelve34.std_dev(0.00001f);
+ CHECK_USED(twelve34, "12.340000"); // trailing zeros show uncertainty.
+ // Now increase std above the step 1.9999
+
+ twelve34.std_dev(1.f);
+ CHECK_USED(twelve34, "12.3"); //
+ CHECK_USED(addnoisyDigit << twelve34, "12.34"); // 1 more sig digit because requested.
+
+ twelve34.std_dev(2.f);
+ CHECK_USED(twelve34, "12."); // 1 less sig digit because over the 1.9999 stdDev step.
+ CHECK_USED(addnoisyDigit << twelve34, "12.3"); // 1 more sig digit because requested.
+
+ uncun twelve(12., 0.25f); // Implicit from input of 12. is +|- 0.5
+ // so for 0.95 probability, to get std deviation halve 0.5 to 0.25.
+ CHECK_USED(twelve, "12.0"); // Implicit noplusminus.
+ CHECK_USED(twelve << noplusminus, "12.0"); // Explicit NO plusminus.
+ CHECK_USED(plusminus << twelve, "12.0 +/-0.25"); // Explicit plusminus.
+
+ uncun twoPoint54(2.54, 0.f); // Real and exact.
+ BOOST_CHECK( (twoPoint54.types() & VALUE_EXACT)); // Check IS flagged as exact.
+ BOOST_CHECK(!(twoPoint54.types() & VALUE_INTEGER)); // Check NOT flagged as integer.
+ CHECK_USED(noplusminus << twoPoint54, "2.54"); // Check no added +/- .
+ CHECK_USED(plusminus << twoPoint54, "2.54 +/-0"); // Check do get added +/-
+
+ uncun onepoint2(1.2);
+ CHECK_USED(onepoint2, "1.2"); // Exact.
+ onepoint2.std_dev(1.f);
+ CHECK_USED(onepoint2, "1.2");
+ onepoint2.std_dev(0.1f);
+ CHECK_USED(onepoint2, "1.20");
+ onepoint2.std_dev(0.01f);
+ CHECK_USED(onepoint2, "1.200");
+ onepoint2.std_dev(0.001f);
+ CHECK_USED(onepoint2, "1.2000");
+ onepoint2.std_dev(0.005f);
+ CHECK_USED(onepoint2, "1.200");
+} // BOOST_AUTO_TEST_CASE(unc_test_12345)
+
+BOOST_AUTO_TEST_CASE(unc_test_input)
+{
+ // zero integer rational uncKnown noPlus noMinus at end of read.
+ uncun r1;
+ //outUncTypes(r1.types(), cout);
+ istringstream isr1("0"); // Read from integer.
+ isr1 >> r1;
+ BOOST_CHECK_EQUAL(r1.value(), 0.);
+ BOOST_CHECK_CLOSE_FRACTION(r1.value(), 0., std::numeric_limits<double>::epsilon());
+ BOOST_CHECK_EQUAL(r1.std_dev(), 0.f);
+ BOOST_CHECK_EQUAL(r1.deg_free(), 0);
+ BOOST_CHECK_EQUAL(r1.types(),
+ (VALUE_ZERO | VALUE_INTEGER | VALUE_RATIONAL | UNC_KNOWN | VALUE_EXACT | UNC_NOPLUS | UNC_NOMINUS));
+
+ // Read from real zero 0. with implicit +/- 0.5 == std deviation 0.5.
+ CHECK_IN("0.", 0., 0.5f, 0, (VALUE_ZERO | UNC_KNOWN | UNC_QUAN_DECIMAL) );
+ // Read from real unit 1. with implicit +/- 0.5 == std deviation 0.5.
+ CHECK_IN("1.", 1., 0.5f, 0, (UNC_KNOWN | UNC_QUAN_DECIMAL));
+ // Read from real . with implicit +/- 0.5 == std deviation 0.5.
+ CHECK_IN("12.", 12., 0.5f, 0, (UNC_KNOWN | UNC_QUAN_DECIMAL));
+ // Read from real with implicit +/- 0.5 == std deviation 0.5.
+ CHECK_IN("123.", 123., 0.5f, 0, (UNC_KNOWN | UNC_QUAN_DECIMAL));
+ // Read from real with implicit +/- 0.05 == std deviation 0.05.
+ CHECK_IN("0.1", 0.1, 0.05f, 0, (UNC_KNOWN | UNC_QUAN_DECIMAL));
+ // Read from real with implicit +/- 0.05 == std deviation 0.05.
+ CHECK_IN("0.12", 0.12, 0.005f, 0, (UNC_KNOWN | UNC_QUAN_DECIMAL));
+ // Read from real with implicit +/- 0.05 == std deviation 0.05.
+ CHECK_IN("0.01", 0.01, 0.005f, 0, (UNC_KNOWN | UNC_QUAN_DECIMAL));
+ // Read from real with implicit +/- 0.05 == std deviation 0.005.
+ CHECK_IN("0.001", 0.001, 0.0005f, 0, (UNC_KNOWN | UNC_QUAN_DECIMAL));
+ // Read from real with implicit +/- 0.05 == std deviation 0.005.
+
+ // Read from real with explicit +/-.
+ CHECK_IN("12. +/-0.1", 12., 0.1f, 0, (UNC_KNOWN | UNC_QUAN_DECIMAL | UNC_EXPLICIT));
+ // Read from real with -/+ instead of +/-.
+ CHECK_IN("12. +/-0.1", 12., 0.1f, 0, (UNC_KNOWN | UNC_QUAN_DECIMAL | UNC_EXPLICIT));
+ // Read real zero, but +/1.
+ CHECK_IN("0. +/-0.1", 0., 0.1f, 0, (VALUE_ZERO | UNC_KNOWN | UNC_QUAN_DECIMAL | UNC_EXPLICIT));
+ // Read real zero, but -/+.
+ CHECK_IN("0. -/+0.1", 0., 0.1f, 0, (VALUE_ZERO | UNC_KNOWN | UNC_QUAN_DECIMAL | UNC_EXPLICIT));
+
+ // Read from real zero, plus only.
+ CHECK_IN("0. +0.01", 0., 0.01f, 0, (VALUE_ZERO | UNC_KNOWN | UNC_QUAN_DECIMAL | UNC_EXPLICIT | UNC_NOMINUS));
+ // Read from real, minus only.
+ CHECK_IN("0. -0.2", 0., 0.2f, 0, (VALUE_ZERO | UNC_KNOWN | UNC_QUAN_DECIMAL | UNC_EXPLICIT | UNC_NOPLUS));
+
+ CHECK_IN("12. +|-0.1 (19)", 12., 0.1f, 19, (UNC_KNOWN | UNC_QUAN_DECIMAL | UNC_EXPLICIT | DEG_FREE_KNOWN | DEG_FREE_EXACT));
+ CHECK_IN("12. +\\-0.1 (19)", 12., 0.1f, 19, (UNC_KNOWN | UNC_QUAN_DECIMAL | UNC_EXPLICIT | DEG_FREE_KNOWN | DEG_FREE_EXACT));
+ CHECK_IN("12. +/+0.1 (19)", 12., 0.1f, 19, (UNC_KNOWN | UNC_QUAN_DECIMAL | UNC_EXPLICIT | DEG_FREE_KNOWN | DEG_FREE_EXACT | UNC_NOMINUS ));
+ CHECK_IN("12. -/-0.1 (19)", 12., 0.1f, 19, (UNC_KNOWN | UNC_QUAN_DECIMAL | UNC_EXPLICIT | DEG_FREE_KNOWN | DEG_FREE_EXACT | UNC_NOPLUS));
+ // Extra layout chars.
+ CHECK_IN("12. +/-0.1", 12., 0.1f, 0, (UNC_KNOWN | UNC_QUAN_DECIMAL | UNC_EXPLICIT));
+ CHECK_IN("12.+/- 0.1", 12., 0.1f, 0, (UNC_KNOWN | UNC_QUAN_DECIMAL | UNC_EXPLICIT));
+
+ CHECK_IN("12. +/- 0.1", 12., 0.1f, 0, (UNC_KNOWN | UNC_QUAN_DECIMAL | UNC_EXPLICIT));
+
+ // Integer (and hence rational too)
+ CHECK_IN("12 +/-0.1", 12., 0.1f, 0, (VALUE_INTEGER | VALUE_RATIONAL | UNC_KNOWN | UNC_QUAN_DECIMAL | UNC_EXPLICIT ));
+ // Rational - not implemented yet.
+ //CHECK_IN("2/3", 2/3, 0.1f, 0, (VALUE_RATIONAL | UNC_KNOWN | UNC_QUAN_DECIMAL | UNC_EXPLICIT ));
+ //CHECK_IN("2/3 +/-0.1", 2/3, 0.1f, 0, (VALUE_RATIONAL | UNC_KNOWN | UNC_QUAN_DECIMAL | UNC_EXPLICIT ));
+
+ {
+ uncun r1;
+ istringstream isr1("2/3"); // Read from string.
+ isr1 >> r1;
+ cout << r1.value() << ' ' << r1.std_dev() << ' ' << r1.degFree() << r1.types() << ", " ;
+ outUncTypes(r1.types(), cout);
+ cout << endl;
+ }
+
+ {
+ uncun r1;
+ istringstream isr1("2/3+/-0.02f"); // Read from string.
+ isr1 >> r1;
+ cout << r1.value() << ' ' << r1.std_dev() << ' ' << r1.degFree() << r1.types() << ", " ;
+ outUncTypes(r1.types(), cout);
+ cout << endl;
+ }
+
+
+ // Exponent value and uncertainty.
+ CHECK_IN("12.e1 +/-0.1", 12., 0.1f, 0, (UNC_KNOWN | UNC_QUAN_DECIMAL | UNC_EXPLICIT));
+ CHECK_IN("12. +/-0.1e-1", 12., 0.01f, 0, (UNC_KNOWN | UNC_QUAN_DECIMAL | UNC_EXPLICIT));
+ CHECK_IN("12.e1 +/-0.1e-1", 12., 0.01f, 0, (UNC_KNOWN | UNC_QUAN_DECIMAL | UNC_EXPLICIT));
+
+ /*
+
+ */
+ // #define CHECK_OUT_IN(manips, result, value, sd, df, types)
+} // BOOST_AUTO_TEST_CASE(unc_test_input)
+
+BOOST_AUTO_TEST_CASE(unc_test_unity2)
+{
+ uncun one(1.); // Exact one from double.
+ // Check get and set functions.
+ BOOST_CHECK_EQUAL(one.value(), 1.); // value
+ BOOST_CHECK_EQUAL(one.std_dev(), 0.f); // std_dev
+ BOOST_CHECK_EQUAL(one.deg_free(), 1); // deg_free
+ BOOST_CHECK(!(one.types() & VALUE_ZERO)); // Check not zero.
+ BOOST_CHECK(!(one.types() & VALUE_INTEGER)); // Check NOT recognised as integer.
+ // Because constructed from double should not be integer.
+ CHECK_USED(one, "1."); // Sd = 0 so is exact, but not integer.
+ CHECK_USED(showpos << one, "+1."); // Show + sign.
+ CHECK_USED(plusminus << one, "1. +/-0"); // Do show +/-0 (and .) for NOT integer value.
+
+ one.setUncTypes(VALUE_INTEGER); // Set the integer flag.
+ BOOST_CHECK(one.types() & VALUE_INTEGER); // Check IS recognised as integer.
+ CHECK_USED(one, "1"); // Implicit so no . wanted.
+ CHECK_USED(noshowpoint << one, "1"); // Explicit no . wanted.
+ //CHECK_USED(showpoint << one, "1."); // Explicitly want "1." showpoint is ignored for integers.
+ CHECK_USED(plusminus << one, "1"); // Don't show +/-0 for _integer_ value, despite plusminus.
+ uncun realOne(1.); // is implicitly Exact.
+// Construct from doubles: 1., unc 0.0, df 0 uncTypes (0x6420) uncKnown explicit df_exact df_known
+// Constructed from doubles: m_value 1., m_unc 0.0, m_df 0, uncTypes (0x64e0) uncKnown noPlus noMinus explicit df_exact df_known
+ BOOST_CHECK(!(realOne.types() & VALUE_INTEGER)); // Check NOT recognised as integer.
+ CHECK_USED(plusminus << realOne, "1. +/-0"); // explicit plusminus, but NOT integer, so show +/-
+ realOne.std_dev(0.1f); // Change to inexact
+ BOOST_CHECK_EQUAL(realOne.std_dev(), 0.1f); // sd = 0.1.
+ BOOST_CHECK(!(realOne.types() & VALUE_EXACT)); // Check NOT now recognised as exact because sd no longer zero.
+ CHECK_USED(plusminus << realOne, "1.00 +/-0.10");
+ // Output sd 0.20, stdDevsigDigits 2
+ realOne.std_dev(0.2f);
+ CHECK_USED(plusminus << realOne, "1.0 +/-0.20");
+ realOne.std_dev(0.3f);
+ CHECK_USED(plusminus << realOne, "1.0 +/-0.30");
+ realOne.std_dev(0.01f);
+ CHECK_USED(plusminus << realOne, "1.000 +/-0.010");
+ realOne.std_dev(0.0101f);
+ CHECK_USED(plusminus << realOne, "1.000 +/-0.010");
+
+ realOne.std_dev(0.05f);
+ CHECK_USED(plusminus << realOne, "1.00 +/-0.050");
+ realOne.std_dev(0.001f);
+ CHECK_USED(plusminus << realOne, "1.0000 +/-0.0010");
+ realOne.std_dev(0.075f);
+ CHECK_USED(plusminus << realOne, "1.00 +/-0.075"); // Note rounding because df = 1
+ BOOST_CHECK_EQUAL(realOne.deg_free(), 1); // deg_free
+ realOne.deg_free(11); // Increase degfree.
+ BOOST_CHECK_EQUAL(realOne.deg_free(), 11); // Check has increased.
+ CHECK_USED(plusminus << realOne, "1.00 +/-0.075"); // Note NO rounding because df = 10
+ realOne.deg_free(101); // and more
+ BOOST_CHECK_EQUAL(realOne.deg_free(), 101); //
+ CHECK_USED(plusminus << realOne, "1.00 +/-0.075"); // Note NO rounding because df = 100
+ realOne.deg_free(1001);
+ BOOST_CHECK_EQUAL(realOne.deg_free(), 1001); //
+ CHECK_USED(plusminus << realOne, "1.00 +/-0.075"); // Note NO rounding because df = 1000
+} // BOOST_AUTO_TEST_CASE(unc_test_unity2)
+
+BOOST_AUTO_TEST_CASE(unc_test_123)
+{
+ uncun onetwothree(1.23); // Exact from double,
+ BOOST_CHECK_EQUAL(onetwothree.value(), 1.23);
+ BOOST_CHECK_EQUAL(onetwothree.std_dev(), 0.f);
+ BOOST_CHECK_EQUAL(onetwothree.deg_free(), 1);
+ BOOST_CHECK(!(onetwothree.types() & VALUE_ZERO));
+ BOOST_CHECK(!(onetwothree.types() & VALUE_INTEGER));
+ CHECK_USED(onetwothree, "1.23");
+ CHECK_USED(showpos << onetwothree, "+1.23"); // Check showpos works.
+ //CHECK_USED(setw(10) << showpos << onetwothree, "+1.23 "); // TODO fails.
+
+ uncun minusone(-1.); // Exact minus one from double.
+ CHECK_USED(minusone, "-1.");
+ uncun minusonetwothree(-1.23); // Exact negative from double,
+ CHECK_USED(minusonetwothree, "-1.23");
+
+ uncun one2345(1.2345, 0.01f, 2); // Inexact from double, sd 0.01, df 2 values.
+ BOOST_CHECK_EQUAL(one2345.value(), 1.2345); // Check contructor.
+ BOOST_CHECK_EQUAL(one2345.std_dev(), 0.01f);
+ BOOST_CHECK_EQUAL(one2345.deg_free(), 2); // Now 2 means 2 values.
+ BOOST_CHECK(!(one2345.types() & VALUE_ZERO));
+ BOOST_CHECK(!(one2345.types() & VALUE_INTEGER));
+ CHECK_USED(one2345, "1.235"); // Round-up 4 sigDigits because sd 0.01
+ // Check that > 10 values means that more significant digits are used.
+ one2345.deg_free(10); // 0 is one value, so 10 means 11 values.
+ one2345.std_dev(0.01234f); // Check rounding of std deviation.
+ BOOST_CHECK_EQUAL(one2345.std_dev(), 0.01234f);
+ BOOST_CHECK_EQUAL(one2345.deg_free(), 10); // 0 is one value, so 10 means 11 values.
+ CHECK_USED(plusminus << one2345, "1.235 +/-0.012"); // Not +/-0.0123 despite sd < 0.02
+ one2345.deg_free(10); // 1 value.
+} // BOOST_AUTO_TEST_CASE(unc_test_123)
+
+BOOST_AUTO_TEST_CASE(unc_test_nines)
+{
+ uncun nine95B(_nextafter(9.95, numeric_limits<double>::min()), 2.f); // Inexact from double, sd 0.01, df 2 = 3 values.
+ uncun nine95A(_nextafter(9.95, numeric_limits<double>::max()), 2.f); // Inexact from double, sd 0.01, df 2 = 3 values.
+ uncun nine95(9.95, 2.f); // Inexact from double, sd 0.01, df 2 = 3 values.
+ uncun nine94(9.94, 2.f); // Inexact from double, sd 0.01, df 2 = 3 values.
+ uncun nine96(9.96, 2.f); // Inexact from double, sd 0.01, df 2 = 3 values.
+}
+
+BOOST_AUTO_TEST_CASE(unc_test_rounding)
+{
+ // Uncertain values.
+ uncun one2345(1.2345, 0.01f, 2); // Inexact from double, sd 0.01, df 2 = 3 values.
+ one2345.std_dev(0.0049f);
+ CHECK_USED(plusminus << one2345, "1.235 +/-0.0049"); // 3 significant value, but only 1 sd digits.
+ one2345.std_dev(0.005f);
+ CHECK_USED(plusminus << one2345, "1.235 +/-0.0050"); //
+ one2345.std_dev(0.009f);
+ CHECK_USED(plusminus << one2345, "1.235 +/-0.0090"); //
+ one2345.std_dev(0.01f);
+ CHECK_USED(plusminus << one2345, "1.235 +/-0.010"); //
+ one2345.std_dev(0.011f);
+ CHECK_USED(plusminus << one2345, "1.235 +/-0.011"); //
+ one2345.std_dev(0.02f);
+ CHECK_USED(plusminus << one2345, "1.23 +/-0.020"); // Round up to 1.24, 2 significant value digits.
+ one2345.std_dev(0.05f);
+ CHECK_USED(plusminus << one2345, "1.23 +/-0.050"); // 1 significant sd digit.
+ one2345.std_dev(0.06f);
+ CHECK_USED(plusminus << one2345, "1.23 +/-0.060"); //
+ one2345.std_dev(0.07f);
+ CHECK_USED(plusminus << one2345, "1.23 +/-0.070"); //
+ one2345.std_dev(0.08f);
+ CHECK_USED(plusminus << one2345, "1.23 +/-0.080"); //
+ one2345.std_dev(0.09f);
+ CHECK_USED(plusminus << one2345, "1.23 +/-0.090"); //
+ one2345.std_dev(0.095f);
+ CHECK_USED(plusminus << one2345, "1.23 +/-0.095"); //
+
+ one2345.std_dev(0.01f);
+ // without noscientific << causes std dev shows in exp format: 1.235 +/-1.00e-002
+ CHECK_USED(scientific << noplusminus << one2345, "1.235");
+ CHECK_USED(scientific << plusminus << one2345, "1.235 +/-0.010"); // OK note not +/-0.010 because < 0.02.
+ one2345.std_dev(0.019f);
+ CHECK_USED(scientific << plusminus << one2345, "1.23 +/-0.019"); // Note still 2 significant digits.
+ one2345.std_dev(0.02f);
+ CHECK_USED(scientific << plusminus << one2345, "1.23 +/-0.020"); // Note step change to 1 significant digits at 1.999.
+ one2345.std_dev(0.09f);
+ CHECK_USED(scientific << plusminus << one2345, "1.23 +/-0.090"); // Note sd 1 significant digit.
+ one2345.std_dev(0.1f);
+ CHECK_USED(scientific << plusminus << one2345, "1.23 +/-0.10"); // OK note not +/-0.01 because < 0.02.
+ one2345.std_dev(0.19f);
+ CHECK_USED(scientific << plusminus << one2345, "1.2 +/-0.19"); // Note still 2 significant digits.
+ one2345.std_dev(0.2f);
+ CHECK_USED(scientific << plusminus << one2345, "1.2 +/-0.20"); // Note step change to 1 significant digits at 1.999.
+ one2345.std_dev(0.9f);
+ CHECK_USED(scientific << plusminus << one2345, "1.2 +/-0.90"); // Note 1 significant digit.
+ CHECK_USED(scientific << plusminus << addnoisyDigit << one2345, "1.23 +/-0.90"); // Note 1 more significant digits for value & sd.
+} // BOOST_AUTO_TEST_CASE(unc_test_rounding)
+
+BOOST_AUTO_TEST_CASE(unc_test_big)
+{
+ uncun bigish(1e14, 2e12f); // Not bigger than maxdigits10 limit 1 and 15 zeros, small unc.
+ CHECK_USED(bigish, "100000000000000."); //
+ uncun bigish2(1.23456789e14, 2e12f); //
+ CHECK_USED(bigish2, "123000000000000."); // Show some non-zero digits.
+ uncun bigish3(1.23456789e14, 1e6f); //
+ CHECK_USED(bigish3, "123456789000000."); // Show many non-zero digits.
+
+ // Check on too big values.
+ uncun big(1e39, 2e36f); // Bigger than exponent limit.
+ //cout << big << endl;
+ CHECK_USED(big, "1e+039"); // Default exp format, precision 6 total decimal digits.
+
+ uncun bigSI(1e25, 2.f); // Bigger than SI exponent limit.
+ CHECK_USED(bigSI, "1e+025"); // // Default exp format, precision 6
+ // Some very big integers and exacts.
+ uncun million = uncun(1000000); // Exact integer million 1000000
+ CHECK_USED(million, "1000000"); // integer.
+ uncun billion = uncun(1000000000); // Exact integer billion 1000000000
+ CHECK_USED(billion, "1000000000"); // integer.
+
+ // Exact but not integer.
+ uncun i10e3 = uncun(1.e3, 0.0f); // Exact real thousand 1000,
+ CHECK_USED(i10e3, "1000."); // 1000. exact, but not integer.
+
+ uncun i10e6 = uncun(1.e6, 0.f); // Exact real million 1000000.
+ CHECK_USED(i10e6, "1000000."); // exact.
+
+ uncun i10e6u = uncun(1.e6, 0.000001f); // Nearly exact real million 1000000.
+ CHECK_USED(i10e6u, "1000000.0000000"); //
+ uncun i10e61 = uncun(1000000.123, 0.f); // Exact real million 1000000.123.
+ CHECK_USED(i10e61, "1000000.123"); // exact.
+ uncun i10e62 = uncun(1000000.123, 0.000001f); // Nearly Exact real million 1000000
+ CHECK_USED(i10e62, "1000000.1230000"); // exact.
+ uncun i10e9 = uncun(1.0e9, 0.0f); // Exact billion 1000000000.
+ CHECK_USED(i10e9, "1000000000.");
+
+ uncun i10e99 = uncun(987654321., 0.0f); // Exact 9 billion 987654321.
+ CHECK_USED(i10e99, "987654321.");
+
+} // BOOST_AUTO_TEST_CASE(unc_test_big)
+
+BOOST_AUTO_TEST_CASE(unc_test_manips)
+{
+ // Examples of scientific and unc values including setw.
+ uncun one2345(1.2345, 0.01f, 2); // Inexact from double, sd 0.01, df 2 = 3 values.
+ one2345.std_dev(0.01f);
+ CHECK_USED(scientific << noplusminus << setw(20) << left << one2345, "1.235 "); //
+ CHECK_USED(scientific << plusminus << setw(20) << left << one2345, "1.235 +/-0.010 "); //
+ CHECK_USED(scientific << plusminus << setw(20) << right << one2345, " 1.235 +/-0.010"); //
+ CHECK_USED(scientific << plusminus << setw(20) << noadjust << one2345, " 1.235 +/-0.010"); // == right adjust.
+ CHECK_USED(scientific << plusminus << setw(20) << showpos << one2345, " +1.235 +/-0.010"); // == right adjust.
+ CHECK_USED(scientific << plusminus << setw(20) << showpos
+ << internal << one2345, " +1.235 +/-0.010"); // Expect same as right.
+
+ CHECK_USED(scientific << plusminus << setw(20) << noadjust << setfill('~') << one2345, "~~~~~~1.235 +/-0.010"); // expect same as right adjust.
+ CHECK_USED(scientific << plusminus << setw(20) << setfill('~') << left << one2345, "1.235 +/-0.010~~~~~~"); //
+ CHECK_USED(scientific << plusminus << setw(20) << setfill('~') << internal << one2345, "~~~~~~1.235 +/-0.010");
+ CHECK_USED(scientific << plusminus << setw(20) << setfill('~') << right << one2345, "~~~~~~1.235 +/-0.010"); // Expect same as right.
+
+ // Some bigger values.
+ uncun ten2345(10.2345, 0.01f, 2); // Inexact from double, sd 0.01, df 2 = 3 values.
+ CHECK_USED(scientific << noplusminus << setw(20) << left << ten2345, "10.235 "); //
+
+} // BOOST_AUTO_TEST_CASE(unc_test_manips)
+
+BOOST_AUTO_TEST_CASE(unc_test_setsigfigs)
+{ // Tests of fixing sigfigs.
+ uncun u0(0, 0); // Exact Zero, using constructor from int zero.
+
+ fout << "setSigDigits(4) " << setSigDigits(4) << endl; // Check can set setsigdigits,
+ BOOST_CHECK_EQUAL(fout.iword(setSigDigitsIndex), 4); // and read back correctly.
+
+ fout << "setUncSigDigits(1) " << setUncSigDigits(1) << endl; // Check can set setuncsigdigits,
+ BOOST_CHECK_EQUAL(fout.iword(setUncSigDigitsIndex), 1); // and read back correctly.
+
+ CHECK(setSigDigits(4) << u0, "0"); // Not yet setsigdigits, so has no effect.
+ // setsigdigits should force to 4 digits set by setSigDigits(4).
+ CHECK(setSigDigits(4) << setsigdigits << u0, "0.0000"); // Fails!
+
+ uncun one(1., 0.001f); //
+ CHECK(setSigDigits(3) << setsigdigits << one, "1.00"); // getting 1.
+ CHECK_USED(setSigDigits(-1) << setsigdigits << u0, "0.00000000000000000"); // Invalid sigDigits (show max_digits10).
+ CHECK_USED(setSigDigits(0) << setsigdigits << u0, "0.00000000000000000"); // Zero sigDigits (show max_digits10).
+ CHECK_USED(setSigDigits(1) << setsigdigits << u0, "0.0"); // Override normal is still exact, so no decimal point.
+ CHECK_USED(setSigDigits(2) << setsigdigits << u0, "0.00"); // Is still exact, so no decimal point.
+ CHECK_USED(setSigDigits(3) << setsigdigits << u0, "0.000"); //
+ CHECK_USED(setSigDigits(4) << setsigdigits << u0, "0.0000"); //
+ CHECK_USED(setSigDigits(1) << setsigdigits << showpoint << u0, "0.0"); // Override normal is still exact, but showpoint demands a decimal point.
+ CHECK_USED(setSigDigits(1) << setsigdigits << showpos << u0, "+0.0"); // Show plus sign.
+ CHECK_USED(setSigDigits(1) << setsigdigits << left << setw(6) << u0, "0.0 "); // Trailing spaces.
+
+
+ uncun u(12.345678, 0.09876F);
+ CHECK_USED(plusminus << u, "12.35 +/-0.099");
+ CHECK_USED(setSigDigits(6) << setsigdigits << plusminus << u, "12.3457 +/-0.099");
+ CHECK_USED(setSigDigits(6) << setsigdigits << plusminus << showpos << u, "+12.3457 +/-0.099");
+ CHECK_USED(setUncSigDigits(6) << setuncsigdigits << plusminus << u, "12.35 +/-0.0988");
+ // Uncertainty controls value but not uncertainty digits of precision.
+
+}
+
+BOOST_AUTO_TEST_CASE(unc_test_setscale)
+{ // Tests of unc setscale and autoscale functions.
+ // These may not be necessary because Boost.Units provides autoscaling via autoprefix.
+ // uncun int10000(10000); // Should not be autoscaled nor set scaled.
+ // CHECK_USED(int10000, "10000"); // NOT 10.000 k because is neither autoscaled nor set scaled.
+ // CHECK_USED(autoscale << int10000, "10000"); // NOT 10.000 k because is integer.
+ // CHECK_USED(scale << int10000, "10000"); // NOT 10.000 k because is integer.
+ // uncun zero(0, 0.000001f);
+ // CHECK_USED(zero, "0");
+ // CHECK_USED(autoscale << zero, "0"); // zero Should not be autoscaled
+ // CHECK_USED(setScale(6) << scale << zero, "0"); // nor set scaled.
+
+ // uncun uScaled1(0.00123456); // Input scaled by unit prefix or symbol.
+ // uncun uScaled2(2345.678); //
+ // uncun uScaled3(1.23456); //
+ // CHECK_USED(autoscale << addsisymbol << uScaled3, "1.23456 "); // Is trailing space if no symbol right?
+ // CHECK_USED(autoscale << addsisymbol << uScaled1, "1.23456 m");
+ // CHECK_USED(autoscale << addsisymbol << uScaled2 , "2.345678 k");
+ // CHECK_USED(autoscale << addsiprefix << uScaled1, "1.23456 milli");
+ // CHECK_USED(autoscale << addsiprefix << uScaled2, "2.345678 kilo");
+ // CHECK_USED(autoscale << addsiprefix << addsisymbol << uScaled2, "2.345678 kilo");
+ // // Check get prefix if specify both.
+ // CHECK_USED(noautoscale << scale << setScale(3) << addsisymbol << uScaled2, "2.345678 k");
+ // CHECK_USED(scale << addsisymbol << uScaled2 , "2345.678 "); // Can't test re-use of previous set scale(3).
+
+ // CHECK_USED(scale << setScale(6) << addsisymbol << uScaled2 , "0.002345678 M");
+ // CHECK_USED(scale << setScale(4) << addsisymbol << uScaled2 , "0.2345678 ");
+ // CHECK_USED(scale << setScale(2) << addsisymbol << uScaled2 , "23.45678 h");
+ // CHECK_USED(scale << setScale(1) << addsisymbol << uScaled2 , "234.5678 da");
+ // CHECK_USED(scale << setScale(0) << addsisymbol << uScaled2 , "2345.678 ");
+ // CHECK_USED(scale << setScale(-1) << addsisymbol << uScaled2 , "23456.78 d");
+ // CHECK_USED(scale << setScale(-2) << addsisymbol << uScaled2 , "234567.8 c");
+ // CHECK_USED(scale << setScale(-3) << addsisymbol << uScaled2 , "2345678 m");
+ // CHECK_USED(scale << setScale(-4) << addsisymbol << uScaled2 , "23456780 ");
+ // CHECK_USED(scale << setScale(-6) << addsisymbol << uScaled2 , "2345678000 u"); // Silly scaling!
+ // CHECK_USED(scale << setScale(-9) << addsisymbol << uScaled2 , "2345678000000 n"); // Silly scaling!
+ // CHECK_USED(scale << setScale(-6) << addsisymbol << uScaled1 , "1234.56 u"); //
+ // CHECK_USED(scale << setScale(-3) << addsisymbol << uScaled1 , "1.23456 m"); //
+
+ // CHECK_USED(setSigDigits(2) << setsigdigits << uScaled2 << addsisymbol, "2345.678"); // exact so didn't use setsigdigits
+ // uScaled2.std_dev(0.1f);
+ // CHECK_USED(uScaled2 << addsisymbol, "2345.68");
+ // CHECK_USED(setSigDigits(2) << setsigdigits << uScaled2 << addsisymbol, "2400.");
+} // BOOST_AUTO_TEST_CASE(unc_test_setscale)
+
+BOOST_AUTO_TEST_CASE(unc_test_asym)
+{ // Some asymetric uncertainties.
+ uncun notMore(1.71, 0.2f, 0, UNC_NOPLUS); // Only minus.
+ BOOST_CHECK((notMore.types() & UNC_NOPLUS)); //
+ CHECK_USED(plusminus << notMore, "1.71 +0/-0.20");
+ uncun notLess(1.81, 0.2f, 0, UNC_NOMINUS); // Only plus.
+ BOOST_CHECK((notLess.types() & UNC_NOMINUS)); //
+ CHECK_USED(plusminus << notLess, "1.81 -0/+0.20");
+}
+
+BOOST_AUTO_TEST_CASE(unc_test_set_manips)
+{
+ fout << "\nTest one parameter manips to set unc width, scale, sigdigits & unc sigdigits.\n";
+ setUncDefaults(fout); // Resets stream's format flags to default.
+ fout << resetiosflags(ios_base::basefield | ios_base::adjustfield | ios_base::floatfield
+ | ios_base::showpos | ios_base::showpoint | ios_base::uppercase | ios_base::showbase )
+ << endl;
+ setiosDefaults(fout); // &
+ setUncDefaults(fout);
+
+ BOOST_CHECK_EQUAL(fout.flags(), ios_base::skipws | ios_base::dec);
+ BOOST_CHECK_EQUAL(fout.iword(oldUncSigDigitsIndex), -1);
+ BOOST_CHECK_EQUAL(fout.iword(sigDigitsIndex), 3); // default
+ BOOST_CHECK_EQUAL(fout.iword(scaleIndex), 0);
+ BOOST_CHECK_EQUAL(fout.iword(widthIndex), -1);
+ BOOST_CHECK_EQUAL(fout.iword(oldScaleIndex),-1);
+ BOOST_CHECK_EQUAL(fout.iword(setScaleIndex), 0);
+ BOOST_CHECK_EQUAL(fout.iword(scaleIndex), 0);
+
+ fout << "setSigDigits(4) " << setSigDigits(4) << endl;
+ BOOST_CHECK_EQUAL(fout.iword(setSigDigitsIndex), 4);
+
+ fout << setSigDigits(2) << endl;
+ BOOST_CHECK_EQUAL(fout.iword(setSigDigitsIndex), 2);
+ BOOST_CHECK_EQUAL(fout.iword(oldSigDigitsIndex), 4); // Check save.
+
+ BOOST_CHECK_EQUAL(fout.iword(oldUncSigDigitsIndex),-1); // Default means not set yet.
+ fout << setUncSigDigits(5) << endl; // Bigger that makes sense.
+ BOOST_CHECK_EQUAL(fout.iword(setUncSigDigitsIndex), 3); // Reduces to max sensible.
+ fout << setUncSigDigits(2) << endl; // ISO default.
+ BOOST_CHECK_EQUAL(fout.iword(setUncSigDigitsIndex), 2); // Is default.
+ BOOST_CHECK_EQUAL(fout.iword(oldUncSigDigitsIndex), 3); // Previous set to 3.
+
+ fout << "setUncWidth(10) " << setUncWidth(20) << flush;
+ BOOST_CHECK_EQUAL(fout.iword(uncWidthIndex), 20);
+
+ fout << "setScale(-3) " << setScale(-3) << flush;
+ BOOST_CHECK_EQUAL(fout.iword(setScaleIndex), -3);
+
+ fout << "setsigdigits(5) " << setSigDigits(5) << flush;
+ BOOST_CHECK_EQUAL(fout.iword(setSigDigitsIndex), 5);
+
+ fout << "setuncsigdigits(1) " << setUncSigDigits(1) << flush;
+ BOOST_CHECK_EQUAL(fout.iword(setUncSigDigitsIndex), 1);
+
+
+} // BOOST_AUTO_TEST_CASE(unc_test_set_manips)
+
+BOOST_AUTO_TEST_CASE(unc_test_more_naninf)
+{ // "\nNative method of display of floating point infinity & Not a Number\n";
+ CHECK(numeric_limits<double>::infinity(), "1.#INF");
+ CHECK(-numeric_limits<double>::infinity(), "-1.#INF");
+ CHECK(numeric_limits<float>::quiet_NaN() , "1.#QNAN");
+ CHECK(-numeric_limits<float>::quiet_NaN() , "-1.#IND");
+
+ // Uncertain type Infinite value - known exactly.
+ uncun infinite(numeric_limits<double>::infinity(), 0.f); // Exact plus infinity.
+ CHECK_USED(infinite, "inf");
+ CHECK_USED(plusminus << infinite, "inf +/-0");
+ CHECK_USED(std::showpos << infinite, "+inf");
+ CHECK_USED(std::showpos << plusminus << infinite, "+inf +/-0");
+
+ uncun infiniteUK(numeric_limits<double>::infinity(), 0.1f); // unknown plus infinity.
+ CHECK_USED(plusminus << infiniteUK, "inf +/-0.10");
+ CHECK_USED(std::showpos << plusminus << infiniteUK, "+inf +/-0.10");
+
+ uncun exactNaN(numeric_limits<double>::quiet_NaN(), 0.f); // Exact NaN
+ CHECK_USED(exactNaN, "NaN");
+ CHECK_USED(plusminus << exactNaN, "NaN +/-0");
+
+ // NaN with known uncertainty.
+ uncun NaNknown(numeric_limits<double>::quiet_NaN(), 0.01f);
+ CHECK_USED(NaNknown, "NaN");
+ CHECK_USED(plusminus << NaNknown, "NaN +/-0.010");
+ uncun NaNknown2(numeric_limits<double>::quiet_NaN(), 0.1f);
+ CHECK_USED(plusminus << NaNknown2, "NaN +/-0.10");
+
+ uncun undefined_uncertain = uncun(numeric_limits<double>::quiet_NaN(), 0.1f);
+ CHECK_USED(plusminus << undefined_uncertain, "NaN +/-0.10");
+
+ uncun NaNUnknown(numeric_limits<double>::quiet_NaN(), numeric_limits<float>::quiet_NaN()); // NaN of NaN uncertainty.
+ CHECK_USED(plusminus << NaNUnknown, "NaN +/-?");
+
+ // Values with unknown uncertainty.
+ // Try to treat stdDev==NaN as a special case,
+ // but get different results for zero and other values.
+ // max_digits10 used for zero (for which a case could be made),
+ // default precision 6 for others.
+ // Unable to see why at present, but other cases may be flawed too.
+
+} // BOOST_AUTO_TEST_CASE(unc_test_naninf)
+
+BOOST_AUTO_TEST_CASE(unc_test_unc_Nan_inf)
+{
+ uncun zeroMaybe(0., numeric_limits<float>::quiet_NaN() );
+ CHECK_USED(zeroMaybe, "0.00000000000000000"); // Show max_digits10 because uncertainty is NaN.
+
+ CHECK_USED(plusminus << zeroMaybe, "0.00000000000000000 +/-?");
+
+ uncun postwoMaybe(+2., numeric_limits<float>::quiet_NaN()); // +1.234 with unknown uncertainty.
+ //cout << postwoMaybe << endl;
+ uncun posonetwoMaybe(+1.234, numeric_limits<float>::quiet_NaN()); // +1.234 with unknown uncertainty.
+ //cout << posonetwoMaybe << endl;
+ CHECK_USED(posonetwoMaybe, "1.2340000000000000");
+
+ uncun negtwoMaybe(-2.2, numeric_limits<float>::quiet_NaN()); // -2.2 with unknown uncertainty.
+ CHECK_USED(negtwoMaybe, "-2.2000000000000002");
+ CHECK_USED(plusminus << negtwoMaybe, "-2.2000000000000002 +/-?")
+ // Fails here on release version.
+ uncun twoMaybe(+2.2, numeric_limits<float>::quiet_NaN()); // +2.2 with unknown uncertainty.
+ CHECK_USED(twoMaybe, "2.2000000000000002");
+ CHECK_USED(plusminus << twoMaybe, "2.2000000000000002 +/-?")
+ uncun infUnknown(9.8, numeric_limits<float>::infinity() ); // Value with infinite uncertainty.
+ CHECK_USED(infUnknown, "9.8000000000000007");
+ CHECK_USED(plusminus << infUnknown, "9.8000000000000007 +/-inf");
+} // BOOST_AUTO_TEST_CASE(unc_test_unc_Nan_inf)
+
+BOOST_AUTO_TEST_CASE(unc_test_setsegdigits)
+{
+ uncun zeroMaybe(0., numeric_limits<float>::quiet_NaN() );
+ //CHECK_USED(setSigDigits(7) << setsigdigits << zeroMaybe, "0.0000000"); // TODO
+// setSigDigits must override all other options (and also set stddev sigfigs too).
+} // BOOST_AUTO_TEST_CASE(unc_test_setsegdigits)
+
+BOOST_AUTO_TEST_CASE(unc_test_coda)
+{
+ BOOST_MESSAGE("Uncertain Class tests log end. " << __FILE__ << ' ' << __TIMESTAMP__ );
+
+ dout << "\n""Unc Diagnostics log end. " << endl; // \x0F1 = +- on screen, but ~n in files!
+
+ cerr.rdbuf(dout.rdbuf()); // Switch diagnostic log back to cerr before close!
+ // cerr = fout; in effect.
+ dout.close(); // Diagnostics.
+ cerr << "\n\nClosed diagnostics file " << diagFilename << ' '<< __TIMESTAMP__ << endl;
+
+ fout << "\nClosed test output "<< __FILE__ << ' ' << __TIMESTAMP__ << endl;
+ fout.close(); // Test output.
+ //lout << logFilename << " end." << endl;
+
+ //unit_test_log.set_stream(cout); // Switch back to cout,
+ //lout.close(); // before close in case there is more log output,
+ // which is almost certain, else ends unhappily!
+
+ cout << "\nClosed fout "<< __FILE__ << ' ' << __TIMESTAMP__ << endl;
+// fin.close();
+// cout << "\nClosed fin "<< __FILE__ << ' ' << __TIMESTAMP__ << endl;
+ cerr << endl; // Needed to avoid crash right at end.
+} // BOOST_AUTO_TEST_CASE(unc_test_coda)
+
+
+/*
+
+// Display of all 8-bit characters, showing differences between cout and fout.
+//{for (int i = 1; i < 0xFF; ++i)
+ //{ // Output all 256 8-bit chars.
+ // fout << char(i);
+ // if ((i % 64) == 0)
+ // { // 64 chars per line, 4 lines.
+ // fout << nl;
+ // }
+ //}} // for i
+ //fout << endl;
+ //!"#$%&'()*+,-./0123456789:;<=>?@
+ //ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€
+ //‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿À
+ //ÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþ
+
+// No minus infinity in numeric_limits,
+// but <cfloat> int _fpclass (double) == _FPCLASS_NINF if negative infinity.
+// uncun minus_infinite(MINUS_INFINITY, 0.0f); // exact minus infinity.
+// fout << " (MINUS_INFINITY, 0.) " << minus_infinite << endl;
+// infinite = uncun(MINUS_INFINITY, 0.1f); // uncertain plus infinity.
+// fout << " (MINUS_INFINITY, 0.1) " << minus_infinite << endl;
+if (testMath)
+{
+cerr << "Test math functions." << nl;
+// New scope for some unc variables.
+uncun a(0), b(0), c(0), d(0), e(0), t(0);
+fout <<
+"\nLibrary functions ceil(), floor(), fabs(), modf(), frexp(), and fmod()\n"
+"all exist primarily for their discontinuities. All give bad results\n"
+"(and warnings from the test class) when used near a discontinuity.\n"
+"Extreme care needed in using these functions with uncertain arguments!\n";
+{
+// double fmod (double x, double y) returns the floating-point remainder of x / y.
+uncun mod(0);
+uncun x(0);
+mod = fmod(x + 0.5, 1.0); // Floating point modulus or remainder.
+fout << "fmod(" << (x + 0.5) << ", " << 1.0 << ") = " << mod << endl;
+mod = fmod(5.5, 0.9 + 0.1 * a);
+fout << "fmod(" << 5.5 << ", " << (0.9 + 0.1 * a) << ") = " << mod << endl;
+}
+{
+// unc modf(unc x, double* intPart)
+// modf breaks floating-point value x into fractional & integer parts,
+// (each of which has the same sign as x).
+// Returns signed fractional portion of x.
+// Integer portion is stored as a double floating-point value at intPart.
+uncun x(0); // to split.
+uncun frac(0.88); // for return.
+
+double intPartdbl; // for integer part as double.
+frac = modf(x, &intPartdbl); // integer part as double.
+fout << "modf(" << x << ", intPart) = " << intPartdbl << " & " << frac << endl;
+frac = modf(x + 0.5, &intPartdbl);
+fout << "modf(" << (x + 0.5) << ", intPart) = " << intPartdbl << " & "<< frac << endl;
+}
+// double frexp( double x, int *expptr );
+// breaks floating-point value (x) into a mantissa (m) and an exponent (n),
+// such that the absolute value of 1.0 > m >= 0.5 and x = m*2n.
+// Integer exponent n is stored at the location pointed to by expptr.
+
+int intPart; // for exponent part of double.
+t = frexp(c, &intPart); // split c to mantissa & exponent.
+fout << "frexp(" << c << ", i) = " << t << endl;
+t = frexp(c + 0.5, &intPart);
+fout << "frexp(" << (c + 0.5) << ", i) = " << t << endl;
+t = ceil(c); // integer (as double) >= double.
+fout << "ceil(" << c << ") = " << " " << t << endl;
+t = ceil(c + 0.5);
+fout << "ceil(" << (c + 0.5) << ") = " << t << endl;
+t = floor(c); // integer (as double) <= double.
+fout << "floor(" << c << ") = " << t << endl;
+t = floor(c + 0.5);
+fout << "floor(" << (c + 0.5) << ") = " << t << endl;
+
+t = fabs(c); // absolute value of a double.
+fout << "fabs(" << c << ") = " << t << endl;
+b = -1.2;
+t = fabs(b);
+fout << "fabs(" << b << ") = " << t << endl;
+t = fabs(b + 0.02);
+fout << "fabs(" << (b + 0.02) << ") = " << t << endl;
+// End scope of uncun a,b,c, ...
+} // test Meth
+
+fout << "\nUnits test Output from "
+<< __FILE__ << space << __DATE__ << " " << __TIME__
+<< "\n" << endl;
+
+uncun uGiven; // Give on input.
+uncun uScaled; // Input scaled by unit prefix or symbol.
+uncun uSIvalue (0.); // Copy or converted from non-SI.
+string test; // = " 123.45 +/- 0.1 mA (99) ! description";
+while(!fin.fail())
+{
+if (fin) getline(fin, test);
+if (test.size() == 0) break; // to quit.
+if (test.size() > 0)
+{
+fout << "\nINPUT: " << test << endl; // Echo input to file.
+cerr << "\nINPUT: " << test << endl; // Echo input to console.
+istringstream is(test);
+is >> uGiven;
+if (is.fail() == true || is.eof() == true)
+{ // No units given.
+
+fout << uGiven << "(no unit)." << flush;
+continue;
+}
+bool isSIsymbol = false; // true if is k, m, M, G ...
+bool isSIprefix = false; // true if is kilo, mill, Mega ...
+bool isSImultiple = false; // if SIsymbol or SIprefix
+bool isUnit = false; // if a unit like length, mass ... defined.
+bool isSIunit = false; // true if meter, but false if foot.
+string multipleUnit = ""; // "mm", "Mm", "m", "um" "centim", "inches"...
+string SIsymbol; // Examples: k, m, M ...
+string SIprefix; // Examples: "kilo", milli, Mega ...
+string SIunitName = ""; // SI unit for type of unit, meter for length.
+string addSIsymbol = ""; // Example: m for meter
+string unitName = ""; // base unit name, for example meter, inch, oz
+string givenName = ""; // name, abbreviation or alias.
+double confactor; // multiply by this to convert non-SI to SI unit.
+const unit* u = &length; // unitps[unitno]; // &length, &mass, &current ...
+unsigned int SIindex = notOK; // Index to SIsymbols, SIprefixes & powersOfTen
+// == SI maxPowerTen if unity scale factor.
+const char** uNames;
+const char* unitAbbreviation = "";
+unsigned int unitNamesIndex = notOK;
+unsigned int givenIndex = 0; // uNames[givenIndex] = given name string
+
+is >> ws; // Needed because whitespace made significant by:
+// is.unsetf(ios_base::skipws); or >> noskipws to make all chars significant.
+if (is.peek() == '!')
+{ // comment follows, so
+string comment;
+getline(is, comment); // to end of line.
+// No units given.
+fout << uGiven << "(no unit)." << flush;
+continue;
+}
+
+is >> multipleUnit; // 1 meter, 2.2 mm, 1 inch, 3.4 uin or u"
+cerr << "multipleUnit " << multipleUnit << endl;
+is >> ws; // Ensure any trailing whitespace read.
+
+// TODO multiple units like mg/ml also written as mg ml-1???
+
+if (multipleUnit[0] == '?')
+{
+if (multipleUnit[1] == '?')
+{ // Show all units for all types, mass, length, current ...
+// fout << "\nshowAllUnits(u, fout); for all units.\n" << endl;
+for (int unitno = 0; unitno < unitsCount; unitno++) // All units.
+{
+const unit* unit = unitps[unitno];
+showAllUnits(unit, fout);
+}
+continue; // while more test input.
+}
+else
+{ // Just some examples - or select somehow length, mass etc.
+// showAllUnits(&current, fout); // Show possible units for current.
+// showAllUnits(&mass, fout); // Show possible units for mass.
+// showAllUnits(&length, fout); // Show all possible units for length.
+showAllUnits(u, fout); // Show all possible units for current unit of .
+continue; // while more test input.
+} // ?? option all units.
+} // ? option current unit.
+
+// Try to decipher the unit, & SI symbol or prefix multiple, if any.
+// unitNamesIndex is one of unitNames like meter, inch, feet ...
+unitNamesIndex = findUnit(multipleUnit, u, givenIndex, SIindex);
+
+isUnit = !(unitNamesIndex == notOK);
+if (isUnit) // of specified unit type like mass, length ...
+{
+uNames = u->unitNames[unitNamesIndex]; // gram, ton, cwt, lb, oz ...
+givenName = uNames[givenIndex]; // Name actually given on input.
+unitName = uNames[0]; // Base unit name: meter, inch, feet ...
+// not abbreviation or alias.
+unitAbbreviation = uNames[1]; // Base unit abbreviation: m, in, ft ..
+SIunitName = u->SIunitNames[0]; // For example: meter, gram, second ...
+addSIsymbol = u->SIunitNames[1]; // m, g, s ...
+confactor = u->unitToSIfactors[unitNamesIndex]; // Conversion factor to SI unit.
+}
+else // isUnit == false
+{
+cerr << "Unit " << multipleUnit << " is NOT a unit of " << u->unitOf << '.' << endl;
+fout << "Unit " << multipleUnit << " is NOT a unit of " << u->unitOf << '.' << endl;
+const unit& ur = findAnyUnit(multipleUnit, unitNamesIndex, givenIndex, SIindex);
+if (&ur == &unknownUnit || unitNamesIndex == notOK)
+{
+fout << "Unit " << multipleUnit << " is NOT a known unit!" << endl;
+continue;
+}
+
+fout << "But unit " << multipleUnit << " IS a unit of " << ur.unitOf << '.' << endl;
+isUnit = (unitNamesIndex != notOK);
+if (!isUnit)
+{
+continue;
+}
+const unit* uu = u;
+u = &ur;
+uNames = u->unitNames[unitNamesIndex]; // gram, ton, cwt, lb, oz ...
+givenName = uNames[givenIndex]; // Name actually given on input.
+unitName = uNames[0]; // Base unit name: meter, inch, feet ...
+// not abbreviation or alias.
+unitAbbreviation = uNames[1]; // Base unit abbreviation: m, in, ft ..
+SIunitName = u->SIunitNames[0]; // For example: meter, gram, second ...
+addSIsymbol = u->SIunitNames[1]; // m, g, s ...
+confactor = u->unitToSIfactors[unitNamesIndex]; // Conversion factor to SI unit.
+} // is Unit
+
+isSIunit = (unitNamesIndex == 0); // If meter not inch.
+isSImultiple = !(SIindex == notOK); // SI symbol or prefix found.
+
+uScaled = uGiven; // Assume no conversion factor.
+if (isSImultiple)
+{ // Scale using SIindex.
+uScaled *= powersOfTen[SIindex + maxPowerTen - SImaxPowerTen];
+// Works for non-SU units like inch too!
+} //isSImultiple
+else
+{
+SIindex = SImaxPowerTen; // So SI symbol & prefix = ""
+} // no SImultiple.
+SIsymbol = SIsymbols[SIindex];
+SIprefix = SIprefixes[SIindex];
+
+if (isSIunit)
+{
+confactor = u->unitToSIfactors[unitNamesIndex];
+if (confactor != 1.)
+{ // Internal data error, expect SI unit confactor to be unity!
+cerr << "SI unit conversion factor not unity but " << confactor << "!" << endl;
+// Ignoring error.
+uSIvalue = uScaled;
+}
+}
+else
+{ // not SI unit, so convert to SI.
+confactor = u->unitToSIfactors[unitNamesIndex];
+if (confactor != 0.)
+{ // Normal case of valid non-zero conversion factor.
+uSIvalue = uScaled * confactor; // Convert to SI unit.
+}
+else
+{ // Special formula needed, for example degrees Celsius.
+if (unitName == "Celsius")
+{
+uSIvalue = uScaled + 273.15; // To degrees Kelvin.
+}
+else if (unitName == "Fahrenheit")
+{
+uSIvalue = (uScaled + 459.67) / 1.8; // NIST 811 p 49.
+} // C or F.
+// else other complex conversion identified by (unitName == "???").
+} // confactor.
+} // SI unit or not.
+
+if (isSIunit)
+{
+fout << "SI unit of " << u->unitOf << ' '
+<< flexform << plusminus << noautoscale << noSIprefix
+<< uGiven << SIprefix << unitName // millimeter
+<< " or " << SIsymbol << unitAbbreviation ; // mm
+if (isSImultiple)
+{
+fout << ", SI " // "SI 1.23 meter or m"
+<< uScaled << ' ' << SIunitName << " or " << unitAbbreviation;
+}
+if (fabs(double((uScaled.value()) > 1000.0)) || fabs(double((uScaled.value()) < 1.0)))
+{ // Useful to autoscale.
+fout << "\nAutoscaled " << plusminus << autoscale << addSIprefix
+<< uScaled << SIunitName
+<< " or " << noplusminus << noSIprefix << addSIsymbol << uScaled << addSIsymbol;
+}
+}
+else
+{ // NOT SI unit, so show the value in appropriate SI unit.
+fout << "Non-SI unit " << flexform << plusminus << noautoscale
+<< uScaled
+<< noSIsymbol // To avoid trailing space.
+// << '_' // testing
+// But want space after "1.0 +/- ?"
+<< givenName // non-SI like feet, fortnight etc.
+<< " in SI is "
+<< plusminus << addSIsymbol << noSIprefix << uSIvalue
+<< addSIsymbol;// For symbol and abbreviation like mm.
+if (
+(fabs(double(uSIvalue.value() > 1000.0) ) )
+|| fabs(double(uSIvalue.value() < 1.0) ) )
+{ // Useful to autoscale.
+fout << "\nAutoscaled SI "
+<< plusminus << autoscale
+<< addSIprefix << uSIvalue << SIunitName
+// For prefix & unit name like millimeter.
+<< " or " << noplusminus << noSIprefix << addSIsymbol << uSIvalue << addSIsymbol;
+}
+} // if SIunit or not.
+
+is >> noskipws >> ws; // Needed if whitespace made significant by:
+// is.unsetf(ios_base::skipws); or noskipws >> to make all chars significant.
+is.unsetf(ios_base::skipws); // == >> noskipws
+if (is.peek() == '!')
+{ // A comment follows, so read and echo it.
+string comment;
+// is >> comment; // still stops at ws.
+getline(is, comment); // to end of line.
+//fout << " Comment: "<< comment << ", length " << comment.length()<< endl;
+}
+}
+}
+
+
+/*
+
+------ Rebuild All started: Project: unc_tests, Configuration: Debug Win32 ------
+Build started 24-Apr-2012 12:20:16.
+_PrepareForClean:
+ Deleting file "Debug\unc_tests.lastbuildstate".
+InitializeBuildStatus:
+ Touching "Debug\unc_tests.unsuccessfulbuild".
+ClCompile:
+ cvt.cpp
+ si_units.cpp
+ unc.cpp
+ unc_print.cpp
+ unc_read.cpp
+ xiostream.cpp
+ unc_tests.cpp
+ Generating Code...
+Manifest:
+ Deleting file "Debug\unc_tests.exe.embed.manifest".
+LinkEmbedManifest:
+ unc_tests.vcxproj -> J:\Cpp\quan\MSVC\Debug\unc_tests.exe
+CustomBuildStep:
+ Description: Autorun J:\Cpp\quan\MSVC\Debug\unc_tests.exe
+ Running 1 test case...
+ Platform: Win32
+ Compiler: Microsoft Visual C++ version 10.0
+ STL : Dinkumware standard library version 520
+ Boost : 1.49.0
+ ± Uncertain Class Test output to unc_test_output.txt ..\..\libs\quan\test\unc_tests.cpp Fri Mar 9 19:18:39 2012
+ Unc Diagnostics logged to unc_diag.txt
+../../libs/quan/test/unc_tests.cpp(653): error : in "unc_test": check oss.str() == "0.0000" failed [0 != 0.0000]
+ 0.00
+ Value 1 flagged as exact, but uncertainty 1 is not zero!
+ Value 1 flagged as exact, but degfree 2 is not zero!
+ uncTypes (0x60e7) zero integer rational uncKnown noPlus noMinus df_exact df_known.0.000000000000000
+../../libs/quan/test/unc_tests.cpp(1231): error : in "unc_test": check oss.str() == "0.00000" failed [0.000000000000000 != 0.00000]
+ 2.00000
+ 1.23400
+
+ Closed fout ..\..\libs\quan\test\unc_tests.cpp Fri Mar 9 19:18:39 2012
+C:\Program Files\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(183,5): error MSB3073: The command ""J:\Cpp\quan\MSVC\Debug\unc_tests.exe" --result_code=yes --report_level=detailed --catch_system_errors=no --build_info=yes
+C:\Program Files\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(183,5): error MSB3073: :VCEnd" exited with code 201.
+
+Build FAILED.
+
+Time Elapsed 00:00:08.71
+========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========
+
+*/
\ No newline at end of file


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk