1 // Copyright Paul A. Bristow 2017, 2018
2 // Copyright John Z. Maddock 2017
4 // Distributed under the Boost Software License, Version 1.0.
5 // (See accompanying file LICENSE_1_0.txt or
6 // copy at http ://www.boost.org/LICENSE_1_0.txt).
8 /*! \brief Graph showing differences of Lambert W function double from nearest representable values.
14 #include <boost/math/special_functions/lambert_w.hpp>
15 using boost::math::lambert_w0
;
16 using boost::math::lambert_wm1
;
17 #include <boost/math/special_functions.hpp>
18 using boost::math::isfinite
;
19 #include <boost/svg_plot/svg_2d_plot.hpp>
20 using namespace boost::svg
;
22 // For higher precision computation of Lambert W.
23 #include <boost/multiprecision/cpp_bin_float.hpp>
24 #include <boost/math/special_functions/next.hpp> // For float_distance.
25 using boost::math::float_distance
;
42 using std::numeric_limits
;
43 #include <cmath> // exp
53 std::cout
<< "Lambert W errors graph." << std::endl
;
54 using boost::multiprecision::cpp_bin_float_50
;
55 using boost::multiprecision::cpp_bin_float_quad
;
57 typedef cpp_bin_float_quad HPT
; // High precision type.
59 using boost::math::float_distance
;
60 using boost::math::policies::precision
;
61 using boost::math::policies::digits10
;
62 using boost::math::policies::digits2
;
63 using boost::math::policies::policy
;
65 std::cout
.precision(std::numeric_limits
<double>::max_digits10
);
69 //] [/lambert_w_graph_1]
71 std::map
<const double, double> w0s
; // Lambert W0 branch values, default double precision, digits2 = 53.
72 std::map
<const double, double> w0s_50
; // Lambert W0 branch values digits2 = 50.
75 int total_distance
= 0;
78 double min_z
= -0.367879; // Close to singularity at -0.3678794411714423215955237701614608727 -exp(-1)
79 //double min_z = 0.06; // Above 0.05 switch point.
83 for (HPT z
= min_z
; z
< max_z
; z
+= step_z
)
85 double zd
= static_cast<double>(z
);
86 double w0d
= lambert_w0(zd
); // double result from same default.
87 HPT w0_best
= lambert_w0
<HPT
>(z
);
88 double w0_best_d
= static_cast<double>(w0_best
); // reference result.
89 // w0s[zd] = (w0d - w0_best_d); // absolute difference.
90 // w0s[z] = 100 * (w0 - w0_best) / w0_best; // difference relative % .
91 w0s
[zd
] = float_distance
<double>(w0d
, w0_best_d
); // difference in bits.
92 double fd
= float_distance
<double>(w0d
, w0_best_d
);
93 int distance
= static_cast<int>(fd
);
94 int abs_distance
= abs(distance
);
96 // std::cout << count << " " << zd << " " << w0d << " " << w0_best_d
97 // << ", Difference = " << w0d - w0_best_d << ", % = " << (w0d - w0_best_d) / w0d << ", Distance = " << distance << std::endl;
99 total_distance
+= abs_distance
;
100 if (abs_distance
> max_distance
)
102 max_distance
= abs_distance
;
106 std::cout
<< "points " << count
<< std::endl
;
107 std::cout
.precision(3);
108 std::cout
<< "max distance " << max_distance
<< ", total distances = " << total_distance
109 << ", mean distance " << (float)total_distance
/ count
<< std::endl
;
111 typedef std::map
<const double, double>::const_iterator Map_Iterator
;
113 /* for (std::map<const double, double>::const_iterator it = w0s.begin(); it != w0s.end(); ++it)
115 std::cout << " " << *(it) << "\n";
118 svg_2d_plot data_plot_0
; // <-0.368, -46> <-0.358, -4> <-0.348, 1>...
120 data_plot_0
.title("Lambert W0 function differences from 'best' for double.")
125 //.legend_font_weight(1)
127 .y_label("W0 difference (bits)")
130 //.xy_values_on(false)
133 .x_major_interval(10.)
134 .y_major_interval(2.)
135 .x_major_grid_on(true)
136 .y_major_grid_on(true)
137 .x_label_font_size(9)
138 .y_label_font_size(9)
141 .y_values_rotation(horizontal
)
142 //.plot_window_on(true)
143 .x_values_precision(3)
144 .y_values_precision(3)
145 .coord_precision(3) // Needed to avoid stepping on curves.
146 //.coord_precision(4) // Needed to avoid stepping on curves.
147 .copyright_holder("Paul A. Bristow")
148 .copyright_date("2018")
149 //.background_border_color(black);
153 data_plot_0
.plot(w0s
, "W0 branch").line_color(red
).shape(none
).line_on(true).bezier_on(false).line_width(0.2);
154 //data_plot.plot(wm1s, "W-1 branch").line_color(blue).shape(none).line_on(true).bezier_on(false).line_width(1);
155 data_plot_0
.write("./lambert_w0_errors_graph");
157 } // end W0 branch plot.
158 { // Repeat for Lambert W-1 branch.
160 std::map
<const double, double> wm1s
; // Lambert W-1 branch values.
161 std::map
<const double, double> wm1s_50
; // Lambert Wm1 branch values digits2 = 50.
163 int max_distance
= 0;
164 int total_distance
= 0;
167 double min_z
= -0.367879; // Close to singularity at -0.3678794411714423215955237701614608727 -exp(-1)
168 //double min_z = 0.06; // Above 0.05 switch point.
169 double max_z
= -0.0001;
170 double step_z
= 0.001;
172 for (HPT z
= min_z
; z
< max_z
; z
+= step_z
)
178 double zd
= static_cast<double>(z
);
179 double wm1d
= lambert_wm1(zd
); // double result from same default.
180 HPT wm1_best
= lambert_wm1
<HPT
>(z
);
181 double wm1_best_d
= static_cast<double>(wm1_best
); // reference result.
182 // wm1s[zd] = (wm1d - wm1_best_d); // absolute difference.
183 // wm1s[z] = 100 * (wm1 - wm1_best) / wm1_best; // difference relative % .
184 wm1s
[zd
] = float_distance
<double>(wm1d
, wm1_best_d
); // difference in bits.
185 double fd
= float_distance
<double>(wm1d
, wm1_best_d
);
186 int distance
= static_cast<int>(fd
);
187 int abs_distance
= abs(distance
);
189 //std::cout << count << " " << zd << " " << wm1d << " " << wm1_best_d
190 // << ", Difference = " << wm1d - wm1_best_d << ", % = " << (wm1d - wm1_best_d) / wm1d << ", Distance = " << distance << std::endl;
192 total_distance
+= abs_distance
;
193 if (abs_distance
> max_distance
)
195 max_distance
= abs_distance
;
200 std::cout
<< "points " << count
<< std::endl
;
201 std::cout
.precision(3);
202 std::cout
<< "max distance " << max_distance
<< ", total distances = " << total_distance
203 << ", mean distance " << (float)total_distance
/ count
<< std::endl
;
205 typedef std::map
<const double, double>::const_iterator Map_Iterator
;
207 /* for (std::map<const double, double>::const_iterator it = wm1s.begin(); it != wm1s.end(); ++it)
209 std::cout << " " << *(it) << "\n";
212 svg_2d_plot data_plot_m1
; // <-0.368, -46> <-0.358, -4> <-0.348, 1>...
214 data_plot_m1
.title("Lambert W-1 function differences from 'best' for double.")
219 //.legend_font_weight(1)
221 .y_label("W-1 difference (bits)")
222 .x_range(-0.39, +0.0001)
224 .x_major_interval(0.1)
225 .y_major_interval(2.)
226 .x_major_grid_on(true)
227 .y_major_grid_on(true)
228 .x_label_font_size(9)
229 .y_label_font_size(9)
232 .y_values_rotation(horizontal
)
233 //.plot_window_on(true)
234 .x_values_precision(3)
235 .y_values_precision(3)
236 .coord_precision(3) // Needed to avoid stepping on curves.
237 //.coord_precision(4) // Needed to avoid stepping on curves.
238 .copyright_holder("Paul A. Bristow")
239 .copyright_date("2018")
240 //.background_border_color(black);
242 data_plot_m1
.plot(wm1s
, "W-1 branch").line_color(darkblue
).shape(none
).line_on(true).bezier_on(false).line_width(0.2);
243 data_plot_m1
.write("./lambert_wm1_errors_graph");
246 catch (std::exception
& ex
)
248 std::cout
<< ex
.what() << std::endl
;
253 //[lambert_w_errors_graph_1_output
254 Lambert W errors graph.
256 max distance 46, total distances = 717, mean distance 0.357
259 max distance 23, total distances = 329, mean distance 0.894
261 //] [/lambert_w_errors_graph_1_output]