[system] / trunk / webwork / system / courseScripts / PGmatrixmacros.pl Repository: Repository Listing bbplugincoursesdistsnplrochestersystemwww

# Diff of /trunk/webwork/system/courseScripts/PGmatrixmacros.pl

Revision 861 Revision 862
108 108
109############ 109############
110 110
112 112
113 Usage \{ display_matrix( [ [1, '$$\sin x$$'], [ans_rule(5), 6] ]) \}
114 \{ display_matrix(A, align=>'crvl') \} 115 $\{ display_matrix_mm(A) \}$ 113 Usage $\{ display_matrix(A) \}$ 116 $\{ display_matrix_mm([ [1, 3], [4, 6] ]) \}$ 114 $\{ display_matrix([ [ 1, 3], [4, 6] ]) \}$ 117 115 118 display_matrix produces a matrix for display purposes. It checks whether 116 Output is text which represents the matrix in TeX format used in math display mode. 119 it is producing LaTeX output, or if it is displaying on a web page in one 120 of the various modes. The input can either be of type Matrix, or a 121 reference to an array. 122 123 Entries can be numbers, bits of math mode, or answer boxes. 124 125 display_matrix_mm functions similarly, except that it should be inside 126 math mode. display_matrix_mm cannot contain answer boxes in its entries. 127 Entries to display_matrix_mm should assume that they are already in 128 math mode. 129 130 Both functions take an optional alignment string, similar to ones in 131 LaTeX tabulars and arrays. Here c for centered columns, l for left 132 flushed columns, and r for right flushed columns. 133 134 The alignment string can also specify vertical rules to be placed in the 135 matrix. Here s or | denote a solid line, d is a dashed line, and v 136 requests the default vertical line. This can be set on a system-wide 137 or course-wide basis via the variabledefaultDisplayMatrixStyle, and
138 it can default to solid, dashed, or no vertical line (n for none).
139
140 The matrix has left and right delimiters also specified by
141 $defaultDisplayMatrixStyle. They can be parentheses, square brackets, 142 braces, vertical bars, or none. The default can be overridden in 143 an individual problem with optional arguments such as left=>"|", or 144 right=>"]". 145 117 146 118 147=cut 119=cut 148 120 149 121 150sub display_matrix_mm{ # will display a matrix in tex format. 122sub display_matrix_mm{ # will display a matrix in tex format. 151 # the matrix can be either of type array or type 'Matrix' 123 # the matrix can be either of type array or type 'Matrix' 124# my$ra_matrix = shift;
125# my $out=''; 126# if (ref($ra_matrix) eq 'Matrix' ) {
127# my ($rows,$cols) = $ra_matrix->dim(); 128#$out = q!\\left(\\begin{array}{! . 'c'x$cols . q!}!; 129# for( my$i=1; $i<=$rows; $i++) { 130# for (my$j=1; $j<=$cols; $j++) { 131# my$entry = $ra_matrix->element($i,$j); 132#$entry = "#" unless defined($entry); 133#$out.= $entry; 134#$out .= ($j <$cols) ? ' & ' : "\\cr\n";
135# }
136# }
137# $out .= "\\end{array}\\right)"; 138# } elsif( ref($ra_matrix) eq 'ARRAY') {
139# my $rows = @$ra_matrix;
140# my $cols = @{$ra_matrix->[0]};
141# $out = q!\\left(\\begin{array}{! . 'c' x$cols . q!}!;
142# for(my $i=0;$i<$rows;$i++) {
143# my @row = @{$ra_matrix->[$i]};
144# while (@row) {
145# my $entry = shift(@row); 146#$entry = "#" unless defined($entry); 147#$out.= $entry; 148# if (@row) { 149#$out .= "& ";
150# } else {
151# next;
152# }
153# }
154# $out .= "\\cr\n"; 155# } 156#$out .= "\\end{array}\\right)";
157# } else {
158# warn "The input" . ref($ra_matrix) . " doesn't make sense as input to display_matrix. "; 159# } 160#$out;
161
152 return display_matrix(@_, 'force_tex'=>1); 162 return display_matrix(@_, 'force_tex'=>1);
153} 163}
154 164
155sub display_matrix_math_mode { 165sub display_matrix_math_mode {
156 return display_matrix_mm(@_); 166 return display_matrix_mm(@_);
157} 167}
158 168
159sub display_matrix { 169sub display_matrix {
160 my $ra_matrix = shift; 170 my$ra_matrix = shift;
161 my %opts = @_; 171 my %opts = @_;
162 # Maybe this will become a global variable?
163 my $styleParams = defined($main::defaultDisplayMatrixStyle) ?
164 $main::defaultDisplayMatrixStyle : "(s)"; 165 166 set_default_options(\%opts, 172 set_default_options(\%opts, 167 '_filter_name' => 'displaymat', 173 '_filter_name' => 'displaymat', 168 'force_tex' => 0, 174 'force_tex' => 0, 169 'left' => substr($styleParams,0,1),
170 'right' => substr($styleParams,2,1), 171 'midrule' => substr($styleParams,1,1),
172 'allow_unknown_options'=> 1); 175 'allow_unknown_options'=> 1);
173 176
174 my ($numRows,$numCols, @myRows); 177 my ($numRows,$numCols, @myRows);
175 178
176 if (ref($ra_matrix) eq 'Matrix' ) { 179 if (ref($ra_matrix) eq 'Matrix' ) {
182 $entry = "#" unless defined($entry); 185 $entry = "#" unless defined($entry);
183 push @{ $myRows[$i] }, $entry; 186 push @{$myRows[$i] },$entry;
184 } 187 }
185 } 188 }
186 } else { # matrix is input at [ [1,2,3],[4,5,6]] 189 } else { # matrix is input at [ [1,2,3],[4,5,6]]
187 $numCols = 0; 188 @myRows = @{$ra_matrix}; 190 @myRows = @{$ra_matrix}; 189$numRows = scalar(@myRows); # counts horizontal rules too 191 $numRows = scalar(@myRows); 190 my$tmp;
191 for $tmp (@myRows) { 192 if($tmp ne 'hline') {
193 my @arow = @{$tmp}; 192 my @arow = @{$myRows[0]};
194 $numCols= scalar(@arow); #number of columns in table 193$numCols= scalar(@arow); #number of columns in table
195 last;
196 }
197 }
198 } 194 }
199 my $out; 195 my$out;
200 my $j; 196 my$j;
201 my alignString=''; # alignment as a string for dvi/pdf 197 myalignString=''; # alignment as a string for dvi/pdf
202 my alignList; # alignment as a list 198 myalignList; # alignment as a list
203 199
204 if(defined(opts{'align'})) { 200 if(defined(opts{'align'})) {
205 alignString=opts{'align'}; 201 alignString=opts{'align'};
206 alignString =~ s/v/opts{'midrule'}/g;
207 alignString =~ tr/s/|/; # Treat "s" as "|" 202alignString =~ tr/s/|/; # Treat "s" as "|"
208 alignString =~ tr/n//; # Remove "n" altogether 209 @alignList = split //, alignString; 203 @alignList = split //, opts{'align'}; 210 } else { 204 } else { 211 for(j=0; $j<$numCols; $j++) { 205 for($j=0; $j<$numCols; $j++) { 212$alignList->[$j] = "c"; 206$alignList->[$j] = "c"; 213$alignString .= "c"; 207 alignString .= "c"; 214 } 208 } 215 } 209 } 216 210 217out .= dm_begin_matrix(alignString, %opts); 211out .= dm_begin_matrix(alignString, %opts); 218out .= dm_mat_left($numRows, %opts); 212$out .= dm_mat_left($numRows, %opts); 219 # vertical lines put in with first row 220$j = shift @myRows;
221 $out .= dm_mat_row($j, alignList, %opts, 'isfirst'=>numRows);
222 for $j (@myRows) { 213 for$j (@myRows) {
223 $out .= dm_mat_row($j, alignList, %opts, 'isfirst'=>0); 214out .= dm_mat_row($j,$alignList, %opts);
224 } 215 }
225 $out .= dm_mat_right($numRows, %opts); 216 $out .= dm_mat_right($numRows, %opts);
226 $out .= dm_end_matrix(%opts); 217$out .= dm_end_matrix(%opts);
227 $out; 218$out;
228} 219}
230sub dm_begin_matrix { 221sub dm_begin_matrix {
231 my (aligns)=shift; #alignments of columns in table 222 my (aligns)=shift; #alignments of columns in table
232 my %opts = @_; 223 my %opts = @_;
233 my $out = ""; 224 my$out = "";
234 if ($main::displayMode eq 'TeX' or$opts{'force_tex'}) { 225 if ($main::displayMode eq 'TeX' or$opts{'force_tex'}) {
235# $out .= "\n"; 226$out .= "\n";
236 # This should be doable by regexp, but it wasn't working for me
237 my ($j, @tmp); 238 @tmp = split //,$aligns;
239 aligns=''; 240 forj (@tmp) {
241 # I still can't get an @ expression sent to TeX, so plain
242 # vertical line
243 aligns .= (j eq "d") ? '|' : $j; 244 } 245$out .= opts{'force_tex'} ? '' : ''; 227 out .= opts{'force_tex'} ? '' : '\('; 246 out .= '\displaystyle\left'.opts{'left'}."\\begin{array}{aligns} \n"; 228 out .= "\\displaystyle\\left(\\begin{array}{aligns} \n"; 247 } 229 } 248 elsif (main::displayMode eq 'Latex2HTML') { 230 elsif (main::displayMode eq 'Latex2HTML') { 249 out .= "\n\\begin{rawhtml} <TABLE BORDER=0>\n\\end{rawhtml}"; 231 out .= "\n\\begin{rawhtml} <TABLE BORDER=0>\n\\end{rawhtml}"; 250 } 232 } 251 elsif (main::displayMode eq 'HTML' || main::displayMode eq 'HTML_tth' || main::displayMode eq 'HTML_dpng') { 233 elsif (main::displayMode eq 'HTML' || main::displayMode eq 'HTML_tth' || main::displayMode eq 'HTML_dpng') { 264 if (main::displayMode eq 'TeX' or opts{'force_tex'}) { 246 if (main::displayMode eq 'TeX' or opts{'force_tex'}) { 265 return ""; 247 return ""; 266 } 248 } 267 my out=''; 249 my out=''; 268 my j; 250 my j; 269 my (brh, erh) = ("",""); # Start and end raw html 270 if(main::displayMode eq 'Latex2HTML') { 271 brh = "\\begin{rawhtml}"; 272 erh = "\\end{rawhtml}"; 273 } 274 251 275 if((main::displayMode eq 'HTML_dpng') || (main::displayMode eq 'Latex2HTML')) { 252 if((main::displayMode eq 'HTML_dpng') || (main::displayMode eq 'Latex2HTML')) { 253# if(numrows>12) { numrows = 12; } 254 if(main::displayMode eq 'Latex2HTML') { out .= '\begin{rawhtml}'; } 276 out .= "brh<tr valign=\"center\"><td nowrap=\"nowrap\" align=\"left\">erh"; 255 out .= "<tr><td nowrap=\"nowrap\" align=\"left\">"; 277 out .= dm_image_delimeter(numrows, opts{'left'}); 256 if(main::displayMode eq 'Latex2HTML') { out .= '\end{rawhtml}'; } 257# out .= "<img alt=\"(\" src = \"". 258# main::imagesURL."/leftnumrows.png\" >"; 259# return out; 260 out .= '\(\left.\begin{array}{c}'; 261 for(j=0;j<numrows;j++) { out .= ' \\\\'; } 262 out .= '\end{array}\right('; 263 264 if(main::displayMode eq 'Latex2HTML') { $out .= '\begin{rawhtml}'; } 278$out .= "$brh<td><table border=0 cellspacing=5>\n$erh"; 265 $out .= "<td><table border=0 cellspacing=5>\n"; 266 if($main::displayMode eq 'Latex2HTML') { $out .= '\end{rawhtml}'; } 279 return$out; 267 return $out; 280 } 268 } 281 # Mode is now tth 269 # Mode is now tth 282 270$out = "<tr><td nowrap=\"nowrap\" align=\"left\"><font face=\"symbol\">æ<br />";
283 $out .= dm_tth_delimeter($numrows, $opts{'left'}); 271 for($j=0;$j<$numrows;$j++) { 272$out .= "ç<br />";
273 }
274 $out .= "è</font></td>\n"; 284$out .= "<td><table border=0 cellspacing=5>\n"; 275 $out .= "<td><table border=0 cellspacing=5>\n"; 285 return$out; 276 return $out; 286} 277} 287 278 288sub dm_mat_right { 279sub dm_mat_right { 300$out .= "</table><td nowrap=\"nowrap\" align=\"right\">"; 291 out .= "</table><td nowrap=\"nowrap\" align=\"right\">"; 301 if(main::displayMode eq 'Latex2HTML') { $out .= '\end{rawhtml}'; } 292 if($main::displayMode eq 'Latex2HTML') { $out .= '\end{rawhtml}'; } 302 293 303#$out .= "<img alt=\"(\" src = \"". 294# $out .= "<img alt=\"(\" src = \"". 304# "/webwork_system_html/images"."/right$numrows.png\" >"; 295# "/webwork_system_html/images"."/right$numrows.png\" >"; 305$out.= dm_image_delimeter($numrows,$opts{'right'}); 296 $out .= '$$\left)\begin{array}{c}'; 297 for(j=0;j<numrows;j++) { out .= ' \\\\'; } 298 out .= '\end{array}\right.$$'; 306 return$out; 299 return $out; 307 } 300 } 308 301 309$out .= "</table>"; 302 $out .= "</table>"; 310 303$out .= "<td nowrap=\"nowrap\" align=\"left\"><font face=\"symbol\">ö<br />";
311 $out .= dm_tth_delimeter($numrows, $opts{'right'}); 304 for($j=0;$j<$numrows;$j++) { 305$out .= "÷<br />";
306 }
307 $out .= "ø</font></td>\n"; 312 return$out; 308 return $out; 313} 309} 314 310 315sub dm_end_matrix { 311sub dm_end_matrix { 316 my %opts = @_; 312 my %opts = @_; 317 313 318 my$out = ""; 314 my $out = ""; 319 if ($main::displayMode eq 'TeX' or $opts{'force_tex'}) { 315 if ($main::displayMode eq 'TeX' or $opts{'force_tex'}) { 320$out .= "\n\\end{array}\\right$opts{right}"; 316$out .= "\n\\end{array}\\right)";
321 $out .=$opts{'force_tex'} ? '' : "\\) "; 317 $out .=$opts{'force_tex'} ? '' : "\\)\n";
322 } 318 }
323 elsif ($main::displayMode eq 'Latex2HTML') { 319 elsif ($main::displayMode eq 'Latex2HTML') {
324 $out .= "\n\\begin{rawhtml} </TABLE >\n\\end{rawhtml}"; 320$out .= "\n\\begin{rawhtml} </TABLE >\n\\end{rawhtml}";
325 } 321 }
326 elsif ($main::displayMode eq 'HTML' ||$main::displayMode eq 'HTML_tth' || $main::displayMode eq 'HTML_dpng') { 322 elsif ($main::displayMode eq 'HTML' || $main::displayMode eq 'HTML_tth' ||$main::displayMode eq 'HTML_dpng') {
330 $out = "Error: PGmatrixmacros: dm_end_matrix: Unknown displayMode:$main::displayMode.\n"; 326 $out = "Error: PGmatrixmacros: dm_end_matrix: Unknown displayMode:$main::displayMode.\n";
331 } 327 }
332 $out; 328$out;
333} 329}
334 330
335# Make an image of a big delimiter for a matrix
336sub dm_image_delimeter {
337 my $numRows = shift; 338 my$char = shift;
339 my ($out,$j);
340 331
341 if($char eq ".") {return("");} 342 if($char eq "d") { # special treatment for dashed lines
343 $out='$$\vbox to '.(numRows*1.7).'\baselineskip '; 344 out .='{\cleaders\hbox{\vbox{\hrule width0pt height3pt depth0pt'; 345 out .='\hrule width0.3pt height6pt depth0pt'; 346 out .='\hrule width0pt height3pt depth0pt}}\vfil}$$'; 347 return($out);
348 }
349 if($char eq "|") { 350$out='$$\vbox to '.(numRows*1.4).'\baselineskip '; 351 out .='{\cleaders\vrule width0.3pt'; 352 out .='\vfil}$$';
353 return($out); 354 } 355 if($char eq "{") {$char = '\lbrace';} 356 if($char eq "}") {$char = '\rbrace';} 357$out .= '$$\left.\begin{array}{c}'; 358 for(j=0;j<=numRows;j++) { out .= '\strut \\\\'; } 359 out .= '\end{array}\right'.char.'$$';
360 return($out); 361} 362 363# Basically uses a table of special characters and simple 364# recipe to produce big delimeters a la tth mode 365sub dm_tth_delimeter { 366 my$numRows = shift;
367 my $char = shift; 368 369 if($char eq ".") { return("");}
370 my ($top,$mid, $bot,$extra);
371 my ($j,$out);
372
373 if($char eq "(") { ($top, $mid,$bot, $extra) = ('æ','ç','è','ç');} 374 elsif($char eq ")") { ($top,$mid, $bot,$extra) = ('ö','÷','ø','÷');}
375 elsif($char eq "|") { ($top, $mid,$bot, $extra) = ('ê','ê','ê','ê');} 376 elsif($char eq "[") { ($top,$mid, $bot,$extra) = ('é','ê','ë','ê');}
377 elsif($char eq "]") { ($top, $mid,$bot, $extra) = ('ù','ú','û','ú');} 378 elsif($char eq "{") { ($top,$mid, $bot,$extra) = ('ì','ï','î','í');}
379 elsif($char eq "}") { ($top, $mid,$bot, $extra) = ('ü','ï','þ','ý');} 380 else { warn "Unknown delimiter in dm_tth_delimeter";} 381 382$out = '<td nowrap="nowrap" align="left"><font face="symbol">';
383 $out .= "$top<br />";
384 for($j=1;$j<$numRows;$j++) {
385 $out .= "$mid<br />";
386 }
387 $out .= "$extra<br />";
388 for($j=1;$j<$numRows;$j++) {
389 $out .= "$mid<br />";
390 }
391 $out .= "$bot</font></td>\n";
392 return $out; 393} 394 395# Make a row for the matrix 396sub dm_mat_row { 332sub dm_mat_row { 397 my$elements = shift; 333 my $elements = shift; 398 my$tmp = shift; 334 my tmp = shift; 399 my @align = @{tmp} ; 335 my @align = @{$tmp} ; 400 my %opts = @_; 336 my %opts = @_; 401 my @elements = @{$elements}; 337 my @elements = @{$elements}; 402 my$out = ""; 338 my $out = ""; 403 my ($brh, $erh) = ("",""); # Start and end raw html 404 if($main::displayMode eq 'Latex2HTML') {
405 $brh = "\\begin{rawhtml}"; 406$erh = "\\end{rawhtml}";
407 }
408 if ($main::displayMode eq 'TeX' or$opts{'force_tex'}) { 339 if ($main::displayMode eq 'TeX' or$opts{'force_tex'}) {
409 while (@elements) { 340 while (@elements) {
410 $out .= shift(@elements) . " &"; 341$out .= shift(@elements) . " &";
411 } 342 }
412 chop($out); # remove last & 343 chop($out); # remove last &
413 $out .= "\\cr \n"; 344$out .= "\\cr \n";
414 # carriage returns must be added manually for tex 345 # carriage returns must be added manually for tex
415 } elsif ($main::displayMode eq 'HTML' ||$main::displayMode eq 'HTML_tth' 346 }
416 || $main::displayMode eq 'HTML_dpng' 417 ||$main::displayMode eq 'Latex2HTML') { 347 elsif ($main::displayMode eq 'Latex2HTML') { 418$out .= "$brh\n<TR>\n$erh"; 348 $out .= "\n\\begin{rawhtml}\n<TR>\n\\end{rawhtml}\n"; 349 while (@elements) { 350$out .= " \n\\begin{rawhtml}\n<TD> \n\\end{rawhtml}\n" . shift(@elements) . " \n\\begin{rawhtml}\n</TD> \n\\end{rawhtml}\n";
351 }
352 $out .= " \n\\begin{rawhtml}\n</TR> \n\\end{rawhtml}\n"; 353 } 354 elsif ($main::displayMode eq 'HTML' || $main::displayMode eq 'HTML_tth' ||$main::displayMode eq 'HTML_dpng') {
355 $out .= "<TR><td nowrap=\"nowrap\">\n"; 419 while (@elements) { 356 while (@elements) { 420 my$myalign; 357 my myalign; 358 #do {myalign = shift @align;} until(myalign ne "|"); 421myalign = shift @align; 359 myalign = shift @align; 422 if(myalign eq "|" or myalign eq "d") { 360 if(myalign eq "|") {
423 if($opts{'isfirst'} &&$main::displayMode ne 'HTML_tth') {
424 $out .=$brh.'<td rowspan="'.$opts{'isfirst'}.'">'.$erh;
425 $out .= dm_image_delimeter($opts{'isfirst'}-1, myalign); 426 } elsif(main::displayMode eq 'HTML_tth') {
427 if(myalign eq "d") { # dashed line in tth mode 428out .= '<td> | </td>'; 361 $out .= '<td> | </td>'; 429 } elsif($opts{'isfirst'}) { # solid line in tth mode
430 $out .= '<td rowspan="'.$opts{'isfirst'}.'"<table border="0"><tr>';
431 $out .= dm_tth_delimeter($opts{'isfirst'}-1, "|");
432 $out .= '</td></tr></table>'; 433 } 434 } 435 } else { 362 } else { 436 if($myalign eq "c") { myalign = "center";} 363 if(myalign eq "c") { myalign = "center";} 437 if(myalign eq "l") { myalign = "left";} 364 if(myalign eq "l") { myalign = "left";} 438 if(myalign eq "r") { myalign = "right";} 365 if(myalign eq "r") { myalign = "right";} 439out .= "brh<TD nowrap=\"nowrap\" align=\"myalign\">$erh" . shift(@elements) . "$brh</TD>$erh"; 366$out .= "<TD nowrap=\"nowrap\" align=\"myalign\">" . shift(@elements) . "</TD>"; 440 } 367 } 441 } 368 } 442out .= "$brh\n</TR>\n$erh"; 369 $out .= "<td>\n</TR>\n"; 443 } 370 } 444 else { 371 else { 445$out = "Error: dm_mat_row: Unknown displayMode: $main::displayMode.\n"; 372$out = "Error: dm_mat_row: Unknown displayMode: $main::displayMode.\n"; 446 } 373 } 447$out; 374 out; 448} 375} 449 376 450=head4 mbox 451 452 Usage \{ mbox(thing1, thing2, thing3) \} 453 \{ mbox([thing1, thing2, thing3], valign=>'top') \} 454 455 mbox takes a list of constructs, such as strings, or outputs of 456 display_matrix, and puts them together on a line. Without mbox, the 457 output of display_matrix would always start a new line. 458 459 The inputs can be just listed, or given as a reference to an array. 460 With the latter, optional arguments can be given. 461 462 Optional arguments are allowbreaks=>'yes' to allow line breaks in TeX 463 output; and valign which sets vertical alignment on web page output. 464 465=cut 466 467sub mbox { 468 myinList = shift;
469 my %opts;
470 if(ref($inList) eq 'ARRAY') { 471 %opts = @_; 472 } else { 473 %opts = (); 474$inList = [inList, @_]; 475 } 476 477 set_default_options(\%opts, 478 '_filter_name' => 'mbox', 479 'valign' => 'middle', 480 'allowbreaks' => 'no', 481 'allow_unknown_options'=> 0); 482 if(!opts{'allowbreaks'}) { $opts{'allowbreaks'}='no';} 483 my$out = "";
484 my $j; 485 my ($brh, $erh) = ("",""); # Start and end raw html if needed 486 if($main::displayMode eq 'Latex2HTML') {
487 $brh = "\\begin{rawhtml}"; 488$erh = "\\end{rawhtml}";
489 }
490 my @hlist = @{$inList}; 491 if($main::displayMode eq 'TeX') {
492 if($opts{allowbreaks} ne 'no') {$out .= '\mbox{';}
493 for $j (@hlist) {$out .= $j;} 494 if($opts{allowbreaks} ne 'no') {$out .= '}';} 495 } else { 496$out .= qq!brh<table><tr valign="opts{'valign'}">$erh!; 497 for$j (@hlist) {
498 $out .= qq!$brh<td align="center" nowrap="nowrap">$erh$j$brh</td>$erh!;
499 }
500 $out .= "$brh</table>$erh"; 501 } 502 return$out;
503}
504 377
505 378
507 380
508 Usage: ra_flatten_matrix($A) 381 Usage: ra_flatten_matrix($A)
573 } 446 }
574 } 447 }
575 $ra_out; 448$ra_out;
576} 449}
577 450
451
453
454 Usage $\{ answer_matrix(rows,columns,width_of_ans_rule, @options) \}$
455
456 Creates an array of answer blanks and passes it to display_matrix which returns
457 text which represents the matrix in TeX format used in math display mode. Answers
458 are then passed back to whatever answer evaluators you write at the end of the problem.
459 (note, if you have an m x n matrix, you will need mn answer evaluators, and they will be
460 returned to the evaluaters starting in the top left hand corner and proceed to the left
461 and then at the end moving down one row, just as you would read them.)
462
463 The options are passed on to display_matrix.
464
465
466=cut
467
468
470 my $m = shift; 471 my$n = shift;
472 my $width = shift; 473 my @options = @_; 474 my @array=(); 475 for( my$i = 0; $i <$m; $i+=1) 476 { 477 my @row_array = (); 478 479 for( my$i = 0; $i <$n; $i+=1) 480 { 481 push @row_array, ans_rule($width);
482 }
483 my $r_row_array = \@row_array; 484 push @array,$r_row_array;
485 }
486 display_matrix( \@array, @options );
487
488}
578 489
580# my $ra_eigenvalues = shift; 491# my$ra_eigenvalues = shift;
581# my $ra_eigenvectors = shift; 492# my$ra_eigenvectors = shift;
582# my $functionName = shift; 493# my$functionName = shift;