Parent Directory
|
Revision Log
Added HTML_img mode to PGmatrixmacros.pl display commands. --Mike
1 #!/usr/local/bin/webwork-perl 2 3 ########### 4 #use Carp; 5 6 =head1 NAME 7 8 Matrix macros for the PG language 9 10 =head1 SYNPOSIS 11 12 13 14 =head1 DESCRIPTION 15 16 Almost all of the macros in the file are very rough at best. The most useful is display_matrix. 17 Many of the other macros work with vectors and matrices stored as anonymous arrays. 18 19 Frequently it may be 20 more useful to use the Matrix objects defined RealMatrix.pm and Matrix.pm and the constructs listed there. 21 22 23 =cut 24 25 BEGIN { 26 be_strict(); 27 } 28 29 sub _PGmatrixmacros_init { 30 } 31 32 # this subroutine zero_check is not very well designed below -- if it is used much it should receive 33 # more work -- particularly for checking relative tolerance. More work needs to be done if this is 34 # actually used. 35 36 sub zero_check{ 37 my $array = shift; 38 my %options = @_; 39 my $num = @$array; 40 my $i; 41 my $max = 0; my $mm; 42 for ($i=0; $i< $num; $i++) { 43 $mm = $array->[$i] ; 44 $max = abs($mm) if abs($mm) > $max; 45 } 46 my $tol = $options{tol}; 47 $tol = 0.01*$options{reltol}*$options{avg} if defined($options{reltol}) and defined $options{avg}; 48 $tol = .000001 unless defined($tol); 49 ($max <$tol) ? 1: 0; # 1 if the array is close to zero; 50 } 51 sub vec_dot{ 52 my $vec1 = shift; 53 my $vec2 = shift; 54 warn "vectors must have the same length" unless @$vec1 == @$vec2; # the vectors must have the same length. 55 my @vec1=@$vec1; 56 my @vec2=@$vec2; 57 my $sum = 0; 58 59 while(@vec1) { 60 $sum += shift(@vec1)*shift(@vec2); 61 } 62 $sum; 63 } 64 sub proj_vec { 65 my $vec = shift; 66 warn "First input must be a column matrix" unless ref($vec) eq 'Matrix' and ${$vec->dim()}[1] == 1; 67 my $matrix = shift; # the matrix represents a set of vectors spanning the linear space 68 # onto which we want to project the vector. 69 warn "Second input must be a matrix" unless ref($matrix) eq 'Matrix' and ${$matrix->dim()}[1] == ${$vec->dim()}[0]; 70 $matrix * transpose($matrix) * $vec; 71 } 72 73 sub vec_cmp{ #check to see that the submitted vector is a non-zero multiple of the correct vector 74 my $correct_vector = shift; 75 my %options = @_; 76 my $ans_eval = sub { 77 my $in = shift @_; 78 79 my $ans_hash = new AnswerHash; 80 my @in = split("\0",$in); 81 my @correct_vector=@$correct_vector; 82 $ans_hash->{student_ans} = "( " . join(", ", @in ) . " )"; 83 $ans_hash->{correct_ans} = "( " . join(", ", @correct_vector ) . " )"; 84 85 return($ans_hash) unless @$correct_vector == @in; # make sure the vectors are the same dimension 86 87 my $correct_length = vec_dot($correct_vector,$correct_vector); 88 my $in_length = vec_dot(\@in,\@in); 89 return($ans_hash) if $in_length == 0; 90 91 if (defined($correct_length) and $correct_length != 0) { 92 my $constant = vec_dot($correct_vector,\@in)/$correct_length; 93 my @difference = (); 94 for(my $i=0; $i < @correct_vector; $i++ ) { 95 $difference[$i]=$constant*$correct_vector[$i] - $in[$i]; 96 } 97 $ans_hash->{score} = zero_check(\@difference); 98 99 } else { 100 $ans_hash->{score} = 1 if vec_dot(\@in,\@in) == 0; 101 } 102 $ans_hash; 103 104 }; 105 106 $ans_eval; 107 } 108 109 ############ 110 111 =head4 display_matrix 112 113 Usage \{ display_matrix( [ [1, '\(\sin x\)'], [ans_rule(5), 6] ]) \} 114 \{ display_matrix($A, align=>'crvl') \} 115 \[ \{ display_matrix_mm($A) \} \] 116 \[ \{ display_matrix_mm([ [1, 3], [4, 6] ]) \} \] 117 118 display_matrix produces a matrix for display purposes. It checks whether 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 variable $defaultDisplayMatrixStyle, 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 146 147 =cut 148 149 150 sub display_matrix_mm{ # will display a matrix in tex format. 151 # the matrix can be either of type array or type 'Matrix' 152 return display_matrix(@_, 'force_tex'=>1); 153 } 154 155 sub display_matrix_math_mode { 156 return display_matrix_mm(@_); 157 } 158 159 sub display_matrix { 160 my $ra_matrix = shift; 161 my %opts = @_; 162 # Now a global variable? 163 my $styleParams = defined($main::defaultDisplayMatrixStyle) ? 164 $main::defaultDisplayMatrixStyle : "(s)"; 165 166 set_default_options(\%opts, 167 '_filter_name' => 'displaymat', 168 '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); 173 174 my ($numRows, $numCols, @myRows); 175 176 if (ref($ra_matrix) eq 'Matrix' ) { 177 ($numRows, $numCols) = $ra_matrix->dim(); 178 for( my $i=0; $i<$numRows; $i++) { 179 $myRows[$i] = []; 180 for (my $j=0; $j<$numCols; $j++) { 181 my $entry = $ra_matrix->element($i+1,$j+1); 182 $entry = "#" unless defined($entry); 183 push @{ $myRows[$i] }, $entry; 184 } 185 } 186 } else { # matrix is input at [ [1,2,3],[4,5,6]] 187 $numCols = 0; 188 @myRows = @{$ra_matrix}; 189 $numRows = scalar(@myRows); # counts horizontal rules too 190 my $tmp; 191 for $tmp (@myRows) { 192 if($tmp ne 'hline') { 193 my @arow = @{$tmp}; 194 $numCols= scalar(@arow); #number of columns in table 195 last; 196 } 197 } 198 } 199 my $out; 200 my $j; 201 my $alignString=''; # alignment as a string for dvi/pdf 202 my $alignList; # alignment as a list 203 204 if(defined($opts{'align'})) { 205 $alignString= $opts{'align'}; 206 $alignString =~ s/v/$opts{'midrule'}/g; 207 $alignString =~ tr/s/|/; # Treat "s" as "|" 208 $alignString =~ tr/n//; # Remove "n" altogether 209 @$alignList = split //, $alignString; 210 } else { 211 for($j=0; $j<$numCols; $j++) { 212 $alignList->[$j] = "c"; 213 $alignString .= "c"; 214 } 215 } 216 217 $out .= dm_begin_matrix($alignString, %opts); 218 $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) { 223 $out .= dm_mat_row($j, $alignList, %opts, 'isfirst'=>0); 224 } 225 $out .= dm_mat_right($numRows, %opts); 226 $out .= dm_end_matrix(%opts); 227 $out; 228 } 229 230 sub dm_begin_matrix { 231 my ($aligns)=shift; #alignments of columns in table 232 my %opts = @_; 233 my $out = ""; 234 if ($main::displayMode eq 'TeX' or $opts{'force_tex'}) { 235 # $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 for $j (@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'} ? '' : '\('; 246 $out .= '\displaystyle\left'.$opts{'left'}."\\begin{array}{$aligns} \n"; 247 } 248 elsif ($main::displayMode eq 'Latex2HTML') { 249 $out .= "\n\\begin{rawhtml} <TABLE BORDER=0>\n\\end{rawhtml}"; 250 } 251 elsif ($main::displayMode eq 'HTML' || $main::displayMode eq 'HTML_tth' || $main::displayMode eq 'HTML_dpng' || $main::displayMode eq 'HTML_img') { 252 $out .= "<TABLE BORDER=0>\n" 253 } 254 else { 255 $out = "Error: dm_begin_matrix: Unknown displayMode: $main::displayMode.\n"; 256 } 257 $out; 258 } 259 260 261 sub dm_mat_left { 262 my $numrows = shift; 263 my %opts = @_; 264 if ($main::displayMode eq 'TeX' or $opts{'force_tex'}) { 265 return ""; 266 } 267 my $out=''; 268 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 275 if(($main::displayMode eq 'HTML_dpng') || $main::displayMode eq 'HTML_img' || ($main::displayMode eq 'Latex2HTML')) { 276 $out .= "$brh<tr valign=\"center\"><td nowrap=\"nowrap\" align=\"left\">$erh"; 277 $out .= dm_image_delimeter($numrows, $opts{'left'}); 278 $out .= "$brh<td><table border=0 cellspacing=5>\n$erh"; 279 return $out; 280 } 281 # Mode is now tth 282 283 $out .= dm_tth_delimeter($numrows, $opts{'left'}); 284 $out .= "<td><table border=0 cellspacing=5>\n"; 285 return $out; 286 } 287 288 sub dm_mat_right { 289 my $numrows = shift; 290 my %opts = @_; 291 my $out=''; 292 my $j; 293 294 if ($main::displayMode eq 'TeX' or $opts{'force_tex'}) { 295 return ""; 296 } 297 298 if(($main::displayMode eq 'HTML_dpng') ||$main::displayMode eq 'HTML_img'|| ($main::displayMode eq 'Latex2HTML')) { 299 if($main::displayMode eq 'Latex2HTML') { $out .= '\begin{rawhtml}'; } 300 $out .= "</table><td nowrap=\"nowrap\" align=\"right\">"; 301 if($main::displayMode eq 'Latex2HTML') { $out .= '\end{rawhtml}'; } 302 303 # $out .= "<img alt=\"(\" src = \"". 304 # "/webwork_system_html/images"."/right$numrows.png\" >"; 305 $out.= dm_image_delimeter($numrows, $opts{'right'}); 306 return $out; 307 } 308 309 $out .= "</table>"; 310 311 $out .= dm_tth_delimeter($numrows, $opts{'right'}); 312 return $out; 313 } 314 315 sub dm_end_matrix { 316 my %opts = @_; 317 318 my $out = ""; 319 if ($main::displayMode eq 'TeX' or $opts{'force_tex'}) { 320 $out .= "\n\\end{array}\\right$opts{right}"; 321 $out .= $opts{'force_tex'} ? '' : "\\) "; 322 } 323 elsif ($main::displayMode eq 'Latex2HTML') { 324 $out .= "\n\\begin{rawhtml} </TABLE >\n\\end{rawhtml}"; 325 } 326 elsif ($main::displayMode eq 'HTML' || $main::displayMode eq 'HTML_tth' || $main::displayMode eq 'HTML_dpng'||$main::displayMode eq 'HTML_img') { 327 $out .= "</TABLE>\n"; 328 } 329 else { 330 $out = "Error: PGmatrixmacros: dm_end_matrix: Unknown displayMode: $main::displayMode.\n"; 331 } 332 $out; 333 } 334 335 # Make an image of a big delimiter for a matrix 336 sub dm_image_delimeter { 337 my $numRows = shift; 338 my $char = shift; 339 my ($out, $j); 340 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 .= '\(\setlength{\arraycolsep}{0in}\left.\begin{array}{c}'; 358 for($j=0;$j<=$numRows;$j++) { $out .= '\! \\\\'; } 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 365 sub 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 396 sub dm_mat_row { 397 my $elements = shift; 398 my $tmp = shift; 399 my @align = @{$tmp} ; 400 my %opts = @_; 401 my @elements = @{$elements}; 402 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'}) { 409 while (@elements) { 410 $out .= shift(@elements) . " &"; 411 } 412 chop($out); # remove last & 413 $out .= "\\cr \n"; 414 # carriage returns must be added manually for tex 415 } elsif ($main::displayMode eq 'HTML' || $main::displayMode eq 'HTML_tth' 416 || $main::displayMode eq 'HTML_dpng' 417 || $main::displayMode eq 'HTML_img' 418 || $main::displayMode eq 'Latex2HTML') { 419 $out .= "$brh\n<TR>\n$erh"; 420 while (@elements) { 421 my $myalign; 422 $myalign = shift @align; 423 if($myalign eq "|" or $myalign eq "d") { 424 if($opts{'isfirst'} && $main::displayMode ne 'HTML_tth') { 425 $out .= $brh.'<td rowspan="'.$opts{'isfirst'}.'">'.$erh; 426 $out .= dm_image_delimeter($opts{'isfirst'}-1, $myalign); 427 } elsif($main::displayMode eq 'HTML_tth') { 428 if($myalign eq "d") { # dashed line in tth mode 429 $out .= '<td> | </td>'; 430 } elsif($opts{'isfirst'}) { # solid line in tth mode 431 $out .= '<td rowspan="'.$opts{'isfirst'}.'"<table border="0"><tr>'; 432 $out .= dm_tth_delimeter($opts{'isfirst'}-1, "|"); 433 $out .= '</td></tr></table>'; 434 } 435 } 436 } else { 437 if($myalign eq "c") { $myalign = "center";} 438 if($myalign eq "l") { $myalign = "left";} 439 if($myalign eq "r") { $myalign = "right";} 440 $out .= "$brh<TD nowrap=\"nowrap\" align=\"$myalign\">$erh" . shift(@elements) . "$brh</TD>$erh"; 441 } 442 } 443 $out .= "$brh\n</TR>\n$erh"; 444 } 445 else { 446 $out = "Error: dm_mat_row: Unknown displayMode: $main::displayMode.\n"; 447 } 448 $out; 449 } 450 451 =head4 mbox 452 453 Usage \{ mbox(thing1, thing2, thing3) \} 454 \{ mbox([thing1, thing2, thing3], valign=>'top') \} 455 456 mbox takes a list of constructs, such as strings, or outputs of 457 display_matrix, and puts them together on a line. Without mbox, the 458 output of display_matrix would always start a new line. 459 460 The inputs can be just listed, or given as a reference to an array. 461 With the latter, optional arguments can be given. 462 463 Optional arguments are allowbreaks=>'yes' to allow line breaks in TeX 464 output; and valign which sets vertical alignment on web page output. 465 466 =cut 467 468 sub mbox { 469 my $inList = shift; 470 my %opts; 471 if(ref($inList) eq 'ARRAY') { 472 %opts = @_; 473 } else { 474 %opts = (); 475 $inList = [$inList, @_]; 476 } 477 478 set_default_options(\%opts, 479 '_filter_name' => 'mbox', 480 'valign' => 'middle', 481 'allowbreaks' => 'no', 482 'allow_unknown_options'=> 0); 483 if(! $opts{'allowbreaks'}) { $opts{'allowbreaks'}='no';} 484 my $out = ""; 485 my $j; 486 my ($brh, $erh) = ("",""); # Start and end raw html if needed 487 if($main::displayMode eq 'Latex2HTML') { 488 $brh = "\\begin{rawhtml}"; 489 $erh = "\\end{rawhtml}"; 490 } 491 my @hlist = @{$inList}; 492 if($main::displayMode eq 'TeX') { 493 if($opts{allowbreaks} ne 'no') {$out .= '\mbox{';} 494 for $j (@hlist) { $out .= $j;} 495 if($opts{allowbreaks} ne 'no') {$out .= '}';} 496 } else { 497 $out .= qq!$brh<table><tr valign="$opts{'valign'}">$erh!; 498 for $j (@hlist) { 499 $out .= qq!$brh<td align="center" nowrap="nowrap">$erh$j$brh</td>$erh!; 500 } 501 $out .= "$brh</table>$erh"; 502 } 503 return $out; 504 } 505 506 507 =head4 ra_flatten_matrix 508 509 Usage: ra_flatten_matrix($A) 510 511 where $A is a matrix object 512 The output is a reference to an array. The matrix is placed in the array by iterating 513 over columns on the inside 514 loop, then over the rows. (e.g right to left and then down, as one reads text) 515 516 517 =cut 518 519 520 sub ra_flatten_matrix{ 521 my $matrix = shift; 522 warn "The argument must be a matrix object" unless ref($matrix) =~ /Matrix/; 523 my @array = (); 524 my ($rows, $cols ) = $matrix->dim(); 525 foreach my $i (1..$rows) { 526 foreach my $j (1..$cols) { 527 push(@array, $matrix->element($i,$j) ); 528 } 529 } 530 \@array; 531 } 532 533 # This subroutine is probably obsolete and not generally useful. It was patterned after the APL 534 # constructs for multiplying matrices. It might come in handy for non-standard multiplication of 535 # of matrices (e.g. mod 2) for indice matrices. 536 sub apl_matrix_mult{ 537 my $ra_a= shift; 538 my $ra_b= shift; 539 my %options = @_; 540 my $rf_op_times= sub {$_[0] *$_[1]}; 541 my $rf_op_plus = sub {my $sum = 0; my @in = @_; while(@in){ $sum = $sum + shift(@in) } $sum; }; 542 $rf_op_times = $options{'times'} if defined($options{'times'}) and ref($options{'times'}) eq 'CODE'; 543 $rf_op_plus = $options{'plus'} if defined($options{'plus'}) and ref($options{'plus'}) eq 'CODE'; 544 my $rows = @$ra_a; 545 my $cols = @{$ra_b->[0]}; 546 my $k_size = @$ra_b; 547 my $out ; 548 my ($i, $j, $k); 549 for($i=0;$i<$rows;$i++) { 550 for($j=0;$j<$cols;$j++) { 551 my @r = (); 552 for($k=0;$k<$k_size;$k++) { 553 $r[$k] = &$rf_op_times($ra_a->[$i]->[$k] , $ra_b->[$k]->[$j]); 554 } 555 $out->[$i]->[$j] = &$rf_op_plus( @r ); 556 } 557 } 558 $out; 559 } 560 561 sub matrix_mult { 562 apl_matrix_mult($_[0], $_[1]); 563 } 564 565 sub make_matrix{ 566 my $function = shift; 567 my $rows = shift; 568 my $cols = shift; 569 my ($i, $j, $k); 570 my $ra_out; 571 for($i=0;$i<$rows;$i++) { 572 for($j=0;$j<$cols;$j++) { 573 $ra_out->[$i]->[$j] = &$function($i,$j); 574 } 575 } 576 $ra_out; 577 } 578 579 580 =head5 answer_matrix 581 582 Usage \[ \{ answer_matrix(rows,columns,width_of_ans_rule, @options) \} \] 583 584 Creates an array of answer blanks and passes it to display_matrix which returns 585 text which represents the matrix in TeX format used in math display mode. Answers 586 are then passed back to whatever answer evaluators you write at the end of the problem. 587 (note, if you have an m x n matrix, you will need mn answer evaluators, and they will be 588 returned to the evaluaters starting in the top left hand corner and proceed to the left 589 and then at the end moving down one row, just as you would read them.) 590 591 The options are passed on to display_matrix. 592 593 594 =cut 595 596 597 sub answer_matrix{ 598 my $m = shift; 599 my $n = shift; 600 my $width = shift; 601 my @options = @_; 602 my @array=(); 603 for( my $i = 0; $i < $m; $i+=1) 604 { 605 my @row_array = (); 606 607 for( my $i = 0; $i < $n; $i+=1) 608 { 609 push @row_array, ans_rule($width); 610 } 611 my $r_row_array = \@row_array; 612 push @array, $r_row_array; 613 } 614 display_matrix( \@array, @options ); 615 616 } 617 618 # sub format_answer{ 619 # my $ra_eigenvalues = shift; 620 # my $ra_eigenvectors = shift; 621 # my $functionName = shift; 622 # my @eigenvalues=@$ra_eigenvalues; 623 # my $size= @eigenvalues; 624 # my $ra_eigen = make_matrix( sub {my ($i,$j) = @_; ($i==$j) ? "e^{$eigenvalues[$j] t}": 0 }, $size,$size); 625 # my $out = qq! 626 # $functionName(t) =! . 627 # displayMatrix(apl_matrix_mult($ra_eigenvectors,$ra_eigen, 628 # 'times'=>sub{($_[0] and $_[1]) ? "$_[0]$_[1]" : ''}, 629 # 'plus'=>sub{ my $out = join("",@_); ($out) ?$out : '0' } 630 # ) ) ; 631 # $out; 632 # } 633 # sub format_vector_answer{ 634 # my $ra_eigenvalues = shift; 635 # my $ra_eigenvectors = shift; 636 # my $functionName = shift; 637 # my @eigenvalues=@$ra_eigenvalues; 638 # my $size= @eigenvalues; 639 # my $ra_eigen = make_matrix( sub {my ($i,$j) = @_; ($i==$j) ? "e^{$eigenvalues[$j] t}": 0 }, $size,$size); 640 # my $out = qq! 641 # $functionName(t) =! . 642 # displayMatrix($ra_eigenvectors)."e^{$eigenvalues[0] t}" ; 643 # $out; 644 # } 645 # sub format_question{ 646 # my $ra_matrix = shift; 647 # my $out = qq! y'(t) = ! . displayMatrix($B). q! y(t)! 648 # 649 # } 650 651 1;
| aubreyja at gmail dot com | ViewVC Help |
| Powered by ViewVC 1.0.9 |