Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r77285 - in sandbox/SOC/2007/visualization/boost/svg_plot: . detail
From: pbristow_at_[hidden]
Date: 2012-03-09 10:11:15


Author: pbristow
Date: 2012-03-09 10:11:14 EST (Fri, 09 Mar 2012)
New Revision: 77285
URL: http://svn.boost.org/trac/boost/changeset/77285

Log:
New version of uncertain type allowing correlated or not.
Text files modified:
   sandbox/SOC/2007/visualization/boost/svg_plot/detail/auto_axes.hpp | 19 ++--
   sandbox/SOC/2007/visualization/boost/svg_plot/detail/axis_plot_frame.hpp | 8 +-
   sandbox/SOC/2007/visualization/boost/svg_plot/detail/functors.hpp | 37 +++++----
   sandbox/SOC/2007/visualization/boost/svg_plot/detail/numeric_limits_handling.hpp | 7 +
   sandbox/SOC/2007/visualization/boost/svg_plot/svg_1d_plot.hpp | 14 +-
   sandbox/SOC/2007/visualization/boost/svg_plot/svg_2d_plot.hpp | 62 +++++++-------
   sandbox/SOC/2007/visualization/boost/svg_plot/uncertain.hpp | 160 +++++++++++++++++++++++++++------------
   7 files changed, 187 insertions(+), 120 deletions(-)

Modified: sandbox/SOC/2007/visualization/boost/svg_plot/detail/auto_axes.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/detail/auto_axes.hpp (original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/detail/auto_axes.hpp 2012-03-09 10:11:14 EST (Fri, 09 Mar 2012)
@@ -111,21 +111,20 @@
 
 // Definitions.
 
-//! \tparam iter iterator into STL container.
+ /*! \brief Inspect values to find min and max.
+ \details Inspect all values between begin and (one before) end to work out and update min and max.
+ Similar to boost::minmax_element, but ignoring at 'limit': non-finite, +-infinity, max & min, & NaN).
+ If can't find a max and a min, then throw a runtime_error exception.
+ \tparam iter InputIterator into STL container.
+ \return number of normal values (not 'at limit' neither too big, NaN nor infinite).
+ */
 template <typename iter>
 int mnmx(
   iter begin, //!< iterator to chosen first item in container.
   iter end, //!< iterator to chosen last item in container.
   double* min, //!< Updated with Minimum value found (not 'at limit').
   double* max) //!< Updated with Maximum value found (not 'at limit').
-{ //! \brief Inspect values to find min and max.
- /*! \details Inspect all values between begin and (one before) end to work out and update min and max.
-
- Similar to boost::minmax_element, but ignoring at 'limit': non-finite, +-infinity, max & min, & NaN).
- If can't find a max and a min, then throw a runtime_error exception.
- \tparam iter STL container iterator.
- \return number of normal values (not 'at limit' neither too big, NaN nor infinite).
- */
+{
   *max = std::numeric_limits<double>::quiet_NaN();
   *min = std::numeric_limits<double>::quiet_NaN();
   using boost::svg::detail::is_limit; // Either x and/or y not a proper data value.
@@ -182,7 +181,7 @@
     throw std::runtime_error("Autoscale could not find useful min & max to scale axis!");
   }
   return goods; // If goods < 2,
-} // inmmax(iter begin, iter end, double* min, double* max)
+} // template <typename iter>int mnmx((iter begin, iter end, double* min, double* max)
 
 //! Scale axis function to define axis marker ticks based on min & max parameters values.
 void scale_axis(

Modified: sandbox/SOC/2007/visualization/boost/svg_plot/detail/axis_plot_frame.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/detail/axis_plot_frame.hpp (original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/detail/axis_plot_frame.hpp 2012-03-09 10:11:14 EST (Fri, 09 Mar 2012)
@@ -1032,7 +1032,7 @@
                   legend_x_pos,
                   legend_y_pos,
                   *g_inner_ptr,
- sty, unc(0.), unc(0.));
+ sty, unc<false>(), unc<false>());
                   //was derived().serieses_[i].point_style_, unc(0.), unc(0.));
                 legend_x_pos += 1.5 * spacing;
                 if (was_unc_ellipse)
@@ -1079,7 +1079,7 @@
           //void draw_plot_point(unc x, unc y, // SVG coordinates.
             g_element& g_ptr,
             plot_point_style& sty,
- unc ux, unc uy) // Default unc ux = 0.? and uy = 0.
+ unc<false> ux, unc<false> uy) // Default unc ux = 0.? and uy = 0.
           { /*! Draw a plot data point marker shape
               whose size and stroke and fill colors are specified in plot_point_style.
             */
@@ -1231,7 +1231,7 @@
             }
           } // void draw_plot_point
 
- void draw_plot_point_value(double x, double y, g_element& g_ptr, value_style& val_style, plot_point_style& point_style, unc uvalue)
+ void draw_plot_point_value(double x, double y, g_element& g_ptr, value_style& val_style, plot_point_style& point_style, unc<false> uvalue)
           { /*!
              Write one data point (X or Y) value as a string, for example "1.23e-2",
              near the data point marker.
@@ -1393,7 +1393,7 @@
               label.str(); // Leave unstripped.
           } // std::string sv(double v, const value_style& sty)
 
- void draw_plot_point_values(double x, double y, g_element& x_g_ptr, g_element& y_g_ptr, const value_style& x_sty, const value_style& y_sty, unc uncx, unc uncy)
+ void draw_plot_point_values(double x, double y, g_element& x_g_ptr, g_element& y_g_ptr, const value_style& x_sty, const value_style& y_sty, unc<false> uncx, unc<false> uncy)
           { /*! \brief Write the \b pair of data point's X and Y values as a string.
                \details
                \verbatim If a separator, then both on the same line, for example "1.23, 3.45", or "[5.6, 7.8]

Modified: sandbox/SOC/2007/visualization/boost/svg_plot/detail/functors.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/detail/functors.hpp (original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/detail/functors.hpp 2012-03-09 10:11:14 EST (Fri, 09 Mar 2012)
@@ -78,53 +78,58 @@
     }
 }; // class pair_double_2d_convert
 
+template <bool correlated>
 class pair_unc_2d_convert
 { /*! \class boost::svg::detail::pair_unc_2d_convert
       \brief This functor allows any 2D data convertible to type std::pair<unc, unc> to be plotted.
 */
 public:
- typedef std::pair<unc, unc> result_type; //!< result type is pair of uncertain values.
- unc i; //!< Start uncertain value.
- void start(unc i)
+ typedef std::pair<unc<correlated>, unc<correlated>> result_type; //!< result type is pair of uncertain values.
+ unc<correlated> i; //!< Start uncertain value.
+ void start(unc<correlated> i)
     { //!< Set a start value.
        i = i;
     }
 
     //!< \tparam T type convertible to double.
     template <class T, class U>
- std::pair<unc, unc> operator()(const std::pair<T, U>& a) const
+ std::pair<unc<correlated>, unc<correlated> > operator()(const std::pair<T, U>& a) const
     { //!< Convert a pair of X and Y uncertain type values to a pair of doubles.
        //! \return pair of uncs.
- return std::pair<unc, unc>((unc)(a.first), (unc)(a.second));
+ return std::pair<unc<correlated>, unc<correlated> >((unc<correlated>)(a.first), (unc<correlated>)(a.second));
     }
 
     template <class T> //!< \tparam T Any type convertible to double.
- std::pair<unc, unc> operator()(T a)
+ std::pair<unc<correlated>, unc<correlated> > operator()(T a)
     { //!< Convert a pair of X and Y uncertain type values to a pair of unc.
- return std::pair<unc, unc>(i++, (unc)a); //! \return pair of unc.
+ return std::pair<un<correlated>c, unc<correlated> >(i++, (unc<correlated>)a); //! \return pair of unc.
     }
 }; // class pair_unc_2d_convert
 
+template <bool correlated>
 class unc_1d_convert
 { /*! \class boost::svg::detail::unc_1d_convert
       \brief This functor allows any 1D data convertible to unc (uncertain doubles) to be plotted.
       \details Defaults provided by the unc class constructor ensure that
- uncertainty, degrees of freedom information, and type are suitably set too.
+ uncertainty, degrees of freedom information, and type are suitably set too.
 */
 public:
- typedef unc result_type; //!< result type is an uncertain floating-point type.
+ typedef unc<correlated> result_type; //!< result type is an uncertain floating-point type.
 
- //! \tparam T Any type convertible to double.
+ //! \tparam T Any data type with a value convertible to double, for example: double, unc, Meas.
     template <class T>
- unc operator()(T val) const /*!< Convert to uncertain type, providing defaults for uncertainty,
- degrees of freedom information, and type (meaning undefined).
+ unc<correlated> operator()(T val) const
+ /*!< Convert to uncertain type,
+ providing defaults for uncertainty, degrees of freedom information, and type (meaning undefined).
     \return value including uncertainty information.
     */
     {
- return (unc)val; //! \return uncertain type (uncertainty, degrees of freedom information, and type meaning undefined).
- // warning C4244: 'argument' : conversion from 'long double' to 'double', possible loss of data.
- // because unc only holds values to double precision.
- // Suppressed by pragma for MSVC above. Need similar for other compilers.
+ return (unc<correlated>)val;
+ /*! \return uncertain type (uncertainty, degrees of freedom information, and type meaning undefined).
+ warning C4244: 'argument' : conversion from 'long double' to 'double', possible loss of data.
+ because unc only holds values to double precision.
+ Suppressed by pragma for MSVC above. Need similar for other compilers.
+ */
     }
 }; // class default_1d_convert
 

Modified: sandbox/SOC/2007/visualization/boost/svg_plot/detail/numeric_limits_handling.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/detail/numeric_limits_handling.hpp (original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/detail/numeric_limits_handling.hpp 2012-03-09 10:11:14 EST (Fri, 09 Mar 2012)
@@ -103,7 +103,8 @@
     || limit_max(a.second) || limit_min(a.second) || limit_NaN(a.second);
 }
 
-inline bool pair_is_limit(std::pair<const unc, unc> a)
+template <bool correlated>
+inline bool pair_is_limit(std::pair<const unc<correlated>, unc<correlated> > a)
 { //! Check on values of both x and y unc data points.
   // \return false if either or both are at limit.
   return limit_max(value_of(a.first)) || limit_min(value_of(a.first)) || limit_NaN(value_of(a.first))
@@ -121,6 +122,8 @@
 bool boost::svg::detail::is_limit(double); // max, min, infinity or NaN - not a 'proper' data value.
 bool boost::svg::detail::pair_is_limit(std::pair<double, double>); // x and/or y not a proper data value.
 bool boost::svg::detail::pair_is_limit(std::pair<const double, double>); // x and/or y not a proper data value.
-bool boost::svg::detail::pair_is_limit(std::pair<const unc, unc>); // x and/or y not a proper data value.
+
+template <bool correlated>
+bool boost::svg::detail::pair_is_limit(std::pair<const unc<correlated>, unc<correlated> >); // x and/or y not a proper data value.
 
 #endif // BOOST_SVG_NUMERIC_LIMITS_HANDLING_DETAIL_HPP

Modified: sandbox/SOC/2007/visualization/boost/svg_plot/svg_1d_plot.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/svg_1d_plot.hpp (original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/svg_1d_plot.hpp 2012-03-09 10:11:14 EST (Fri, 09 Mar 2012)
@@ -80,7 +80,7 @@
 */
 
 public:
- std::vector<unc> series_; //!< Normal 'OK to plot' data values.
+ std::vector<unc<false> > series_; //!< Normal 'OK to plot' data values.
   std::vector<double> series_limits_; //!< 'limit' values: too big, too small or NaN.
   // TODO should these be unc too?
 
@@ -761,7 +761,7 @@
 
       for(unsigned int j = 0; j < serieses_[i].series_.size(); ++j)
       { // Draw jth point for ith serieses.
- unc ux = serieses_[i].series_[j];
+ unc<false> ux = serieses_[i].series_[j];
         double x = ux.value();
         // TODO symbols are offset downwards because
         // the origin of the point is the top left of the glyph.
@@ -770,7 +770,7 @@
         if((x >= plot_left_) && (x <= plot_right_)) // Check point is inside plot_window.
         // May need a margin here to avoid points just over the window not being shown.
         {
- draw_plot_point(x, y, g_ptr, serieses_[i].point_style_, ux, unc(0)); // Marker. (y uncertainty is zero)
+ draw_plot_point(x, y, g_ptr, serieses_[i].point_style_, ux, unc<false>()); // Marker. (y uncertainty is zero)
           if (x_values_on_)
           { // Show the value (& perhaps uncertainty) of the data point too.
             g_element& g_ptr_v = image_.g(detail::PLOT_X_POINT_VALUES).add_g_element();
@@ -806,7 +806,7 @@
             x = plot_right_;
           }
           //else X axis includes zero, so x is OK.
- draw_plot_point(x, y, g_ptr, serieses_[i].limit_point_style_, 0, 0);
+ draw_plot_point(x, y, g_ptr, serieses_[i].limit_point_style_, unc<false>(), unc<false>());
         }
         else
         { // Not NaN
@@ -825,7 +825,7 @@
           serieses_[i].limit_point_style_.fill_color_ = image_.g(detail::PLOT_LIMIT_POINTS).style().fill_color();
           // This is a kludge. limit_point_style_ should probably be common to all data series.
 
- draw_plot_point(x, y, g_ptr, serieses_[i].limit_point_style_, 0, 0);
+ draw_plot_point(x, y, g_ptr, serieses_[i].limit_point_style_, unc<false>(), unc<false>());
         }
       } // for j
     } // for i limits point
@@ -920,8 +920,8 @@
    */
     serieses_.push_back(
       svg_1d_plot_series(
- boost::make_transform_iterator(container.begin(), detail::unc_1d_convert()),
- boost::make_transform_iterator(container.end(), detail::unc_1d_convert()),
+ boost::make_transform_iterator(container.begin(), detail::unc_1d_convert<false>()),
+ boost::make_transform_iterator(container.end(), detail::unc_1d_convert<false>()),
       title)
     );
     return serieses_[serieses_.size() - 1];

Modified: sandbox/SOC/2007/visualization/boost/svg_plot/svg_2d_plot.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/svg_2d_plot.hpp (original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/svg_2d_plot.hpp 2012-03-09 10:11:14 EST (Fri, 09 Mar 2012)
@@ -75,7 +75,7 @@
 
     public:
       // 2-D Data series points to plot.
- std::multimap<unc, unc> series_; //!< Normal 'OK to plot' data values.
+ std::multimap<unc<false>, unc<false>> series_; //!< Normal 'OK to plot' data values.
       std::multimap<double, double> series_limits_; //!< 'limit' values: too big or small, or NaN.
 
       std::string title_; //!< Title of data series (to show on legend using legend style).
@@ -150,9 +150,9 @@
   { // Constructor.
     for(T i = begin; i != end; ++i)
     { // Sort data points into normal and limited series.
- std::pair<unc, unc> temp = *i;
- unc ux = temp.first;
- unc uy = temp.second;
+ std::pair<unc<false>, unc<false>> temp = *i;
+ unc<false> ux = temp.first;
+ unc<false> uy = temp.second;
       std::pair<double, double> xy = std::make_pair<double, double>(ux.value(), uy.value());
       if(detail::pair_is_limit(xy))
       { // Either x and/or y is at limit.
@@ -1620,13 +1620,13 @@
         double prev_y;
         if(series.series_.size() > 1)
         { // Need at least two points for a line ;-)
- std::multimap<unc, unc>::const_iterator j = series.series_.begin();
+ std::multimap<unc<false>, unc<false>>::const_iterator j = series.series_.begin();
           // If required to fill the area under the plot,
           // we first have to move from the X-axis (y = 0) to the first point,
           // and again to the X-axis (y = 0) at the end after the last point.
 
           // std::multimap<double, double> was prev_x = (*j).first;
- unc prev_ux = (*j).first;
+ unc<false> prev_ux = (*j).first;
           prev_x = prev_ux.value(); // 1st point X-value.
           prev_y = 0.; // y = 0, so on horizontal X-axis.
           transform_point(prev_x, prev_y);
@@ -1636,7 +1636,7 @@
             path.M(prev_x, prev_y);
           }
           // std::multimap<double, double> was transform_y(prev_y = (*j).second);
- unc prev_uy = (*j).second;
+ unc<false> prev_uy = (*j).second;
           prev_y = prev_uy.value();
           transform_y(prev_y);
           if(is_fill == true)
@@ -1654,9 +1654,9 @@
           double temp_y;
           for(; j != series.series_.end(); ++j)
           {
- unc temp_ux = (*j).first;
+ unc<false> temp_ux = (*j).first;
             temp_x = temp_ux.value();
- unc temp_uy = (*j).second;
+ unc<false> temp_uy = (*j).second;
             temp_y = temp_uy.value();
             transform_point(temp_x, temp_y);
             path.L(temp_x, temp_y); // Line to next point.
@@ -1699,13 +1699,13 @@
 
         if(series.series_.size() > 2)
         { // Need >= 3 points for a cubic curve (start point, 2 control points, and end point).
- std::multimap<unc, unc>::const_iterator iter = series.series_.begin();
- std::pair<unc, unc> un_minus_1 = *(iter++); // 1st unc X & Y data.
+ std::multimap<unc<false>, unc<false> >::const_iterator iter = series.series_.begin();
+ std::pair<unc<false>, unc<false> > un_minus_1 = *(iter++); // 1st unc X & Y data.
           n_minus_1 = std::make_pair(un_minus_1.first.value(), un_minus_1.second.value()); // X and Y values.
           //n_minus_1 = *(iter++); // begin()
           transform_pair(n_minus_1);
 
- std::pair<unc, unc> un = *(iter++); // middle
+ std::pair<unc<false>, unc<false> > un = *(iter++); // middle
           n = std::make_pair(un.first.value(), un.second.value()); // X and Y values.
           transform_pair(n);
           path.M(n_minus_1.first, n_minus_1.second); // move m_minus_1, the 1st data point.
@@ -1724,7 +1724,7 @@
           {
             n_minus_2 = n_minus_1;
             n_minus_1 = n;
- std::pair<unc, unc> un = *iter; // middle
+ std::pair<unc<false>, unc<false> > un = *iter; // middle
             n = std::make_pair(un.first.value(), un.second.value()); // X and Y values.
             transform_pair(n);
 
@@ -1785,13 +1785,13 @@
             .fill_color(serieses_[i].point_style_.fill_color_)
             .stroke_color(serieses_[i].point_style_.stroke_color_);
 
- for(std::multimap<unc, unc>::const_iterator j = serieses_[i].series_.begin();
+ for(std::multimap<unc<false>, unc<false> >::const_iterator j = serieses_[i].series_.begin();
             j != serieses_[i].series_.end(); ++j)
           {
- unc ux = j->first;
+ unc<false> ux = j->first;
             x = ux.value(); // Just the X value.
             //double vx = x; // Note the true X value.
- unc uy = j->first;
+ unc<false> uy = j->first;
             uy = j->second;
             y = uy.value(); // Just the Y value
             //double vy = y; // Note the true Y value.
@@ -1891,12 +1891,12 @@
             serieses_[i].limit_point_style_.fill_color_ = image_.g(detail::PLOT_LIMIT_POINTS).style().fill_color();
             // This is a kludge. limit_point_style_ should probably be common to all data series.
 
- draw_plot_point(x, y, g_ptr, serieses_[i].limit_point_style_, unc(0.), unc(0.)); // No uncertainty info for values at limit infinity & NaN.
+ draw_plot_point(x, y, g_ptr, serieses_[i].limit_point_style_, unc<false>(), unc<false>()); // No uncertainty info for values at limit infinity & NaN.
 
             if((x > plot_left_) && (x < plot_right_) && (y > plot_top_) && (y < plot_bottom_))
             { // Is inside plot window, so draw a point.
               // draw_plot_point(x, y, g_ptr, plot_point_style(blank, blank, s, cone)); default.
- draw_plot_point(x, y, g_ptr, serieses_[i].limit_point_style_, unc(0.), unc(0.));
+ draw_plot_point(x, y, g_ptr, serieses_[i].limit_point_style_, unc<false>(), unc<false>());
             }
           }
         } // limits point
@@ -1926,12 +1926,12 @@
 
           double h_w = serieses_[i].bar_style_.width_; // For block bar chart.
           //double h_h = 0.;
- for(std::multimap<unc, unc>::const_iterator j = serieses_[i].series_.begin();
+ for(std::multimap<unc<false>, unc<false> >::const_iterator j = serieses_[i].series_.begin();
             j != serieses_[i].series_.end(); ++j)
           { // All the 'good' data points.
- unc ux = j->first;
+ unc<false> ux = j->first;
             x = ux.value();
- unc uy = j->second;
+ unc<false> uy = j->second;
             y = uy.value();
             transform_point(x, y);
             if((x > plot_left_) && (x < plot_right_) && (y > plot_top_) && (y < plot_bottom_))
@@ -2017,26 +2017,26 @@
             path.style().fill_color(blank);
           }
 
- std::multimap<unc, unc>::const_iterator last = serieses_[i].series_.end();
+ std::multimap<unc<false>, unc<false> >::const_iterator last = serieses_[i].series_.end();
           last--; // Final pair with first the last bin end, and value zero or NaN.
- unc u = last->second;
+ unc<false> u = last->second;
           if (u.value() != 0)
           {
             std::cout << "Last bin end " << last->first << " should have zero value! but is " << last->second << std::endl;
             // Or Throw? or skip this series?
           }
- for(std::multimap<unc, unc>::const_iterator j = serieses_[i].series_.begin();
+ for(std::multimap<unc<false>, unc<false> >::const_iterator j = serieses_[i].series_.begin();
             j != last; ++j)
           { // All the 'good' 'real' data points.
- unc ux = j->first;
+ unc<false> ux = j->first;
             double x = ux.value();
- unc uy = j->second;
+ unc<false> uy = j->second;
             double y = uy.value();
- std::multimap<unc, unc>::const_iterator j_next = j;
+ std::multimap<unc<false>, unc<false> >::const_iterator j_next = j;
             j_next++;
             if (j != last)
             { // Draw a column (perhaps filled) to show bin.
- unc ux_next= j_next->first;
+ unc<false> ux_next= j_next->first;
               double x_next = ux_next.value();
               double w = x_next - x;
               double h = y / w;
@@ -3154,7 +3154,7 @@
   template <class T> //! \tparam T Type of data in series (must be convertible to unc double).
   svg_2d_plot_series& svg_2d_plot::plot(const T& container, const std::string& title)
   { /*! Add a container of a data series to the plot.
- This version assumes that \b ALL the data values in the container are used.
+ This version assumes that \b ALL the data values in the container are to be plotted.
       \code
 my_plot.plot(data1, "Sqrt(x)");
       \endcode
@@ -3162,8 +3162,8 @@
     */
     serieses_.push_back(
       svg_2d_plot_series(
- boost::make_transform_iterator(container.begin(), detail::pair_unc_2d_convert()),
- boost::make_transform_iterator(container.end(), detail::pair_unc_2d_convert()),
+ boost::make_transform_iterator(container.begin(), detail::pair_unc_2d_convert<false>()),
+ boost::make_transform_iterator(container.end(), detail::pair_unc_2d_convert<false>()),
       title)
     );
     return serieses_[serieses_.size()-1]; //! \return Reference to data series just added to make chainable.

Modified: sandbox/SOC/2007/visualization/boost/svg_plot/uncertain.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/uncertain.hpp (original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/uncertain.hpp 2012-03-09 10:11:14 EST (Fri, 09 Mar 2012)
@@ -17,7 +17,7 @@
   \author Paul A. Bristow
   \date Mar 2009
 */
-// Copyright Paul A. Bristow 2009, 2011
+// Copyright Paul A. Bristow 2009, 2011, 2012
 
 // Use, modification and distribution are subject to the
 // Boost Software License, Version 1.0.
@@ -27,6 +27,13 @@
 #ifndef BOOST_SVG_UNCERTAIN_HPP
 #define BOOST_SVG_UNCERTAIN_HPP
 
+#ifdef _MSC_VER
+# pragma once
+//# pragma warning (disable : 4520) // multiple default constructors specified.
+// Removed explicit default constructor to avoid this, relying on normal constructor
+// having defaults for all parameters.
+#endif
+
 #include <boost/svg_plot/detail/pair.hpp>
 
 #include <iostream>
@@ -43,7 +50,6 @@
    //! Nominal factor of 2 (strictly 1.96) corresponds to 95% confidence limit.
    static const double plusminus = 2.; //!< Number of standard deviations used for plusminus text display.\n
 
-// template <bool correlated = false>
 /*! \brief Uncertain class for storing an observed or measured value together with information
     about its uncertainty (previously called 'error' or 'plusminus', but now deprecated) represented
     nominally one standard deviation (but displayed as a multiple, usually two standard deviations).
@@ -53,22 +59,48 @@
     ISO, Guide to the expression of uncertainty in measurement, ISO, Geneva, 1993.\n
     Eurochem, Quantifying uncertainty in analytical measurements.
 */
-class unc
+
+// Forward declarations.
+template <bool correlated>
+class unc;
+
+typedef unc<false> uncun; //! Uncertainties are NOT correlated.
+//! Uncorrelated is the normal case when uncertainties add.
+
+typedef unc<true> uncorr; //! Uncertainties ARE correlated.
+//! Correlated is an unusual case where the sum of uncertainties is fixed.
+
+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 <bool correlated = false>
+class unc : public std::char_traits<char>
 {
 public:
- unc(); //!< Default constructor with value .
- unc(double v, float u, short unsigned df, short unsigned ty);
- /*! \brief Output an value with (if defined) uncertainty and degrees of freedom (and type).
+ // Constructors.
+ //unc(); //!< Default constructor with value zero not needed because all parameters have defaults.
+ unc(double v = 0., float u = -1.f, short unsigned df = (std::numeric_limits<unsigned short int>::max)(), short unsigned ty = 0U);
+
+ /*! \brief Output an value with (if defined) uncertainty and degrees of freedom (and type).
        For example: "1.23 +/- 0.01 (13)".\n
        \details Note that the uncertainty is input and stored as one standard deviation,
        but output multiplied for a user configurable 'confidence factor' plusminus,
- default two for about 95% confidence (but could also be one for 67% or 3 for 99% confidence).
+ default is two standard deviation for about 95%
+ confidence (but could also be one for 67% or 3 for 99% confidence).
   */
- friend std::ostream& operator<< (std::ostream& os, const unc& u);
- /*! Output a pair (X and Y) value with (if defined) uncertainty and degrees of freedom.
+ friend std::ostream& operator<< <> (std::ostream& os, const unc<correlated>& u);
+
+ /*! Output a pair of (X and Y) values with (if defined) uncertainty and degrees of freedom.
        \details For example: "1.23 +/- 0.01 (13), 3.45 +/- 0.06 (78)".
    */
- friend std::ostream& operator<< (std::ostream& os, const std::pair<unc, unc>& u);
+ friend std::ostream& operator<< <> (std::ostream& os, const std::pair<unc, unc>& u);
+
   bool operator<(const unc& rhs)const;
   bool operator<(unc& rhs)const;
   bool operator==(const unc& rhs) const;
@@ -85,7 +117,7 @@
   void deg_free(short unsigned); //!< Set degrees of freedom, usually = number of observations -1;
   void types(short unsigned); //!< Set other information about the value.
 
-private:
+ private:
   // Note that this class should fit into 128 bytes, same as two 64 bit doubles,
   // so it only doubles the memory required.
   double value_; //!< Most likely value, typically the mean.
@@ -104,36 +136,39 @@
   // (Hopefully, this only uses up the bits that would otherwise be padding).
 };
 
-unc::unc(double v, float u = -1.f, short unsigned df = (std::numeric_limits<unsigned short int>::max)(), short unsigned ty = 0U)
+
+template <bool correlated>
+//unc<correlated>::unc(double v = 0., float u = -1.f, short unsigned df = (std::numeric_limits<unsigned short int>::max)(), short unsigned ty = 0U)
+unc<correlated>::unc(double v, float u, short unsigned df, short unsigned ty)
 :
- value_(v), uncertainty_(u), deg_free_(df), types_(ty)
+value_(v), uncertainty_(u), deg_free_(df), types_(ty)
 { //! Constructor allowing an unc to be constructed from just value providing defaults for all other parameters.
   //! Note the defaults so that unspecified variables have 'undefined' status.
 }
 
-unc::unc()
-:
- value_(0.), uncertainty_(-1.F), deg_free_((std::numeric_limits<unsigned short int>::max)()), types_(0U)
-{ //! Default constructor.
- //! Note the defaults so that value is zero, but others have 'undefined' status.
-}
 
-bool unc::operator<(const unc& u) const
+
+template <bool correlated>
+bool unc<correlated>::operator<(const unc& u) const
 { //! Less operator only compares the value, ignoring any uncertainty information.
   return value_ < u.value_;
 }
 
-bool unc::operator<(unc& u) const
+template <bool correlated>
+bool unc<correlated>::operator<(unc& u) const
 { //! Less operator only compares the value, ignoring any uncertainty information.
   return value_ < u.value_;
 }
 
-bool unc::operator ==(const unc& u) const
+template <bool correlated>
+bool unc<correlated>::operator ==(const unc& u) const
 { //! Equality operator only compares the value, ignoring any uncertainty information.
- return value_ == u.value_; // But might check ALL are equal? Or that are approximately equal taking uncertainty infor account?
+ return value_ == u.value_; // But might check ALL are equal?
+ // Or that are approximately equal taking uncertainty infor account?
 }
 
-unc& unc::operator=(const unc& u)
+template <bool correlated>
+unc<correlated>& unc<correlated>::operator=(const unc& u)
 { //! Assignment simply copies all values, including those with 'undefined' status.
   value_ = u.value_;
   uncertainty_ = u.uncertainty_;
@@ -142,47 +177,58 @@
   return *this; //! to make chainable.
 }
 
-double unc::value() const
+template <bool correlated>
+double unc<correlated>::value() const
 { //! \return Most likely value, typically the mean.
   return value_;
 }
 
-float unc::uncertainty() const
+template <bool correlated>
+float unc<correlated>::uncertainty() const
 { //! \return Estimate of uncertainty, typically standard deviation.
   return uncertainty_;
 }
 
-short unsigned unc::deg_free() const
+template <bool correlated>
+short unsigned unc<correlated>::deg_free() const
 { //! \return Degrees of freedom, usually the number of observations -1.
   return deg_free_;
 }
 
-short unsigned unc::types() const
+template <bool correlated>
+short unsigned unc<correlated>::types() const
 { //! \return Other information about the uncertain value.
   return types_;
 }
 
-void unc::value(double v)
+
+template <bool correlated>
+void unc<correlated>::value(double v)
 { //! Set most likely value, typically the mean.
   value_ = v;
 }
 
-void unc::uncertainty(float u)
+template <bool correlated>
+void unc<correlated>::uncertainty(float u)
 { //! Set estimate of uncertainty, typically standard deviation.
   uncertainty_ = u;
 }
-void unc::deg_free(short unsigned df)
+
+template <bool correlated>
+void unc<correlated>::deg_free(short unsigned df)
 { //! Set degrees of freedom, usually = number of observations -1;
   deg_free_ = df;
 }
 
-void unc::types(short unsigned t)
+template <bool correlated>
+void unc<correlated>::types(short unsigned t)
 { //! Set other information about the uncertain value.
   types_ = t;
 }
 
-std::ostream& operator<< (std::ostream& os, const unc& u)
-{ /*! \brief Output an value with (if defined) uncertainty and degrees of freedom (and type).
+template <bool correlated>
+std::ostream& operator<< (std::ostream& os, const unc<correlated>& u)
+{ /*! \brief Output a single value with (if defined) uncertainty and degrees of freedom (and type).
      For example: "1.23 +/- 0.01 (13)".\n
      /details Note that the uncertainty is input and stored as one standard deviation,
      but output multiplied for a user configurable 'confidence factor' plusminus,
@@ -215,15 +261,21 @@
     os << " [" << u.types_ << "] ";
   }
   return os;
-} // ostream& operator<< (ostream& os, const unc& u)
+} // template <bool correlated> ostream& operator<< (ostream& os, const unc<correlated>c& u)
+
+// Explicit instantiation (but this is not enough - see note above).
+template std::ostream& operator<< (std::ostream& os, const unc<false>& u);
 
-std::ostream& operator<< (std::ostream& os, const std::pair<unc, unc>& u)
+template <bool correlated>
+std::ostream& operator<< (std::ostream& os, const std::pair< unc<correlated>, unc<correlated> >& u)
 { /*! Output a pair (X and Y) value 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, unc>& u)
+} // 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);
 
 /*! 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.
@@ -231,14 +283,20 @@
 template <class T>
 double value_of(T v);
 
-template <class T> //!< \tparam value type convertible to double.
+template <class T> //!< \tparam T value type convertible to double.
 double value_of(T v)
 { //! \return value as a double.
   return double(v);
 }
 
 template<>
-double value_of(unc v)
+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();
 }
@@ -255,8 +313,9 @@
   return float(0.);
 }
 
-template<>
-float unc_of(unc v)
+// template<>
+template <bool correlated>
+float unc_of(unc<correlated> v)
 { //! \return unc.uncertainty() as a float. (Can be cast or converted to double without loss of accuracy).
   return v.uncertainty();
 }
@@ -264,7 +323,7 @@
 // Two helper functions to provide values and uncertainties as pairs.
 // Note names plural valueS_of
 
-template <class T> //! \tparam T Built-infloating-point type, float, double, long double or unc.
+template <class T> //! \tparam T Built-in floating-point type, float, double, long double or unc.
 std::pair<double, double> values_of(T); //!< Get double values of a pair of values.
 
 template <class T> //! \tparam T Built-infloating-point type, float, double, long double or unc.
@@ -273,19 +332,20 @@
   return std::make_pair(value_of(vp.first), value_of(vp.second));
 }
 
+/* already defined
 template <class T> //! \tparam T Builtin-floating point type or unc.
-std::pair<double, double> values_of(std::pair<const unc, unc> up)
-{ //! \return value (part) as a pair of doubles.
- /* \noteso can write
- @c std::pair<const double, double> minmax = value_of(*result.first); // x min & max
- whether T is double 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;
 }
+*/
 
 template <class T>
 std::pair<double, double> values_of(std::pair<T, T> vp)
@@ -293,8 +353,8 @@
   return std::make_pair(value_of(vp.first), value_of(vp.second));
 }
 
-template <class T>
-std::pair<double, double> values_of(std::pair<unc, unc> up)
+template <bool correlated>
+std::pair<double, double> values_of(std::pair<unc<correlated>, unc<correlated> > up)
 { //! \return value (part) as a pair of doubles.
   /* \note so can write
   @c std::pair<const double, double> minmax = value_of(*result.first); // x min & max


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