| … | |
… | |
| 108 | |
108 | |
| 109 | ############ |
109 | ############ |
| 110 | |
110 | |
| 111 | =head4 display_matrix |
111 | =head4 display_matrix |
| 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 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 | |
117 | |
| 146 | |
118 | |
| 147 | =cut |
119 | =cut |
| 148 | |
120 | |
| 149 | |
121 | |
| 150 | sub display_matrix_mm{ # will display a matrix in tex format. |
122 | sub 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 | |
| 155 | sub display_matrix_math_mode { |
165 | sub display_matrix_math_mode { |
| 156 | return display_matrix_mm(@_); |
166 | return display_matrix_mm(@_); |
| 157 | } |
167 | } |
| 158 | |
168 | |
| 159 | sub display_matrix { |
169 | sub 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 | my $alignString=''; # alignment as a string for dvi/pdf |
| 202 | my $alignList; # alignment as a list |
198 | my $alignList; # 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 "|" |
202 | $alignString =~ 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 | |
| 217 | $out .= dm_begin_matrix($alignString, %opts); |
211 | $out .= dm_begin_matrix($alignString, %opts); |
| 218 | $out .= 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); |
214 | $out .= 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 | } |
| … | |
… | |
| 230 | sub dm_begin_matrix { |
221 | sub 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 | 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'} ? '' : '\('; |
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."/left$numrows.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 | |
| 288 | sub dm_mat_right { |
279 | sub 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 | |
| 315 | sub dm_end_matrix { |
311 | sub 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 |
|
|
| 336 | sub 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 |
|
|
| 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 { |
332 | sub 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 "|"); |
| 421 | $myalign = 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 |
|
|
| 428 | $out .= '<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";} |
| 439 | $out .= "$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 | } |
| 442 | $out .= "$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 | |
|
|
| 467 | sub mbox { |
|
|
| 468 | my $inList = 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 | |
| 506 | =head4 ra_flatten_matrix |
379 | =head4 ra_flatten_matrix |
| 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 | |
|
|
452 | =head5 answer_matrix |
|
|
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 | |
|
|
469 | sub answer_matrix{ |
|
|
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 | |
| 579 | # sub format_answer{ |
490 | # sub format_answer{ |
| 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; |