You can subscribe to this list here.
2004 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(58) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
(53) |
Feb
(56) |
Mar
|
Apr
|
May
(30) |
Jun
(78) |
Jul
(121) |
Aug
(155) |
Sep
(77) |
Oct
(61) |
Nov
(45) |
Dec
(94) |
2006 |
Jan
(116) |
Feb
(33) |
Mar
(11) |
Apr
(23) |
May
(60) |
Jun
(89) |
Jul
(130) |
Aug
(109) |
Sep
(124) |
Oct
(63) |
Nov
(82) |
Dec
(45) |
2007 |
Jan
(31) |
Feb
(35) |
Mar
(123) |
Apr
(36) |
May
(18) |
Jun
(134) |
Jul
(133) |
Aug
(241) |
Sep
(126) |
Oct
(31) |
Nov
(15) |
Dec
(5) |
2008 |
Jan
(11) |
Feb
(6) |
Mar
(16) |
Apr
(29) |
May
(43) |
Jun
(149) |
Jul
(27) |
Aug
(29) |
Sep
(37) |
Oct
(20) |
Nov
(4) |
Dec
(6) |
2009 |
Jan
(34) |
Feb
(30) |
Mar
(16) |
Apr
(6) |
May
(1) |
Jun
(32) |
Jul
(22) |
Aug
(7) |
Sep
(18) |
Oct
(50) |
Nov
(22) |
Dec
(8) |
2010 |
Jan
(17) |
Feb
(15) |
Mar
(10) |
Apr
(9) |
May
(67) |
Jun
(30) |
Jul
|
Aug
|
Sep
(2) |
Oct
|
Nov
(1) |
Dec
|
From: dpvc v. a. <we...@ma...> - 2009-01-17 15:15:24
|
Log Message: ----------- Avoid ambiguity with CORE::abs() versus overloaded abs(). Modified Files: -------------- pg/macros: contextFraction.pl Revision Data ------------- Index: contextFraction.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/contextFraction.pl,v retrieving revision 1.1 retrieving revision 1.2 diff -Lmacros/contextFraction.pl -Lmacros/contextFraction.pl -u -r1.1 -r1.2 --- macros/contextFraction.pl +++ macros/contextFraction.pl @@ -331,7 +331,7 @@ $self->Error("The denominator of a fraction must be a (non-negative) integer") unless $self->{rop}->class eq 'INTEGER'; $self->Error("The numerator must be less than the denominator in a proper fraction") - if $self->context->flag("requireProperFractions") && abs($self->{lop}->eval) >= abs($self->{rop}->eval); + if $self->context->flag("requireProperFractions") && CORE::abs($self->{lop}->eval) >= CORE::abs($self->{rop}->eval); } # @@ -436,7 +436,7 @@ sub reduce { my $self = shift; my $reduce = $self->{equation}{context}{reduction}; - my ($a,($b,$c)) = (abs($self->{lop}->eval),$self->{rop}->eval->value); + my ($a,($b,$c)) = (CORE::abs($self->{lop}->eval),$self->{rop}->eval->value); if ($reduce->{'a b/c'}) { ($b,$c) = context::Fraction::reduce($b,$c) if $reduce->{'a/b'}; $a += int($b/$c); $b = $b % $c; @@ -712,8 +712,8 @@ my $self = shift; my $equation = shift; my $prec = shift; my ($a,$b) = @{$self->{data}}; my $n = ""; return $a if $b == 1; - if ($self->getFlag("showProperFractions") && abs($a) > $b) - {$n = int($a/$b); $a = abs($a) % $b; $n .= " " unless $a == 0} + if ($self->getFlag("showProperFractions") && CORE::abs($a) > $b) + {$n = int($a/$b); $a = CORE::abs($a) % $b; $n .= " " unless $a == 0} $n .= "$a/$b" unless $a == 0 && $n ne ''; $n = "($n)" if defined $prec && $prec >= 1; return $n; @@ -723,8 +723,8 @@ my $self = shift; my $equation = shift; my $prec = shift; my ($a,$b) = @{$self->{data}}; my $n = ""; return $a if $b == 1; - if ($self->getFlag("showProperFractions") && abs($a) > $b) - {$n = int($a/$b); $a = abs($a) % $b; $n .= " " unless $a == 0} + if ($self->getFlag("showProperFractions") && CORE::abs($a) > $b) + {$n = int($a/$b); $a = CORE::abs($a) % $b; $n .= " " unless $a == 0} my $s = ""; ($a,$s) = (-$a,"-") if $a < 0; $n .= ($self->{isHorizontal} ? "$s$a/$b" : "${s}{\\textstyle\\frac{$a}{$b}}") unless $a == 0 && $n ne ''; |
From: Mike G. v. a. <we...@ma...> - 2009-01-17 03:34:50
|
Log Message: ----------- Fixed comment Modified Files: -------------- pg/macros: AppletObjects.pl Revision Data ------------- Index: AppletObjects.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/AppletObjects.pl,v retrieving revision 1.11 retrieving revision 1.12 diff -Lmacros/AppletObjects.pl -Lmacros/AppletObjects.pl -u -r1.11 -r1.12 --- macros/AppletObjects.pl +++ macros/AppletObjects.pl @@ -22,7 +22,7 @@ =head1 DESCRIPTION This subroutines in this -file provide mechanisms to insert Flash applets (and later Java applets) +file provide mechanisms to insert Flash applets (and Java applets) into a WeBWorK problem. |
From: Mike G. v. a. <we...@ma...> - 2009-01-17 03:33:25
|
Log Message: ----------- Fixed error in hint() associated with always showing the instructor that a hint exists. Modified Files: -------------- pg/macros: PGbasicmacros.pl Revision Data ------------- Index: PGbasicmacros.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/PGbasicmacros.pl,v retrieving revision 1.56 retrieving revision 1.57 diff -Lmacros/PGbasicmacros.pl -Lmacros/PGbasicmacros.pl -u -r1.56 -r1.57 --- macros/PGbasicmacros.pl +++ macros/PGbasicmacros.pl @@ -998,22 +998,23 @@ my @in = @_; my $out = ''; my $permissionLevel = PG_restricted_eval(q!$main::envir{permissionLevel}!); - my $PRINT_FILE_NAMES_PERMISSION_LEVEL = PG_restricted_eval(q!$envir->{'PRINT_FILE_NAMES_PERMISSION_LEVEL'}!); + my $PRINT_FILE_NAMES_PERMISSION_LEVEL = (PG_restricted_eval(q!defined( $main::envir{'PRINT_FILE_NAMES_PERMISSION_LEVEL'} )!))? + PG_restricted_eval(q!$main::envir{'PRINT_FILE_NAMES_PERMISSION_LEVEL'}!) : 10000; # protect against undefined values my $printHintForInstructor = $permissionLevel >= $PRINT_FILE_NAMES_PERMISSION_LEVEL; my $showHint = PG_restricted_eval(q!$main::showHint!); - my $displayHint = PG_restricted_eval(q!$envir->{'displayHintsQ'}!); + my $displayHint = PG_restricted_eval(q!$envir{'displayHintsQ'}!); PG_restricted_eval(q!$main::hintExists =1!); PG_restricted_eval(q!$main::numOfAttempts = 0 unless defined($main::numOfAttempts);!); my $attempts = PG_restricted_eval(q!$main::numOfAttempts!); if ($displayMode eq 'TeX') { if ($printHintForInstructor) { - $out = join(' ',@in, "$BR(Show hint after $showHint attempts. ) $BR"); + $out = join(' ', "$BR(Show the student hint after $showHint attempts: ) $BR",@in); } else { $out = ''; # do nothing since hints are not available for download for students } } elsif ($printHintForInstructor) { # always print hints for instructor types - $out = join(' ',@in, "$BR(Show hint after $showHint attempts. )$BR "); + $out = join(' ', "$BR(Show the student hint after $showHint attempts: )$BR ", @in); } elsif ( $displayHint and ( $attempts > $showHint )) { ## the second test above prevents a hint being shown if a doctored form is submitted |
From: dpvc v. a. <we...@ma...> - 2009-01-15 23:05:28
|
Log Message: ----------- Typo that prevented the context name from being set properly. Modified Files: -------------- pg/macros: contextOrdering.pl Revision Data ------------- Index: contextOrdering.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/contextOrdering.pl,v retrieving revision 1.7 retrieving revision 1.8 diff -Lmacros/contextOrdering.pl -Lmacros/contextOrdering.pl -u -r1.7 -r1.8 --- macros/contextOrdering.pl +++ macros/contextOrdering.pl @@ -116,7 +116,7 @@ $context->{error}{msg}{"Missing operand after '%s'"} = "Missing letter after '%s'"; $context = $main::context{'Ordering-List'} = $context->copy; - $context->{name} eq 'Ordering-List'; + $context->{name} = 'Ordering-List'; $context->operators->redefine(',',from => "Full"); $context->{value}{List} = "context::Ordering::Value::List"; |
From: dpvc v. a. <we...@ma...> - 2009-01-15 13:20:39
|
Log Message: ----------- Fixed a typo in an error message. Modified Files: -------------- pg/macros: contextOrdering.pl Revision Data ------------- Index: contextOrdering.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/contextOrdering.pl,v retrieving revision 1.6 retrieving revision 1.7 diff -Lmacros/contextOrdering.pl -Lmacros/contextOrdering.pl -u -r1.6 -r1.7 --- macros/contextOrdering.pl +++ macros/contextOrdering.pl @@ -190,7 +190,7 @@ sub _check { my $self = shift; - $self->Error("Operators of %s must be letters",$self->{bop}) + $self->Error("Operands of %s must be letters",$self->{bop}) unless $self->isOrdering($self->{lop}) && $self->isOrdering($self->{rop}); $self->{letters} = $self->{lop}{letters}; # we modify {lop}{letters} this way, but that doesn't matter foreach my $x (keys %{$self->{rop}{letters}}) { |
From: dpvc v. a. <we...@ma...> - 2009-01-15 12:59:46
|
Log Message: ----------- Make Ordering() break a string at > and = rather than assume the variable names are single letters. Modified Files: -------------- pg/macros: contextOrdering.pl Revision Data ------------- Index: contextOrdering.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/contextOrdering.pl,v retrieving revision 1.5 retrieving revision 1.6 diff -Lmacros/contextOrdering.pl -Lmacros/contextOrdering.pl -u -r1.5 -r1.6 --- macros/contextOrdering.pl +++ macros/contextOrdering.pl @@ -32,7 +32,7 @@ would both produce the same ordering. The first form gives the ordering as the student must type it, and the second gives the ordering by specifying numeric values for the various letters that -determine the resulting order. Note that equality is determined using +induce the resulting order. Note that equality is determined using the default tolerances for the Ordering context. You can change these using commands like the following: @@ -149,8 +149,8 @@ unless $context->{name} =~ m/Ordering/; if (scalar(@_) == 1) { $string = shift; - my $letters = $string; $letters =~ s/[^A-Z]//ig; - context::Ordering::Letters($context,split(//,$letters)); + my $letters = $string; $letters =~ s/ //g; + context::Ordering::Letters($context,split(/[>=]/,$letters)); } else { my %letter = @_; my @letters = keys %letter; context::Ordering::Letters($context,@letters); |
From: dpvc v. a. <we...@ma...> - 2009-01-14 13:49:04
|
Log Message: ----------- Make the Prob. List. button inactive when used on an Undefined_Set (i.e., in the Library Browser). This prevents an error page when an instructor clicks on the button rather than going back to the Library Browser page. Modified Files: -------------- webwork2/lib/WeBWorK/ContentGenerator: Problem.pm Added Files: ----------- webwork2/htdocs/images: navProbListGrey.gif Revision Data ------------- Index: Problem.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator/Problem.pm,v retrieving revision 1.215 retrieving revision 1.216 diff -Llib/WeBWorK/ContentGenerator/Problem.pm -Llib/WeBWorK/ContentGenerator/Problem.pm -u -r1.215 -r1.216 --- lib/WeBWorK/ContentGenerator/Problem.pm +++ lib/WeBWorK/ContentGenerator/Problem.pm @@ -698,12 +698,12 @@ })}, "Problem $problemID") ); } - + print CGI::end_ul(); #print CGI::end_li(); #print CGI::end_ul(); print CGI::end_div(); - + return ""; } @@ -712,17 +712,17 @@ my $r = $self->r; my $db = $r->db; my $urlpath = $r->urlpath; - + return "" if ( $self->{invalidSet} ); my $courseID = $urlpath->arg("courseID"); my $setID = $self->{set}->set_id if !($self->{invalidSet}); my $problemID = $self->{problem}->problem_id if !($self->{invalidProblem}); my $eUserID = $r->param("effectiveUser"); - + my ($prevID, $nextID); - if (!$self->{invalidProblem}) { + if (!$self->{invalidProblem}) { my @problemIDs = $db->listUserProblems($eUserID, $setID); foreach my $id (@problemIDs) { $prevID = $id if $id < $problemID @@ -731,9 +731,9 @@ and (not defined $nextID or $id < $nextID); } } - + my @links; - + if ($prevID) { my $prevPage = $urlpath->newFromModule(__PACKAGE__, courseID => $courseID, setID => $setID, problemID => $prevID); @@ -741,9 +741,13 @@ } else { push @links, "Previous Problem", "", "navPrevGrey"; } - - push @links, "Problem List", $r->location . $urlpath->parent->path, "navProbList"; - + + if (defined($setID) && $setID ne 'Undefined_Set') { + push @links, "Problem List", $r->location . $urlpath->parent->path, "navProbList"; + } else { + push @links, "Problem List", "", "navProbListGrey"; + } + if ($nextID) { my $nextPage = $urlpath->newFromModule(__PACKAGE__, courseID => $courseID, setID => $setID, problemID => $nextID); @@ -751,9 +755,9 @@ } else { push @links, "Next Problem", "", "navNextGrey"; } - + my $tail = ""; - + $tail .= "&displayMode=".$self->{displayMode} if defined $self->{displayMode}; $tail .= "&showOldAnswers=".$self->{will}->{showOldAnswers} if defined $self->{will}->{showOldAnswers}; @@ -766,7 +770,7 @@ # using the url arguments won't break if the set/problem are invalid my $setID = WeBWorK::ContentGenerator::underscore2nbsp($self->r->urlpath->arg("setID")); my $problemID = $self->r->urlpath->arg("problemID"); - + return "$setID: Problem $problemID"; } |
From: dpvc v. a. <we...@ma...> - 2009-01-14 04:07:05
|
Log Message: ----------- This file implements a Fraction object for the MathObjects library. See the comments in the file for details about how they work and how to control the various options. Added Files: ----------- pg/macros: contextFraction.pl Revision Data ------------- --- /dev/null +++ macros/contextFraction.pl @@ -0,0 +1,780 @@ +=head1 NAME + +contextFraction.pl - Implements a MathObject class for Fractions. + +=head1 DESCRIPTION + +This context implements a Fraction object that works like a Real, but +keeps the numerator and denominator separate. It provides methods for +reducing the fractions, and for allowing fractions with a whole-number +preceeding it, as in 4 1/2 for "four and one half". The answer +checker can require that students reduce their results, and there are +contexts that don't allow entery of decimal values (only fractions), +and that don't allow any operators or functions (other than division +and negation). + +To use these contexts, first load the contextFraction.pl file: + + loadMacros("contextFraction.pl"); + +and then select the appropriate context -- one of the following three: + + Context("Fraction"); + Context("Fraction-NoDecimal"); + Context("LimitedFraction"); + +The first is the most general, and allows fractions to be intermixed +with real numbers, so 1/2 + .5 would be allowed. Also, 1/2.5 is +allowed, though it produces a real number, not a fraction, since this +fraction class only implements fractions of integers. All operators +and functions are defined, so there are no restrictions on what is +allowed by the student. + +The second does not allow decimal numbers to be entered, but they can +still be produced as the result of function calls, or by named +constants such as "pi". For example, 1/sqrt(2) is allowed (and +produces a real number result). All functions and operations are +defined, and the only real difference between this and the previous +context is that decimal numbers can't be typed in explicitly. + +The third context limits the operations that can be performed: in +addition to not being able to type decimal numbers, no operations +other than division and negation are allowed, and no function calls at +all. Thus 1/sqrt(2) would be illegal, as would 1/2 + 2. The student +must enter a whole number or a fraction in this context. It is also +permissible to enter a whole number WITH a fraction, as in 2 1/2 for +"two and one half", or 5/2. + +You can use the Compute() function to generate fraction objects, or +the Fraction() constructor to make one explicitly. For example: + + Context("Fraction"); + $a = Compute("1/2"); + $b = Compute("4 - 1/6"); + $c = Compute("(4/9)^(1/2)"); + + Context("LimitedFraction"); + $d = Compute("4 2/3"); + $e = Compute("-1 1/2"); + + $f = Fraction(-2,5); + +Note that $c will be 2/3, $d will be 14/3, $e will be -3/2, and $f +will be -2/5. + +Once you have created a fraction object, you can use it as you would +any real number. For example: + + Context("Fraction"); + $a = Compute("1/2"); + $b = Compute("1/3"); + $c = $a - $b; + $d = asin($a); + $e = $b**2; + +Here $c will be the equivalent of Compute("1/6"), $d will be +equivalent to Compute("pi/6"), and $e will be the same as Compute("1/9"); + +You can an answer checker for a fraction in the same way as you do for +ALL MathObjects -- via its cmp() method: + + ANS(Compute("1/2")->cmp); + +or + + $b = Compute("1/2"); + ANS($b->cmp); + +There are several options to the cmp() method that control how the +answer checker will work. The first is controls whether unreduced +fractions are accepted as correct. Unreduced fractions are allowed in +the Fraction and Fraction->NoDecimals contexts, but not in the +LimitedFraction context. You can control this using the +studentsMustReduceFractions option: + + Context("Fraction"); + ANS(Compute("1/2")->cmp(studentsMustReduceFractions=>1)); + +or + + Context("LimitedFraction"); + ANS(Compute("1/2")->cmp(studentsMustReduceFractions=>0)); + +The second controls whether warnings are issued when students don't +reduce their answers, or to mark the answer incorrect silently. This +is specified by the showFractionReductionWarnings option. The default +is to report the warnings, but this option has an effect only when +studentsMustReduceFractions is 1, and so only in the LimitedFraction +context. For example, + + Context("LimitedFraction"); + ANS(Compute("1/2")->cmp(showFractionReductionWarnings=>0)); + +turns off these warnings. + +The final option, requireFraction, specifies whether a fraction MUST +be entered (e.g. one would have to enter 2/1 for a whole number). The +default is 0. + +In addition to these options for cmp(), there are Context flags that +control how fractions are handled. These include the following. + +=over + +=item S<C<< reduceFractions >>> + +This determines whether fractions are reduced automatically when they +are created. The default is to reduce fractions (except when +studentsMustReduceFractions is set), so Compute("4/6") would produce +the fraction 2/3. To leave fractions unreduced, set +reduceFractions=>0. The LimitedFraction context has +studentsMustReduceFractions set, so reduceFractions is unset +automatically for students, but not for correct answers, so +Fraction(2,4) would still produce 1/2, even though 2/4 would not be +allowed in a student answer. + +=item S<C<< strictFractions >>> + +This determines whether division is allowed only between integers or +not. If you want to prevent division from accepting non-integers, +then set strictFractions=>1 (and also strictMinus=>1 and +strictMultiplication=>1). These are all three 0 by default in the +Fraction and Fraction->NoDecimals contexts, but 1 in LimitedFraction. + +=item S<C<< allowProperFractions >>> + +This determines whether a space between a whole number and a fraction +is interpretted as implicit multiplication (as it usually would be in +WeBWorK), or as addition, allowing "4 1/2" to mean "4 and 1/2". By +default, it acts as multiplication in the Fraction and +Fraction->NoDecimals contexts, and as addition in LimitedFraction. If +you set allowProperFractions=>1 you should also set reduceConstants=>0. + +=item S<C<< requireProperFractions >>> + +This determines whether fractions MUST be entered as proper fractions. +It is 0 by default, meaning improper fractions are allowed. When set, +you will not be able to enter 5/2 as a fraction, but must use "2 1/2". +Set it to 1 only when you also set allowProperFractions, or you will +not be able to specify fractions bigger than one. It is off by +default in all three contexts. + +=item S<C<< showProperFractions >>> + +This controls whether fractions are displayed as proper fractions or +not. When set, 5/2 will be displayed as 2 1/2 in the answer preview +area, otherwise it will be displayed as 5/2. This flag is 0 by +default in the Fraction and Fraction-NoDecimals contexts, and 1 in +LimitedFraction. + +=back + +Fraction objects have two methods that can be useful when +reduceFractions is set to 0. The reduce() method will reduce a +fraction to lowest terms, and the isReduced() method returns true when +the fraction is reduced and false otherwise. + +If you wish to convert a fraction to its numeric (real number) form, +use the Real() constructor to coerce it to a real. E.g., + + $a = Compute("1/2"); + $r = Real($a); + +would set $r to the value 0.5. Similarly, use Fraction() to convert a +real number to (an approximating) fraction. E.g., + + $r = Real(.5); + $a = Fraction($r); + +would set $a to be 1/2. The fraction produced is good to about 6 +decimal places, so it can't be used for numbers that are too small. + +A side-effect of using the Fraction context is that fractions can be +used to take powers of negative numbers when the reduced form of the +fraction has an odd denominator. Thus (-8)^(1/3) will produce -2 as a +result, while in the standard Numeric context it would produce an +error. + +=cut + +sub _contextFraction_init {context::Fraction::Init()}; + +########################################################################### + +package context::Fraction; + +# +# Initialize the contexts and make the creator function. +# +sub Init { + my $context = $main::context{Fraction} = Parser::Context->getCopy("Numeric"); + $context->{name} = "Fraction"; + $context->{pattern}{signedNumber} .= '|-?\d+/\d+'; + $context->operators->set( + "/" => {class => "context::Fraction::BOP::divide"}, + "//" => {class => "context::Fraction::BOP::divide"}, + "/ " => {class => "context::Fraction::BOP::divide"}, + " /" => {class => "context::Fraction::BOP::divide"}, + "u-" => {class => "context::Fraction::UOP::minus"}, + " " => {precedence => 2.8, string => ' *'}, + " *" => {class => "context::Fraction::BOP::multiply", precedence => 2.8}, + # precedence is lower to get proper parens in string() and TeX() calls + " " => {precedence => 2.7, associativity => 'left', type => 'bin', string => ' ', + class => 'context::Fraction::BOP::multiply', TeX => [' ',' '], hidden => 1}, + ); + $context->flags->set( + reduceFractions => 1, + strictFractions => 0, strictMinus => 0, strictMultiplication => 0, + allowProperFractions => 0, # also set reduceConstants => 0 if you change this + requireProperFractions => 0, + showProperFractions => 0, + ); + $context->reduction->set('a/b' => 1,'a b/c' => 1, '0 a/b' => 1); + $context->{value}{Fraction} = "context::Fraction::Fraction"; + $context->{value}{Real} = "context::Fraction::Real"; + $context->{parser}{Value} = "context::Fraction::Value"; + $context->{parser}{Number} = "Parser::Legacy::LimitedNumeric::Number"; + + $context = $main::context{'Fraction-NoDecimals'} = $context->copy; + $context->{name} = "Fraction-NoDecimals"; + Parser::Number::NoDecimals($context); + + $context = $main::context{LimitedFraction} = $context->copy; + $context->{name} = "LimitedFraction"; + $context->operators->undefine( + '+', '-', '*', '* ', '^', '**', + 'U', '.', '><', 'u+', '!', '_', ',', + ); + $context->parens->undefine('|','{','['); + $context->functions->disable('All'); + $context->flags->set( + strictFractions => 1, strictMinus => 1, strictMultiplication => 1, + allowProperFractions => 1, reduceConstants => 0, + showProperFractions => 1, + ); + $context->{cmpDefaults}{Fraction} = {studentsMustReduceFractions => 1}; + + main::PG_restricted_eval('sub Fraction {Value->Package("Fraction()")->new(@_)};'); +} + +# +# Convert a real to a reduced fraction approximation +# +sub toFraction { + my $context = shift; my $x = shift; + my $Real = $context->Package("Real"); + my $d = 1000000; + my ($a,$b) = reduce(int($x*$d),$d); + return [$Real->make($a),$Real->make($b)]; +} + +# +# Greatest Common Divisor +# +sub gcd { + my $a = abs(shift); my $b = abs(shift); + ($a,$b) = ($b,$a) if $a < $b; + return $a if $b == 0; + my $r = $a % $b; + while ($r != 0) { + ($a,$b) = ($b,$r); + $r = $a % $b; + } + return $b; +} + +# +# Least Common Multiple +# +sub lcm { + my ($a,$b) = @_; + return ($a/gcd($a,$b))*$b; +} + + +# +# Reduced fraction +# +sub reduce { + my $a = shift; my $b = shift; + ($a,$b) = (-$a,-$b) if $b < 0; + my $gcd = gcd($a,$b); + return ($a/$gcd,$b/$gcd); +} + +########################################################################### + +package context::Fraction::BOP::divide; +our @ISA = ('Parser::BOP::divide'); + +# +# Create a Fraction or Real from the given data +# +sub _eval { + my $self = shift; my $context = $self->{equation}{context}; + return $_[0]/$_[1] if Value::isValue($_[0]) || Value::isValue($_[1]); + my $n = $context->Package("Fraction")->make($context,@_); + $n->{isHorizontal} = 1 if $self->{def}{noFrac}; + return $n; +} + +# +# When strictFraction is in effect, only allow division +# with integers and negative integers +# +sub _check { + my $self = shift; + $self->SUPER::_check; + return unless $self->context->flag("strictFractions"); + $self->Error("The numerator of a fraction must be an integer") + unless $self->{lop}->class =~ /INTEGER|MINUS/; + $self->Error("The denominator of a fraction must be a (non-negative) integer") + unless $self->{rop}->class eq 'INTEGER'; + $self->Error("The numerator must be less than the denominator in a proper fraction") + if $self->context->flag("requireProperFractions") && abs($self->{lop}->eval) >= abs($self->{rop}->eval); +} + +# +# Reduce the fraction, if it is one, otherwise do the usual reduce +# +sub reduce { + my $self = shift; + return $self->SUPER::reduce unless $self->class eq 'FRACTION'; + my $reduce = $self->{equation}{context}{reduction}; + return $self->{lop} if $self->{rop}{isOne} && $reduce->{'x/1'}; + $self->Error("Division by zero"), return $self if $self->{rop}{isZero}; + return $self->{lop} if $self->{lop}{isZero} && $reduce->{'0/x'}; + if ($reduce->{'a/b'}) { + my ($a,$b) = context::Fraction::reduce($self->{lop}->eval,$self->{rop}->eval); + if ($self->{lop}->class eq 'INTEGER') {$self->{lop}{value} = $a} else {$self->{lop}{op}{value} = -$a} + $self->{rop}{value} = $b; + } + return $self; +} + +# +# Display minus signs outside the fraction +# +sub TeX { + my $self = shift; my $bop = $self->{def}; + return $self->SUPER::TeX(@_) if $self->class ne 'FRACTION' || $bop->{noFrac}; + my ($precedence,$showparens,$position,$outerRight) = @_; + $showparens = '' unless defined($showparens); + my $addparens = + defined($precedence) && + ($showparens eq 'all' || ($precedence > $bop->{precedence} && $showparens ne 'nofractions') || + ($precedence == $bop->{precedence} && ($bop->{associativity} eq 'right' || $showparens eq 'same'))); + + my $TeX = $self->eval->TeX; + $TeX = '\left('.$TeX.'\right)' if ($addparens); + return $TeX; +} + +# +# Indicate if the value is a fraction or not +# +sub class { + my $self = shift; + return "FRACTION" if $self->{lop}->class =~ /INTEGER|MINUS/ && + $self->{rop}->class eq 'INTEGER'; + return $self->SUPER::class; +} + +########################################################################### + +package context::Fraction::BOP::multiply; +our @ISA = ('Parser::BOP::multiply'); + +# +# For proper fractions, add the integer to the fraction +# +sub _eval { + my ($self,$a,$b)= @_; + return ($a > 0 ? $a + $b : $a - $b); +} + +# +# If the implied multiplication represents a proper fraction with a +# preceeding integer, then switch to the proper fraction operator +# (for proper handling of string() and TeX() calls), otherwise, +# convert the object to a standard multiplication. +# +sub _check { + my $self = shift; + $self->SUPER::_check; + my $isFraction = 0; + if ($self->context->flag("allowProperFractions")) { + $isFraction = ($self->{lop}->class =~ /INTEGER|MINUS/ && !$self->{lop}{hadParens} && + $self->{rop}->class eq 'FRACTION' && !$self->{rop}{hadParens} && + $self->{rop}->eval >= 0); + } + if ($isFraction) { + $self->{bop} = " "; + $self->{def} = $self->context->{operators}{$self->{bop}}; + if ($self->{lop}->class eq 'MINUS') { + # + # Hack to replace BOP with unary negation of BOP. + # (When check() is changed to accept a return value, + # this will not be necessary.) + # + my $copy = bless {%$self}, ref($self); $copy->{lop} = $copy->{lop}{op}; + my $neg = $self->Item("UOP")->new($self->{equation},"u-",$copy); + map {delete $self->{$_}} (keys %$self); + map {$self->{$_} = $neg->{$_}} (keys %$neg); + bless $self, ref($neg); + } + } else { + $self->Error("Can't use implied multiplication in this context",$self->{bop}) + if $self->context->flag("strictMultiplication"); + bless $self, $ISA[0]; + } +} + +# +# Reduce the fraction +# +sub reduce { + my $self = shift; + my $reduce = $self->{equation}{context}{reduction}; + my ($a,($b,$c)) = (abs($self->{lop}->eval),$self->{rop}->eval->value); + if ($reduce->{'a b/c'}) { + ($b,$c) = context::Fraction::reduce($b,$c) if $reduce->{'a/b'}; + $a += int($b/$c); $b = $b % $c; + $self->{lop}{value} = $a; + $self->{rop}{lop}{value} = $b; + $self->{rop}{rop}{value} = $c; + return $self->{lop} if $b == 0 || $c == 1; + } + return $self->{rop} if $a == 0 && $reduce->{'0 a/b'}; + return $self; +} + +########################################################################### + +package context::Fraction::UOP::minus; +our @ISA = ('Parser::UOP::minus'); + +# +# For strict fractions, only allow minus on certain operands +# +sub _check { + my $self = shift; + $self->SUPER::_check; + $self->{hadParens} = 1 if $self->{op}{hadParens}; + return unless $self->context->flag("strictMinus"); + my $uop = $self->{def}{string} || $self->{uop}; + $self->Error("You can only use '%s' with (non-negative) numbers",$uop) + unless $self->{op}->class =~ /Number|INTEGER|FRACTION/; +} + +# +# class is MINUS if it is a negative number +# +sub class { + my $self = shift; + return "MINUS" if $self->{op}->class =~ /Number|INTEGER/; + $self->SUPER::class; +} + +########################################################################### + +package context::Fraction::Value; +our @ISA = ('Parser::Value'); + +# +# Indicate if the Value object is a fraction or not +# +sub class { + my $self = shift; + return "FRACTION" if $self->{value}->classMatch('Fraction'); + return $self->SUPER::class; +} + +########################################################################### + +package context::Fraction::Real; +our @ISA = ('Value::Real'); + +# +# Allow Real to convert Fractions to Reals +# +sub new { + my $self = shift; my $class = ref($self) || $self; + my $context = (Value::isContext($_[0]) ? shift : $self->context); + my $x = shift; $x = $x->eval if scalar(@_) == 0 && Value::classMatch($x,'Fraction'); + $self->SUPER::new($context,$x,@_); +} + +########################################################################### +########################################################################### +# +# Implements the MathObject for fractions +# + +package context::Fraction::Fraction; +our @ISA = ('Value'); + +sub new { + my $self = shift; my $class = ref($self) || $self; + my $context = (Value::isContext($_[0]) ? shift : $self->context); + my $x = shift; $x = [$x,@_] if scalar(@_) > 0; + return $x->inContext($context) if Value::classMatch($x,'Fraction'); + $x = [$x] unless ref($x) eq 'ARRAY'; $x->[1] = 1 if scalar(@{$x}) == 1; + Value::Error("Can't convert ARRAY of length %d to %s",scalar(@{$x}),Value::showClass($self)) + unless (scalar(@{$x}) == 2); + $x->[0] = Value::makeValue($x->[0],context=>$context); + $x->[1] = Value::makeValue($x->[1],context=>$context); + return $x->[0] if Value::classMatch($x->[0],'Fraction') && scalar(@_) == 0; + $x = context::Fraction::toFraction($context,$x->[0]->value) if Value::isReal($x->[0]) && scalar(@_) == 0; + return $self->formula($x) if Value::isFormula($x->[0]) || Value::isFormula($x->[1]); + Value::Error("Fraction numerators must be integers") unless isInteger($x->[0]); + Value::Error("Fraction denominators must be integers") unless isInteger($x->[1]); + my ($a,$b) = ($x->[0]->value,$x->[1]->value); ($a,$b) = (-$a,-$b) if $b < 0; + Value::Error("Denominator can't be zero") if $b == 0; + ($a,$b) = context::Fraction::reduce($a,$b) if $context->flag("reduceFractions"); + bless {data => [$a,$b], context => $context}, $class; +} + +# +# Produce a real if one of the terms is not an integer +# otherwise produce a fraction. +# +sub make { + my $self = shift; my $class = ref($self) || $self; + my $context = (Value::isContext($_[0]) ? shift : $self->context); + push(@_,0) if scalar(@_) == 0; push(@_,1) if scalar(@_) == 1; + my ($a,$b) = @_; ($a,$b) = (-$a,-$b) if $b < 0; + return $context->Package("Real")->make($context,$a/$b) unless isInteger($a) && isInteger($b); + ($a,$b) = context::Fraction::reduce($a,$b) if $context->flag("reduceFractions"); + bless {data => [$a,$b], context => $context}, $class; +} + +# +# Promote to a fraction, allowing reals to be $x/1 even when +# not an integer (later $self->make() will produce a Real in +# that case) +# +sub promote { + my $self = shift; my $class = ref($self) || $self; + my $context = (Value::isContext($_[0]) ? shift : $self->context); + my $x = (scalar(@_) ? shift : $self); + if (scalar(@_) == 0) { + return $x->inContext($context) if ref($x) eq $class; + return (bless {data => [$x->value,1], context => $context}, $class) if Value::isReal($x); + return (bless {data => [$x,1], context => $context}, $class) if Value::matchNumber($x); + } + return $self->new($context,$x,@_); +} + + +# +# Create a new formula from the number +# +sub formula { + my $self = shift; my $value = shift; + my $formula = $self->Package("Formula")->blank($self->context); + my ($l,$r) = Value::toFormula($formula,@{$value}); + $formula->{tree} = $formula->Item("BOP")->new($formula,'/',$l,$r); + return $formula; +} + +# +# Return the real number type +# +sub typeRef {return $Value::Type{number}} +sub length {2} + +sub isZero {(shift)->{data}[0] == 0} +sub isOne {(shift)->eval == 1} + +# +# Return the real value +# +sub eval { + my $self = shift; + my ($a,$b) = $self->value; + return $a/$b; +} + +# +# parts are not Value objects, so don't transfer +# +sub transferFlags {} + +# +# Check if a value is an integer +# +sub isInteger { + my $n = shift; + $n = $n->value if Value::isReal($n); + return $n =~ m/^-?\d+$/; +}; + + +################################################## +# +# Binary operations +# + +sub add { + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); + my (($a,$b),($c,$d)) = ($l->value,$r->value); + my $M = context::Fraction::lcm($b,$d); + return $self->inherit($other)->make($a*($M/$b)+$c*($M/$d),$M); +} + +sub sub { + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); + my (($a,$b),($c,$d)) = ($l->value,$r->value); + my $M = context::Fraction::lcm($b,$d); + return $self->inherit($other)->make($a*($M/$b)-$c*($M/$d),$M); +} + +sub mult { + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); + my (($a,$b),($c,$d)) = ($l->value,$r->value); + return $self->inherit($other)->make($a*$c,$b*$d); +} + +sub div { + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); + my (($a,$b),($c,$d)) = ($l->value,$r->value); + Value::Error("Division by zero") if $c == 0; + return $self->inherit($other)->make($a*$d,$b*$c); +} + +sub power { + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); + my (($a,$b),($c,$d)) = ($l->value,$r->reduce->value); + ($a,$b,$c) = ($b,$a,-$c) if $c < 0; + my ($x,$y) = ($c == 1 ? ($a,$b) : ($a**$c,$b**$c)); + if ($d != 1) { + if ($x < 0 && $d % 2 == 1) {$x = -(-$x)**(1/$d)} else {$x = $x**(1/$d)}; + if ($y < 0 && $d % 2 == 1) {$y = -(-$y)**(1/$d)} else {$y = $y**(1/$d)}; + } + return $self->inherit($other)->make($x,$y) unless $x eq 'nan' || $y eq 'nan'; + Value::Error("Can't raise a negative number to a power") if $a*$b < 0; + Value::Error("Result of exponention is not a number"); +} + +sub compare { + my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); + return $l->eval <=> $r->eval; +} + +################################################## +# +# Numeric functions +# + +sub abs {my $self = shift; $self->make(CORE::abs($self->{data}[0]),CORE::abs($self->{data}[1]))} +sub neg {my $self = shift; $self->make(-($self->{data}[0]),$self->{data}[1])} +sub exp {my $self = shift; $self->make(CORE::exp($self->eval))} +sub log {my $self = shift; $self->make(CORE::log($self->eval))} +sub sqrt {my $self = shift; $self->make(CORE::sqrt($self->{data}[0]),CORE::sqrt($self->{data}[1]))} + +################################################## +# +# Trig functions +# + +sub sin {my $self = shift; $self->make(CORE::sin($self->eval))} +sub cos {my $self = shift; $self->make(CORE::cos($self->eval))} + +sub atan2 { + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); + return $self->inherit($other)->make(CORE::atan2($l->eval,$r->eval)); +} + +################################################## +# +# Utility +# + +sub reduce { + my $self = shift; + my ($a,$b) = context::Fraction::reduce($self->value); + return $self->make($a,$b); +} + +sub isReduced { + my $self = shift; + my (($a,$b),($c,$d)) = ($self->value,$self->reduce->value); + return $a == $c && $b == $d; +} + +################################################## +# +# Formatting +# + +sub string { + my $self = shift; my $equation = shift; my $prec = shift; + my ($a,$b) = @{$self->{data}}; my $n = ""; + return $a if $b == 1; + if ($self->getFlag("showProperFractions") && abs($a) > $b) + {$n = int($a/$b); $a = abs($a) % $b; $n .= " " unless $a == 0} + $n .= "$a/$b" unless $a == 0 && $n ne ''; + $n = "($n)" if defined $prec && $prec >= 1; + return $n; +} + +sub TeX { + my $self = shift; my $equation = shift; my $prec = shift; + my ($a,$b) = @{$self->{data}}; my $n = ""; + return $a if $b == 1; + if ($self->getFlag("showProperFractions") && abs($a) > $b) + {$n = int($a/$b); $a = abs($a) % $b; $n .= " " unless $a == 0} + my $s = ""; ($a,$s) = (-$a,"-") if $a < 0; + $n .= ($self->{isHorizontal} ? "$s$a/$b" : "${s}{\\textstyle\\frac{$a}{$b}}") + unless $a == 0 && $n ne ''; + $n = "\\left($n\\right)" if defined $prec && $prec >= 1; + return $n; +} + +########################################################################### +# +# Answer Checker +# + +sub cmp_defaults {( + shift->SUPER::cmp_defaults(@_), + ignoreInfinity => 1, + studentsMustReduceFractions => 0, + showFractionReduceWarnings => 1, + requireFraction => 0, +)} + +sub cmp_contextFlags { + my $self = shift; my $ans = shift; + return ( + $self->SUPER::cmp_contextFlags($ans), + reduceFractions => !$ans->{studentsMustReduceFractions}, + ); +} + +sub cmp_class {"a fraction of integers"} + +sub typeMatch { + my $self = shift; my $other = shift; my $ans = shift; + return 1 unless ref($other); + return 0 if Value::isFormula($other); + return 1 if $other->type eq 'Infinity' && $ans->{ignoreInfinity}; + return 0 if $ans->{requireFraction} && !$other->classMatch("Fraction"); + $self->type eq $other->type; +} + +sub cmp_postprocess { + my $self = shift; my $ans = shift; + my $student = $ans->{student_value}; + return if $ans->{isPreview} || + !$ans->{studentsMustReduceFractions} || + !Value::classMatch($student,'Fraction') || + $student->isReduced; + $ans->score(0); + $self->cmp_Error($ans,"Your fraction is not reduced") if $ans->{showFractionReduceWarnings}; +} + +########################################################################### + +1; |
From: dpvc v. a. <we...@ma...> - 2009-01-13 02:23:49
|
Log Message: ----------- Simplify mechanism of maintaining the letters used in an ordering. No need for the ugly hack to get around reducing to Value objects; just leave the letters attached to the Value object rather than deleting them. Modified Files: -------------- pg/macros: contextOrdering.pl Revision Data ------------- Index: contextOrdering.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/contextOrdering.pl,v retrieving revision 1.4 retrieving revision 1.5 diff -Lmacros/contextOrdering.pl -Lmacros/contextOrdering.pl -u -r1.4 -r1.5 --- macros/contextOrdering.pl +++ macros/contextOrdering.pl @@ -107,7 +107,6 @@ ); $context->{parser}{String} = "context::Ordering::Parser::String"; $context->{parser}{Value} = "context::Ordering::Parser::Value"; - $context->{parser}{BOP} = "context::Ordering::Parser::BOP"; $context->{value}{String} = "context::Ordering::Value::String"; $context->{value}{Ordering} = "context::Ordering::Value::Ordering"; $context->strings->add('='=>{hidden=>1},'>'=>{hidden=>1}); @@ -201,7 +200,6 @@ } $self->{letters}{$x} = $self->{rop}{letters}{$x}; } - $self->{equation}{letters} = $self->{letters}; # removed by context::Ordering::Parser::BOP; } sub _eval { @@ -293,7 +291,7 @@ sub cmp_postprocess { my $self = shift; my $ans = shift; return if $ans->{isPreview} || $ans->{score} != 0; - $self->cmp_Error($ans,"Your ordering should include more letters") + $self->cmp_Error($ans,"Your ordering should include all the letters") if $ans->{showMissingLetterHints} && scalar(keys %{$ans->{correct_formula}{tree}{letters}}) != scalar(keys %{$ans->{student_formula}{tree}{letters}}); @@ -354,10 +352,7 @@ sub new { my $self = shift; $self = $self->SUPER::new(@_); - if (defined($self->{value}{letters})) { - $self->{letters} = $self->{value}{letters}; - delete $self->{value}{letters}; - } + $self->{letters} = $self->{value}{letters} if defined $self->{value}{letters}; return $self; } @@ -370,26 +365,6 @@ return $self->SUPER::class; } -######################### - -package context::Ordering::Parser::BOP; -our @ISA = ('Parser::BOP'); - -# -# If a BOP is constant and so reduced automatically we will lose the -# letters hash, so it is stored temporarily in the equation by _check(), -# and replaced here. A hack, but that avoids adding letters to the -# Ordering object in eval() and having them remain there after parsing. -# -sub new { - my $self = shift; - $self = $self->SUPER::new(@_); - $self->{letters} = $self->{equation}{letters} unless defined $self->{letters} || $self->class ne 'Ordering'; - delete $self->{equation}{letters}; - return $self; -} - - ############################################################# # # This overrides the cmp_equal method to make sure that |
From: dpvc v. a. <we...@ma...> - 2009-01-12 17:32:04
|
Log Message: ----------- Added a message for when the student answer does not include all the letters used in the correct answer. Modified Files: -------------- pg/macros: contextOrdering.pl Revision Data ------------- Index: contextOrdering.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/contextOrdering.pl,v retrieving revision 1.3 retrieving revision 1.4 diff -Lmacros/contextOrdering.pl -Lmacros/contextOrdering.pl -u -r1.3 -r1.4 --- macros/contextOrdering.pl +++ macros/contextOrdering.pl @@ -63,6 +63,17 @@ orderings produced by calls to the Ordering() function. Changes to the current context WILL affect $a and $b. +If the ordering contains duplicate letters (e.g., "A > B > A"), then a +warning message will be issued. If not all the letters are used by +the student, then that also produces a warning message. The latter +can be controlled by the showMissingLetterHints flag to the cmp() +method. For example: + + ANS(Ordering("A > B > C")->cmp(showMissingLetterHints => 0)); + +would prevent the message from being issued if the student submitted +just "A > B". + =cut loadMacros("MathObjects.pl"); @@ -186,7 +197,7 @@ foreach my $x (keys %{$self->{rop}{letters}}) { if (defined($self->{letters}{$x})) { $self->{ref} = $self->{rop}{letters}{$x}; - $self->Error("Letters can appear only once in an ordering"); + $self->Error("Each letter may appear only once in an ordering"); } $self->{letters}{$x} = $self->{rop}{letters}{$x}; } @@ -195,7 +206,9 @@ sub _eval { my $self = shift; - return $self->Package("Ordering")->new($self->context,$self->{bop},@_); + my $ordering = $self->Package("Ordering")->new($self->context,$self->{bop},@_); + $ordering->{letters} = $self->{letters}; + return $ordering; } sub string { @@ -262,12 +275,30 @@ sub cmp_equal { my $self = shift; my $ans = $_[0]; $ans->{typeMatch} = $ans->{firstElement} = $self; + $ans->{correct_formula} = $self->{equation}; $self = $ans->{correct_value} = Value::List->make($self); $ans->{student_value} = Value::List->make($ans->{student_value}) - if Value::classMatch($ans->{student_value},'Ordering'); + if Value::classMatch($ans->{student_value},'Ordering'); return $self->SUPER::cmp_equal(@_); } +sub cmp_defaults { + my $self = shift; + return ( + $self->SUPER::cmp_defaults(@_), + showMissingLetterHints => 1, + ); +} + +sub cmp_postprocess { + my $self = shift; my $ans = shift; + return if $ans->{isPreview} || $ans->{score} != 0; + $self->cmp_Error($ans,"Your ordering should include more letters") + if $ans->{showMissingLetterHints} && + scalar(keys %{$ans->{correct_formula}{tree}{letters}}) != + scalar(keys %{$ans->{student_formula}{tree}{letters}}); +} + # # Add more letters to the ordering's context (so student answers # can include them even if they aren't in the correct answer). |
From: dpvc v. a. <we...@ma...> - 2009-01-12 15:22:52
|
Log Message: ----------- Produce error messages if a letter is used more than once in an ordering. Modified Files: -------------- pg/macros: contextOrdering.pl Revision Data ------------- Index: contextOrdering.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/contextOrdering.pl,v retrieving revision 1.2 retrieving revision 1.3 diff -Lmacros/contextOrdering.pl -Lmacros/contextOrdering.pl -u -r1.2 -r1.3 --- macros/contextOrdering.pl +++ macros/contextOrdering.pl @@ -91,10 +91,13 @@ $context->functions->clear(); $context->strings->clear(); $context->operators->add( - '>' => {precedence => 1.5, associativity => 'left', type => 'bin', class => 'context::Ordering::BOP'}, - '=' => {precedence => 1.7, associativity => 'left', type => 'bin', class => 'context::Ordering::BOP'}, + '>' => {precedence => 1.5, associativity => 'left', type => 'bin', class => 'context::Ordering::BOP::ordering'}, + '=' => {precedence => 1.7, associativity => 'left', type => 'bin', class => 'context::Ordering::BOP::ordering'}, ); - $context->{value}{String} = "context::Ordering::Value::String"; + $context->{parser}{String} = "context::Ordering::Parser::String"; + $context->{parser}{Value} = "context::Ordering::Parser::Value"; + $context->{parser}{BOP} = "context::Ordering::Parser::BOP"; + $context->{value}{String} = "context::Ordering::Value::String"; $context->{value}{Ordering} = "context::Ordering::Value::Ordering"; $context->strings->add('='=>{hidden=>1},'>'=>{hidden=>1}); $context->{error}{msg}{"Variable '%s' is not defined in this context"} = "'%s' is not defined in this context"; @@ -165,21 +168,29 @@ # nested List. # -package context::Ordering::BOP; +package context::Ordering::BOP::ordering; our @ISA = ('Parser::BOP'); sub class {"Ordering"} sub isOrdering { my $self = shift; my $obj = shift; my $class = $obj->class; - return ($class eq 'Value' && $obj->{value}->class eq 'Ordering') || - ($class eq 'Ordering') || $obj->{def}{isLetter}; + return $class eq 'Ordering' || $obj->{def}{isLetter}; } sub _check { my $self = shift; - return if $self->isOrdering($self->{lop}) && $self->isOrdering($self->{rop}); - $self->Error("Operators of %s must be letters",$self->{bop}); + $self->Error("Operators of %s must be letters",$self->{bop}) + unless $self->isOrdering($self->{lop}) && $self->isOrdering($self->{rop}); + $self->{letters} = $self->{lop}{letters}; # we modify {lop}{letters} this way, but that doesn't matter + foreach my $x (keys %{$self->{rop}{letters}}) { + if (defined($self->{letters}{$x})) { + $self->{ref} = $self->{rop}{letters}{$x}; + $self->Error("Letters can appear only once in an ordering"); + } + $self->{letters}{$x} = $self->{rop}{letters}{$x}; + } + $self->{equation}{letters} = $self->{letters}; # removed by context::Ordering::Parser::BOP; } sub _eval { @@ -197,6 +208,7 @@ return $self->{lop}->TeX." ".$self->{bop}." ".$self->{rop}->TeX; } + ############################################################# # # This is the Value object used to implement the list That represents @@ -248,7 +260,7 @@ # the ordering) # sub cmp_equal { - my $self = shift; my $ans = $_[0]; + my $self = shift; my $ans = $_[0]; $ans->{typeMatch} = $ans->{firstElement} = $self; $self = $ans->{correct_value} = Value::List->make($self); $ans->{student_value} = Value::List->make($ans->{student_value}) @@ -284,6 +296,71 @@ ############################################################# # +# Override Parser classes so that we can check for repeated letters +# + +package context::Ordering::Parser::String; +our @ISA = ('Parser::String'); + +# +# Save the letters positional reference +# +sub new { + my $self = shift; + $self = $self->SUPER::new(@_); + $self->{letters}{$self->{value}} = $self->{ref} if $self->{def}{isLetter}; + return $self; +} + +######################### + +package context::Ordering::Parser::Value; +our @ISA = ('Parser::Value'); + +# +# Move letters to Value object +# +sub new { + my $self = shift; + $self = $self->SUPER::new(@_); + if (defined($self->{value}{letters})) { + $self->{letters} = $self->{value}{letters}; + delete $self->{value}{letters}; + } + return $self; +} + +# +# Return Ordering class if the object is one +# +sub class { + my $self = shift; + return "Ordering" if $self->{value}->classMatch('Ordering'); + return $self->SUPER::class; +} + +######################### + +package context::Ordering::Parser::BOP; +our @ISA = ('Parser::BOP'); + +# +# If a BOP is constant and so reduced automatically we will lose the +# letters hash, so it is stored temporarily in the equation by _check(), +# and replaced here. A hack, but that avoids adding letters to the +# Ordering object in eval() and having them remain there after parsing. +# +sub new { + my $self = shift; + $self = $self->SUPER::new(@_); + $self->{letters} = $self->{equation}{letters} unless defined $self->{letters} || $self->class ne 'Ordering'; + delete $self->{equation}{letters}; + return $self; +} + + +############################################################# +# # This overrides the cmp_equal method to make sure that # Ordering lists are put into nested lists (since the # underlying ordering is a list, we don't want the @@ -300,3 +377,7 @@ if Value::classMatch($ans->{student_value},'Ordering'); return $self->SUPER::cmp_equal(@_); } + +############################################################# + +1; |
From: dpvc v. a. <we...@ma...> - 2009-01-11 20:00:58
|
Log Message: ----------- When a parentheses have been removed, mark the enclosed item so that we can tell later, if we need to know about the missing parens. Modified Files: -------------- pg/lib: Parser.pm Revision Data ------------- Index: Parser.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Parser.pm,v retrieving revision 1.52 retrieving revision 1.53 diff -Llib/Parser.pm -Llib/Parser.pm -u -r1.52 -r1.53 --- lib/Parser.pm +++ lib/Parser.pm @@ -389,7 +389,9 @@ $self->Item("List")->new($self,[$top->makeList],$top->{isConstant},$paren, ($top->type eq 'Comma') ? $top->entryType : $top->typeRef, ($type ne 'start') ? ($self->top->{value},$type) : () )}; - } + } else { + $top->{value}{hadParens} = 1; + } $self->pop; $self->push($top); $self->CloseFn() if ($paren->{function} && $self->prev->{type} eq 'fn'); } elsif ($paren->{formInterval} eq $type && $self->top->{value}->length == 2) { |
From: dpvc v. a. <we...@ma...> - 2009-01-11 15:13:43
|
Log Message: ----------- Use the Package() method to create the ordering object, so that ordering objects can be properly subclassed. Modified Files: -------------- pg/macros: contextOrdering.pl Revision Data ------------- Index: contextOrdering.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/contextOrdering.pl,v retrieving revision 1.1 retrieving revision 1.2 diff -Lmacros/contextOrdering.pl -Lmacros/contextOrdering.pl -u -r1.1 -r1.2 --- macros/contextOrdering.pl +++ macros/contextOrdering.pl @@ -95,6 +95,7 @@ '=' => {precedence => 1.7, associativity => 'left', type => 'bin', class => 'context::Ordering::BOP'}, ); $context->{value}{String} = "context::Ordering::Value::String"; + $context->{value}{Ordering} = "context::Ordering::Value::Ordering"; $context->strings->add('='=>{hidden=>1},'>'=>{hidden=>1}); $context->{error}{msg}{"Variable '%s' is not defined in this context"} = "'%s' is not defined in this context"; $context->{error}{msg}{"Unexpected character '%s'"} = "Can't use '%s' in this context"; @@ -183,7 +184,7 @@ sub _eval { my $self = shift; - return context::Ordering::Value::Ordering->new($self->context,$self->{bop},@_); + return $self->Package("Ordering")->new($self->context,$self->{bop},@_); } sub string { |
From: dpvc v. a. <we...@ma...> - 2009-01-10 19:45:54
|
Log Message: ----------- New Context for handling ordered lists of letters like "D > A = C > B". See the comments for details about how to use it. Added Files: ----------- pg/macros: contextOrdering.pl Revision Data ------------- --- /dev/null +++ macros/contextOrdering.pl @@ -0,0 +1,301 @@ +=head1 NAME + +contextOrdering.pl - Parses ordered lists of letters like "B > A = C > D" + +=head1 DESCRIPTION + +This context provides a structured way to parse and check answers that +are ordered lists of letters, where the letters are separated by +greater-than signs or equal signs. The only operators allowed are > +and =, and the only letters allowed are the ones you specify explicitly. + +To access the context, you must include + + loadMacros("contextOrdering.pl"); + +at the top of your problem file, and then specify the Ordering context: + + Context("Ordering"); + +There are two main ways to use the Ordering context. The first is to +use the Ordering() command to generate your ordering. This command +creates a context in which the proper letters are defined, and returns +a MathObject that represents the ordering you have provided. For +example, + + $ans = Ordering("B > A > C"); + +or + + $ans = Ordering(A => 2, B => 2.5, C => 1); + +would both produce the same ordering. The first form gives the +ordering as the student must type it, and the second gives the +ordering by specifying numeric values for the various letters that +determine the resulting order. Note that equality is determined using +the default tolerances for the Ordering context. You can change these +using commands like the following: + + Context("Ordering"); + Context()->flags->set(tolerance => .01, tolType => 'absolute'); + +If you want to allow lists of orderings, use the Ordering-List context: + + Context("Ordering-List"); + $ans = Ordering("A > B , B = C"); + +Note that each Ordering() call uses its own copy of the current +context. If you need to modify the actual context used, then use the +context() method of the resulting object. + +The second method of generating orderings is to declare the letters +you wish to use explicitly, and then build the Ordering objects using +the standard Compute() method: + + Context("Ordering"); + Letters("A","B","C","D"); + $a = Compute("A > B = C"); + $b = Compute("C > D"); + +Note that in this case, D is still a valid letter that students can +enter in response to an answer checker for $a, and similarly for A and +B with $b. Note also that both $a and $b use the same context, unlike +orderings produced by calls to the Ordering() function. Changes to +the current context WILL affect $a and $b. + +=cut + +loadMacros("MathObjects.pl"); + +sub _contextOrdering_init {context::Ordering::Init()} + +########################################### +# +# The main Ordering routines +# + +package context::Ordering; + +# +# Here we set up the prototype contexts and define the needed +# functions in the main:: namespace. Some error messages are +# modified to read better for these contexts. +# +sub Init { + my $context = $main::context{Ordering} = Parser::Context->getCopy("Numeric"); + $context->{name} = "Ordering"; + $context->parens->clear(); + $context->variables->clear(); + $context->constants->clear(); + $context->operators->clear(); + $context->functions->clear(); + $context->strings->clear(); + $context->operators->add( + '>' => {precedence => 1.5, associativity => 'left', type => 'bin', class => 'context::Ordering::BOP'}, + '=' => {precedence => 1.7, associativity => 'left', type => 'bin', class => 'context::Ordering::BOP'}, + ); + $context->{value}{String} = "context::Ordering::Value::String"; + $context->strings->add('='=>{hidden=>1},'>'=>{hidden=>1}); + $context->{error}{msg}{"Variable '%s' is not defined in this context"} = "'%s' is not defined in this context"; + $context->{error}{msg}{"Unexpected character '%s'"} = "Can't use '%s' in this context"; + $context->{error}{msg}{"Missing operand before '%s'"} = "Missing letter before '%s'"; + $context->{error}{msg}{"Missing operand after '%s'"} = "Missing letter after '%s'"; + + $context = $main::context{'Ordering-List'} = $context->copy; + $context->{name} eq 'Ordering-List'; + $context->operators->redefine(',',from => "Full"); + $context->{value}{List} = "context::Ordering::Value::List"; + + main::PG_restricted_eval('sub Letters {context::Ordering::Letters(@_)}'); + main::PG_restricted_eval('sub Ordering {context::Ordering::Ordering(@_)}'); +} + +# +# A routine to set the letters allowed in this context. +# (Old letters are cleared, and > and = are allowed, but hidden, +# since they are used in the List() objects that implement the context). +# +sub Letters { + my $context = (Value::isContext($_[0]) ? shift : main::Context()); + my @strings; + foreach my $x (@_) {push(@strings, $x => {isLetter => 1, caseSensitive => 1})} + $context->strings->are(@strings); + $context->strings->add('='=>{hidden=>1},'>'=>{hidden=>1}); +} + +# +# Create orderings from strings or lists of letter => value pairs. +# A copy of the current context is created that contains the proper +# letters, and the correct string is created and parsed into an +# Ordering object. +# +sub Ordering { + my $context = main::Context()->copy; my $string; + Value->Error("The current context is not the Ordering context") + unless $context->{name} =~ m/Ordering/; + if (scalar(@_) == 1) { + $string = shift; + my $letters = $string; $letters =~ s/[^A-Z]//ig; + context::Ordering::Letters($context,split(//,$letters)); + } else { + my %letter = @_; my @letters = keys %letter; + context::Ordering::Letters($context,@letters); + foreach my $x (@letters) {$letter{$x} = Value::Real->new($context,$letter{$x})} + my @order = main::PGsort( + sub {$letter{$_[0]} == $letter{$_[1]} ? $_[0] lt $_[1] : $letter{$_[0]} > $letter{$_[1]}}, + @letters + ); + my $a = shift(@order); my $b; $string = $a; + while ($b = shift(@order)) { + $string .= ($letter{$a} == $letter{$b} ? " = " : " > ") . $b; + $a = $b; + } + } + return main::Formula($context,$string)->eval; +} + +############################################################# +# +# This is a Parser BOP used to create the Ordering objects +# used internally. They are actually lists with the operator +# and the two operands, and the comparisons is based on the +# standard list comparisons. The operands are either the strings +# for individual letters, or another Ordering object as a +# nested List. +# + +package context::Ordering::BOP; +our @ISA = ('Parser::BOP'); + +sub class {"Ordering"} + +sub isOrdering { + my $self = shift; my $obj = shift; my $class = $obj->class; + return ($class eq 'Value' && $obj->{value}->class eq 'Ordering') || + ($class eq 'Ordering') || $obj->{def}{isLetter}; +} + +sub _check { + my $self = shift; + return if $self->isOrdering($self->{lop}) && $self->isOrdering($self->{rop}); + $self->Error("Operators of %s must be letters",$self->{bop}); +} + +sub _eval { + my $self = shift; + return context::Ordering::Value::Ordering->new($self->context,$self->{bop},@_); +} + +sub string { + my $self = shift; + return $self->{lop}->string." ".$self->{bop}." ".$self->{rop}->string; +} + +sub TeX { + my $self = shift; + return $self->{lop}->TeX." ".$self->{bop}." ".$self->{rop}->TeX; +} + +############################################################# +# +# This is the Value object used to implement the list That represents +# one ordering operation. It is simply a normal Value::List with the +# operator as the first entry and the two operands as the remaing +# entries in the list. The new() method is overriden to make binary +# trees of equal operators into flat sorted lists. We override the +# List string and TeX methods so that they print correctly as binary +# operators. The cmp_equal method is overriden to make sure the that +# the lists are treated as a unit during answer checking. There is +# also a routine for adding letters to the object's context. +# + +package context::Ordering::Value::Ordering; +our @ISA = ('Value::List'); + +# +# Put all equal letters into one list and sort them +# +sub new { + my $self = shift; + my $context = (Value::isContext($_[0]) ? shift : $self->context); + my $bop = shift; my @letters = @_; + if ($bop eq '=') { + if (Value::classMatch($letters[0],'Ordering') && $letters[0]->{data}[0] eq '=') + {@letters = ($letters[0]->value,$letters[1]); shift @letters} + @letters = main::lex_sort(@letters); + } + return $self->SUPER::new($context,$bop,@letters); +} + +sub string { + my $self = shift; + my ($bop,@rest) = $self->value; + foreach my $x (@rest) {$x = $x->string}; + return join(" $bop ",@rest); +} + +sub TeX { + my $self = shift; + my ($bop,@rest) = $self->value; + foreach my $x (@rest) {$x = $x->TeX}; + return join(" $bop ",@rest); +} + +# +# Make sure we do comparison as a list of lists (rather than as the +# individual entries in the underlying Value::List that encodes +# the ordering) +# +sub cmp_equal { + my $self = shift; my $ans = $_[0]; + $ans->{typeMatch} = $ans->{firstElement} = $self; + $self = $ans->{correct_value} = Value::List->make($self); + $ans->{student_value} = Value::List->make($ans->{student_value}) + if Value::classMatch($ans->{student_value},'Ordering'); + return $self->SUPER::cmp_equal(@_); +} + +# +# Add more letters to the ordering's context (so student answers +# can include them even if they aren't in the correct answer). +# +sub AddLetters { + my $self = shift; my $context = $self->context; + my @strings; + foreach my $x (@_) { + push(@strings, $x => {isLetter => 1, caseSensitive => 1}) + unless $context->strings->get($x); + } + $context->strings->add(@strings) if scalar(@strings); +} + +############################################################# +# +# This overrides the TeX method of the letters +# so that they don't print using the \rm font. +# + +package context::Ordering::Value::String; +our @ISA = ('Value::String'); + +sub TeX {shift->value} + + +############################################################# +# +# This overrides the cmp_equal method to make sure that +# Ordering lists are put into nested lists (since the +# underlying ordering is a list, we don't want the +# list checker to test the individual parts of the list, +# but rather the list as a whole). +# + +package context::Ordering::Value::List; +our @ISA = ('Value::List'); + +sub cmp_equal { + my $self = shift; my $ans = $_[0]; + $ans->{student_value} = Value::List->make($ans->{student_value}) + if Value::classMatch($ans->{student_value},'Ordering'); + return $self->SUPER::cmp_equal(@_); +} |
From: Mike G. v. a. <we...@ma...> - 2009-01-02 04:10:38
|
Log Message: ----------- Added comments to file about where wwlink state is stored Modified Files: -------------- wwmoodle/wwassignment4/moodle/blocks/wwlink: block_wwlink.php Revision Data ------------- Index: block_wwlink.php =================================================================== RCS file: /webwork/cvs/system/wwmoodle/wwassignment4/moodle/blocks/wwlink/block_wwlink.php,v retrieving revision 1.4 retrieving revision 1.5 diff -Lwwassignment4/moodle/blocks/wwlink/block_wwlink.php -Lwwassignment4/moodle/blocks/wwlink/block_wwlink.php -u -r1.4 -r1.5 --- wwassignment4/moodle/blocks/wwlink/block_wwlink.php +++ wwassignment4/moodle/blocks/wwlink/block_wwlink.php @@ -78,6 +78,9 @@ // $this->content->footer = ''; // return $this->content; // } + +// new method for storing state: +// we can store it in the configuration data for the block! we don't need the wwassignment_bridge table to store state. function get_content() { global $COURSE; //print_r($this->config ); |
From: Mike G. v. a. <we...@ma...> - 2009-01-02 03:46:11
|
Log Message: ----------- wwassignment_bridge table is not needed Modified Files: -------------- wwmoodle/wwassignment4/moodle/mod/wwassignment/db: install.xml Revision Data ------------- Index: install.xml =================================================================== RCS file: /webwork/cvs/system/wwmoodle/wwassignment4/moodle/mod/wwassignment/db/install.xml,v retrieving revision 1.6 retrieving revision 1.7 diff -Lwwassignment4/moodle/mod/wwassignment/db/install.xml -Lwwassignment4/moodle/mod/wwassignment/db/install.xml -u -r1.6 -r1.7 --- wwassignment4/moodle/mod/wwassignment/db/install.xml +++ wwassignment4/moodle/mod/wwassignment/db/install.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" ?> <XMLDB PATH="mod/wwassignment/db" VERSION="2008092818" COMMENT="XMLDB file for Moodle mod/wwassignment" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"> <TABLES> - <TABLE NAME="wwassignment" COMMENT="" NEXT="wwassignment_bridge"> + <TABLE NAME="wwassignment" COMMENT="" > <FIELDS> <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" ENUM="false" NEXT="course"/> <FIELD NAME="course" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="id" NEXT="name"/> |
From: Mike G. v. a. <we...@ma...> - 2009-01-02 03:42:36
|
Log Message: ----------- spell webwork right! Modified Files: -------------- wwmoodle/wwassignment4/moodle/mod/wwassignment/db: install.xml Revision Data ------------- Index: install.xml =================================================================== RCS file: /webwork/cvs/system/wwmoodle/wwassignment4/moodle/mod/wwassignment/db/install.xml,v retrieving revision 1.5 retrieving revision 1.6 diff -Lwwassignment4/moodle/mod/wwassignment/db/install.xml -Lwwassignment4/moodle/mod/wwassignment/db/install.xml -u -r1.5 -r1.6 --- wwassignment4/moodle/mod/wwassignment/db/install.xml +++ wwassignment4/moodle/mod/wwassignment/db/install.xml @@ -8,7 +8,7 @@ <FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" ENUM="false" PREVIOUS="course" NEXT="description"/> <FIELD NAME="description" TYPE="text" LENGTH="small" NOTNULL="true" SEQUENCE="false" ENUM="false" PREVIOUS="name" NEXT="webwork_set"/> <FIELD NAME="webwork_set" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" ENUM="false" DEFAULT="undefined" PREVIOUS="description" NEXT="grade"/> - <FIELD NAME="grade" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="wework_set" NEXT="timemodified"/> + <FIELD NAME="grade" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="webwork_set" NEXT="timemodified"/> <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="grade"/> </FIELDS> <KEYS> |
From: Mike G. v. a. <we...@ma...> - 2009-01-02 03:33:39
|
Log Message: ----------- Corrected xml code -- I had the previous and next fields incorrectly labeled when adding the grade field. Modified Files: -------------- wwmoodle/wwassignment4/moodle/mod/wwassignment/db: install.xml Revision Data ------------- Index: install.xml =================================================================== RCS file: /webwork/cvs/system/wwmoodle/wwassignment4/moodle/mod/wwassignment/db/install.xml,v retrieving revision 1.4 retrieving revision 1.5 diff -Lwwassignment4/moodle/mod/wwassignment/db/install.xml -Lwwassignment4/moodle/mod/wwassignment/db/install.xml -u -r1.4 -r1.5 --- wwassignment4/moodle/mod/wwassignment/db/install.xml +++ wwassignment4/moodle/mod/wwassignment/db/install.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<XMLDB PATH="mod/wwassignment/db" VERSION="20070620" COMMENT="XMLDB file for Moodle mod/wwassignment" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"> +<XMLDB PATH="mod/wwassignment/db" VERSION="2008092818" COMMENT="XMLDB file for Moodle mod/wwassignment" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"> <TABLES> <TABLE NAME="wwassignment" COMMENT="" NEXT="wwassignment_bridge"> <FIELDS> @@ -7,9 +7,9 @@ <FIELD NAME="course" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="id" NEXT="name"/> <FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" ENUM="false" PREVIOUS="course" NEXT="description"/> <FIELD NAME="description" TYPE="text" LENGTH="small" NOTNULL="true" SEQUENCE="false" ENUM="false" PREVIOUS="name" NEXT="webwork_set"/> - <FIELD NAME="webwork_set" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" ENUM="false" DEFAULT="undefined" PREVIOUS="description" NEXT="timemodified"/> - <FIELD NAME="grade" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="timeavailable" NEXT="timemodified"/> - <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="webwork_set"/> + <FIELD NAME="webwork_set" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" ENUM="false" DEFAULT="undefined" PREVIOUS="description" NEXT="grade"/> + <FIELD NAME="grade" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="wework_set" NEXT="timemodified"/> + <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="grade"/> </FIELDS> <KEYS> <KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="Primary key for data"/> |
From: dpvc v. a. <we...@ma...> - 2009-01-01 04:05:27
|
Log Message: ----------- Fixed \angle in safari. Modified Files: -------------- webwork-modperl/htdocs/jsMath/uncompressed: jsMath.js Revision Data ------------- Index: jsMath.js =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/htdocs/jsMath/uncompressed/jsMath.js,v retrieving revision 1.18 retrieving revision 1.19 diff -Lhtdocs/jsMath/uncompressed/jsMath.js -Lhtdocs/jsMath/uncompressed/jsMath.js -u -r1.18 -r1.19 --- htdocs/jsMath/uncompressed/jsMath.js +++ htdocs/jsMath/uncompressed/jsMath.js @@ -5068,7 +5068,7 @@ '_': ['Replace','ord','_','normal',-.4,.1], ' ': ['Replace','ord',' ','normal'], // angle: ['Replace','ord','∠','normal'], - angle: ['Macro','\\raise1.54pt{\\kern2.5mu\\rlap{\\scriptstyle\\char{cmsy10}{54}}\\kern1pt\\rule{.45em}{-1.2pt}{1.54pt}\\kern2.5mu}'], + angle: ['Macro','\\kern2.5mu\\raise1.54pt{\\rlap{\\scriptstyle \\char{cmsy10}{54}}\\kern1pt\\rule{.45em}{-1.2pt}{1.54pt}\\kern2.5mu}'], matrix: 'Matrix', array: 'Matrix', // ### still need to do alignment options ### |
From: dpvc v. a. <we...@ma...> - 2009-01-01 03:43:18
|
Log Message: ----------- Bring to version 3.6b. Changes include: * Fixed an error in the Unicode fallback tables for the PC (the "floor" and "ceil" characters were reversed). * Fixed a problem with MSIE where a relative URL used to obtain jsMath from a server that requires a port number was not handled properly by jsMath. * Fixed a bug in which alignments could be clipped on the right in MSIE under certain font-scaling conditions. * Added an eqnarray* environment for consistency with other starred environments, and made the eqn-number extension honor the star. * Updated the bbox extension to avoid a problem with box widths not being properly computed when \bbox commands are nested. Also the old version was inefficient about typesetting the contents of the box (it was performed twice, so nested boxes caused the processing to go up exponentially). Finally, boxed elements now have superscripts and subscripts applied to the box, rather than the contents of the box. * Fixed a problem with how jsMath measures the heights of characters (by removing an old hack that no longer appears to be necessary). This improves spacing in \overline and other situations that are height-sensitive. * Fixed a bug introduced in v3.6a (by a typo) that would prevent processing of mathematics within an \hbox. * In v3.6, the method for handling the position:fixed bug in MSIE caused type-in areas in forms to be difficult to select (due to another bug in MSIE), so the solution had to be scaled back a bit. It now allows you to override the horizontal position of the jsMath button and message box, but you can't position it relative to the top of the window in MSIE. Repositioning works fine in all other browsers. I'll keep working to see if I can get around this. * Properly detect the Google Chrome browser. * Fixed \angle to not use unicode but rather construct it from the fonts similar to how TeX does. * Fixed bug where \char did not properly respect the current style (e.g., in scripts) * Added a new macros field to the easy/load.js file that lets you define custom macros automatically. (This is easier than having to make your own local.js file.) * Fixed a bug with \operatorname in the AMSmath package that incorrectly handled the unstarred version of the operator in displayed math mode. Modified Files: -------------- webwork-modperl/htdocs/jsMath: jsMath-easy-load.js jsMath-fallback-pc.js jsMath.js webwork-modperl/htdocs/jsMath/easy: load.js webwork-modperl/htdocs/jsMath/extensions: AMSmath.js bbox.js eqn-number.js webwork-modperl/htdocs/jsMath/plugins: autoload.js noImageFonts.js webwork-modperl/htdocs/jsMath/uncompressed: jsMath-fallback-pc.js jsMath.js Revision Data ------------- Index: noImageFonts.js =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/htdocs/jsMath/plugins/noImageFonts.js,v retrieving revision 1.7 retrieving revision 1.8 diff -Lhtdocs/jsMath/plugins/noImageFonts.js -Lhtdocs/jsMath/plugins/noImageFonts.js -u -r1.7 -r1.8 --- htdocs/jsMath/plugins/noImageFonts.js +++ htdocs/jsMath/plugins/noImageFonts.js @@ -24,12 +24,4 @@ */ if (!window.jsMath) {window.jsMath = {}} -jsMath.noImgFonts = 1; - -if (!jsMath.Font) {jsMath.Font = {}} -if (!jsMath.Font.extra_message) { - jsMath.Font.extra_message = - 'Extra TeX fonts not found: <b><span id="jsMath_ExtraFonts"></span></b><br/>' - + 'Using unicode fonts instead. This may be slow and might not print well.<br/>\n' - + 'Use the jsMath control panel to get additional information.'; -} \ No newline at end of file +window.jsMath.noImgFonts = 1; Index: autoload.js =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/htdocs/jsMath/plugins/autoload.js,v retrieving revision 1.12 retrieving revision 1.13 diff -Lhtdocs/jsMath/plugins/autoload.js -Lhtdocs/jsMath/plugins/autoload.js -u -r1.12 -r1.13 --- htdocs/jsMath/plugins/autoload.js +++ htdocs/jsMath/plugins/autoload.js @@ -405,6 +405,16 @@ if (typeof(files) != 'object') {files = [files]} for (var i = 0; i < files.length; i++) {jsMath.Setup.Script(files[i])} } + var macros = jsMath.Autoload.macros; + if (macros) { + for (var id in macros) { + if (typeof(macros[id]) == 'string') { + jsMath.Macro(id,macros[id]); + } else { + jsMath.Macro(id,macros[id][0],macros[id][1]); + } + } + } jsMath.Synchronize(function () {jsMath.Autoload.Script.RunStack()}); jsMath.Autoload.setMessage(); }, Index: bbox.js =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/htdocs/jsMath/extensions/bbox.js,v retrieving revision 1.4 retrieving revision 1.5 diff -Lhtdocs/jsMath/extensions/bbox.js -Lhtdocs/jsMath/extensions/bbox.js -u -r1.4 -r1.5 --- htdocs/jsMath/extensions/bbox.js +++ htdocs/jsMath/extensions/bbox.js @@ -63,38 +63,26 @@ * Creates the box HTML */ bbox: function (style,size,mitem,prev,mlist) { - var box = jsMath.Box.Set(mitem.nuc2,style,size,1).Remeasured(); - delete mitem.nuc2; - /* - * If the box has super- or subscripts, move them - * to the contained item if is in a big operator - * (does anything else need this?) - */ - if (mitem.sup || mitem.sub) { - if (mitem.nuc.type == 'mlist' && mitem.nuc.mlist.Length() == 1) { - var atom = mitem.nuc.mlist.Last(); - if (atom.atom && atom.type == 'op' && !atom.sup && !atom.sub) { - if (mitem.sup) {atom.sup = mitem.sup; delete mitem.sup} - if (mitem.sub) {atom.sub = mitem.sub; delete mitem.sub} - } - } - } - jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); + var box; var w; var h; var d; + var nuc = mitem.nuc = jsMath.Box.Set(mitem.nuc,style,size).Remeasured(); + if (box == null) {w = nuc.w; h = nuc.h; d = nuc.d} // values before super/subs-cript var nuc = mitem.nuc; nuc.Styled(); var pad = mitem.pad; - if (pad) {box.w += 2*pad; box.h += pad; box.d += pad; nuc.w += pad} + if (pad) {w += 2*pad; h += pad; d += pad; nuc.w += pad} if (jsMath.Browser.msieCenterBugFix) {nuc.html = '<span style="position:relative">'+nuc.html+'</span>'} nuc.html = - jsMath.HTML.BBox(box.w,box.h,box.d,mitem.color,mitem.style) + - jsMath.HTML.Spacer(pad-box.w) + + jsMath.HTML.BBox(w,h,d,mitem.color,mitem.style) + + jsMath.HTML.Spacer(pad-w) + nuc.html; - if (pad && nuc.w < box.w) { - nuc.html += jsMath.HTML.Spacer(box.w-nuc.w); - nuc.w = box.w; + nuc.Remeasured(); + if (pad && nuc.w < w) { + nuc.html += jsMath.HTML.Spacer(w-nuc.w); + nuc.w = w; } - nuc.h = Math.max(nuc.h,box.h); nuc.d = Math.max(nuc.d,box.d); - nuc.bh = Math.max(nuc.bh,box.h); nuc.bd = Math.max(nuc.bd,box.d); + nuc.h = Math.max(nuc.h,h); nuc.d = Math.max(nuc.d,d); + nuc.bh = Math.max(nuc.bh,nuc.h); nuc.bd = Math.max(nuc.bd,nuc.d); mitem.type = 'ord'; + jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); } }); @@ -109,7 +97,6 @@ var extra = this.GetBrackets(this.cmd+name); if (this.error) return; var arg = this.GetArgument(this.cmd+name); if (this.error) return; var nuc = this.Process(arg); if (this.error) return; - var nuc2 = this.Process(arg); // need a second copy since Box.Set changes the list var color; var pad = 0; var style = ''; if (extra != '') { var parts = extra.split(/,/); @@ -120,9 +107,7 @@ else {color = parts[i]} } } - this.mlist.Add(new jsMath.mItem('bbox',{ - nuc: nuc, nuc2: nuc2, atom: 1, pad: pad, color: color, style: style - })); + var atom = {nuc: nuc, atom: 1, pad: pad, color: color, style: style}; + this.mlist.Add(new jsMath.mItem('bbox',atom)); } - }); Index: AMSmath.js =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/htdocs/jsMath/extensions/AMSmath.js,v retrieving revision 1.2 retrieving revision 1.3 diff -Lhtdocs/jsMath/extensions/AMSmath.js -Lhtdocs/jsMath/extensions/AMSmath.js -u -r1.2 -r1.3 --- htdocs/jsMath/extensions/AMSmath.js +++ htdocs/jsMath/extensions/AMSmath.js @@ -125,7 +125,7 @@ }, HandleOperatorName: function (name) { - var limits = ""; + var limits = "\\nolimits"; var op = this.trimSpaces(this.GetArgument(this.cmd+name)); if (this.error) return; if (op == "*") { limits = "\\limits"; Index: eqn-number.js =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/htdocs/jsMath/extensions/eqn-number.js,v retrieving revision 1.3 retrieving revision 1.4 diff -Lhtdocs/jsMath/extensions/eqn-number.js -Lhtdocs/jsMath/extensions/eqn-number.js -u -r1.3 -r1.4 --- htdocs/jsMath/extensions/eqn-number.js +++ htdocs/jsMath/extensions/eqn-number.js @@ -158,6 +158,7 @@ environments: { 'equation*': 'Star', + 'eqnarray*': 'Star', 'align*': 'Star', 'multline*': 'Star', 'gather*': 'Star', Index: jsMath-easy-load.js =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/htdocs/jsMath/jsMath-easy-load.js,v retrieving revision 1.5 retrieving revision 1.6 diff -Lhtdocs/jsMath/jsMath-easy-load.js -Lhtdocs/jsMath/jsMath-easy-load.js -u -r1.5 -r1.6 --- htdocs/jsMath/jsMath-easy-load.js +++ htdocs/jsMath/jsMath-easy-load.js @@ -93,6 +93,7 @@ jsMath.Autoload.findCustomSettings = jsMath.Easy.findCustomSettings; jsMath.Autoload.loadFiles = jsMath.Easy.loadFiles; jsMath.Autoload.loadFonts = jsMath.Easy.loadFonts; + jsMath.Autoload.macros = jsMath.Easy.macros; jsMath.Autoload.delayCheck = 1; jsMath.Easy.autoloadCheck = 1; document.write('<script src="'+jsMath.Autoload.root+'plugins/autoload.js"></script>'); @@ -110,12 +111,26 @@ if (!jsMath.Setup) {jsMath.Setup = {}} if (!jsMath.Setup.UserEvent) {jsMath.Setup.UserEvent = {}} jsMath.Setup.UserEvent.onload = function () { - if (jsMath.Easy.tex2math) jsMath.Setup.Script("plugins/tex2math.js"); + var easy = jsMath.Easy; + if (easy.tex2math) jsMath.Setup.Script("plugins/tex2math.js"); var i; - for (i = 0; i < jsMath.Easy.loadFiles.length; i++) - jsMath.Setup.Script(jsMath.Easy.loadFiles[i]); - for (i = 0; i < jsMath.Easy.loadFonts.length; i++) - jsMath.Font.Load(jsMath.Easy.loadFonts[i]); + if (easy.loadFiles) { + for (i = 0; i < easy.loadFiles.length; i++) + jsMath.Setup.Script(easy.loadFiles[i]); + } + if (easy.loadFonts) { + for (i = 0; i < easy.loadFonts.length; i++) + jsMath.Font.Load(easy.loadFonts[i]); + } + if (easy.macros) { + for (i in easy.macros) { + if (typeof(easy.macros[i]) == 'string') { + jsMath.Macro(i,easy.macros[i]); + } else { + jsMath.Macro(i,easy.macros[i][0],easy.macros[i][1]); + } + } + } } document.write('<script src="'+jsMath.Easy.root+'/jsMath.js"></script>'+"\n"); } Index: jsMath.js =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/htdocs/jsMath/jsMath.js,v retrieving revision 1.43 retrieving revision 1.44 diff -Lhtdocs/jsMath/jsMath.js -Lhtdocs/jsMath/jsMath.js -u -r1.43 -r1.44 --- htdocs/jsMath/jsMath.js +++ htdocs/jsMath/jsMath.js @@ -40,11 +40,11 @@ //start = new Date().getTime(); jsMath.Script.Uncompress([ - ['if(!','window','.jsMath','||!',1,'.','jsMath.','loaded','){var ','jsMath_old','=',1,2,';',0,'document.','getElementById','||!',15,'childNodes||!',15,'createElement','){','alert("','The',' mathematics ','on this page requires W3C DOM support in its JavaScript. Unfortunately, your ','browser',' doesn\'t seem to have this.")}else{',1,2,'={version:"3.6a",document:document,',1,':',1,',','platform',':(','navigator.',36,'.match(/','Mac/)?"mac":',38,36,40,'Win/)?"pc":"unix"),','sizes',':[50,60,70,85,100,120,144,173,207,249],styles:{".math','":{"font-family":"serif","font-style":"normal","font-weight":"normal','"},".typeset',48,'","line-height":"normal','","text-indent":"0px','"},".typeset .','normal',48,'"},"div','.typeset','":{"text-align":"','center",margin:"1em 0px"},"span',57,58,'left',49,' span',58,'left",border',':"0px",margin:"0px','",padding',':"0px"},"a .typeset img, .typeset a img','":{border:"0px','","border-bottom":"','1px solid',' blue;"},".typeset .size0','":{"fon! t-size":"','50','%"},".typeset .','size1',74,'60',76,'size2',74,'70',76,'size3',74,'85',76,'size4',74,'100',76,'size5',74,'120',76,'size6',74,'144',76,'size7',74,'173',76,'size8',74,'207',76,'size9',74,'249',76,'cmr10','":{"font-family":"jsMath-',113,', serif',53,'cmbx10',114,118,', ','jsMath-cmr10',53,'cmti10',114,124,', ',122,53,'cmmi10',114,130,53,'cmsy10',114,134,53,'cmex10',114,138,53,'textit','":{"font-family":"','serif","','font-style":"italic',53,'textbf',143,'serif","font-weight":"bold',53,'link":{"','text-decoration":"none',53,'error',74,'90%","',145,'","background-color','":"#FFFFCC',68,':"1px','",border:"',72,' #CC0000',53,'blank','":{display:"','inline-block','",overflow:"','hidden',162,'0px none",width:"0px",height:"0px',53,'spacer',167,168,'"},"#','jsMath_hiddenSpan":{','visibility:"hidden",position:"absolute",','top:"0px",left:"0px',51,52,177,'jsMath_message','":{position:"fixed",bottom:"','1px",left:"2px',158,'":"#E6E6E6','",border:"solid 1px #959595",margi! n:"0px",padding:"','1px 8px','","z-index":"','102','",color:"b! lack","f ont-size":"','small",width:"auto','"},"#jsMath_panel',185,'1.75em",right:"1.5em',68,':".8em 1.6em',158,'":"#DDDDDD',162,'outset 2px',191,'103",','width:"auto',193,'10pt","font-style":"',54,195,' .disabled":{color:"#888888',195,' .infoLink',74,'85%"},"#jsMath_panel *":{"','font-size":"inherit","font-style":"inherit","font-family":"inherit',51,195,' div":{"','background-color":"inherit",color:"inherit"},"#jsMath_panel ','span":{"',220,'td',70,68,67,'","',220,'tr',70,68,67,'","',220,'table',70,68,67,158,'":"inherit",color:"inherit",height:"auto",',206,177,'jsMath_button',185,'1px",right:"2px',158,'":"white',189,'0px 3px 1px 3px',191,'102",color:"black","',152,'","font-size":"x-',194,'",cursor:"hand"},"#',243,' *":{padding:"0px",border',67,51,'","',216,177,'jsMath_global":{"',145,177,'jsMath_noFont',' .message":{"text-align":"center",padding:".8em 1.6em",border:"3px solid #DD0000","background-color":"#FFF8F8",color:"#AA0000","font-size":"',194,177,'jsMath_noFont .link":{padding:! "0px 5px 2px 5px',162,'2px outset',158,'":"#E8E8E8',193,'80%",',206,255,'jsMath_PrintWarning',267,'x-',194,'"},"@media print":{"#',243,167,'none',177,'jsMath_Warning',167,'none"}},"@media screen":{"#',279,167,'none"}}},Element',':function(','A','){return ',6,15,16,'("jsMath_"+A)},','BBoxFor',294,'A','){this.','hidden.innerHTML','=\'<nobr><','span class="','typeset"><',307,'scale">\'+A+"</span></span></nobr>";var B={w:this.',170,'.offsetWidth',',h:this.',170,'.offsetHeight','};this.',305,'="";return B},EmBoxFor',294,'B){var A=',6,'Global.cache.R;if(!A[this.em]){A[this.em]={}}if(!A[this.em][B]){var C=this.BBoxFor(B);','A[this.em][B]={w:C.w/this.em,h:C.h/this.em}}return A[this.em][B]},','EmBoxForItalics',294,320,6,322,'if(B.match(/<i>|class=\\"(icm|italic|igreek|iaccent)/i)){C.w=C.Mw=','this.BBoxFor','(B+',6,'Browser.','italicString',').w-',6,333,'italicCorrection','}',323,'Init',':function(){','if(',6,'Setup.inited','!=1){',0,6,345,'){',6,'Setup.','Body()}if(',6,345,'!=1){if(! ',6,345,'==-100','){return }',23,'It looks like jsMath failed ! to set u p properly (error code "+',6,345,'+"). I will try to keep going, but it could get ugly.");',6,345,'=1}}this.em=this.CurrentEm();','var A=',6,'Global.cache','.B;',0,'A[this.em]){A[this.em]={};','A[this.em].','bb=',330,'("x");var C=',375,'bb.h;',375,'d=',330,'("x"+',6,'HTML.Rule(1,','C/',6,'em)).h-C;if(',6,333,334,'){',375,'ic=',6,301,'(',6,333,334,').w}}',6,333,338,'=',375,'ic;var F=',375,'bb;var D=F.h;var E=',375,'d;this.h=(D-E)/this.em;this.d=E/this.em;this.hd=this.h+','this.d;this.',352,'TeXfonts','();var B=this.EmBoxFor(\'<',307,113,'">M</span>\').w/2;this.TeX.M_height=B*(26/14);this.TeX.h=this.h;this.TeX.d=',413,'TeX.hd=this.hd;this.Img.Scale();',0,'this.initialized',304,352,'Sizes','();this.','Img.UpdateFonts()}this.p_height=(','this.TeX.cmex10[0].','h+',429,'d)/0.85;',423,'=1},ReInit',342,'if(this.','em!=this.CurrentEm()){this.Init()}},CurrentEm',342,369,330,'(\'<span style="\'+',6,333,'block+\';','width:13em;height:1em','"></span>\').','w/13;if(A>0',296,'A}return ',3! 30,'(\'<img src="\'+',6,166,'+\'" style="',445,'"/>\').w/13},Loaded',342,'if(',9,8,'B=["Process","ProcessBeforeShowing","ConvertTeX","ConvertTeX2","ConvertLaTeX","ConvertCustom","CustomSearch","Synchronize","Macro","document"];','for(var A=0;A<','B','.length;A++){','if(',9,'[B[A]]){','delete ',9,'[B[A]]}}}if(',9,304,'Insert(jsMath,',9,')}',9,'=null;',6,7,'=1},Add',294,'C,A){for(var B in A){','C[B]=A[B]}},Insert',294,482,'if(C[B]&&typeof (A[B])=="object"&&(','typeof (C[B])=="','object"||',487,'function")){this.Insert(C[B],A[B])}else{C[B]=A[B]}}},Package',294,'B,A',304,'Insert(B.prototype,A)}};',6,'Global={isLocal:1,cache:{','T:{},D:{},R:{},B',':{}},ClearCache',342,6,371,'={',497,':{}}},GoGlobal',294,320,'String(',6,1,'.','location);var C','=(',6,'isCHMmode','?"#":"?");if(B){A=A.replace(/\\?.*/,"")+"?"+B}',6,'Controls.','Reload(',6,'root+"jsMath-','global.html"+C+escape(A))},Init',342,'if(',6,'Controls.cookie.','global=="always"&&!',6,'noGoGlobal','){if(',38,'accentColorName'! ,360,0,6,1,'){',6,1,'=',1,'}',6,517,7,'=1;',6,517,'defaults.hi! ddenGlob al=null;this.GoGlobal(',6,517,'SetCookie(2))}},Register',342,369,6,1,'.parent;',0,6,'isCHMode){',6,514,'=(',6,1,'.','location.','protocol=="mk:")}try{',0,6,514,304,'Domain()}if(A',2,'&&A.',6,'isGlobal){A.',6,'Register(',6,1,')}}catch(B){',6,528,'=1}},Domain',342,'if(',38,'appName=="Microsoft Internet Explorer"&&',6,36,'=="mac"&&',38,'userProfile','!=null',360,'if(',1,'==parent',360,'var B=',6,15,'domain',';try{while(true){try{if(parent.',15,'title',594,'){return }}','catch(A){}',0,15,603,'.match(/\\..*\\./)){break}',6,15,603,'=',6,15,603,'.replace(/^[^.]*\\./,"")}}',609,6,15,603,'=B}};',6,'Script={request:null,Init',342,'if(!(',6,525,'asynch&&',6,525,'progress',')){if(',1,'.XMLHttpRequest','){try{','this.request','=new XMLHttpRequest}catch(C){}if(',641,'&&',6,'root.match','(/^file:\\/\\//)){try{',641,'.open("GET",',6,'root+"',6,'js",false);',641,'.send(null)}catch(','C){',641,'=null;if(',1,'.postMessage&&',1,'.addEventListener',304,'mustPost','=1;',6,1,662,'("message",',6,'P! ost.','Listener,false)}}}}',0,641,'&&',1,'.ActiveXObject&&!this.',664,8,'A=["MSXML2.XMLHTTP.5','.0","MSXML2.XMLHTTP','.4',681,'.3',681,'","Microsoft.XMLHTTP"];','for(var B=0;B<','A.length&&!',641,';B++){try{',641,'=new ActiveXObject(A[B])}catch(C){}}}}',0,641,'||',6,352,'domainChanged',304,'Load=this.delayedLoad;this.needsBody=1}},Load',294,'B,A){','if(A){',6,'Message.Set("Loading "+','B);',6,'Script.','Delay(1);',6,'Script.Push(','this,"xmlRequest",B',');',6,711,6,'Message',',"Clear")}else{',6,711,712,')}},xmlRequest',294,'url){','this.blocking','=1;try{',641,649,'url,false);',641,655,'err){',725,'=0;if(',6,'Translate.','restart&&',6,'Translate.asynchronous){return""}throw"jsMath can\'t load the file \'"+url+"\'\\','nMessage: "+err.message}if(',641,'.status',594,'&&(',641,742,'>=400||',641,742,'<0)){',725,'=0;if(',6,736,'restart&&',6,739,'nError status: "+',641,742,'}',0,'url','.match(/\\.js$/)){','return(',641,'.responseText',')}var tmpQueue','=this.queue;this.queue','=[]! ;',6,1,'.eval(',641,767,');',725,'=0;','this.queue=this.queue.! concat(' ,'tmpQueue);this.Process();return""},cancelTimeout:30*1000,blocking:0,cancelTimer:null,needsBody:0,queue:[],Synchronize',294,'A,B){','if(typeof (','A)!="string"){',6,711,'null,A,B',')}else{',6,711,6,1,',"eval",A)}},Push',294,'A,C,B',304,'queue[','this.queue.length',']=[A,C,B];if(!(',725,'||(this.needsBody&&!',6,15,'body))){this.Process()}},Process',342,'while(',798,'&&!',725,8,'C=this.queue[0];this.queue=this.queue.slice(1);',369,'this.SaveQueue();var B=C[0];var E=C[1];var D=C[2];if(B){B[E](D',788,'if(E){E(D)}}this.','RestoreQueue','(A)}},SaveQueue',342,'var A',769,'=[];return A},',816,294,'A){',779,'A)},delayedLoad',294,'A',304,'Push(','this,"','startLoad','",A)},',832,294,'A',8,'B=',6,15,21,'("iframe");','B.style.','visibility="','hidden";',843,'position="absolute";',843,'width="0px";B','.style.height="','0px";if(',6,15,'body.firstChild','){',6,15,'body.insertBefore(B,',6,15,854,788,6,15,'body','.appendChild(','B)}',725,'=1;this.','url=A;if(A','.substr(0,',6,'root.length',! ')==',6,'root){A=A.substr(',6,873,')}',6,705,'A);this.cancelTimer=setTimeout("',6,708,'cancelLoad','()",this.cancelTimeout);',436,664,'){B.src=',6,671,832,'(A,B',788,'if(A',764,'B.src=',6,520,'loader.html"}else{B.src=this.url}}},','endLoad',294,'A){if(this.cancelTimer){clearTimeout(this.cancelTimer);this.cancelTimer=null}',6,671,901,'();',6,717,'.Clear();if(A!="cancel"){',725,'=0;this.Process','()}},Start',342,'this.tmpQueue',769,'=[]},End',342,779,915,');',468,915,'},',885,294,'B,',903,'if(B==null){B','="Can\'t load file"}if(A==null){A=2000}',6,717,'.Set(B);setTimeout(\'',6,708,901,'("cancel")\',A)},Delay',294,'A){',725,'=1;setTimeout("',6,708,'endDelay','()",A)},',944,342,725,912,'()},','imageCount',':0,WaitForImage',294,'B){',725,869,951,'++;',436,'img==null',304,'img=[]}',369,'new Image',427,'img[this.img.length]=A;A.onload=function(){if(--',6,708,951,'==0){',6,708,944,'()}};A.onerror=A.onload;A.onabort=A.onload;A.src=B},Uncompress',294,'data){for(var k=0;k<data.length;! k++){var d=data[k];var n=d.length;for(var i=0;i<n;i++){',783,'! d[i])==" number"){d[i]=d[d[i]]}}data[k]=d.join("")}',1,773,'data.join(""))}};',6,'Post={',1,':null,Listener',294,'D){if(D.source!=',6,671,1,360,'var E=D.origin','.replace(/^file:\\/\\//,"");',369,15,603,993,'if(E==null||E==""){E','="localhost"}if(','A==null||A==""){A',999,'E!=A||!','D.data.substr(','0,6).match(/jsM(CP|LD):/)){return }var B=',1003,'6,3).replace(/ /g,"");var C=',1003,'10);if(',6,'Post.Commands[B',']){(',6,1010,'])(C)}},Commands:{SCR',294,'message){',6,1,773,'message)},ERR',294,'A){',6,708,885,'(A,3000)},BGN',294,'A){',6,708,'Start()},END',294,'A){',703,6,708,'End()}',6,708,901,'()}},',832,294,'A,B',304,1,'=B.contentWindow;',0,'A',764,'return ',6,'root+',449,6,520,'loader-post.html?"+A},',901,342,'this.',1,'=null}};',6,717,'={',166,':null,message:null,text:null,clear:null,Init',342,0,6,15,'body||!',6,525,636,360,'if(',6,352,'stylesReady){','this.message','=',6,'Setup.DIV("','message",{visibility:"',170,'"},',6,'fixedDiv',788,1081,'=',6,1084,'message",{',179,'bottom:"',1! 86,'",','backgroundColor',':"#E6E6E6',189,190,'",zIndex:102,color:"black",fontSize:"',194,'"},',6,1089,')}','this.text','=',6,15,'createTextNode','("");',1081,866,1110,');',1081,'.onmousedown=',6,736,'Cancel},Set',294,702,'if(this.clear){clearTimeout(this.clear',');this.clear=null}if(',6,525,636,'){',0,1110,304,'Init();',0,1110,608,'if(',6,333,'textNodeBug','){',1081,'.innerHTML','=B','}else{',1110,'.nodeValue','=B}','this.message.style.',844,'visible";',703,1152,'cursor="pointer','";',0,1152,'cursor){',1152,'cursor="hand"}',1081,'.title=" Cancel Processing of Math "}else{',1152,'cursor="";',1081,'.title=""}}else{if(B',871,'8)!="Loading "){',6,1,742,'=B}}},Clear',342,1127,')}this.clear=setTimeout("',6,717,'.doClear()",1000)},doClear',342,436,'clear',304,'clear=null;',6,1,742,'="";',436,'text){',1110,1150,'=""}if(',1081,'){',1152,844,170,'"}}},Blank',342,436,166,'||!',6,15,'body',360,'this.blank','=',6,1084,166,'",{position',':(',6,333,'msiePositionFixedBug','?"absolute":"fi! xed"),',180,'",bottom:"0px",right:"0px",zIndex:101,',1100,':"w! hite"},' ,6,1089,');if(',6,333,'msieBlankBug){',1210,1146,'=" ";',1210,'.style.width="110%";',1210,850,'110%"}},UnBlank',342,436,166,'){',6,15,'body.removeChild(',1210,')}',1210,'=null}};',6,'Setup={',7,':[],DIV',294,'E,C,B){',929,'=',6,15,'body}var D=',6,15,21,'("div");D.id="jsMath_"+E;','for(var A in C){','D.style[A]=C[A]}',0,'B.hasChildNodes){B',866,'D',788,'B.insertBefore(D,','B.firstChild',')}return D},Script',294,702,436,7,'[B]){return }else{this.',7,'[B]=1}',0,'B.match("^([a-zA-Z]+:/?)?/")){B=',6,'root+B}',6,708,'Load(B,A)},Hidden',342,6,170,'=this.DIV("Hidden",{',179,'top:0,left:0,border:0,padding:0,margin:0});',6,'hiddenTop=',6,170,';return },Source',342,'if(',6,'Autoload','&&',6,1303,'.root){',6,'root=',6,1303,'.','root}else{',6,'root="";',369,6,15,'getElementsByTagName("','script");',703,687,'A.','length;B++){','var D=A[B].src;if(D&&D.match("(^|/|\\\\\\\\)',6,'js$")){',6,1309,'D.replace','(/',6,'js$/,"");break}}}}if(',6,'root.charAt(','0)=="\\\\"){',6,1309,6,'root.rep! lace','(/\\\\/g,"/")}if(',6,1335,'0)=="/"){if(',6,1335,'1)!="/"){if(',6,15,566,'port){',6,'root=":"+',6,15,566,'port+',6,'root}',6,'root="//"+',6,15,566,'host+',6,1359,6,1309,6,15,566,'protocol+',6,1313,0,6,646,'(/^[a-z]+:/i)){var D=','new String(',6,15,511,'=new RegExp("/[^/]*/\\\\.\\\\./");',6,1309,1330,'(new RegExp("[^/]*$"),"")+',6,'root;while(',6,646,'(C)){',6,1309,6,1340,'(C,"/")}}}',6,'Img.',1309,6,651,'fonts/";',6,166,'=',6,651,166,'.gif";this.Domain()},Domain',342,'try{',6,15,603,'}catch(D',360,'var C="";',369,6,15,603,';if(',6,646,'("://([^/]*)/")){C=RegExp.$1}C=C.replace(/:\\d+$/,"");if(C==""||C==A',360,'if(',38,'appName=="Microsoft Internet Explorer"&&',6,36,'=="mac"&&',38,'onLine&&',38,593,'&&',6,15,'all',360,'C=C.split(/\\./);A=A.split(/\\./);if(C.length<2||A.length<2||','C[C.length-','1',']!=A[A.length-','1]||',1445,'2',1447,'2]){this.','DomainWarning','();return }var E=',1445,'2]+"."+',1445,'1];for(var B=3;B<=C.length&&B<=A.',1324,'if(',1445,'B',1447,'B]){br! eak}E=',1445,'B]+"."+E}',6,15,603,'=E;this.',698,'=1},',1453,3! 42,23,'I n order for jsMath to be able to load the additional components that it may need, the ',6,'js file must be ',7,' from a server in the same ',603,' as the page that contains it. Because that is not the case for this page, the',25,'displayed here may not appear correctly.")},','EncodeFont',294,'C',8,'B=',6,'TeX[C];if(B','[0].c',594,360,462,'128;A++){var D=B[A];B[A]=D[3];if(B[A]==null){B[A]={}}B[A].w=D[0];B[A].h=D[1];if(D[2]!=null){B[A].d=D[2]}B[A].c=',6,'TeX.encoding[A]}},Fonts',342,687,6,'TeX.fam','.',1324,369,6,1502,'[B];if(A',304,1485,'(A)}}},TeXfont',294,'C',8,'B=',6,1491,'==null',360,369,6,'EmBoxFor(\'<span class="\'+C+\'">\'+B[65].c','+"</span>");B.hd=A.h;B.dh=0.05;B.d=',6,1522,'+',6,386,'B.hd)+"</span>").h-B.hd;B.h=B.hd-B.d;if(C=="',130,'"){B.skewchar=','127','}else{if(','C=="',134,1531,'48}}},',415,342,462,6,1502,464,'if(',6,1502,'[A]){this.TeXfont(',6,1502,'[A])}}},Sizes',342,6,'TeXparams','=[];var B;var A;for(A=0;A<',6,46,464,6,1553,'[A]={}}for(B in ',6,'TeX){',783,! 6,'TeX[B])!="object"){for(A=0;A<',6,46,464,6,1553,'[A][B]=',6,46,'[A]*',6,'TeX[B]/100}}}},Styles',294,'A){',0,'A){A=',6,'styles;A[".typeset .scale"]={"font-size":',6,525,'scale+"%"};this.stylesReady=1}',6,711,831,'AddStyleSheet','",A);if(',6,333,'styleChangeDelay','){',6,711,6,'Script,"Delay",1)}},StyleString',294,'E',8,'A={},F;for(F in E){if(typeof E[F]==="string"){A[F]=E[F]}else{if(F',871,'1)==="@"){A[F]=','this.StyleString(','E[F])}else{if(E[F]!=null',8,'D=[];for(var C in E[F]){if(E[F][C]!=null){D[D.length]=C+": "+E[F][C]}}A[F]=D.join("; ")}}}}var B="";for(F in A){B+=F+" {"+A[F]+"}\\n"}return B},',1589,294,'D',8,'B=',6,15,1319,'head")[0];',369,1605,'D);if(',6,15,'createStyleSheet){B.insertAdjacentHTML("beforeEnd",\'<','span style="display:','none">x</span><style type="text/css">\'+A+"</style>")}else{var C=',6,15,21,'("style");C.type="text/css";C',866,6,15,1114,'(A));B',866,'C)}},Body',342,436,'inited',360,'this.inited=-','1;',6,352,'Hidden();',1641,'2;',6,333,1136,1641,'! 3;if(',6,525,166,'){',6,717,'.Blank()}',1641,'4;',6,352,'Style! s();',16 41,'5;',6,517,1136,1641,'6;',6,711,6,'Setup,"User","pre-font");',1641,'7;',6,711,6,'Font,"Check");if(',6,'Font.register.length){',6,711,6,'Font,"LoadRegistered")}this.inited=1},User',294,'A){if(',6,'Setup.UserEvent[A',']){(',6,1691,'])()}},UserEvent:{"pre-font":null,onload:null}};',6,'Update={',415,294,'D){for(var A in D){for(var B in D[A]){for(var C in D[A][B]){',6,'TeX[A][B][C]=D[A][B][C]}}}},TeXfontCodes',294,'C){',1265,687,'C[A].',1324,6,'TeX[A][B].c=C[A][B]}}}};',6,'Browser={allowAbsolute:1,allowAbsoluteDelim:0,','separateSkips',':0,valignBug:0,operaHiddenFix:"",','msieCenterBugFix',':"",','msieInlineBlockFix',':"",msieSpaceFix:"",imgScale:1,renameOK:1,',1593,':0,delay:1,version:0,','TestSpanHeight',342,6,305,'=\'<span><','span style="\'+this.block','+\';height:2em;width:','1px"></span></span>\';var B=',6,'hidden.firstChild;',369,1273,';this.','spanHeightVaries','=(B',315,'>=A',315,'&&B',315,'>0);','this.spanHeightTooBig','=(B',315,'>A',315,');',6,305,'=""},','TestInlin! eBlock',342,'this.block="display',':-','moz-inline-box";','this.hasInlineBlock','=',6,'BBoxFor(\'<span style="\'+this.block','+\';width:10px;height:5px"></span>\').w>0;if','(',1756,'){',6,'styles[".typeset',' .',166,'"].display="-',1755,468,6,1765,' .spacer"].display',1148,1753,':',168,'";',1756,'=',6,1759,1760,'(!',1756,608,'this.block+=";overflow:',845,369,6,301,'("x").h;this.mozInlineBlockBug=',6,1759,'+";height:"+A+\'px;width:1px','"></span>x','<',1726,'+";height:"+A+"px;width:1px;vertical-align:-"+A+\'px',446,'h>2*A;this.widthAddsBorder=',6,1759,'+\';overflow:',170,';height:1px;width:10px',';border-left:','10px solid',446,'w>10;','this.msieBorderBug','=',6,1759,1795,1796,'\').h!=',6,1759,1795,1807,72,1796,'\').h;','this.blankWidthBug=',1811,'||',6,1759,1727,'0px',446,'h==0},','TestRenameOK',342,6,305,'="<span></span>";',369,6,1730,'A.setAttribute("name","','jsMath_test','");this.renameOK=(',6,15,'getElementsByName("',1843,'").length>0);',6,305,1750,'TestStyleChange',34! 2,6,305,'=\'<span ID="',1843,'">x</span>\';var B=',6,1730,369,! 'B',312, ';',6,352,1589,'({"#',1843,'":"font-size:200%"});this.',1593,'=(B',312,'==A);',6,305,1750,'VersionAtLeast',294,320,1380,'this.version).split(".");B=',1380,'B).split(".");if(B[1]==null){B[1]="0"}return A[0]>B[0]||(A[0]==B[0]&&A[1]>=B[1])},Init',342,6,27,'="unknown";this.',1751,427,1721,427,1834,427,1853,427,'MSIE',427,'Mozilla',427,'Opera',427,'OmniWeb',427,'Safari',427,'Konqueror();if(','this.allowAbsoluteDelim','){',6,'Box.DelimExtend=',6,'Box.DelimExtendAbsolute;',6,'Box.Layout=',6,'Box.LayoutAbsolute',1148,6,'Box.DelimExtend=',6,'Box.DelimExtendRelative;',6,'Box.Layout=',6,'Box.LayoutRelative}',436,1713,'){',6,'HTML.Place=',6,'HTML.','PlaceSeparateSkips',';',6,'Typeset.prototype.','Place=',6,1938,1935,'}},MSIE',342,436,1734,'&&!',1742,'){',6,27,'="MSIE";if(',6,36,'=="pc"){this.','IE7=(',1,639,594,');','this.quirks','=(',6,15,'compatMode=="BackCompat");this.msieStandard6=!',1961,'&&!this.IE7;',1909,869,1713,'=1',';this.buttonCheck=1;this.','msieBlankBug=1;this.','msieAccen! tBug',869,'msieRelativeClipBug','=1;this.msieDivWidthBug=1;this.',1219,869,'msieIntegralBug',869,'waitForImages',869,'msieAlphaBug','=!this.IE7;this.','alphaPrintBug',1985,1715,'="position:relative; ";this.',1717,'=" display:',168,';";this.msieTeXfontBaselineBug=!',1961,';',1811,'=',1825,'1;this.msieSpaceFix=\'<',1624,168,'"></span>\';',6,'Macro("joinrel","\\\\mathrel{\\\\kern-5mu}"),',6,'Parser.prototype.mathchardef.','mapstocharOrig','=',6,2006,'mapstochar;',468,6,2006,2011,6,'Macro("mapstochar","\\\\rlap{\\\\',2007,'\\\\,}\\\\kern1mu"),',6,1765,' .arial"]={"font-family":"\'Arial unicode MS\'"};',0,'this.IE7||',1961,'){',6,'styles["#jsMath_message"].',847,468,6,2028,'width;',6,'styles["#jsMath_panel"].',847,468,6,2035,'width;',6,'styles["#jsMath_button"].','width="1px";',6,2042,847,468,6,2042,'width;',6,1089,'=',6,1084,1089,1215,':"absolute",zIndex:101});',6,1,'.attachEvent("','onscroll",',6,'Controls.MoveButton',');',6,1,2061,'onresize",',6,2064,');',6,2064,'()}',6,'styl! es["#jsMath_noFont .link"].','display="',168,'";',468,6,1765,1! 773,';', 6,'styles[".tex2math_div','"]={};',6,'Add(',6,2087,'"],',6,'styles["div',57,'"]);',6,2087,'"].width="100%";',6,2087,'"].',2078,168,'";',6,1765,'"]["letter-spacing"]="0";if(','screen.deviceXDPI','&&','screen.logicalXDPI','&&',2110,'!=',2112,304,'imgScale*=',2112,'/',2110,';',6,525,'alpha=0}this.',334,'="<i>x</i>";',6,'EmBoxFor=',6,324,1533,6,36,'=="mac"){this.msieAbsoluteBug',869,'msieButtonBug',1977,1973,'quirks=1;',6,'Setup.Script("jsMath-','msie-mac.js");',6,'Parser.prototype.macros.angle=["Replace","ord",\'<font face="Symbol">‹</font>\',"',54,'"];',6,2035,'width="42em";',6,525,'printwarn=0}}',6,'Macro("not","\\\\mathrel{\\\\rlap{\\\\kern3mu','/}}")}},',1900,342,'if(',6,170,'.ATTRIBUTE_NODE){',6,27,'="',1900,'";if(',6,36,1955,1986,'=1}',1909,'=1;',6,2042,'cursor=',6,2077,1157,'",',6,2155,'/}}");if(',38,'vendor=="Firefox"){','this.version=',38,'vendorSub',1533,38,'userAgent.match','(" Firefox/([0-9.]+)([a-z ]|$)")){',2187,'RegExp.$1}}',436,1879,'("3.0")){this.mozImageS! izeBug=1}}},',1904,342,'if(',38,'accentColorName){',6,27,'="',1904,'";','this.allowAbsolute','=',1756,';',1909,'=',2209,';this.valignBug=!',2209,1972,1143,'=1;',6,'noChangeGlobal=1;',0,1756,'){',6,2142,'old-browsers.js','")}}},Opera',342,'if(',1742,'){',6,27,'="Opera";var B=',38,2192,'("Opera 7");',2209,'=0;this.delay=10;this.operaHiddenFix="[Processing]";if(B){',6,2142,2228,'")}',369,38,'appVersion.match(/^(\\d+\\.\\d+)/);',703,2187,'A[1]}else{this.vesion=0}this.operaAbsoluteWidthBug=this.operaL'], - ['ineHeightBug=(A[1]>=9.5)}},Safari',':function(){','if(navigator.','appVersion.match(/Safari\\//)){','jsMath.','browser','="Safari";','var A=','navigator.userAgent.match','("Safari/([0-9]+)");A=(A)?A[1]:400;this.version=A;','for(var B=0;B<',4,'TeX.fam','.length',';B++){','if(',4,12,'[B]&&',4,'TeX[',4,12,'[B]]){',4,20,4,12,'[B]].dh=0.1}}',4,'TeX.axis_height+=0.05;',4,'TeX.','default_rule_thickness','+=0.025',';this.allowAbsoluteDelim=','A>=125;this.safariIFRAMEbug=A>=312&&A<412;this.safariButtonBug=A<412;this.safariImgBug=1;this.textNodeBug=1;this.buttonCheck=A<500;this.styleChangeDelay=1}},','Konqueror',1,2,'product&&navigator.product.match("',37,'")){',4,5,'="',37,'";this.allowAbsolute=0',35,'0;if(',8,'(/',37,'\\/(\\d+)\\.(\\d+)/)){if(RegExp.$1<3||(RegExp.$1==3&&RegExp.$2<3)){this.separateSkips=1;this.valignBug=1;',4,'Setup.Script("jsMath-','old-browsers.js")}}',4,'Add(',4,'styles,{".typeset .cmr10','":"font-family: jsMath-','cmr10',', jsMath ','cmr10, serif','",".types! et .','cmbx10',61,66,63,66,', jsMath-cmr10, jsMath cmr10",".typeset .','cmti10',61,72,63,72,71,'cmmi10',61,78,63,78,65,'cmsy10',61,84,63,84,65,'cmex10',61,'cmex10, jsMath cmex10','"});',4,'Font.testFont','="jsMath','-',92,'"}}};',4,'Font={testFont:"jsMath-cmex10",','fallback',':"symbol",register:[],message:"<b>No jsMath TeX fonts found</b> -- using',' image fonts instead','.<br/>\\nThese',' may be slow and might not print well.<br/>\\nUse the jsMath control panel to get additional information','.",','extra_message',':\'Extra TeX fonts not found: <b><span id="jsMath_ExtraFonts"></span></b><br/>Using',104,'. This',106,'.\',','print_message',':"To print higher-resolution math symbols, click the<br/>\\n<b>Hi-Res Fonts for Printing</b> button on',' the jsMath control panel.<br/>\\n",','alpha_message',':"If the math symbols print as black boxes, turn off <b>image alpha channels</b><br/>\\nusing the <B>Options</B> pane of',116,'Test1',':function(','C',',F,D,E){if(F==null){F=124}i! f(D==null){D=2}if(E==null){E=""}var B=jsMath.BBoxFor(\'<span s! tyle="fo nt-family: \'+E+C+\', serif">\'+jsMath.TeX[C][F].c+"</span>");var A=jsMath.BBoxFor(\'<span style="font-family: serif">\'+jsMath.TeX[C][F].c+"</span>");return','(B.w>D*A.w&&B.h!=0)},Test2',121,'C',123,'(A.w>D*B.w&&B.h!=0)},CheckTeX',1,7,4,'BBoxFor(\'<span style="font-family',': \'+',4,95,'+\', serif">\'+',4,'TeX.cmex10[1','].c+"</span>");',4,'nofonts=((A.w*3>A.h||A.h==0)&&!this.Test1("cmr10','",null,null,"jsMath-"));if(!',4,'nofonts){','return }if(',4,5,'!="Mozilla"||(',4,'platform','=="mac"&&(!',4,'Browser.VersionAtLeast(','1.5)||',4,153,'3)))||(',4,150,'!="mac"&&!',4,153,'3))){A=',4,132,': CMEX10, serif">\'+',4,'TeX.cmex10[1',139,4,141,'"));if(!',4,144,4,55,'BaKoMa-fonts.js")}}},Check',1,7,4,'Controls.','cookie;this.CheckTeX();if(',4,144,'if(A.autofont','||A','.font=="tex"){','A.font=this.',102,';if(A.warn){',4,'nofontMessage=1;A.warn=0;',4,181,'SetCookie(0);if','(',4,'window.NoFontMessage','){',4,198,'()}else{','this.Message(this.','message)}}}}else{',185,'){A.font="tex"}i! f(A',187,'return }}if(',4,'noImgFonts){','A.font="unicode"}if(A','.font=="unicode','"){',4,55,102,'-"+',4,150,'+".js");',4,'Box.TeXnonfallback=',4,'Box.TeX',';',4,224,'=',4,'Box.TeXfallback;return }','if(!A.print&&A.printwarn){this.','PrintMessage','((',4,'Browser.','alphaPrintBug&&',4,181,'cookie.alpha)?this.',114,'+this.',117,':this.',114,')}if(',4,235,'waitForImages){',4,'Script.','Push(',4,'Script,"WaitForImage",',4,'blank)}if(A.font=="symbol"){',4,55,102,'-symbols.js");',4,'Box.TeXnonfallback=',4,224,';',4,224,'=',4,230,4,'Img.SetFont','({cmr10',':["all"],',78,273,84,273,'cmex10',273,66,273,72,':["all"]});',4,'Img.LoadFont','("cm-fonts")},Message',121,'A){if(',4,'Element("Warning',42,'return }var ','B=',4,'Setup.DIV("','Warning','",{});B.innerHTML=\'<center><table><tr><td><div ','id="jsMath_noFont"><div ','class="message">\'+A','+\'<div style="text-align:left"><span style="float:left; margin: 8px 0px 0px 20px"><span onclick="',4,181,'Panel()" ','title=" Open ','the ','! jsMath Control Panel',' " class="link">',306,'</span></span','! ><span s tyle="margin: 8px 20px 0px 0px; float:right"><span onclick="',4,'Font.','HideMessage','()" title=" Remove this font warning message',307,'Hide this Message',309,'></div><div style="height:6px"></div><br clear="all"/></div></','div><div style="width:22em; height:1px"></div></td></tr></table></center><hr/>\'},',313,1,7,4,290,'");if(A','){A.style.display="none"}},',232,121,288,4,'Element("','PrintWarning',42,292,'B=',4,295,332,297,299,'+\'</',319,'Register',121,'H,B){if(typeof (H)=="string"){H={name:H}}if(!',4,'Setup.inited','&&!B){','this.register','[',349,13,']=H;',292,'I=H.name;',7,'I.replace(/10$/,"");var F=',4,12,13,';if(H.prefix==null){H.prefix=""}if(!H.style){H.style="font-family: "+H.prefix+I+", serif"}if(!H.styles){H.styles={}}if(!H.macros){H.macros={}}',4,12,'[F]=I;',4,'TeX.famName[I]=F;H.macros[A]=["HandleFont",F];',4,58,4,'Parser.prototype.macros,H.macros);H.styles[".typeset ."+I]=H.style;',4,'Setup.Styles(H.styles);if(',4,'initialized){',4,250,'Push(',4,'Setup,"TeX! font",I)}var C=',4,181,'cookie;var E=!',4,'nofonts&&H.test(I,H.testChar,H.testFactor,H.prefix);if(E&&C',187,'if(H.tex){H.tex(I,F,H)}return }if(!E&&C.warn&&C.font=="tex"&&!',4,144,'if(!C.fonts.match("/"+I+"/")){C.fonts+=I+"/";',4,181,195,'(!',4,290,42,203,108,')}var G=',4,331,'ExtraFonts");if(G){if(G','.innerHTML','!=""){G',403,'+=","}G',403,'+=" "+H.prefix+I}}}if(C',212,'"||',4,210,'if(H.',102,'){H.',102,'(I,F,H)}',292,'D={};if(C.font=="symbol"&&H.symbol!=null){D[I]=H.symbol(I,F,H)}else{D[I]=["all"]}',4,271,'(D);',4,285,'(I);if(',4,'initialized){',4,250,'Push(',4,'Img,"Scale");',4,250,'Push(',4,'Img,"UpdateFonts")}},LoadRegistered',1,7,'0;while(A<',349,13,'){this.Register(',349,'[A++],1)}',349,'=[]},Load',121,'A){',4,'Setup.Script(this.URL(A))},URL',121,'A){','return ',4,'Img.root+A+"/def.js"}};',4,'Controls={cookie:{scale:100,font:"tex",autofont:1,scaleImg:0,alpha:1,warn:1,fonts:"/",printwarn:1,stayhires:0,button:1,progress:1,asynch:0,blank:0,print:0,keep:"0D",global:"auto! ",hiddenGlobal:1},cookiePath:"/",','noCookiePattern',':/^(file! |mk):$/, Init',1,'this.panel=',4,295,'panel",{display:"none"},',4,'fixedDiv);','if(!',4,235,'msieButtonBug){this.Button',202,'setTimeout("',4,181,'Button()",500)}},Panel',1,4,'Translate.Cancel();if(this.loaded){this.Main',202,4,250,'delayedLoad(',4,'root+"jsMath-controls.html")}},Button',1,7,4,295,'button",{},',4,467,'A.',304,306,' ";A',403,'=\'<span onclick="',4,181,'Panel()">jsMath</span>\';if(!',4,'Global.','isLocal&&!',4,'noShowGlobal){A',403,'+=\'<span id="jsMath_global" ',304,'jsMath Global Panel " onclick="',4,503,'Show(1)">Global </span>\'}if(A.offsetWidth<30){A.style.width="auto"}if(!','this.cookie','.button',326,'MoveButton',1,4,'fixedDiv.style.','left','=document.body.','scrollLeft+"px";',4,520,'top',522,'scrollTop+"px";',4,520,'width',522,'clientWidth+"px";',4,520,'height',522,'clientHeight+"px"},GetCookie',1,'if(','this.defaults','==null){',541,'={}}',4,58,541,',',514,');this.userSet={};var C=',4,'document.cookie',';if(',4,'window.location','.protocol.match(this.',4! 59,')){C=this.','localGetCookie','();','this.isLocalCookie','=1}if(','C.match(/jsMath','=([^;]+)/)){var D=unescape(RegExp.$1).split(/,/);',10,'D',13,14,7,'D[B].match(/(.*):(.*)/);if(A[2].match(/^\\d+$/)){A[2]=1*A[2]}',514,'[A[1]]=A[2];this.userSet[A[1]]=1}}},',559,1,454,4,555,'.search.substr(1)},SetCookie',121,'F){var B=[];for(var E in ',514,'){if(',541,'[E]==null||',514,'[E]!=',541,'[E]){B[B',13,']=E+":"+',514,'[E]}}B=B.join(",");if(',561,'){if(F==2){return"','jsMath="+escape(B)}','this.','localSetCookie','(B,F)}else{B=escape(B);if(B==""){F=0}if(','this.cookiePath','){B+="; path="+',599,'}if(','this.cookieDomain','){B+="; domain="+',603,'}if(',514,'.keep!="0D"){var A={D',':1000*60*60*24',',W',609,'*7,M',609,'*30,Y',609,'*365};var D=new Date;D.setTime(D.getTime()+',514,'.keep.substr(','0,1)*A[',514,618,'1,1)]);B+="; expires="+D.toGMTString()}if(B!=""){',4,552,96,'="+B;var C=',4,552,';if(F&&!',563,'=/)){alert("Cookies must be enabled in order to save jsMath options")}}}',454! ,'null},',597,121,'B,C){if(!C){return }',7,'String(',4,555,').! replace( /\\?.*/,"");if(B!=""){A+="?',595,'if(A!=',4,555,'.href){this.Reload(A)}},Reload',121,'A){if(!this.loaded){return }this.loaded=0;',4,347,'=-100;',4,503,'ClearCache();if(A){',4,555,'.replace(A)}else{',4,555,'.reload()}}};',4,'Click={CheckClick',121,'A){if(!A){A=',4,'window.event}if','(A.altKey){',4,181,'Panel()}},CheckDblClick',121,'B){if(!B){B=',4,666,'(!',4,'Click.DblClick){',4,'Extension.Require("double-click",1);',7,'B;B={};for(var C in A){B[C]=A[C]}}',4,250,'Push(',4,'Click,"DblClick",[B,this.alt])}};',4,'TeX={thinmuskip:3/18,medmuskip:4/18,thickmuskip:5/18,x_height:0.430554,quad:1,num1:0.676508,num2:0.393732,num3:0.44373,denom1:0.685951,denom2:0.344841,sup1:0.412892,sup2:0.362892,sup3:0.288888,sub1:0.15,sub2:0.247217,sup_drop:0.386108,sub_drop:0.05,delim1:2.39,delim2:1,axis_height:0.25,',33,':0.06,big_op_spacing1:0.111111,big_op_spacing2:0.166666,big_op_spacing3:0.2,big_op_spacing4:0.6,big_op_spacing5:0.1,integer:6553.6,scriptspace:0.05,nulldelimiterspace:0.12,delimiterf! actor:901,delimitershortfall:0.5,scale:1,atom:["ord","op","bin","rel","open","close","punct","ord"],fam:["cmr10","',78,'","',84,'","cmex10","',72,'","","',66,'",""],famName:{cmr10:0,',78,':1,',84,':2,cmex10:3,',72,':4,',66,':6},encoding:["À","Á","Â","Ã","Ä","Å","Æ","Ç","È","É","Ê","Ë","Ì","Í","Î","Ï","°","Ñ","Ò","Ó","Ô","Õ","Ö","·","Ø","Ù","Ú","Û","Ü","µ","¶","ß","ï","!",""","#","$","%","&","'","(",")","*","+",",","-",".","/","0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?","@","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","[","\","]","^","_","`","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","{","|","}","~","ÿ"],cmr10:[[0.625',',0.683],[0.','83! 3',707,'778',707,'694',707,'667',707,'75',707,'722',707,'778',! 707,'722 ',707,'778',707,'722',707,'583',',0.694,0,{ic:0.0778,krn:{"39":0.0778,"63":0.0778,"33":0.0778,"41":0.0778,"93":0.0778},lig:{"105":','14,"108":15}}],[0.556',',0.694],[0.','556',731,'833',731,'833',731,'278',',0.431],[0.','306',',0.431,0.194],[0.','5',731,'5',731,'5,0.628],[0.5',731,'5,0.568],[0.75',731,'444,0,0.17],[0.5',731,'722',739,'778',739,'5,0.528,0.0972],[0.903,0.683],[1.01',707,'778,0.732,0.0486],[0.278',',0.431,0,{','krn:{"108":-0.278,"76":-0.319}}],[0.278',',0.694,0,{','lig:{"96":','60}}],[0.5',731,'833',',0.694,0.194],[','0.5',',0.75,0.0556],[0.','833',768,'778',731,'278',761,'krn:{"63":0.111,"33":0.111},lig:{"39":34}}],[0.389',',0.75,0.25],[0.','389',776,'5,0.75],[','0.778,0.583,0.0833],[','0.278,0.106',',0.194],[0.','333',759,'lig:{"45":','123}}],[',781,'],[0.5',776,'5,0.644','],[0.5,0.644],[0.5,0.','644',791,'644',791,'644',791,'644],[0.5,0.644],[0.278',739,'278',741,'278,0.5',782,'778',',0.367,-0.133],[','0.472,0.5',782,'472',761,762,'62}}],[0.778',731,'75',',0! .683,0,{krn:{"','116','":-0.0278,"','67',816,'79',816,'71',816,'85',816,'81',816,'84":-0.0833,"89":-0.0833,"86":-0.111,"87":-0.111}}],[0.','708',707,'722',707,'764',814,'88',816,'87',816,'65',816,'86',816,'89":-','0.0278}}],[0.','681',707,'653',',0.683,0,{','krn:{"111":-0.0833,"101":-0.0833,"117":-0.0833,"114":-0.0833,"97":-0.0833,"65":-0.111,"79":-0.0278,"67":-0.0278,"71":-0.0278,"81":-0.0278}}],[','0.785',707,'75',707,'361',814,'73":',843,'514',707,'778',814,'79',816,'67',816,'71',816,'81":-',843,'625',814,827,'917',707,'75',707,'778',814,'88',816,'87',816,'65',816,'86',816,'89":-',843,'681',814,'65','":-0.0833,"','111',816,'101',816,'97',816,'46',891,'44":-0.','0833}}],[0.','778,0.683',782,'736',814,'116',816,'67',816,'79',816,'71',816,'85',816,'81',816,827,'556',707,'722',814,'121',816,'101',891,'111',891,'114',891,'97',891,'65',891,'117":-0.',901,'75',707,'75',',0.683,0,{ic:0.','0139,',848,'1.03',940,'0139,',848,'0.75',814,'79',816,'67',816,'71',816,'81":-',843,'75',94! 0,'025,krn:{"101',891,'111',891,'114',891,'97',891,'65',891,93! 5,901,'6 11',707,'278',776,'5',731,'278',776,'5',731,'278,0.668],[0.','278',761,762,'92}}],[0.5',759,'krn:{"118',816,'106":0.0556,"121',816,'119":-',843,'556,0.','694,0',',{krn:{"101":0.0278,"111":0.0278,"120":-0.0278,"100":0.0278,"99":0.0278,"113":0.0278,"118":-0.0278,"106":0.0556,"121":-0.0278,"119":-0.0278}}],[0.','444',759,'krn:{"104',816,'107":-',843,'556',731,'444',739,'306',729,'12,"102":11,"108":13}}],[0.5',',0.431,0.194,{','ic:0.','0139,krn:{"','106":',843,'556',761,'krn:{"116',816,'117',816,'98',816,'121',816,'118',816,'119":-',843,981,'306,0.668',782,'528',761,'krn:{"97','":-0.0556,"','101',816,'97',816,'111',816,'99":-',843,'278',731,'833',759,'krn:{"116',816,'117',816,'98',816,'121',816,'118',816,'119":-',843,'556',759,'krn:{"116',816,'117',816,'98',816,'121',816,'118',816,'119":-',843,'5,0.431,0',995,993,'431,0.194',995,'528',741,'392',739,'394',739,'389,0.615,0,{krn:{"121',816,'119":-',843,'556',759,'krn:{"119":-',843,'528',',0.431,0,{ic:0.',1011,'97',1034,'101',816,'9! 7',816,'111',816,'99":-',843,'722',1093,1011,'101',816,'97',816,'111',816,'99":-',843,'528',739,'528',1009,'ic:0.',1011,'111',816,'101',816,'97',816,'46',891,'44":-0.',901,'444',739,'5',1093,'0278,',785,'124}}],[1',1093,'0278}],[0.','5',731,'5,0.668],[0.5,0.668]],',78,':[[0.615',940,'139',',krn:{"61":-0.0556,"59":-0.111,"58":-0.111,"127":0.',901,'833',814,'127":0.167}}],[0.','763',940,1136,'krn:{"127":0.0833}}],[0.','694',814,1152,'742',940,'0757,',1156,'831',940,'0812,krn:{"61',1034,'59":-0.0556,"58":-0.0556,"127":0.','0556}}],[0.','78',940,'0576,',1156,'583',940,'139',1148,1169,'667',847,1156,'612',940,'11,krn:{"61',1034,1168,1169,'772',940,'0502,',1156,'64',1093,'0037,','krn:{"127":',843,'566',',0.694,0.194,{ic:0.','0528,',1156,'518',1009,'ic:0.0556','}],[0.444',761,'ic:0.0378,krn:{"',1168,1169,'406',759,'krn:{"127":0.0556}}],[0.','438',1198,'0738,',1156,'497',1009,'ic:0.0359',',',1211,'469',761,'ic:0.',1136,1156,'354',759,1211,'576',739,'583',731,'603',1009,1195,843,'49! 4',1093,'0637,krn:{"',1168,'0278}}],[0.','438',1198,'046,',119! 5,'0.111 }}],[0.','57',1093,'0359}],[0.','517',1009,1156,'571',1093,'0359,krn:{"59',1034,'58":-0.',1169,'437',1093,'113,krn:{"',1168,1241,'54',1093,'0359,',1195,843,'596,0.694,0.194,{',1156,'626',1009,1211,'651',1198,'0359,',1195,1246,'622',1093,1249,'466',759,1156,'591',761,1156,'828',1093,1140,'517',1009,1156,'363,0.431,0.0972,{ic:0.0799,',1156,'654',1009,1195,'0.0833}}],[1',805,'1',805,'1',805,'1',805,'0.278',',0.464,-0.0363],[','0.278',1308,'0.5,0.465,-0.0347],[',1311,'0.5',739,'5',739,'5',739,'5',741,'5',741,'5,0.',1076,791,1076,791,'431',782,'278,0.106],[',781,782,'778',',0.539,0.0391],[','0.5,0.75,0.25,{krn:{"1',1034,'65',1034,'77',1034,'78',1034,'89":0.0556,"90":-0.',1169,'778',1334,1311,'0.531',761,1203,',',1156,'75',814,'127":','0.','139}}],[0.','759',940,'0502,',1156,'715',940,'0715,krn:{"61',816,1168,901,'828',940,1136,1211,'738',940,'0576,',1156,'643',940,'139',1148,901,'786',847,1156,'831',940,'0812,krn:{"61',1034,1168,1169,'44',940,'0785,',1195,1246,'555',940,'0962',11! 48,'167}}],[0.','849',940,'0715,krn:{"61',1034,1168,1169,'681',814,1355,843,'97',940,'109,krn:{"','61',1034,1168,901,'803',940,1412,'61',891,'61',816,1168,901,'763',940,1136,1156,'642',940,'139',1148,901,'791,0.683,0.194,{',1156,'759',940,'00773,',1156,'613',940,'0576,krn:{"61',1034,1168,901,'584',940,'139,krn:{"61',816,1168,901,'683',940,1412,'59":-0.111,"',1257,'111,"61',1034,1355,843,'583',940,'222',',krn:{"59":-0.167,"58":-0.167,"61":-0.111}}],[0.','944',940,'139',1465,'828',940,'0785,krn:{"61',891,'61',816,1168,901,'581',940,'222',1465,'683',940,'0715,krn:{"61',1034,1168,901,'389,0.75],[0.389',766,'0.389',766,'1,0.358,-0.142],[',1492,'0.417',761,1195,1246,'529',739,'429',731,'433',759,1211,'52',761,'krn:{"89":0.0556,"90',1034,'106":-0.111,"102":-0.167,"',1152,'466',759,1211,'49',1198,'108,krn:{"',1168,1399,'477',1009,1218,',',1195,843,'576',761,'krn:{"127":-',843,'345,0.66],[0.412,0.66,0.194,{ic:0.0572,krn:{"59',1034,1257,1169,'521',761,'ic:0.0315}],[0.298',761,'ic:0.0! 197,',1156,'878',739,'6',739,'485',759,1211,'503',1009,1156,'4! 46',1009 ,1218,',',1156,'451',1093,1136,'krn:{"',1168,1169,'469',759,1211,'361,0.615,0,{',1156,'572',759,1195,843,'485',1093,'0359,',1195,843,'716',1093,'0269,',1156,'572',759,1195,843,'49',1009,1218,',',1211,'465',1093,'044,',1211,'322',759,1195,843,'384',1009,1156,'636',1009,1195,1246,'5,0.714,0,{ic:0.154}],[0.278',761,'ic:0.399}]],',84,':[[',780,'0.278,0.444,-0.0556],[',780,1311,780,'0.5,0.444,-0.0556],[',780,780,780,780,780,780,780,'1',766,1612,1612,'0.778',1308,'0.778,0.464,-0.0363','],[0.778,0.636,0.136',1627,1627,1627,1627,1627,'],[0.778',805,'0.778,0.483,-0.0169],[0.778',1334,'0.778',1334,'1',1334,'1',1334,'0.778',1334,'0.778',1334,'1',805,'1',805,'0.5',766,'0.5',766,'1',805,'1',766,'1',766,'0.778',1308,'1',805,'1',805,'0.611',766,'0.611',766,'1',805,'1',766,'1',766,'0.778',739,'275,0.556],[1',739,'667',1334,'0.667',1334,'0.889',766,'0.889',766,'0',766,'0',805,'0.556',731,'556',731,'667',739,'5',768,'722',731,'722',731,'778',731,'778',731,'611',731,'798',814,'48":0.','194}}],! [0.657',940,'0304',',krn:{"48":0.',1357,'527',940,'0583',1717,1357,'771',940,'0278',1717,901,'528',940,'0894',1717,'111}}],[0.','719',940,'0993',1717,1733,'595',',0.683,0.0972,{ic:0.','0593',1717,1733,'845',940,'00965',1717,1733,'545',940,'0738,krn:{"48":',843,'678',1740,'185',1717,1399,'762',940,'0144',1717,1169,'69',814,1713,'139}}],[1.2',814,1713,1357,'82',940,'147',1717,901,'796',940,1726,1717,1733,'696',940,'0822',1717,901,'817,0.683,0.0972,{krn:{"48":',1246,'848',814,1713,901,'606',940,'075',1717,1357,'545',940,'254,krn:{"48":',843,'626',940,'0993',1717,901,'613',940,'0822,krn:{"48":',843,'988',940,'0822',1717,901,'713',940,'146',1717,1357,'668',1740,'0822',1717,901,'725',940,'0794',1717,1357,'667,0.556],[0.',1829,1829,1829,1829,'611',731,'611',731,'444',776,'444',776,'444',776,'444',776,'5',776,'5',776,'389',776,'389',776,'278',776,'5',776,'5',776,'611',776,'5',776,'278',766,'0.833,0.04,0.96],[0.75',707,'833',707,'417',1198,'111}],[0.',1829,'667,0.556',1627,1627,'],[! 0.444',766,'0.444',766,'0.444',766,'0.611',766,'0.778,0.694,0.! 13','],[ ',1885,'],[',1885,'],[',1885,']],cmex10:[[0.458',',0.04,1.16,{n:','16}],[0.458',1893,'17}],[0.417',1893,'104}],[0.417',1893,'105','}],[0.472,0.04,1.16,{n:','106',1901,'107',1901,'108',1901,'109}],[0.583',1893,'110}],[0.583',1893,'111',1901,'68',1901,'69}],[0.333',',0,0.6,{delim:{rep:','12}}],[0.556',1917,'13}}],[0.578',1893,'46}],[0.578',1893,'47}],[0.597',',0.04,1.76,{n:','18}],[0.597',1925,'19}],[0.736',',0.04,2.36,{n:','32}],[0.736',1929,'33}],[0.528',1929,'34}],[0.528',1929,'35}],[0.583',1929,'36}],[0.583',1929,'37}],[0.583',1929,'38}],[0.583',1929,'39}],[0.75',1929,'40}],[0.75',1929,'41}],[0.75',1929,'42}],[0.75',1929,'43}],[1.04',1929,'44}],[1.04',1929,'45}],[0.792',',0.04,2.96,{n:','48}],[0.792',1957,'49}],[0.583',1957,'50}],[0.583',1957,'51}],[0.639',1957,'52}],[0.639',1957,'53}],[0.639',1957,'54}],[0.639',1957,'55}],[0.806',1957,'56}],[0.806',1957,'57}],[0.806',',0.04,2.96],[','0.806',1977,'1.28',1977,'1.28',1977,'0.811',1925,'30}],[0.811',1925,'31}],[0.875',',0.04,! 1.76,{delim:{top:','48,bot:64,rep:66}}],[0.875',1989,'49,bot:65,rep:67}}],[0.667',1989,'50,bot:52,rep:54}}],[0.667',1989,'51,bot:53,rep:55','}}],[0.667,0.04,1.76,{delim:{bot:','52,rep:54',1997,'53,rep:55','}}],[0.667,0,0.6,{delim:{top:','50,rep:54',2001,'51,rep:55','}}],[0.889,0,0.9,{delim:{top:','56,mid:60,bot:58,rep:62',2005,'57,mid:61,bot:59,rep:62',2005,'56,bot:58,rep:62',2005,'57,bot:59,rep:62','}}],[0.889,0,1.8,{delim:{rep:','63',2013,'119}}],[0.889,0,0.3,{delim:{rep:62',2001,'120,bot:121,rep:63}}],[0.875',1989,'56,bot:59,rep:62}}],[0.875',1989,'57,bot:58,rep:62}}],[0.875',1917,'66}}],[0.875',1917,'67}}],[0.611',1925,'28}],[0.611',1925,'29','}],[0.833,0,1,{n:','71}],[1.11,0.1,1.5],[','0.472,0,1.11,{ic:0.194,n:','73}],[0.556,0,2.22,{ic:0.444}],[1.','11,0,1,{n:','75}],[1.51',',0.1,1.5],[1.',2035,'77}],[1.51',2037,2035,'79}],[1.51',2037,'06,0,1,{n:88}],[0.944,0,1,{n:89}],[',2033,'90',2031,'91',2031,'92',2031,'93',2031,'94',2031,'95}],[1.44',2037,'28,0.1,1.5],[0.556,0,2.2! 2,{ic:0.444}],[1.11',2037,'11',2037,'11',2037,'11,0.1,1.5],[1.! 11,0.1,1 .5],'], - ['[0.944,0,1,{n:97}],[1.28,0.1,1.5','],[0.556,0.722,0,{n:','99','}],[1,0.75,0,{n:','100}],[1.44,0.75',1,'102',3,'103}],[1.44,0.75],[0.472',',0.04,1.76,{n:','20}],[0.472',9,'21}],[0.528',9,'22}],[0.528',9,'23}],[0.528',9,'24}],[0.528',9,'25}],[0.667',9,'26}],[0.667',9,'27','}],[1,0.04,','1.16,{n:113}],[1',9,'114',25,'2.36,{n:115',25,'2.96,{n:116}],[1.06,0,1.8,{delim:{top:118,bot:116,rep:117}}],[1.06,0,0.6],[1.06,0.04,0.56],[0.778',',0,0.6,{delim:{','top:126,','bot:127,rep:119','}}],[0.667',33,'top:120,rep:63}}],[0.667',33,'bot:121,rep:63}}],[0','.45,0.12],[0',41,41,41,'.778',33,34,'rep:119}}],[0.778',33,35,'}}]],cmti10:[[0.627',',0.683,0,{ic:0.','133}],[0.818,0.683],[0.767',52,'094}],[0.','692,0.683],[0.664',52,'153}],[0.743',52,'164}],[0.','716',52,'12}],[0.','767',52,'111}],[0.716',52,'0599}],[0.767',52,'111}],[0.716',52,'103}],[0.','613',',0.694',',0.194,{ic:0.','212,krn:{"39":0.104,"63":0.104,"33":0.104,"41":0.104,"93":0.104},lig:{"105":','14,"108":15}}],[0.','562',74,! 75,72,'588',74,75,72,'882',74,75,72,'894',74,75,72,'307',',0.431,0,{ic:0.','0767}],[0.','332,0.431',75,'0374}],[0.511',',0.694],[0.','511',',0.694,0,{ic:0.','0969','}],[0.511,0.','628',',0,{ic:0.','083}],[0.511',102,'108',104,'562',106,72,'831',100,'46,0,0.17],[0.537',74,75,'105}],[0.','716',95,'0751','}],[0.716',95,122,104,'528,0.0972,{ic:0.0919}],[0.883',52,63,'985',52,63,'767,0.732,0.0486,{ic:0.',55,'256,0.431,0,{krn:{"108":-0.256,"76":-0.321}}],[0.307',102,'124,lig:{"96":','60}}],[0.','514',102,'0696}],[0.818',74,75,'0662}],[0.769',100,'818',',0.75,0.0556',',{ic:0.136}],[0.','767',102,'0969}],[0.307',102,'124',',krn:{"','63":0.102,"33":0.102','},lig:{"39":34}}],[0.','409',',0.75,0.25,{ic:0.','162}],[0.409',158,'0369',104,'75',106,'149}],[0.767,0.562,0.0567,{ic:0.0369','}],[0.307,0.','106',',0.194],[0.','358',95,'0283,','lig:{"45":123}}],[0.','307,0.106],[0.511',158,'162',104,'644,0',',{ic:0.136}],[0.511,0.644,0',178,178,178,'.194',178,178,178,182,178,178,148,'307',95,'0! 582',166,'431',75,'0582',166,'5',75,'0756}],[0.767,0.367,-0.13! 3,{ic:0. 0662',104,'5',168,'511',102,'122,lig:{"96":62}}],[0.767',102,'096}],[0.743,0.683,0,{','krn:{"110":-0.0256,"108":-0.0256,"114":-0.0256,"117":-0.0256,"109":-0.0256,"116":-0.0256,"105":-0.0256,"67":-0.0256,"79":-0.0256,"71":-0.0256,"104":-0.0256,"98":-0.0256,"85":-0.0256,"107":-0.0256,"118":-0.0256,"119":-0.0256,"81":-','0.0256,"84','":-0.0767,"','89',211,'86','":-0.102,"','87',215,'101":-0.0511,"97":-0.0511,"111":-0.0511,"100":-0.0511,"99":-0.0511,"103":-0.0511,"113":-0.0511}}],[0.','704',52,72,'716',52,'145}],[0.','755',52,'094',154,'88','":-0.0256,"','87',230,'65',230,'86',230,'89','":-0.0256}}],[0.','678',52,63,'653',52,'133',154,'111',211,'101',211,'117','":-0.0767,"114":-0.0767,"97":-0.0767,"','65',215,'79":-0.0256,"67":-0.0256,"71":-0.0256,"81":-0.0256}}],[0.','774',52,'0872}],[0.743',52,60,'386',52,'158}],[0.525',52,'14}],[0.769',52,'145',154,254,'627,0.683,0,{krn:{"84',211,'89',211,'86',215,'87',215,218,'897',52,60,'743',52,60,'767',52,'094',154,'88',230,'87',230,'65',! 230,'86',230,'89',238,'678',52,'103',154,'65":-0.0767}}],[0.','767,0.683',75,55,'729',52,'0387,',209,'0.0256,"84',211,'89',211,'86',215,'87',215,218,'562',52,63,'716',52,'133',154,'121',211,'101',211,'111',251,'117',211,302,'743',52,60,'743',52,'184',154,'111',211,'101',211,'117',251,'65',215,254,'999',52,'184',154,302,'743',52,'158',154,254,'743',52,'194',154,'101',211,'111',251,'117',211,302,'613',52,224,'307',158,'188}],[0.514',102,'169}],[0.307',158,119,'511',102,'0665',166,'668',106,'118}],[0.307',102,137,'92}}],[0.','511',95,96,'46',102,'0631',154,218,'46',95,'0565',154,218,'511',102,'103',',krn:{"108":0.0511}}],[0.','46',95,122,154,218,'307',74,75,76,'12,"102":11,"108":13}}],[0.','46,0.431',75,'0885}],[0.','511',102,96,'307,0.655',106,'102',166,'655',75,224,'46',102,'108}],[0.','256',102,'103',408,'818',95,96,'562',95,'0767',154,'39":-0.102}}],[0.511',95,'0631',154,218,'511,0.431',75,'0631',154,218,'46,0.431',75,421,'422',95,'108',154,218,'409',95,'0821}],[0.332,0.61! 5',106,'0949}],[0.537',95,96,'46',95,434,'664',95,'108',408,'4! 64',95,6 3,'486,0.431',75,421,'409',95,'123}],[0.511',95,'0921',',lig:{"45":124}}],[1.','02',95,'0921}],[0.511',102,'122',104,'668',106,'116',104,'668',106,'105}]],cmbx10:[[0.692',',0.686],[0.','958',503,'894',503,'806',503,'767',503,'9',503,'831',503,'894',503,'831',503,'894',503,'831',503,'671',102,'109,krn:{"39":0.109,"63":0.109,"33":0.109,"41":0.109,"93":0.109},lig:{"105":',77,'639',100,'639',100,'958',100,'958',100,'319',',0.444],[0.','351,0.444',168,'575',100,'575',100,'575,0.','632],[0.575',100,544,'596],[0.869',100,'511,0,0.17],[0.597',100,'831',537,'894',537,544,'542,0.0972],[1.04,0.686],[1.17',503,'894,0.735,0.0486],[0.319',',0.444,0,{krn:{"','108":-0.319,"76":-0.378}}],[0.35',',0.694,0,{lig:{"96":',138,'603',100,'958',74,168,'575',147,'],[0.958',147,'],[0.894',100,'319',',0.694,0,{krn:{"','63":0.128,"33":0.128',156,'447',',0.75,0.25],[0.','447',580,544,'75],[0.894,0.633,0.133],[0.','319,0.156',168,'383,0.444,0,{',172,585,'],[0.575',580,544,'644],[','0.575,0.644],[0.575,0.6! 44],[',594,594,594,'0.',544,'644],[0.319',537,'319,0.444',168,'35,0.5',168,'894,0.391,-0.109],[0.543,0.5',168,'543',562,'62}}],[0.894',100,'869',',0.686,0,{krn:{"','116','":-0.0319,"','67',615,'79',615,'71',615,'85',615,'81',615,'84":-0.0958,"89":-0.0958,"86":-0.128,"87":-0.128}}],[','0.818',503,'831',503,'882',613,'88',615,'87',615,'65',615,'86',615,'89','":-0.0319}}],[0.','756',503,'724,0.686,0,{','krn:{"111":-0.0958,"101":-0.0958,"117":-0.0958,"114":-0.0958,"97":-0.0958,"65":-0.128,"79":-0.0319,"67":-0.0319,"71":-0.0319,"81":-0.0319}}],[','0.904',503,'9',503,'436',613,'73','":0.0319}}],[0.','594',503,'901',613,'79',615,'67',615,'71',615,'81',642,'692',613,626,'1.09',503,'9',503,'864',613,'88',615,'87',615,'65',615,'86',615,'89',642,'786',613,'65":-0.0958,"111',615,'101',615,'97',615,'46":-0.0958,"44":-0.0958}}],[0.','864,0.686',168,'862',613,'116',615,'67',615,'79',615,'71',615,'85',615,'81',615,626,'0.639',503,'8',613,'121',615,'101":-0.0958,"111":-0.0958,"114":-0.0958,! "97":-0.0958,"65":-0.0958,"117":-0.0958}}],[0.','885',503,'869! ,0.686', 106,'016,',646,'1.19,0.686',106,'016,',646,'0.869',613,'79',615,'67',615,'71',615,'81',642,'869,0.686',106,'0287',154,718,'703',503,'319',580,'603',100,'319',580,'575',100,'319',100,'319',562,391,'559',560,'11... [truncated message content] |
From: dpvc v. a. <we...@ma...> - 2008-12-30 14:14:16
|
Log Message: ----------- Combined TeX and string into a common routine since the two were nearly identical. Modified Files: -------------- pg/macros: contextInequalities.pl Revision Data ------------- Index: contextInequalities.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/contextInequalities.pl,v retrieving revision 1.19 retrieving revision 1.20 diff -Lmacros/contextInequalities.pl -Lmacros/contextInequalities.pl -u -r1.19 -r1.20 --- macros/contextInequalities.pl +++ macros/contextInequalities.pl @@ -619,86 +619,60 @@ sub string { my $self = shift; my $equation = shift; shift; shift; my $prec = shift; - my $context = ($equation->{context} || $self->context); - my $X = $self->{varName} || ($context->variables->names)[0]; - $X = $context->{variables}{$X}{string} if defined $context->{variables}{$X}{string}; - my $op = $context->{operators}{'or'}; - my $showNE = $self->getFlag("showNotEquals",1); - my @intervals = (); my @points = (); my $interval; - foreach my $x (@{$self->data}) { - $x->{format} = $self->{format} if defined $self->{format}; - if ($x->type eq 'Interval' && $showNE) { - if (defined($interval)) { - if ($interval->{data}[1] == $x->{data}[0]) { - push(@points,$X . ' != ' . $x->{data}[0]->string); - $interval = $interval->with(isCopy=>1, data=>[$interval->value]) unless $interval->{isCopy}; - $interval->{data}[1] = $x->{data}[1]; - $interval->{rightInfinite} = 1 if $x->{rightInfinite}; - next; - } - push(@intervals,$self->stringAnd($interval,$equation,@points)); - } - $interval = $x; @points = (); next; - } - if (defined($interval)) { - push(@intervals,$self->stringAnd($interval,$equation,@points)); - $interval = undef; @points = (); - } - push(@intervals,$x->string($equation)); - } - push(@intervals,$self->stringAnd($interval,$equation,@points)) if defined($interval); - my $string = join($op->{string} || ' or ',@intervals); - $string = '('.$string.')' if defined($prec) && $prec > ($op->{precedence} || 1.5); - return $string; -} - -sub stringAnd { - my $self = shift; my $interval = shift; my $equation = shift; - unshift(@_,$interval->string($equation)) unless $interval->{leftInfinite} && $interval->{rightInfinite}; - return join(" and ", @_); + return $self->display("string",$equation,$prec); } sub TeX { my $self = shift; my $equation = shift; shift; shift; my $prec = shift; - my $context = $equation->{context} || $self->context; + return $self->display("TeX",$equation,$prec); +} + +sub display { + my $self = shift; my $method = shift; my $equation = shift; my $prec = shift; + my $context = ($equation->{context} || $self->context); my $X = $self->{varName} || ($context->variables->names)[0]; - $X = $context->{variables}{$X}{TeX} if defined $context->{variables}{$X}{TeX}; - $X =~ s/^([^_]+)_?(\d+)$/$1_{$2}/; - my $op = ($equation->{context} || $self->context)->{operators}{'or'}; + $X = $context->{variables}{$X}{$method} if defined $context->{variables}{$X}{$method}; + $X =~ s/^([^_]+)_?(\d+)$/$1_{$2}/ if $method eq 'TeX'; + my $op = $context->{operators}{'or'}; + my ($and,$or,$le,$ge,$ne,$open,$close) = @{{ + string => [' and ',$op->{string} || ' or ',' <= ',' >= ',' != ','(',')'], + TeX => ['\hbox{ and }',$op->{TeX} || $op->{string} || '\hbox{ or }', + ' \le ',' \ge ',' \ne ','\left(','\right)'], + }->{$method}}; my $showNE = $self->getFlag("showNotEquals",1); - my @intervals = (); my $interval; my @points = (); + my @intervals = (); my @points = (); my $interval; foreach my $x (@{$self->data}) { $x->{format} = $self->{format} if defined $self->{format}; if ($x->type eq 'Interval' && $showNE) { if (defined($interval)) { if ($interval->{data}[1] == $x->{data}[0]) { - push(@points,$X . ' \ne ' . $x->{data}[0]->TeX); + push(@points,$X.$ne.$x->{data}[0]->$method($equation)); $interval = $interval->with(isCopy=>1, data=>[$interval->value]) unless $interval->{isCopy}; $interval->{data}[1] = $x->{data}[1]; $interval->{rightInfinite} = 1 if $x->{rightInfinite}; next; } - push(@intervals,$self->TeXAnd($interval,$equation,@points)); + push(@intervals,$self->joinAnd($interval,$method,$and,$equation,@points)); } $interval = $x; @points = (); next; } if (defined($interval)) { - push(@intervals,$self->TeXAnd($interval,$equation,@points)); + push(@intervals,$self->joinAnd($interval,$method,$and,$equation,@points)); $interval = undef; @points = (); } - push(@intervals,$x->TeX($equation)); + push(@intervals,$x->$method($equation)); } - push(@intervals,$self->TeXAnd($interval,$equation,@points)) if defined($interval); - my $TeX = join($op->{TeX} || $op->{string} || '\hbox{ or }',@intervals); - $TeX = '\left('.$TeX.'\right)' if defined($prec) && $prec > ($op->{precedence} || 1.5); - return $TeX; + push(@intervals,$self->joinAnd($interval,$method,$and,$equation,@points)) if defined($interval); + my $string = join($or,@intervals); + $string = $open.$string.$close if defined($prec) && $prec > ($op->{precedence} || 1.5); + return $string; } -sub TeXAnd { - my $self = shift; my $interval = shift; my $equation = shift; - unshift(@_,$interval->TeX($equation)) unless $interval->{leftInfinite} && $interval->{rightInfinite}; - return join('\hbox{ and }', @_); +sub joinAnd { + my $self = shift; $interval = shift; $method = shift, my $and = shift; my $equation = shift; + unshift(@_,$interval->$method($equation)) unless $interval->{leftInfinite} && $interval->{rightInfinite}; + return join($and, @_); } ################################################## |
From: dpvc v. a. <we...@ma...> - 2008-12-30 08:27:09
|
Log Message: ----------- Inequalities that are evaluated and turned into intervals now properly retain the order of operands (x > 10 remains x > 10 rather than becoming 10 < x). Unions of the form "x < a or x > a" will be displayed as "x != a" instead, and "a < x < b or b < x < c" will be shown as "a < x < c and x != b" instead. This behavior is controlled by the showNotEquals context flag. Setting it to zero prevents conversion of unions to their not-equal forms. Modified Files: -------------- pg/macros: contextInequalities.pl Revision Data ------------- Index: contextInequalities.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/contextInequalities.pl,v retrieving revision 1.18 retrieving revision 1.19 diff -Lmacros/contextInequalities.pl -Lmacros/contextInequalities.pl -u -r1.18 -r1.19 --- macros/contextInequalities.pl +++ macros/contextInequalities.pl @@ -114,11 +114,11 @@ '+' => {class => "Inequalities::BOP::add"}, '-' => {class => "Inequalities::BOP::subtract"}, ); - $context->parens->set("(" => {type => "List", formIntervla => ']'}); # trap these later - $context->parens->set("[" => {type => "List", formIntervla => ')'}); # trap these later + $context->parens->set("(" => {type => "List", formInterval => ']'}); # trap these later + $context->parens->set("[" => {type => "List", formInterval => ')'}); # trap these later $context->strings->remove("NONE"); $context->constants->add(NONE=>Value::Set->new()); - $context->flags->set(noneWord => 'NONE'); + $context->flags->set(noneWord => 'NONE', showNotEquals => 1); $context->{parser}{Variable} = "Inequalities::Variable"; $context->{value}{'Interval()'} = "Inequalities::MakeInterval"; $context->{value}{Inequality} = "Inequalities::Inequality"; @@ -218,8 +218,8 @@ sub evalGreaterThan { my ($self,$a,$b) = @_; my $context = $self->context; my $I = Value::Infinity->new; - return $self->Package("Interval")->new($context,'(',$b,$I,')') if $self->{varPos} eq 'lop'; - return $self->Package("Interval")->new($context,'(',-$I,$a,')'); + return $self->Package("Interval")->new($context,'(',$b,$I,')')->with(reversed=>1) if $self->{varPos} eq 'lop'; + return $self->Package("Interval")->new($context,'(',-$I,$a,')')->with(reversed=>1); } sub evalLessThanOrEqualTo { @@ -232,8 +232,8 @@ sub evalGreaterThanOrEqualTo { my ($self,$a,$b) = @_; my $context = $self->context; my $I = Value::Infinity->new; - return $self->Package("Interval")->new($context,'[',$b,$I,')') if $self->{varPos} eq 'lop'; - return $self->Package("Interval")->new($context,'(',-$I,$a,']'); + return $self->Package("Interval")->new($context,'[',$b,$I,')')->with(reversed=>1) if $self->{varPos} eq 'lop'; + return $self->Package("Interval")->new($context,'(',-$I,$a,']')->with(reversed=>1); } sub evalEqualTo { @@ -249,7 +249,7 @@ return $self->Package("Union")->new($context, $self->Package("Interval")->new($context,'(',-$I,$x,')'), $self->Package("Interval")->new($context,'(',$x,$I,')') - ); + )->with(notEqual=>1); } # @@ -534,19 +534,28 @@ sub type {"Interval"} +sub updateParts { + my $self = shift; + $self->{leftInfinite} = 1 if $self->{data}[0]->{isInfinite}; + $self->{rightInfinite} = 1 if $self->{data}[1]->{isInfinite}; +} + sub string { my $self = shift; my ($a,$b,$open,$close) = $self->value; my $x = $self->{varName} || ($self->context->variables->names)[0]; $x = $context->{variables}{$x}{string} if defined $context->{variables}{$x}{string}; - my $left = ($open eq '(' ? ' < ' : ' <= '); - my $right = ($close eq ')' ? ' < ' : ' <= '); - my $inequality = ""; - $inequality .= $a->string.$left unless $self->{leftInfinite}; - $inequality .= $x; - $inequality .= $right.$b->string unless $self->{rightInfinite}; - $inequality = "-infinity < $x < infinity" if $inequality eq $x; - return $inequality; + if ($self->{leftInfinite}) { + return "-infinity < $x < infinity" if $self->{rightInfinite}; + return $b->string . ($close eq ')' ? ' > ' : ' >= ') . $x if $self->{reversed}; + return $x . ($close eq ')' ? ' < ' : ' <= ') . $b->string; + } elsif ($self->{rightInfinite}) { + return $x . ($open eq '(' ? ' > ' : ' >= ') . $a->string if $self->{reversed}; + return $a->string . ($open eq '(' ? ' < ' : ' <= ') . $x; + } else { + return $a->string . ($open eq '(' ? ' < ' : ' <= ') . + $x . ($close eq ')' ? ' < ' : ' <= ') . $b->string; + } } sub TeX { @@ -556,14 +565,17 @@ my $x = $self->{varName} || ($context->variables->names)[0]; $x = $context->{variables}{$x}{TeX} if defined $context->{variables}{$x}{TeX}; $x =~ s/^([^_]+)_?(\d+)$/$1_{$2}/; - my $left = ($open eq '(' ? ' < ' : ' \le '); - my $right = ($close eq ')' ? ' < ' : ' \le '); - my $inequality = ""; - $inequality .= $a->string.$left unless $self->{leftInfinite}; - $inequality .= $x; - $inequality .= $right.$b->string unless $self->{rightInfinite}; - $inequality = "-\\infty < $x < \\infty " if $inequality eq $x; - return $inequality; + if ($self->{leftInfinite}) { + return "-\\infty < $x < \\infty" if $self->{rightInfinite}; + return $b->TeX . ($close eq ')' ? ' > ' : ' \ge ') . $x if $self->{reversed}; + return $x . ($close eq ')' ? ' < ' : ' \le ') . $b->TeX; + } elsif ($self->{rightInfinite}) { + return $x . ($open eq '(' ? ' > ' : ' \ge ') . $a->TeX if $self->{reversed}; + return $a->TeX . ($open eq '(' ? ' < ' : ' \le ') . $x; + } else { + return $a->TeX . ($open eq '(' ? ' < ' : ' \le ') . + $x . ($close eq ')' ? ' < ' : ' \le ') . $b->TeX; + } } ################################################## @@ -607,28 +619,88 @@ sub string { my $self = shift; my $equation = shift; shift; shift; my $prec = shift; - my $op = ($equation->{context} || $self->context)->{operators}{'or'}; - my @intervals = (); + my $context = ($equation->{context} || $self->context); + my $X = $self->{varName} || ($context->variables->names)[0]; + $X = $context->{variables}{$X}{string} if defined $context->{variables}{$X}{string}; + my $op = $context->{operators}{'or'}; + my $showNE = $self->getFlag("showNotEquals",1); + my @intervals = (); my @points = (); my $interval; foreach my $x (@{$self->data}) { $x->{format} = $self->{format} if defined $self->{format}; - push(@intervals,$x->string($equation)) + if ($x->type eq 'Interval' && $showNE) { + if (defined($interval)) { + if ($interval->{data}[1] == $x->{data}[0]) { + push(@points,$X . ' != ' . $x->{data}[0]->string); + $interval = $interval->with(isCopy=>1, data=>[$interval->value]) unless $interval->{isCopy}; + $interval->{data}[1] = $x->{data}[1]; + $interval->{rightInfinite} = 1 if $x->{rightInfinite}; + next; + } + push(@intervals,$self->stringAnd($interval,$equation,@points)); + } + $interval = $x; @points = (); next; + } + if (defined($interval)) { + push(@intervals,$self->stringAnd($interval,$equation,@points)); + $interval = undef; @points = (); + } + push(@intervals,$x->string($equation)); } + push(@intervals,$self->stringAnd($interval,$equation,@points)) if defined($interval); my $string = join($op->{string} || ' or ',@intervals); $string = '('.$string.')' if defined($prec) && $prec > ($op->{precedence} || 1.5); return $string; } +sub stringAnd { + my $self = shift; my $interval = shift; my $equation = shift; + unshift(@_,$interval->string($equation)) unless $interval->{leftInfinite} && $interval->{rightInfinite}; + return join(" and ", @_); +} + sub TeX { my $self = shift; my $equation = shift; shift; shift; my $prec = shift; + my $context = $equation->{context} || $self->context; + my $X = $self->{varName} || ($context->variables->names)[0]; + $X = $context->{variables}{$X}{TeX} if defined $context->{variables}{$X}{TeX}; + $X =~ s/^([^_]+)_?(\d+)$/$1_{$2}/; my $op = ($equation->{context} || $self->context)->{operators}{'or'}; - my @intervals = (); - foreach my $x (@{$self->data}) {push(@intervals,$x->TeX($equation))} + my $showNE = $self->getFlag("showNotEquals",1); + my @intervals = (); my $interval; my @points = (); + foreach my $x (@{$self->data}) { + $x->{format} = $self->{format} if defined $self->{format}; + if ($x->type eq 'Interval' && $showNE) { + if (defined($interval)) { + if ($interval->{data}[1] == $x->{data}[0]) { + push(@points,$X . ' \ne ' . $x->{data}[0]->TeX); + $interval = $interval->with(isCopy=>1, data=>[$interval->value]) unless $interval->{isCopy}; + $interval->{data}[1] = $x->{data}[1]; + $interval->{rightInfinite} = 1 if $x->{rightInfinite}; + next; + } + push(@intervals,$self->TeXAnd($interval,$equation,@points)); + } + $interval = $x; @points = (); next; + } + if (defined($interval)) { + push(@intervals,$self->TeXAnd($interval,$equation,@points)); + $interval = undef; @points = (); + } + push(@intervals,$x->TeX($equation)); + } + push(@intervals,$self->TeXAnd($interval,$equation,@points)) if defined($interval); my $TeX = join($op->{TeX} || $op->{string} || '\hbox{ or }',@intervals); $TeX = '\left('.$TeX.'\right)' if defined($prec) && $prec > ($op->{precedence} || 1.5); return $TeX; } +sub TeXAnd { + my $self = shift; my $interval = shift; my $equation = shift; + unshift(@_,$interval->TeX($equation)) unless $interval->{leftInfinite} && $interval->{rightInfinite}; + return join('\hbox{ and }', @_); +} + ################################################## package Inequalities::Set; |
From: dpvc v. a. <we...@ma...> - 2008-12-30 08:22:30
|
Log Message: ----------- Added a final_period=>1 flag for PiecewiseFunction objects so that the final condition will include a period (so that you can put a piecewise function as the last thing in a sentence). Modified Files: -------------- pg/macros: contextPiecewiseFunction.pl Revision Data ------------- Index: contextPiecewiseFunction.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/contextPiecewiseFunction.pl,v retrieving revision 1.9 retrieving revision 1.10 diff -Lmacros/contextPiecewiseFunction.pl -Lmacros/contextPiecewiseFunction.pl -u -r1.9 -r1.10 --- macros/contextPiecewiseFunction.pl +++ macros/contextPiecewiseFunction.pl @@ -64,12 +64,25 @@ Context()->texStrings; BEGIN_TEXT - Suppose \(f(x)=$f\). Then \(f($a)\) = \{ans_rule(20)\}. + If \[f(x)=$f\] then \(f($a)\) = \{ans_rule(20)\}. END_TEXT Context()->normalStrings; ANS($f->eval(x=>$a)->cmp); +Normally when you use a piecewise function at the end of a sentence, +the period is placed at the end of the last case. Since + + \[ f(x) = $f \]. + +would put the period centered at the right-hand side of the function, +this is not what is desired. To get a period at the end of the last +case, use + + \[ f(x) = \{$f->with(final_period=>1)\} \] + +instead. + =cut loadMacros("MathObjects.pl"); @@ -741,12 +754,13 @@ # sub string { my $self = shift; my @cases = (); + my $period = ($self->{final_period} ? "." : ""); foreach my $If (@{$self->{data}}) { my ($I,$f) = @{$If}; push(@cases,$f->string." if ".$I->string); } push(@cases,$self->{otherwise}->string) if defined $self->{otherwise}; - join(" else\n",@cases); + join(" else\n",@cases) . $period; } # @@ -754,13 +768,14 @@ # sub TeX { my $self = shift; my @cases = (); + my $period = ($self->{final_period} ? "." : ""); foreach my $If (@{$self->{data}}) { my ($I,$f) = @{$If}; push(@cases,'\displaystyle{'.$f->TeX."}&\\text{if}\\ ".$I->TeX); } if (scalar(@cases)) { push(@cases,'\displaystyle{'.$self->{otherwise}->TeX.'}&\text{otherwise}') if defined $self->{otherwise}; - return '\begin{cases}'.join('\cr'."\n",@cases).'\end{cases}'; + return '\begin{cases}'.join('\cr'."\n",@cases).$period.'\end{cases}'; } else { return $self->{otherwise}->TeX; } |
From: dpvc v. a. <we...@ma...> - 2008-12-30 00:50:25
|
Log Message: ----------- Fixed the name stored in the StrictFraction context (removed the trailling s). Modified Files: -------------- pg/lib/Parser/Legacy: LimitedNumeric.pm Revision Data ------------- Index: LimitedNumeric.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Parser/Legacy/LimitedNumeric.pm,v retrieving revision 1.4 retrieving revision 1.5 diff -Llib/Parser/Legacy/LimitedNumeric.pm -Llib/Parser/Legacy/LimitedNumeric.pm -u -r1.4 -r1.5 --- lib/Parser/Legacy/LimitedNumeric.pm +++ lib/Parser/Legacy/LimitedNumeric.pm @@ -120,7 +120,7 @@ $context = $context->copy; $Parser::Context::Default::context{'LimitedNumeric-StrictFraction'} = $context; Parser::Number::NoDecimals($context); -$context->{name} = "LimitedNumeric-StrictFractions"; +$context->{name} = "LimitedNumeric-StrictFraction"; ###################################################################### |
From: dpvc v. a. <we...@ma...> - 2008-12-29 02:23:13
|
Log Message: ----------- The \s regular expression was matching newlines, and so newlines around BEGIN_TEXT/END_TEXT (and other such constructs) were being removed. This is OK when the problem runs correctly, but when an error message is produced, the line number of the error report will not correspond to the proper line number in the code listing. Solution is to use [ \t] instead. Modified Files: -------------- pg/lib/WeBWorK/PG: Translator.pm Revision Data ------------- Index: Translator.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/WeBWorK/PG/Translator.pm,v retrieving revision 1.22 retrieving revision 1.23 diff -Llib/WeBWorK/PG/Translator.pm -Llib/WeBWorK/PG/Translator.pm -u -r1.22 -r1.23 --- lib/WeBWorK/PG/Translator.pm +++ lib/WeBWorK/PG/Translator.pm @@ -908,7 +908,6 @@ =cut - my ($PG_PROBLEM_TEXT_REF, $PG_HEADER_TEXT_REF, $PG_ANSWER_HASH_REF, $PG_FLAGS_REF) =$safe_cmpt->reval(" $evalString"); @@ -1621,26 +1620,26 @@ } -sub original_preprocess_code { - my $evalString = shift; - # BEGIN_TEXT and END_TEXT must occur on a line by themselves. - $evalString =~ s/\n\s*END_TEXT[\s;]*\n/\nEND_TEXT\n/g; - $evalString =~ s/\n\s*BEGIN_TEXT[\s;]*\n/\nTEXT\(EV3\(<<'END_TEXT'\)\);\n/g; - $evalString =~ s/ENDDOCUMENT.*/ENDDOCUMENT();/s; # remove text after ENDDOCUMENT - - $evalString =~ s/\\/\\\\/g; # \ can't be used for escapes because of TeX conflict - $evalString =~ s/~~/\\/g; # use ~~ as escape instead, use # for comments - $evalString; -} +#sub original_preprocess_code { +# my $evalString = shift; +# # BEGIN_TEXT and END_TEXT must occur on a line by themselves. +# $evalString =~ s/\n\s*END_TEXT[\s;]*\n/\nEND_TEXT\n/g; +# $evalString =~ s/\n\s*BEGIN_TEXT[\s;]*\n/\nTEXT\(EV3\(<<'END_TEXT'\)\);\n/g; +# $evalString =~ s/ENDDOCUMENT.*/ENDDOCUMENT();/s; # remove text after ENDDOCUMENT + +# $evalString =~ s/\\/\\\\/g; # \ can't be used for escapes because of TeX conflict +# $evalString =~ s/~~/\\/g; # use ~~ as escape instead, use # for comments +# $evalString; +#} sub default_preprocess_code { my $evalString = shift; # BEGIN_TEXT and END_TEXT must occur on a line by themselves. - $evalString =~ s/\n\s*END_TEXT[\s;]*\n/\nEND_TEXT\n/g; - $evalString =~ s/\n\s*END_SOLUTION[\s;]*\n/\nEND_SOLUTION\n/g; - $evalString =~ s/\n\s*END_HINT[\s;]*\n/\nEND_HINT\n/g; - $evalString =~ s/\n\s*BEGIN_TEXT[\s;]*\n/\nTEXT\(EV3P\(<<'END_TEXT'\)\);\n/g; - $evalString =~ s/\n\s*BEGIN_SOLUTION[\s;]*\n/\nSOLUTION\(EV3P\(<<'END_SOLUTION'\)\);\n/g; - $evalString =~ s/\n\s*BEGIN_HINT[\s;]*\n/\nHINT\(EV3P\(<<'END_HINT'\)\);\n/g; + $evalString =~ s/^[ \t]*END_TEXT[ \t;]*$/END_TEXT/gm; + $evalString =~ s/^[ \t]*END_SOLUTION[ \t;]*$/END_SOLUTION/mg; + $evalString =~ s/^[ \t]*END_HINT[ \t;]*$/END_HINT/mg; + $evalString =~ s/^[ \t]*BEGIN_TEXT[ \t;]*$/TEXT\(EV3P\(<<'END_TEXT'\)\);/mg; + $evalString =~ s/^[ \t]*BEGIN_SOLUTION[ \t;]*$/SOLUTION\(EV3P\(<<'END_SOLUTION'\)\);/mg; + $evalString =~ s/^[ \t]*BEGIN_HINT[ \t;]*$/HINT\(EV3P\(<<'END_HINT'\)\);/mg; $evalString =~ s/ENDDOCUMENT.*/ENDDOCUMENT();/s; # remove text after ENDDOCUMENT $evalString =~ s/\\/\\\\/g; # \ can't be used for escapes because of TeX conflict |