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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6451 - (view) (download) (as text)

1 : sh002i 1050
2 : apizer 1080
3 : sh002i 1050 =head1 NAME
4 :    
5 :     PGgraphmacros -- in courseScripts directory
6 :    
7 :     =head1 SYNPOSIS
8 :    
9 :    
10 :     # use Fun;
11 :     # use Label;
12 :     # use Circle;
13 :     # use WWPlot;
14 :    
15 :     =head1 DESCRIPTION
16 :    
17 :     This collection of macros provides easy access to the facilities provided by the graph
18 :     module WWPlot and the modules for objects which can be drawn on a graph: functions (Fun.pm)
19 : gage 5569 labels (Label.pm) and images. The only images implemented currently are open and closed circles
20 : sh002i 1050 (Circle) which can be used to mark graphs of functions defined on open and closed intervals.
21 :    
22 :     These macros provide an easy ability to graph simple functions. More complicated projects
23 :     may require direct access to the underlying modules. If these complicated projects are common
24 :     then it may be desirable to create additional macros. (See numericalmacros.pl for one example.)
25 :    
26 :    
27 :     =cut
28 :    
29 :     =head2 Other constructs
30 :    
31 : apizer 1080 See F<PGbasicmacros> for definitions of C<image> and C<caption>
32 : sh002i 1050
33 :     =cut
34 :    
35 :    
36 :     #my $User = $main::studentLogin;
37 : gage 6451 #my $psvn = $main::psvn; #$main::in{'probSetKey'}; #in{'probSetNumber'}; #$main::probSetNumber;
38 : sh002i 1050 #my $setNumber = $main::setNumber;
39 :     #my $probNum = $main::probNum;
40 :    
41 :     #########################################################
42 :     # this initializes a graph object
43 :     #########################################################
44 :     # graphObject = init_graph(xmin,ymin,xmax,ymax,options)
45 :     # options include 'grid' =>[8,8] or
46 :     # 'ticks'=>[8,8] and/or
47 :     # 'axes'
48 :     #########################################################
49 :    
50 : gage 5573 #loadMacros("MathObjects.pl"); # avoid loading the entire package
51 :     # of MathObjects since that can mess up
52 :     # problems that don't use MathObjects but use Matrices.
53 : gage 5570
54 : sh002i 1050 my %images_created = (); # this keeps track of the base names of the images created during this session.
55 :     # We tack on
56 :     # $imageNum = ++$images_created{$imageName} to keep from overwriting files
57 :     # when we don't want to.
58 :    
59 :    
60 :    
61 :    
62 : apizer 1080 =head2 init_graph
63 :    
64 : sh002i 1050 =pod
65 :    
66 :     $graphObject = init_graph(xmin,ymin,xmax,ymax,'ticks'=>[4,4],'axes'=>[0,0])
67 :     options are
68 : apizer 1080 'grid' =>[8,8] or
69 : sh002i 1050 # there are 8 evenly spaced lines intersecting the horizontal axis
70 : apizer 1080 'ticks'=>[8,8] and/or
71 : sh002i 1050 # there are 8 ticks on the horizontal axis, 8 on the vertical
72 : apizer 1080 'axes' => [0,0]
73 : sh002i 1050 # axes pass through the point (0,0) in real coordinates
74 : apizer 1080 'size' => [200,200]
75 :     # dimensions of the graph in pixels.
76 : sh002i 1050 'pixels' =>[200,200] # synonym for size
77 :    
78 : apizer 1080 Creates a graph object with the default size 200 by 200 pixels.
79 : sh002i 1050 If you want axes or grids you need to specify them in options. But the default values can be selected for you.
80 :    
81 :    
82 :     =cut
83 :     BEGIN {
84 :     be_strict();
85 :     }
86 :     sub _PGgraphmacros_init {
87 :    
88 :    
89 :     }
90 :     #sub _PGgraphmacros_export {
91 :     #
92 :     # my @EXPORT = (
93 :     # '&init_graph', '&add_functions', '&plot_functions', '&open_circle',
94 : apizer 1080 # '&closed_circle', '&my_math_constants', '&string_to_sub',
95 : sh002i 1050 # );
96 :     # @EXPORT;
97 :     #}
98 :    
99 :     sub init_graph {
100 :     my ($xmin,$ymin,$xmax,$ymax,%options) = @_;
101 :     my @size;
102 :     if ( defined($options{'size'}) ) {
103 :     @size = @{$options{'size'}};
104 :     } elsif ( defined($options{'pixels'}) ) {
105 :     @size = @{$options{'pixels'}};
106 :     } else {
107 : jj 2215 my $defaultSize = $main::envir{onTheFlyImageSize} || 200;
108 :     @size=($defaultSize, $defaultSize);
109 : sh002i 1050 }
110 :     my $graphRef = new WWPlot(@size);
111 :     # select a name for this graph based on the user, the psvn and the problem
112 : jj 2206 my $setName = $main::setNumber;
113 : gage 6451 # replace dots, commmas and @ signs in set and user names to keep latex and html happy
114 :     # this should be abstracted and placed in PGalias.pm or PGcore.pm or perhaps PG.pm
115 :     #FIXME
116 : jj 3577 $setName =~ s/Q/QQ/g;
117 :     $setName =~ s/\./-Q-/g;
118 :     my $studentLogin = $main::studentLogin;
119 :     $studentLogin =~ s/Q/QQ/g;
120 :     $studentLogin =~ s/\./-Q-/g;
121 : gage 6451 $studentLogin =~ s/\,/-Q-/g;
122 :     $studentLogin =~ s/\@/-Q-/g;
123 : jj 3577 my $imageName = "$studentLogin-$main::problemSeed-set${setName}prob${main::probNum}";
124 : sh002i 1050 # $imageNum counts the number of graphs with this name which have been created since PGgraphmacros.pl was initiated.
125 :     my $imageNum = ++$main::images_created{$imageName};
126 :     # this provides a unique name for the graph -- it does not include an extension.
127 :     $graphRef->imageName("${imageName}image${imageNum}");
128 : apizer 1080
129 : sh002i 1050 $graphRef->xmin($xmin) if defined($xmin);
130 :     $graphRef->xmax($xmax) if defined($xmax);
131 :     $graphRef->ymin($ymin) if defined($ymin);
132 :     $graphRef->ymax($ymax) if defined($ymax);
133 :     my $x_delta = ($graphRef->xmax - $graphRef->xmin)/8;
134 :     my $y_delta = ($graphRef->ymax - $graphRef->ymin)/8;
135 :     if (defined($options{grid})) { # draw grid
136 :     my $xdiv = ( ${$options{'grid'}}[0]) ? ${$options{'grid'}}[0] : 8; # number of ticks (8 is default)
137 :     my $ydiv = ( ${$options{'grid'}}[1] ) ? ${$options{'grid'}}[1] : 8;
138 :     my $x_delta = ($graphRef->xmax - $graphRef->xmin)/$xdiv;
139 :     my $y_delta = ($graphRef->ymax - $graphRef->ymin)/$ydiv;
140 :     my $i; my @x_values=(); my @y_values=();
141 :     foreach $i (1..($xdiv-1) ) {
142 :     push( @x_values, $i*$x_delta+$graphRef->{xmin});
143 :     }
144 :     foreach $i (1..($ydiv-1) ) {
145 :     push( @y_values, $i*$y_delta+$graphRef->{ymin});
146 :     }
147 :     $graphRef->v_grid('gray',@x_values);
148 :     $graphRef->h_grid('gray',@y_values);
149 :     $graphRef->lb(new Label($x_delta,0,sprintf("%1.1f",$x_delta),'black','center','middle'));
150 :     $graphRef->lb(new Label(0,$y_delta,sprintf("%1.1f",$y_delta),'black','center','middle'));
151 : apizer 1080
152 : sh002i 1050 $graphRef->lb(new Label($xmax,0,$xmax,'black','right'));
153 :     $graphRef->lb(new Label($xmin,0,$xmin,'black','left'));
154 :     $graphRef->lb(new Label(0,$ymax,$ymax,'black','top'));
155 :     $graphRef->lb(new Label(0,$ymin,$ymin,'black','bottom','right'));
156 : apizer 1080
157 : sh002i 1050 } elsif ($options{ticks}) { # draw ticks -- grid over rides ticks
158 :     my $xdiv = ${$options{ticks}}[0]? ${$options{ticks}}[0] : 8; # number of ticks (8 is default)
159 :     my $ydiv = ${$options{ticks}}[1]? ${$options{ticks}}[1] : 8;
160 :     my $x_delta = ($graphRef->xmax - $graphRef->xmin)/$xdiv;
161 :     my $y_delta = ($graphRef->ymax - $graphRef->ymin)/$ydiv;
162 :     my $i; my @x_values=(); my @y_values=();
163 :     foreach $i (1..($xdiv-1) ) {
164 :     push( @x_values, $i*$x_delta+$graphRef->{xmin});
165 :     }
166 :     foreach $i (1..($ydiv-1) ) {
167 :     push( @y_values, $i*$y_delta+$graphRef->{ymin});
168 :     }
169 : jj 1317 $graphRef->h_ticks(0,'black',@x_values);
170 :     $graphRef->v_ticks(0,'black',@y_values);
171 : sh002i 1050 $graphRef->lb(new Label($x_delta,0,$x_delta,'black','right'));
172 :     $graphRef->lb(new Label(0,$y_delta,$y_delta,'black','top'));
173 : apizer 1080
174 : sh002i 1050 $graphRef->lb(new Label($xmax,0,$xmax,'black','right'));
175 :     $graphRef->lb(new Label($xmin,0,$xmin,'black','left'));
176 :     $graphRef->lb(new Label(0,$ymax,$ymax,'black','top'));
177 :     $graphRef->lb(new Label(0,$ymin,$ymin,'black','bottom','right'));
178 :     }
179 : apizer 1080
180 : sh002i 1050 if ($options{axes}) { # draw axis
181 :     my $ra_axes = $options{axes};
182 :     $graphRef->h_axis($ra_axes->[1],'black');
183 :     $graphRef->v_axis($ra_axes->[0],'black');
184 :     }
185 : apizer 1080
186 :    
187 : sh002i 1050 $graphRef;
188 :     }
189 :    
190 :     sub init_graph_no_labels {
191 :     my ($xmin,$ymin,$xmax,$ymax,%options) = @_;
192 :     my @size;
193 :     if ( defined($options{'size'}) ) {
194 :     @size = @{$options{'size'}};
195 :     } elsif ( defined($options{'pixels'}) ) {
196 :     @size = @{$options{'pixels'}};
197 :     } else {
198 : jj 2215 my $defaultSize = $main::envir{onTheFlyImageSize} || 200;
199 :     @size=($defaultSize, $defaultSize);
200 : sh002i 1050 }
201 :     my $graphRef = new WWPlot(@size);
202 :     # select a name for this graph based on the user, the psvn and the problem
203 : gage 6451 my $imageName = "$main::studentLogin-$main::psvn-set${main::setNumber}prob${main::probNum}";
204 : sh002i 1050 # $imageNum counts the number of graphs with this name which have been created since PGgraphmacros.pl was initiated.
205 :     my $imageNum = ++$main::images_created{$imageName};
206 :     # this provides a unique name for the graph -- it does not include an extension.
207 :     $graphRef->imageName("${imageName}image${imageNum}");
208 : apizer 1080
209 : sh002i 1050 $graphRef->xmin($xmin) if defined($xmin);
210 :     $graphRef->xmax($xmax) if defined($xmax);
211 :     $graphRef->ymin($ymin) if defined($ymin);
212 :     $graphRef->ymax($ymax) if defined($ymax);
213 :     my $x_delta = ($graphRef->xmax - $graphRef->xmin)/8;
214 :     my $y_delta = ($graphRef->ymax - $graphRef->ymin)/8;
215 :     if (defined($options{grid})) { # draw grid
216 :     my $xdiv = ( ${$options{'grid'}}[0]) ? ${$options{'grid'}}[0] : 8; # number of ticks (8 is default)
217 :     my $ydiv = ( ${$options{'grid'}}[1] ) ? ${$options{'grid'}}[1] : 8;
218 :     my $x_delta = ($graphRef->xmax - $graphRef->xmin)/$xdiv;
219 :     my $y_delta = ($graphRef->ymax - $graphRef->ymin)/$ydiv;
220 :     my $i; my @x_values=(); my @y_values=();
221 :     foreach $i (1..($xdiv-1) ) {
222 :     push( @x_values, $i*$x_delta+$graphRef->{xmin});
223 :     }
224 :     foreach $i (1..($ydiv-1) ) {
225 :     push( @y_values, $i*$y_delta+$graphRef->{ymin});
226 :     }
227 :     $graphRef->v_grid('gray',@x_values);
228 :     $graphRef->h_grid('gray',@y_values);
229 :     #$graphRef->lb(new Label($x_delta,0,sprintf("%1.1f",$x_delta),'black','center','top'));
230 :     #$graphRef->lb(new Label($x_delta,0,"|",'black','center','middle'));
231 :     #$graphRef->lb(new Label(0,$y_delta,sprintf("%1.1f ",$y_delta),'black','right','middle'));
232 :     #$graphRef->lb(new Label(0,$y_delta,"-",'black','center','middle'));
233 : apizer 1080
234 :    
235 : sh002i 1050 $graphRef->lb(new Label($xmax,0,$xmax,'black','right'));
236 :     $graphRef->lb(new Label($xmin,0,$xmin,'black','left'));
237 :     $graphRef->lb(new Label(0,$ymax,$ymax,'black','top','right'));
238 :     $graphRef->lb(new Label(0,$ymin,$ymin,'black','bottom','right'));
239 : apizer 1080
240 : sh002i 1050 } elsif ($options{ticks}) { # draw ticks -- grid over rides ticks
241 :     my $xdiv = ${$options{ticks}}[0]? ${$options{ticks}}[0] : 8; # number of ticks (8 is default)
242 :     my $ydiv = ${$options{ticks}}[1]? ${$options{ticks}}[1] : 8;
243 :     my $x_delta = ($graphRef->xmax - $graphRef->xmin)/$xdiv;
244 :     my $y_delta = ($graphRef->ymax - $graphRef->ymin)/$ydiv;
245 :     my $i; my @x_values=(); my @y_values=();
246 :     foreach $i (1..($xdiv-1) ) {
247 :     push( @x_values, $i*$x_delta+$graphRef->{xmin});
248 :     }
249 :     foreach $i (1..($ydiv-1) ) {
250 :     push( @y_values, $i*$y_delta+$graphRef->{ymin});
251 :     }
252 :     $graphRef->v_ticks(0,'black',@x_values);
253 :     $graphRef->h_ticks(0,'black',@y_values);
254 :     $graphRef->lb(new Label($x_delta,0,$x_delta,'black','right'));
255 :     $graphRef->lb(new Label(0,$y_delta,$y_delta,'black','top'));
256 : apizer 1080
257 : sh002i 1050 $graphRef->lb(new Label($xmax,0,$xmax,'black','right'));
258 :     $graphRef->lb(new Label($xmin,0,$xmin,'black','left'));
259 :     $graphRef->lb(new Label(0,$ymax,$ymax,'black','top'));
260 :     $graphRef->lb(new Label(0,$ymin,$ymin,'black','bottom','right'));
261 :     }
262 : apizer 1080
263 : sh002i 1050 if ($options{axes}) { # draw axis
264 :     my $ra_axes = $options{axes};
265 :     $graphRef->h_axis($ra_axes->[1],'black');
266 :     $graphRef->v_axis($ra_axes->[0],'black');
267 :     }
268 : apizer 1080
269 :    
270 : sh002i 1050 $graphRef;
271 :     }
272 :    
273 :    
274 :    
275 :     =head2 plot_functions
276 :    
277 :     =pod
278 :    
279 :     Usage: ($f1, $f2, $f3) = plot_functions($graph, $f1, $f2, $f3);
280 :     Synonym: add_functions($graph,$f1,$f2,$f3);
281 : apizer 1080
282 : sh002i 1050 Where $f1 is a string of the form
283 : apizer 1080
284 : sh002i 1050 $f1 = qq! x^2 - 3*x + 45 for x in [0, 45) using color:red and weight:2!
285 :    
286 :     The phrase translates as: formula B<for> variable B<in> interval B<using> option-list.
287 :     The option-list contains pairs of the form attribute:value.
288 :     The default for color is "default_color" which is usually black.
289 :     The default for the weight (pixel width) of the pen is 2 pixels.
290 :    
291 : apizer 1080 The string_to_sub subroutine is used to translate the formula into a subroutine.
292 :    
293 : sh002i 1050 The functions in the list are installed in the graph object $graph and will appear when the graph object is next drawn.
294 :    
295 :     =cut
296 :    
297 :     sub add_functions {
298 :     &plot_functions;
299 :     }
300 :    
301 :     sub plot_functions {
302 :     my $graph = shift;
303 :     my @function_list = @_;
304 :     my $error = "";
305 :     $error .= "The first argument to plot_functions must be a graph object" unless ref($graph) =~/WWPlot/;
306 :     my $fn;
307 :     my @functions=();
308 :     foreach $fn (@function_list) {
309 :    
310 :     # model: "2.5-x^2 for x in <-1,0> using color:red and weight:2"
311 :     if ($fn =~ /^(.+)for\s*(\w+)\s*in\s*([\(\[\<])\s*([\d\.\-]+)\s*,\s*([\d\.\-]+)\s*([\)\]\>])\s*using\s*(.*)$/ ) {
312 :     my ($rule,$var, $left_br, $left_end, $right_end, $right_br, $options)= ($1, $2, $3, $4, $5, $6, $7);
313 : apizer 1080
314 :     my %options = split( /\s*and\s*|\s*:\s*|\s*,\s*|\s*=\s*|\s+/,$options);
315 : sh002i 1050 my ($color, $weight);
316 :     if ( defined($options{'color'}) ){
317 :     $color = $options{'color'}; #set pen color
318 :     } else {
319 :     $color = 'default_color';
320 :     }
321 :     if ( defined($options{'weight'}) ) {
322 :     $weight = $options{'weight'}; # set pen weight (width in pixels)
323 :     } else {
324 : apizer 1080 $weight =2;
325 : sh002i 1050 }
326 : gage 5573 # a workaround to call Parser code without loading MathObjects.
327 :     my $localContext= Parser::Context->current(\%main::context)->copy;
328 :     $localContext->variables->add($var=>'Real') unless $localContext->variables->get($var);
329 : dpvc 5930 my $formula = Value->Package("Formula()")->new($localContext,$rule)->perlFunction(undef,[$var]);
330 : dpvc 5915 my $subRef = sub {
331 :     my $x = shift;
332 : dpvc 5930 my $y = Parser::Eval($formula,$x); # traps errors, e.g. graph domain is larger than
333 :     # the function's domain.
334 : dpvc 5915 $y = $y->value if defined $y;
335 : dpvc 5930 return $y;
336 : dpvc 5915 };
337 : gage 5573 #my $subRef = string_to_sub($rule,$var);
338 : sh002i 1050 my $funRef = new Fun($subRef,$graph);
339 :     $funRef->color($color);
340 :     $funRef->weight($weight);
341 :     $funRef->domain($left_end , $right_end);
342 :     push(@functions,$funRef);
343 :     # place open (1,3) or closed (1,3) circle at the endpoints or do nothing <1,3>
344 :     if ($left_br eq '[' ) {
345 :     $graph->stamps(closed_circle($left_end,&$subRef($left_end),$color) );
346 :     } elsif ($left_br eq '(' ) {
347 :     $graph->stamps(open_circle($left_end, &$subRef($left_end), $color) );
348 : apizer 1080 }
349 : sh002i 1050 if ($right_br eq ']' ) {
350 :     $graph->stamps(closed_circle($right_end,&$subRef($right_end),$color) );
351 :     } elsif ($right_br eq ')' ) {
352 :     $graph->stamps(open_circle($right_end, &$subRef($right_end), $color) );
353 : apizer 1080 }
354 :    
355 : sh002i 1050 } else {
356 :     $error .= "Error in parsing: $fn $main::BR";
357 :     }
358 : apizer 1080
359 : sh002i 1050 }
360 :     die ("Error in plot_functions: \n\t $error ") if $error;
361 :     @functions; # return function references unless there is an error.
362 :     }
363 :    
364 : gage 5569
365 :    
366 :    
367 : sh002i 1050 =head2 insertGraph
368 :    
369 : apizer 1080 $filePath = insertGraph(graphObject);
370 : sh002i 1050 returns a path to the file containing the graph image.
371 :    
372 :     B<Note:> Because insertGraph involves writing to the disk, it is actually defined in dangerousMacros.pl.
373 :    
374 :     insertGraph(graphObject) writes a image file to the C<html/tmp/gif> directory of the current course.
375 :     The file name is obtained from the graphObject. Warnings are issued if errors occur while writing to
376 : apizer 1080 the file.
377 : sh002i 1050
378 :     The permissions and ownership of the file are controlled by C<$main::tmp_file_permission>
379 :     and C<$main::numericalGroupID>.
380 :    
381 :     B<Returns:> A string containing the full path to the temporary file containing the image.
382 :    
383 :    
384 :    
385 :     InsertGraph draws the object $graph, stores it in "${tempDirectory}gif/$imageName.gif (or .png)" where
386 :     the $imageName is obtained from the graph object. ConvertPath and surePathToTmpFile are used to insure
387 :     that the correct directory separators are used for the platform and that the necessary directories
388 : apizer 1080 are created if they are not already present. The directory address to the file is the result.
389 : sh002i 1050
390 :     The most common use of C,insertGraph> is
391 :    
392 :     TEXT(image(insertGraph($graph)) );
393 :    
394 :     where C<image> takes care of creating the proper URL for accessing the graph and for creating the HTML code to display the image.
395 :    
396 :     Another common usage is:
397 :    
398 :     TEXT(htmlLink( alias(insertGraph($graph), "picture" ) ) );
399 :    
400 : apizer 1080 which inserts the URL pointing to the picture.
401 :     alias converts the directory address to a URL when serving HTML pages and insures that
402 : sh002i 1050 an eps file is generated when creating TeX code for downloading. (Image, automatically applies alias to its input
403 :     in order to obtain the URL.)
404 :    
405 :     See the documentation in F<dangerousMacros.pl> for the latest details.
406 :    
407 :     =cut
408 :    
409 :     =head2 'Circle' lables
410 :    
411 :     Usage: $circle_object = open_circle( $x_position, $y_position, $color );
412 :     $circle_object2 = closed_circle( $x_position, $y_position, $color );
413 :    
414 : apizer 1080 Creates a small open (resp. filled in or closed) circle for use as a stamp in marking graphs.
415 : sh002i 1050 For example
416 :    
417 :     $graph -> stamps($circle_object2); # puts a filled dot at $x_position, $y_position
418 :    
419 :     =cut
420 :    
421 :     #########################################################
422 :     sub open_circle {
423 :     my ($cx,$cy,$color) = @_;
424 :     new Circle ($cx, $cy, 4,$color,'nearwhite');
425 :     }
426 :    
427 :     sub closed_circle {
428 :     my ($cx,$cy, $color) = @_;
429 :     $color = 'black' unless defined $color;
430 :     new Circle ($cx, $cy, 4,$color, $color);
431 :     }
432 :    
433 :    
434 :     =head2 Auxiliary macros
435 :    
436 :     =head3 string_to_sub and my_math_constants
437 :    
438 :    
439 :     These are internal macros which govern the interpretation of equations.
440 :    
441 :    
442 :     Usage: $string = my_math_constants($string)
443 :     $subroutine_reference = my_string_to_sub($string)
444 :    
445 : apizer 1080 C<my_math_constants>
446 : sh002i 1050 interprets pi, e as mathematical constants 3.1415926... and 2.71828... respectively. (Case is important).
447 :     The power operator ^ is replaced by ** to conform with perl constructs
448 :    
449 :     C<string_to_sub>
450 :     converts a string defining a single perl arithmetic expression with independent variable $XVAR into a subroutine.
451 :     The string is first filtered through C<my_math_macros>. The resulting subroutine
452 : apizer 1080 takes a single real number as input and produces a single output value.
453 : sh002i 1050
454 :     =cut
455 :    
456 :     sub my_math_constants {
457 : apizer 1080 my($in) = @_;
458 : sh002i 1050 $in =~s/\bpi\b/(4*atan2(1,1))/g;
459 :     $in =~s/\be\b/(exp(1))/g;
460 :     $in =~s/\^/**/g;
461 :     $in;
462 :     }
463 :    
464 :     sub string_to_sub {
465 :     my $str_in = shift;
466 :     my $var = shift;
467 :     my $out = undef;
468 :     if ( defined(&check_syntax) ) {
469 :     #prepare the correct answer and check it's syntax
470 :     my $rh_correct_ans = new AnswerHash;
471 :     $rh_correct_ans->input($str_in);
472 :     $rh_correct_ans = check_syntax($rh_correct_ans);
473 :     warn $rh_correct_ans->{error_message} if $rh_correct_ans->{error_flag};
474 :     $rh_correct_ans->clear_error();
475 :     $rh_correct_ans = function_from_string2($rh_correct_ans, ra_vars => ['x'], store_in =>'rf_correct_ans');
476 :     my $correct_eqn_sub = $rh_correct_ans->{rf_correct_ans};
477 :     warn $rh_correct_ans->{error_message} if $rh_correct_ans->{error_flag};
478 :     $out = sub{ scalar( &$correct_eqn_sub(@_) ) }; #ignore the error messages from the function.
479 :    
480 :     } else {
481 :     my $in =$str_in;
482 : apizer 1080
483 : sh002i 1050 $in =~ s/\b$var\b/\$XVAR/g;
484 :     $in = &my_math_constants($in);
485 :     my ($subRef, $PG_eval_errors,$PG_full_error_report) = PG_restricted_eval( " sub { my \$XVAR = shift; my \$out = $in; \$out; } ");
486 :     if ($PG_eval_errors) {
487 : apizer 1080 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"
488 : sh002i 1050 } else {
489 :     $out = $subRef;
490 :     }
491 : apizer 1080
492 : sh002i 1050 }
493 :     $out;
494 :     }
495 :    
496 :     #########################################################
497 :    
498 :     1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9