From 6d1d46720fbc04952796ad045de90676195621fd Mon Sep 17 00:00:00 2001 From: jzmaddock Date: Tue, 11 Aug 2020 16:44:32 +0100 Subject: [PATCH] Improve ulps plot: (#417) * Improve ulps plot: - Use numeric_limits for precision comparison, plot out of bounds points at the clip boundary so we can still see that they're there. -Add options for colored marks when clipping and NaN. --- doc/fp_utilities/ulps_plots.qbk | 54 +++++++++++++++++++------- include/boost/math/tools/ulps_plot.hpp | 50 +++++++++++++++++++----- 2 files changed, 82 insertions(+), 22 deletions(-) diff --git a/doc/fp_utilities/ulps_plots.qbk b/doc/fp_utilities/ulps_plots.qbk index 76d8e03539..3a6eca5bda 100644 --- a/doc/fp_utilities/ulps_plots.qbk +++ b/doc/fp_utilities/ulps_plots.qbk @@ -18,32 +18,60 @@ public: ulps_plot(F hi_acc_impl, CoarseReal a, CoarseReal b, size_t samples = 10000, bool perturb_abscissas = false, int random_seed = -1); - + // + // Set a clip value to restrict the range of ULP's shown, values outside [-clip,clip] + // will be shown at the clip boundary and in a different color (red by default): + // ulps_plot& clip(PreciseReal clip); - + // + // The width of the SVG: + // ulps_plot& width(int width); - + // + // The color of the condition number envelope: + // ulps_plot& envelope_color(std::string const & color); - + // + // Title: + // ulps_plot& title(std::string const & title); - + // + // Background color: + // ulps_plot& background_color(std::string const & background_color); - + // + // Font color: + // ulps_plot& font_color(std::string const & font_color); - + // + // Sets the color of points which are cropped, or set to an empty + // string to hide them completely (default is "red"): + // + ulps_plot& crop_color(std::string const & font_color); + // + // Set's the color of points where one of the functions returned a NaN, + // or set to an empty string to hide completely (the default): + // + ulps_plot& nan_color(std::string const & font_color); + // + // Show ULP envelope true/false: + // ulps_plot& ulp_envelope(bool write_ulp); - + // + // The number of horizontal/vertical lines to draw: + // ulps_plot& horizontal_lines(int horizontal_lines); - ulps_plot& vertical_lines(int vertical_lines); - + // + // Add a function, and plot color: + // template ulps_plot& add_fn(G g, std::string const & color = "steelblue"); - + // + // Write to stream or file: + // friend std::ostream& operator<<(std::ostream& fs, ulps_plot const & plot) - void write(std::string const & filename) const; - }; } // namespaces diff --git a/include/boost/math/tools/ulps_plot.hpp b/include/boost/math/tools/ulps_plot.hpp index 9a1e004ee8..3d941f4445 100644 --- a/include/boost/math/tools/ulps_plot.hpp +++ b/include/boost/math/tools/ulps_plot.hpp @@ -79,6 +79,10 @@ class ulps_plot { ulps_plot& font_color(std::string const & font_color); + ulps_plot& crop_color(std::string const & color); + + ulps_plot& nan_color(std::string const & color); + ulps_plot& ulp_envelope(bool write_ulp); template @@ -243,15 +247,28 @@ class ulps_plot { { if (isnan(ulp[j])) { - continue; + if(plot.nan_color_ == "") + continue; + CoarseReal x = x_scale(plot.coarse_abscissas_[j]); + PreciseReal y = y_scale(static_cast(plot.clip_)); + fs << "\n"; + y = y_scale(static_cast(-plot.clip_)); + fs << "\n"; } if (plot.clip_ > 0 && static_cast(abs(ulp[j])) > plot.clip_) { - continue; + if (plot.crop_color_ == "") + continue; + CoarseReal x = x_scale(plot.coarse_abscissas_[j]); + PreciseReal y = y_scale(static_cast(ulp[j] < 0 ? -plot.clip_ : plot.clip_)); + fs << "\n"; + } + else + { + CoarseReal x = x_scale(plot.coarse_abscissas_[j]); + PreciseReal y = y_scale(static_cast(ulp[j])); + fs << "\n"; } - CoarseReal x = x_scale(plot.coarse_abscissas_[j]); - PreciseReal y = y_scale(static_cast(ulp[j])); - fs << "\n"; } } @@ -351,6 +368,8 @@ class ulps_plot { std::string title_; std::string background_color_; std::string font_color_; + std::string crop_color_; + std::string nan_color_; }; template @@ -409,6 +428,20 @@ ulps_plot& ulps_plot::fo return *this; } +template +ulps_plot& ulps_plot::crop_color(std::string const & color) +{ + crop_color_ = color; + return *this; +} + +template +ulps_plot& ulps_plot::nan_color(std::string const & color) +{ + nan_color_ = color; + return *this; +} + template ulps_plot& ulps_plot::ulp_envelope(bool write_ulp_envelope) { @@ -431,11 +464,10 @@ void ulps_plot::write(std::string const & filename) template ulps_plot::ulps_plot(F hi_acc_impl, CoarseReal a, CoarseReal b, - size_t samples, bool perturb_abscissas, int random_seed) + size_t samples, bool perturb_abscissas, int random_seed) : crop_color_("red") { - // This fails for heap allocated types like MPFR. - // Got to think on what to do about it. - static_assert(sizeof(PreciseReal) >= sizeof(CoarseReal), "PreciseReal must have larger size than CoarseReal"); + // Use digits10 for this comparison in case the two types have differeing radixes: + static_assert(std::numeric_limits::digits10 >= std::numeric_limits::digits10, "PreciseReal must have higher precision that CoarseReal"); if (samples < 10) { throw std::domain_error("Must have at least 10 samples, samples = " + std::to_string(samples));