• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright Paul A. Bristow 2017
2 // Copyright John Z. Maddock 2017
3 
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).
7 
8 /*! \brief Graph showing use of Lambert W function.
9 
10 \details
11 
12 Both Lambert W0 and W-1 branches can be shown on one graph.
13 But useful to have another graph for larger values of argument z.
14 Need two separate graphs for Lambert W0 and -1 prime because
15 the sensible ranges and axes are too different.
16 
17 One would get too small LambertW0 in top right and W-1 in bottom left.
18 
19 */
20 
21 #include <boost/math/special_functions/lambert_w.hpp>
22 using boost::math::lambert_w0;
23 using boost::math::lambert_wm1;
24 using boost::math::lambert_w0_prime;
25 using boost::math::lambert_wm1_prime;
26 
27 #include <boost/math/special_functions.hpp>
28 using boost::math::isfinite;
29 #include <boost/svg_plot/svg_2d_plot.hpp>
30 using namespace boost::svg;
31 #include <boost/svg_plot/show_2d_settings.hpp>
32 using boost::svg::show_2d_plot_settings;
33 
34 #include <iostream>
35 // using std::cout;
36 // using std::endl;
37 #include <exception>
38 #include <stdexcept>
39 #include <string>
40 #include <array>
41 #include <vector>
42 #include <utility>
43 using std::pair;
44 #include <map>
45 using std::map;
46 #include <set>
47 using std::multiset;
48 #include <limits>
49 using std::numeric_limits;
50 #include <cmath> //
51 
52   /*!
53   */
main()54 int main()
55 {
56   try
57   {
58     std::cout << "Lambert W graph example." << std::endl;
59 
60 //[lambert_w_graph_1
61 //] [/lambert_w_graph_1]
62     {
63       std::map<const double, double> wm1s;   // Lambert W-1 branch values.
64       std::map<const double, double> w0s;   // Lambert W0 branch values.
65 
66       std::cout.precision(std::numeric_limits<double>::max_digits10);
67 
68       int count = 0;
69       for (double z = -0.36787944117144232159552377016146086744581113103176804; z < 2.8; z += 0.001)
70       {
71         double w0 = lambert_w0(z);
72         w0s[z] = w0;
73    //     std::cout << "z " << z << ", w = " << w0 << std::endl;
74         count++;
75       }
76       std::cout << "points " << count << std::endl;
77 
78       count = 0;
79       for (double z = -0.3678794411714423215955237701614608727; z < -0.001; z += 0.001)
80       {
81         double wm1 = lambert_wm1(z);
82         wm1s[z] = wm1;
83         count++;
84       }
85       std::cout << "points " << count << std::endl;
86 
87       svg_2d_plot data_plot;
88       data_plot.title("Lambert W function.")
89         .x_size(400)
90         .y_size(300)
91         .legend_on(true)
92         .legend_lines(true)
93         .x_label("z")
94         .y_label("W")
95         .x_range(-1, 3.)
96         .y_range(-4., +1.)
97         .x_major_interval(1.)
98         .y_major_interval(1.)
99         .x_major_grid_on(true)
100         .y_major_grid_on(true)
101         //.x_values_on(true)
102         //.y_values_on(true)
103         .y_values_rotation(horizontal)
104         //.plot_window_on(true)
105         .x_values_precision(3)
106         .y_values_precision(3)
107         .coord_precision(4) // Needed to avoid stepping on curves.
108         .copyright_holder("Paul A. Bristow")
109         .copyright_date("2018")
110         //.background_border_color(black);
111         ;
112       data_plot.plot(w0s, "W0 branch").line_color(red).shape(none).line_on(true).bezier_on(false).line_width(1);
113       data_plot.plot(wm1s, "W-1 branch").line_color(blue).shape(none).line_on(true).bezier_on(false).line_width(1);
114       data_plot.write("./lambert_w_graph");
115 
116       show_2d_plot_settings(data_plot); // For plot diagnosis only.
117 
118     } // small z Lambert W
119 
120     {  // bigger argument z Lambert W
121 
122       std::map<const double, double> w0s_big;   // Lambert W0 branch values for large z and W.
123       std::map<const double, double> wm1s_big;   // Lambert W-1 branch values for small z and large -W.
124       int count = 0;
125       for (double z = -0.3678794411714423215955237701614608727; z < 10000.; z += 50.)
126       {
127         double w0 = lambert_w0(z);
128         w0s_big[z] = w0;
129         count++;
130       }
131       std::cout << "points " << count << std::endl;
132 
133       count = 0;
134       for (double z = -0.3678794411714423215955237701614608727; z < -0.001; z += 0.001)
135       {
136         double wm1 = lambert_wm1(z);
137         wm1s_big[z] = wm1;
138         count++;
139       }
140      std::cout << "Lambert W0 large z argument points = " << count << std::endl;
141 
142      svg_2d_plot data_plot2;
143      data_plot2.title("Lambert W0 function for larger z.")
144       .x_size(400)
145       .y_size(300)
146       .legend_on(false)
147       .x_label("z")
148       .y_label("W")
149       //.x_label_on(true)
150       //.y_label_on(true)
151       //.xy_values_on(false)
152       .x_range(-1, 10000.)
153       .y_range(-1., +8.)
154       .x_major_interval(2000.)
155       .y_major_interval(1.)
156       .x_major_grid_on(true)
157       .y_major_grid_on(true)
158       //.x_values_on(true)
159       //.y_values_on(true)
160       .y_values_rotation(horizontal)
161       //.plot_window_on(true)
162       .x_values_precision(3)
163       .y_values_precision(3)
164       .coord_precision(4) // Needed to avoid stepping on curves.
165       .copyright_holder("Paul A. Bristow")
166       .copyright_date("2018")
167       //.background_border_color(black);
168     ;
169 
170     data_plot2.plot(w0s_big, "W0 branch").line_color(red).shape(none).line_on(true).bezier_on(false).line_width(1);
171     // data_plot2.plot(wm1s_big, "W-1 branch").line_color(blue).shape(none).line_on(true).bezier_on(false).line_width(1);
172     // This wouldn't show anything useful.
173     data_plot2.write("./lambert_w_graph_big_w");
174    } // Big argument z Lambert W
175 
176     { //  Lambert W0 Derivative plots
177 
178     //  std::map<const double, double> wm1ps;   // Lambert W-1 prime branch values.
179       std::map<const double, double> w0ps;   // Lambert W0 prime branch values.
180 
181       std::cout.precision(std::numeric_limits<double>::max_digits10);
182 
183       int count = 0;
184       for (double z = -0.36; z < 3.; z += 0.001)
185       {
186         double w0p = lambert_w0_prime(z);
187         w0ps[z] = w0p;
188         // std::cout << "z " << z << ", w0 = " << w0 << std::endl;
189         count++;
190       }
191       std::cout << "points " << count << std::endl;
192 
193       //count = 0;
194       //for (double z = -0.36; z < -0.1; z += 0.001)
195       //{
196       //  double wm1p = lambert_wm1_prime(z);
197       //  std::cout << "z " << z << ", w-1 = " << wm1p << std::endl;
198       //  wm1ps[z] = wm1p;
199       //  count++;
200       //}
201       //std::cout << "points " << count << std::endl;
202 
203       svg_2d_plot data_plotp;
204       data_plotp.title("Lambert W0 prime function.")
205         .x_size(400)
206         .y_size(300)
207         .legend_on(false)
208         .x_label("z")
209         .y_label("W0'")
210         .x_range(-0.3, +1.)
211         .y_range(0., +5.)
212         .x_major_interval(0.2)
213         .y_major_interval(2.)
214         .x_major_grid_on(true)
215         .y_major_grid_on(true)
216         .y_values_rotation(horizontal)
217         .x_values_precision(3)
218         .y_values_precision(3)
219         .coord_precision(4) // Needed to avoid stepping on curves.
220         .copyright_holder("Paul A. Bristow")
221         .copyright_date("2018")
222         ;
223 
224       // derivative of N[productlog(0, x), 55]  at x=0 to 10
225       // Plot[D[N[ProductLog[0, x], 55], x], {x, 0, 10}]
226       // Plot[ProductLog[x]/(x + x ProductLog[x]), {x, 0, 10}]
227       data_plotp.plot(w0ps, "W0 prime branch").line_color(red).shape(none).line_on(true).bezier_on(false).line_width(1);
228       data_plotp.write("./lambert_w0_prime_graph");
229   } // Lambert W0 Derivative plots
230 
231     { //  Lambert Wm1 Derivative plots
232 
233     std::map<const double, double> wm1ps;   // Lambert W-1 prime branch values.
234 
235     std::cout.precision(std::numeric_limits<double>::max_digits10);
236 
237     int count = 0;
238     for (double z = -0.3678; z < -0.00001; z += 0.001)
239     {
240       double wm1p = lambert_wm1_prime(z);
241       // std::cout << "z " << z << ", w-1 = " << wm1p << std::endl;
242       wm1ps[z] = wm1p;
243       count++;
244     }
245     std::cout << "Lambert W-1 prime points = " << count << std::endl;
246 
247     svg_2d_plot data_plotp;
248     data_plotp.title("Lambert W-1 prime function.")
249       .x_size(400)
250       .y_size(300)
251       .legend_on(false)
252       .x_label("z")
253       .y_label("W-1'")
254       .x_range(-0.4, +0.01)
255       .x_major_interval(0.1)
256       .y_range(-20., -5.)
257       .y_major_interval(5.)
258       .x_major_grid_on(true)
259       .y_major_grid_on(true)
260       .y_values_rotation(horizontal)
261       .x_values_precision(3)
262       .y_values_precision(3)
263       .coord_precision(4) // Needed to avoid stepping on curves.
264       .copyright_holder("Paul A. Bristow")
265       .copyright_date("2018")
266       ;
267 
268       // derivative of N[productlog(0, x), 55]  at x=0 to 10
269       // Plot[D[N[ProductLog[0, x], 55], x], {x, 0, 10}]
270       // Plot[ProductLog[x]/(x + x ProductLog[x]), {x, 0, 10}]
271       data_plotp.plot(wm1ps, "W-1 prime branch").line_color(blue).shape(none).line_on(true).bezier_on(false).line_width(1);
272       data_plotp.write("./lambert_wm1_prime_graph");
273     } // Lambert W-1 prime graph
274  } // try
275   catch (std::exception& ex)
276   {
277     std::cout << ex.what() << std::endl;
278   }
279 }  // int main()
280 
281    /*
282 
283    //[lambert_w_graph_1_output
284 
285    //] [/lambert_w_graph_1_output]
286    */
287