Skip to content

Commit

Permalink
Improve ulps plot: (#417)
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
jzmaddock authored Aug 11, 2020
1 parent cbd2af2 commit 6d1d467
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 22 deletions.
54 changes: 41 additions & 13 deletions doc/fp_utilities/ulps_plots.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -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<class G>
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
Expand Down
50 changes: 41 additions & 9 deletions include/boost/math/tools/ulps_plot.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<class G>
Expand Down Expand Up @@ -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<PreciseReal>(plot.clip_));
fs << "<circle cx='" << x << "' cy='" << y << "' r='1' fill='" << plot.nan_color_ << "'/>\n";
y = y_scale(static_cast<PreciseReal>(-plot.clip_));
fs << "<circle cx='" << x << "' cy='" << y << "' r='1' fill='" << plot.nan_color_ << "'/>\n";
}
if (plot.clip_ > 0 && static_cast<PreciseReal>(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<PreciseReal>(ulp[j] < 0 ? -plot.clip_ : plot.clip_));
fs << "<circle cx='" << x << "' cy='" << y << "' r='1' fill='" << plot.crop_color_ << "'/>\n";
}
else
{
CoarseReal x = x_scale(plot.coarse_abscissas_[j]);
PreciseReal y = y_scale(static_cast<PreciseReal>(ulp[j]));
fs << "<circle cx='" << x << "' cy='" << y << "' r='1' fill='" << color << "'/>\n";
}
CoarseReal x = x_scale(plot.coarse_abscissas_[j]);
PreciseReal y = y_scale(static_cast<PreciseReal>(ulp[j]));
fs << "<circle cx='" << x << "' cy='" << y << "' r='1' fill='" << color << "'/>\n";
}
}

Expand Down Expand Up @@ -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<class F, typename PreciseReal, typename CoarseReal>
Expand Down Expand Up @@ -409,6 +428,20 @@ ulps_plot<F, PreciseReal, CoarseReal>& ulps_plot<F, PreciseReal, CoarseReal>::fo
return *this;
}

template<class F, typename PreciseReal, typename CoarseReal>
ulps_plot<F, PreciseReal, CoarseReal>& ulps_plot<F, PreciseReal, CoarseReal>::crop_color(std::string const & color)
{
crop_color_ = color;
return *this;
}

template<class F, typename PreciseReal, typename CoarseReal>
ulps_plot<F, PreciseReal, CoarseReal>& ulps_plot<F, PreciseReal, CoarseReal>::nan_color(std::string const & color)
{
nan_color_ = color;
return *this;
}

template<class F, typename PreciseReal, typename CoarseReal>
ulps_plot<F, PreciseReal, CoarseReal>& ulps_plot<F, PreciseReal, CoarseReal>::ulp_envelope(bool write_ulp_envelope)
{
Expand All @@ -431,11 +464,10 @@ void ulps_plot<F, PreciseReal, CoarseReal>::write(std::string const & filename)

template<class F, typename PreciseReal, typename CoarseReal>
ulps_plot<F, PreciseReal, CoarseReal>::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<PreciseReal>::digits10 >= std::numeric_limits<CoarseReal>::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));
Expand Down

0 comments on commit 6d1d467

Please sign in to comment.