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