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; |