[system] / trunk / pg / macros / PGgraphmacros.pl Repository:
ViewVC logotype

Diff of /trunk/pg/macros/PGgraphmacros.pl

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 1050 Revision 1080
1#!/usr/local/bin/webwork-perl 1
2 2
3=head1 NAME 3=head1 NAME
4 4
5 PGgraphmacros -- in courseScripts directory 5 PGgraphmacros -- in courseScripts directory
6 6
26 26
27=cut 27=cut
28 28
29=head2 Other constructs 29=head2 Other constructs
30 30
31See F<PGbasicmacros> for definitions of C<image> and C<caption> 31See F<PGbasicmacros> for definitions of C<image> and C<caption>
32 32
33=cut 33=cut
34 34
35 35
36#my $User = $main::studentLogin; 36#my $User = $main::studentLogin;
49 49
50my %images_created = (); # this keeps track of the base names of the images created during this session. 50my %images_created = (); # this keeps track of the base names of the images created during this session.
51 # We tack on 51 # We tack on
52 # $imageNum = ++$images_created{$imageName} to keep from overwriting files 52 # $imageNum = ++$images_created{$imageName} to keep from overwriting files
53 # when we don't want to. 53 # when we don't want to.
54
55 54
56 55
57 56
57
58=head2 init_graph 58=head2 init_graph
59 59
60=pod 60=pod
61 61
62 $graphObject = init_graph(xmin,ymin,xmax,ymax,'ticks'=>[4,4],'axes'=>[0,0]) 62 $graphObject = init_graph(xmin,ymin,xmax,ymax,'ticks'=>[4,4],'axes'=>[0,0])
63 options are 63 options are
64 'grid' =>[8,8] or 64 'grid' =>[8,8] or
65 # there are 8 evenly spaced lines intersecting the horizontal axis 65 # there are 8 evenly spaced lines intersecting the horizontal axis
66 'ticks'=>[8,8] and/or 66 'ticks'=>[8,8] and/or
67 # there are 8 ticks on the horizontal axis, 8 on the vertical 67 # there are 8 ticks on the horizontal axis, 8 on the vertical
68 'axes' => [0,0] 68 'axes' => [0,0]
69 # axes pass through the point (0,0) in real coordinates 69 # axes pass through the point (0,0) in real coordinates
70 'size' => [200,200] 70 'size' => [200,200]
71 # dimensions of the graph in pixels. 71 # dimensions of the graph in pixels.
72 'pixels' =>[200,200] # synonym for size 72 'pixels' =>[200,200] # synonym for size
73 73
74Creates a graph object with the default size 200 by 200 pixels. 74Creates a graph object with the default size 200 by 200 pixels.
75If you want axes or grids you need to specify them in options. But the default values can be selected for you. 75If you want axes or grids you need to specify them in options. But the default values can be selected for you.
76 76
77 77
78=cut 78=cut
79BEGIN { 79BEGIN {
85} 85}
86#sub _PGgraphmacros_export { 86#sub _PGgraphmacros_export {
87# 87#
88# my @EXPORT = ( 88# my @EXPORT = (
89# '&init_graph', '&add_functions', '&plot_functions', '&open_circle', 89# '&init_graph', '&add_functions', '&plot_functions', '&open_circle',
90# '&closed_circle', '&my_math_constants', '&string_to_sub', 90# '&closed_circle', '&my_math_constants', '&string_to_sub',
91# ); 91# );
92# @EXPORT; 92# @EXPORT;
93#} 93#}
94 94
95sub init_graph { 95sub init_graph {
107 my $imageName = "$main::studentLogin-$main::psvnNumber-set${main::setNumber}prob${main::probNum}"; 107 my $imageName = "$main::studentLogin-$main::psvnNumber-set${main::setNumber}prob${main::probNum}";
108 # $imageNum counts the number of graphs with this name which have been created since PGgraphmacros.pl was initiated. 108 # $imageNum counts the number of graphs with this name which have been created since PGgraphmacros.pl was initiated.
109 my $imageNum = ++$main::images_created{$imageName}; 109 my $imageNum = ++$main::images_created{$imageName};
110 # this provides a unique name for the graph -- it does not include an extension. 110 # this provides a unique name for the graph -- it does not include an extension.
111 $graphRef->imageName("${imageName}image${imageNum}"); 111 $graphRef->imageName("${imageName}image${imageNum}");
112 112
113 $graphRef->xmin($xmin) if defined($xmin); 113 $graphRef->xmin($xmin) if defined($xmin);
114 $graphRef->xmax($xmax) if defined($xmax); 114 $graphRef->xmax($xmax) if defined($xmax);
115 $graphRef->ymin($ymin) if defined($ymin); 115 $graphRef->ymin($ymin) if defined($ymin);
116 $graphRef->ymax($ymax) if defined($ymax); 116 $graphRef->ymax($ymax) if defined($ymax);
117 my $x_delta = ($graphRef->xmax - $graphRef->xmin)/8; 117 my $x_delta = ($graphRef->xmax - $graphRef->xmin)/8;
130 } 130 }
131 $graphRef->v_grid('gray',@x_values); 131 $graphRef->v_grid('gray',@x_values);
132 $graphRef->h_grid('gray',@y_values); 132 $graphRef->h_grid('gray',@y_values);
133 $graphRef->lb(new Label($x_delta,0,sprintf("%1.1f",$x_delta),'black','center','middle')); 133 $graphRef->lb(new Label($x_delta,0,sprintf("%1.1f",$x_delta),'black','center','middle'));
134 $graphRef->lb(new Label(0,$y_delta,sprintf("%1.1f",$y_delta),'black','center','middle')); 134 $graphRef->lb(new Label(0,$y_delta,sprintf("%1.1f",$y_delta),'black','center','middle'));
135 135
136 $graphRef->lb(new Label($xmax,0,$xmax,'black','right')); 136 $graphRef->lb(new Label($xmax,0,$xmax,'black','right'));
137 $graphRef->lb(new Label($xmin,0,$xmin,'black','left')); 137 $graphRef->lb(new Label($xmin,0,$xmin,'black','left'));
138 $graphRef->lb(new Label(0,$ymax,$ymax,'black','top')); 138 $graphRef->lb(new Label(0,$ymax,$ymax,'black','top'));
139 $graphRef->lb(new Label(0,$ymin,$ymin,'black','bottom','right')); 139 $graphRef->lb(new Label(0,$ymin,$ymin,'black','bottom','right'));
140 140
141 } elsif ($options{ticks}) { # draw ticks -- grid over rides ticks 141 } elsif ($options{ticks}) { # draw ticks -- grid over rides ticks
142 my $xdiv = ${$options{ticks}}[0]? ${$options{ticks}}[0] : 8; # number of ticks (8 is default) 142 my $xdiv = ${$options{ticks}}[0]? ${$options{ticks}}[0] : 8; # number of ticks (8 is default)
143 my $ydiv = ${$options{ticks}}[1]? ${$options{ticks}}[1] : 8; 143 my $ydiv = ${$options{ticks}}[1]? ${$options{ticks}}[1] : 8;
144 my $x_delta = ($graphRef->xmax - $graphRef->xmin)/$xdiv; 144 my $x_delta = ($graphRef->xmax - $graphRef->xmin)/$xdiv;
145 my $y_delta = ($graphRef->ymax - $graphRef->ymin)/$ydiv; 145 my $y_delta = ($graphRef->ymax - $graphRef->ymin)/$ydiv;
152 } 152 }
153 $graphRef->v_ticks(0,'black',@x_values); 153 $graphRef->v_ticks(0,'black',@x_values);
154 $graphRef->h_ticks(0,'black',@y_values); 154 $graphRef->h_ticks(0,'black',@y_values);
155 $graphRef->lb(new Label($x_delta,0,$x_delta,'black','right')); 155 $graphRef->lb(new Label($x_delta,0,$x_delta,'black','right'));
156 $graphRef->lb(new Label(0,$y_delta,$y_delta,'black','top')); 156 $graphRef->lb(new Label(0,$y_delta,$y_delta,'black','top'));
157 157
158 $graphRef->lb(new Label($xmax,0,$xmax,'black','right')); 158 $graphRef->lb(new Label($xmax,0,$xmax,'black','right'));
159 $graphRef->lb(new Label($xmin,0,$xmin,'black','left')); 159 $graphRef->lb(new Label($xmin,0,$xmin,'black','left'));
160 $graphRef->lb(new Label(0,$ymax,$ymax,'black','top')); 160 $graphRef->lb(new Label(0,$ymax,$ymax,'black','top'));
161 $graphRef->lb(new Label(0,$ymin,$ymin,'black','bottom','right')); 161 $graphRef->lb(new Label(0,$ymin,$ymin,'black','bottom','right'));
162 } 162 }
163 163
164 if ($options{axes}) { # draw axis 164 if ($options{axes}) { # draw axis
165 my $ra_axes = $options{axes}; 165 my $ra_axes = $options{axes};
166 $graphRef->h_axis($ra_axes->[1],'black'); 166 $graphRef->h_axis($ra_axes->[1],'black');
167 $graphRef->v_axis($ra_axes->[0],'black'); 167 $graphRef->v_axis($ra_axes->[0],'black');
168 } 168 }
169 169
170 170
171 $graphRef; 171 $graphRef;
172} 172}
173 173
174sub init_graph_no_labels { 174sub init_graph_no_labels {
175 my ($xmin,$ymin,$xmax,$ymax,%options) = @_; 175 my ($xmin,$ymin,$xmax,$ymax,%options) = @_;
186 my $imageName = "$main::studentLogin-$main::psvnNumber-set${main::setNumber}prob${main::probNum}"; 186 my $imageName = "$main::studentLogin-$main::psvnNumber-set${main::setNumber}prob${main::probNum}";
187 # $imageNum counts the number of graphs with this name which have been created since PGgraphmacros.pl was initiated. 187 # $imageNum counts the number of graphs with this name which have been created since PGgraphmacros.pl was initiated.
188 my $imageNum = ++$main::images_created{$imageName}; 188 my $imageNum = ++$main::images_created{$imageName};
189 # this provides a unique name for the graph -- it does not include an extension. 189 # this provides a unique name for the graph -- it does not include an extension.
190 $graphRef->imageName("${imageName}image${imageNum}"); 190 $graphRef->imageName("${imageName}image${imageNum}");
191 191
192 $graphRef->xmin($xmin) if defined($xmin); 192 $graphRef->xmin($xmin) if defined($xmin);
193 $graphRef->xmax($xmax) if defined($xmax); 193 $graphRef->xmax($xmax) if defined($xmax);
194 $graphRef->ymin($ymin) if defined($ymin); 194 $graphRef->ymin($ymin) if defined($ymin);
195 $graphRef->ymax($ymax) if defined($ymax); 195 $graphRef->ymax($ymax) if defined($ymax);
196 my $x_delta = ($graphRef->xmax - $graphRef->xmin)/8; 196 my $x_delta = ($graphRef->xmax - $graphRef->xmin)/8;
211 $graphRef->h_grid('gray',@y_values); 211 $graphRef->h_grid('gray',@y_values);
212 #$graphRef->lb(new Label($x_delta,0,sprintf("%1.1f",$x_delta),'black','center','top')); 212 #$graphRef->lb(new Label($x_delta,0,sprintf("%1.1f",$x_delta),'black','center','top'));
213 #$graphRef->lb(new Label($x_delta,0,"|",'black','center','middle')); 213 #$graphRef->lb(new Label($x_delta,0,"|",'black','center','middle'));
214 #$graphRef->lb(new Label(0,$y_delta,sprintf("%1.1f ",$y_delta),'black','right','middle')); 214 #$graphRef->lb(new Label(0,$y_delta,sprintf("%1.1f ",$y_delta),'black','right','middle'));
215 #$graphRef->lb(new Label(0,$y_delta,"-",'black','center','middle')); 215 #$graphRef->lb(new Label(0,$y_delta,"-",'black','center','middle'));
216 216
217 217
218 $graphRef->lb(new Label($xmax,0,$xmax,'black','right')); 218 $graphRef->lb(new Label($xmax,0,$xmax,'black','right'));
219 $graphRef->lb(new Label($xmin,0,$xmin,'black','left')); 219 $graphRef->lb(new Label($xmin,0,$xmin,'black','left'));
220 $graphRef->lb(new Label(0,$ymax,$ymax,'black','top','right')); 220 $graphRef->lb(new Label(0,$ymax,$ymax,'black','top','right'));
221 $graphRef->lb(new Label(0,$ymin,$ymin,'black','bottom','right')); 221 $graphRef->lb(new Label(0,$ymin,$ymin,'black','bottom','right'));
222 222
223 } elsif ($options{ticks}) { # draw ticks -- grid over rides ticks 223 } elsif ($options{ticks}) { # draw ticks -- grid over rides ticks
224 my $xdiv = ${$options{ticks}}[0]? ${$options{ticks}}[0] : 8; # number of ticks (8 is default) 224 my $xdiv = ${$options{ticks}}[0]? ${$options{ticks}}[0] : 8; # number of ticks (8 is default)
225 my $ydiv = ${$options{ticks}}[1]? ${$options{ticks}}[1] : 8; 225 my $ydiv = ${$options{ticks}}[1]? ${$options{ticks}}[1] : 8;
226 my $x_delta = ($graphRef->xmax - $graphRef->xmin)/$xdiv; 226 my $x_delta = ($graphRef->xmax - $graphRef->xmin)/$xdiv;
227 my $y_delta = ($graphRef->ymax - $graphRef->ymin)/$ydiv; 227 my $y_delta = ($graphRef->ymax - $graphRef->ymin)/$ydiv;
234 } 234 }
235 $graphRef->v_ticks(0,'black',@x_values); 235 $graphRef->v_ticks(0,'black',@x_values);
236 $graphRef->h_ticks(0,'black',@y_values); 236 $graphRef->h_ticks(0,'black',@y_values);
237 $graphRef->lb(new Label($x_delta,0,$x_delta,'black','right')); 237 $graphRef->lb(new Label($x_delta,0,$x_delta,'black','right'));
238 $graphRef->lb(new Label(0,$y_delta,$y_delta,'black','top')); 238 $graphRef->lb(new Label(0,$y_delta,$y_delta,'black','top'));
239 239
240 $graphRef->lb(new Label($xmax,0,$xmax,'black','right')); 240 $graphRef->lb(new Label($xmax,0,$xmax,'black','right'));
241 $graphRef->lb(new Label($xmin,0,$xmin,'black','left')); 241 $graphRef->lb(new Label($xmin,0,$xmin,'black','left'));
242 $graphRef->lb(new Label(0,$ymax,$ymax,'black','top')); 242 $graphRef->lb(new Label(0,$ymax,$ymax,'black','top'));
243 $graphRef->lb(new Label(0,$ymin,$ymin,'black','bottom','right')); 243 $graphRef->lb(new Label(0,$ymin,$ymin,'black','bottom','right'));
244 } 244 }
245 245
246 if ($options{axes}) { # draw axis 246 if ($options{axes}) { # draw axis
247 my $ra_axes = $options{axes}; 247 my $ra_axes = $options{axes};
248 $graphRef->h_axis($ra_axes->[1],'black'); 248 $graphRef->h_axis($ra_axes->[1],'black');
249 $graphRef->v_axis($ra_axes->[0],'black'); 249 $graphRef->v_axis($ra_axes->[0],'black');
250 } 250 }
251 251
252 252
253 $graphRef; 253 $graphRef;
254} 254}
255 255
256 256
257 257
259 259
260=pod 260=pod
261 261
262 Usage: ($f1, $f2, $f3) = plot_functions($graph, $f1, $f2, $f3); 262 Usage: ($f1, $f2, $f3) = plot_functions($graph, $f1, $f2, $f3);
263 Synonym: add_functions($graph,$f1,$f2,$f3); 263 Synonym: add_functions($graph,$f1,$f2,$f3);
264 264
265Where $f1 is a string of the form 265Where $f1 is a string of the form
266 266
267 $f1 = qq! x^2 - 3*x + 45 for x in [0, 45) using color:red and weight:2! 267 $f1 = qq! x^2 - 3*x + 45 for x in [0, 45) using color:red and weight:2!
268 268
269The phrase translates as: formula B<for> variable B<in> interval B<using> option-list. 269The phrase translates as: formula B<for> variable B<in> interval B<using> option-list.
270The option-list contains pairs of the form attribute:value. 270The option-list contains pairs of the form attribute:value.
271The default for color is "default_color" which is usually black. 271The default for color is "default_color" which is usually black.
272The default for the weight (pixel width) of the pen is 2 pixels. 272The default for the weight (pixel width) of the pen is 2 pixels.
273 273
274The string_to_sub subroutine is used to translate the formula into a subroutine. 274The string_to_sub subroutine is used to translate the formula into a subroutine.
275 275
276The functions in the list are installed in the graph object $graph and will appear when the graph object is next drawn. 276The functions in the list are installed in the graph object $graph and will appear when the graph object is next drawn.
277 277
278=cut 278=cut
279 279
291 foreach $fn (@function_list) { 291 foreach $fn (@function_list) {
292 292
293 # model: "2.5-x^2 for x in <-1,0> using color:red and weight:2" 293 # model: "2.5-x^2 for x in <-1,0> using color:red and weight:2"
294 if ($fn =~ /^(.+)for\s*(\w+)\s*in\s*([\(\[\<])\s*([\d\.\-]+)\s*,\s*([\d\.\-]+)\s*([\)\]\>])\s*using\s*(.*)$/ ) { 294 if ($fn =~ /^(.+)for\s*(\w+)\s*in\s*([\(\[\<])\s*([\d\.\-]+)\s*,\s*([\d\.\-]+)\s*([\)\]\>])\s*using\s*(.*)$/ ) {
295 my ($rule,$var, $left_br, $left_end, $right_end, $right_br, $options)= ($1, $2, $3, $4, $5, $6, $7); 295 my ($rule,$var, $left_br, $left_end, $right_end, $right_br, $options)= ($1, $2, $3, $4, $5, $6, $7);
296 296
297 my %options = split( /\s*and\s*|\s*:\s*|\s*,\s*|\s*=\s*|\s+/,$options); 297 my %options = split( /\s*and\s*|\s*:\s*|\s*,\s*|\s*=\s*|\s+/,$options);
298 my ($color, $weight); 298 my ($color, $weight);
299 if ( defined($options{'color'}) ){ 299 if ( defined($options{'color'}) ){
300 $color = $options{'color'}; #set pen color 300 $color = $options{'color'}; #set pen color
301 } else { 301 } else {
302 $color = 'default_color'; 302 $color = 'default_color';
303 } 303 }
304 if ( defined($options{'weight'}) ) { 304 if ( defined($options{'weight'}) ) {
305 $weight = $options{'weight'}; # set pen weight (width in pixels) 305 $weight = $options{'weight'}; # set pen weight (width in pixels)
306 } else { 306 } else {
307 $weight =2; 307 $weight =2;
308 } 308 }
309 309
310 my $subRef = string_to_sub($rule,$var); 310 my $subRef = string_to_sub($rule,$var);
311 my $funRef = new Fun($subRef,$graph); 311 my $funRef = new Fun($subRef,$graph);
312 $funRef->color($color); 312 $funRef->color($color);
313 $funRef->weight($weight); 313 $funRef->weight($weight);
314 $funRef->domain($left_end , $right_end); 314 $funRef->domain($left_end , $right_end);
316 # place open (1,3) or closed (1,3) circle at the endpoints or do nothing <1,3> 316 # place open (1,3) or closed (1,3) circle at the endpoints or do nothing <1,3>
317 if ($left_br eq '[' ) { 317 if ($left_br eq '[' ) {
318 $graph->stamps(closed_circle($left_end,&$subRef($left_end),$color) ); 318 $graph->stamps(closed_circle($left_end,&$subRef($left_end),$color) );
319 } elsif ($left_br eq '(' ) { 319 } elsif ($left_br eq '(' ) {
320 $graph->stamps(open_circle($left_end, &$subRef($left_end), $color) ); 320 $graph->stamps(open_circle($left_end, &$subRef($left_end), $color) );
321 } 321 }
322 if ($right_br eq ']' ) { 322 if ($right_br eq ']' ) {
323 $graph->stamps(closed_circle($right_end,&$subRef($right_end),$color) ); 323 $graph->stamps(closed_circle($right_end,&$subRef($right_end),$color) );
324 } elsif ($right_br eq ')' ) { 324 } elsif ($right_br eq ')' ) {
325 $graph->stamps(open_circle($right_end, &$subRef($right_end), $color) ); 325 $graph->stamps(open_circle($right_end, &$subRef($right_end), $color) );
326 } 326 }
327 327
328 } else { 328 } else {
329 $error .= "Error in parsing: $fn $main::BR"; 329 $error .= "Error in parsing: $fn $main::BR";
330 } 330 }
331 331
332 } 332 }
333 die ("Error in plot_functions: \n\t $error ") if $error; 333 die ("Error in plot_functions: \n\t $error ") if $error;
334 @functions; # return function references unless there is an error. 334 @functions; # return function references unless there is an error.
335} 335}
336 336
337=head2 insertGraph 337=head2 insertGraph
338 338
339 $filePath = insertGraph(graphObject); 339 $filePath = insertGraph(graphObject);
340 returns a path to the file containing the graph image. 340 returns a path to the file containing the graph image.
341 341
342B<Note:> Because insertGraph involves writing to the disk, it is actually defined in dangerousMacros.pl. 342B<Note:> Because insertGraph involves writing to the disk, it is actually defined in dangerousMacros.pl.
343 343
344insertGraph(graphObject) writes a image file to the C<html/tmp/gif> directory of the current course. 344insertGraph(graphObject) writes a image file to the C<html/tmp/gif> directory of the current course.
345The file name is obtained from the graphObject. Warnings are issued if errors occur while writing to 345The file name is obtained from the graphObject. Warnings are issued if errors occur while writing to
346the file. 346the file.
347 347
348The permissions and ownership of the file are controlled by C<$main::tmp_file_permission> 348The permissions and ownership of the file are controlled by C<$main::tmp_file_permission>
349and C<$main::numericalGroupID>. 349and C<$main::numericalGroupID>.
350 350
351B<Returns:> A string containing the full path to the temporary file containing the image. 351B<Returns:> A string containing the full path to the temporary file containing the image.
353 353
354 354
355InsertGraph draws the object $graph, stores it in "${tempDirectory}gif/$imageName.gif (or .png)" where 355InsertGraph draws the object $graph, stores it in "${tempDirectory}gif/$imageName.gif (or .png)" where
356the $imageName is obtained from the graph object. ConvertPath and surePathToTmpFile are used to insure 356the $imageName is obtained from the graph object. ConvertPath and surePathToTmpFile are used to insure
357that the correct directory separators are used for the platform and that the necessary directories 357that the correct directory separators are used for the platform and that the necessary directories
358are created if they are not already present. The directory address to the file is the result. 358are created if they are not already present. The directory address to the file is the result.
359 359
360The most common use of C,insertGraph> is 360The most common use of C,insertGraph> is
361 361
362 TEXT(image(insertGraph($graph)) ); 362 TEXT(image(insertGraph($graph)) );
363 363
365 365
366Another common usage is: 366Another common usage is:
367 367
368 TEXT(htmlLink( alias(insertGraph($graph), "picture" ) ) ); 368 TEXT(htmlLink( alias(insertGraph($graph), "picture" ) ) );
369 369
370which inserts the URL pointing to the picture. 370which inserts the URL pointing to the picture.
371alias converts the directory address to a URL when serving HTML pages and insures that 371alias converts the directory address to a URL when serving HTML pages and insures that
372an eps file is generated when creating TeX code for downloading. (Image, automatically applies alias to its input 372an eps file is generated when creating TeX code for downloading. (Image, automatically applies alias to its input
373in order to obtain the URL.) 373in order to obtain the URL.)
374 374
375See the documentation in F<dangerousMacros.pl> for the latest details. 375See the documentation in F<dangerousMacros.pl> for the latest details.
376 376
379=head2 'Circle' lables 379=head2 'Circle' lables
380 380
381 Usage: $circle_object = open_circle( $x_position, $y_position, $color ); 381 Usage: $circle_object = open_circle( $x_position, $y_position, $color );
382 $circle_object2 = closed_circle( $x_position, $y_position, $color ); 382 $circle_object2 = closed_circle( $x_position, $y_position, $color );
383 383
384Creates a small open (resp. filled in or closed) circle for use as a stamp in marking graphs. 384Creates a small open (resp. filled in or closed) circle for use as a stamp in marking graphs.
385For example 385For example
386 386
387 $graph -> stamps($circle_object2); # puts a filled dot at $x_position, $y_position 387 $graph -> stamps($circle_object2); # puts a filled dot at $x_position, $y_position
388 388
389=cut 389=cut
410 410
411 411
412 Usage: $string = my_math_constants($string) 412 Usage: $string = my_math_constants($string)
413 $subroutine_reference = my_string_to_sub($string) 413 $subroutine_reference = my_string_to_sub($string)
414 414
415C<my_math_constants> 415C<my_math_constants>
416interprets pi, e as mathematical constants 3.1415926... and 2.71828... respectively. (Case is important). 416interprets pi, e as mathematical constants 3.1415926... and 2.71828... respectively. (Case is important).
417The power operator ^ is replaced by ** to conform with perl constructs 417The power operator ^ is replaced by ** to conform with perl constructs
418 418
419C<string_to_sub> 419C<string_to_sub>
420converts a string defining a single perl arithmetic expression with independent variable $XVAR into a subroutine. 420converts a string defining a single perl arithmetic expression with independent variable $XVAR into a subroutine.
421The string is first filtered through C<my_math_macros>. The resulting subroutine 421The string is first filtered through C<my_math_macros>. The resulting subroutine
422takes a single real number as input and produces a single output value. 422takes a single real number as input and produces a single output value.
423 423
424=cut 424=cut
425 425
426sub my_math_constants { 426sub my_math_constants {
427 my($in) = @_; 427 my($in) = @_;
428 $in =~s/\bpi\b/(4*atan2(1,1))/g; 428 $in =~s/\bpi\b/(4*atan2(1,1))/g;
429 $in =~s/\be\b/(exp(1))/g; 429 $in =~s/\be\b/(exp(1))/g;
430 $in =~s/\^/**/g; 430 $in =~s/\^/**/g;
431 $in; 431 $in;
432} 432}
447 warn $rh_correct_ans->{error_message} if $rh_correct_ans->{error_flag}; 447 warn $rh_correct_ans->{error_message} if $rh_correct_ans->{error_flag};
448 $out = sub{ scalar( &$correct_eqn_sub(@_) ) }; #ignore the error messages from the function. 448 $out = sub{ scalar( &$correct_eqn_sub(@_) ) }; #ignore the error messages from the function.
449 449
450 } else { 450 } else {
451 my $in =$str_in; 451 my $in =$str_in;
452 452
453 $in =~ s/\b$var\b/\$XVAR/g; 453 $in =~ s/\b$var\b/\$XVAR/g;
454 $in = &my_math_constants($in); 454 $in = &my_math_constants($in);
455 my ($subRef, $PG_eval_errors,$PG_full_error_report) = PG_restricted_eval( " sub { my \$XVAR = shift; my \$out = $in; \$out; } "); 455 my ($subRef, $PG_eval_errors,$PG_full_error_report) = PG_restricted_eval( " sub { my \$XVAR = shift; my \$out = $in; \$out; } ");
456 if ($PG_eval_errors) { 456 if ($PG_eval_errors) {
457 die " ERROR while defining a function from the string:\n\n$main::BR $main::BR $str_in $main::BR $main::BR\n\n $PG_eval_errors" 457 die " ERROR while defining a function from the string:\n\n$main::BR $main::BR $str_in $main::BR $main::BR\n\n $PG_eval_errors"
458 } else { 458 } else {
459 $out = $subRef; 459 $out = $subRef;
460 } 460 }
461 461
462 } 462 }
463 $out; 463 $out;
464} 464}
465 465
466 466

Legend:
Removed from v.1050  
changed lines
  Added in v.1080

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9