From d7645f4fbb79876a5dbdd0275762024724769264 Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Wed, 20 Nov 2002 11:10:02 +0000 Subject: [PATCH] * lib/Automake/ConditionalSet.pm (conds): Use value() to simplify. (invert): Rewrite as a product-of-sums to sum-of-products converter. (_multiply, multiply): New functions. * lib/Automake/Conditional.pm (not): New function. * lib/Automake/tests/ConditionalSet.pl (test_invert): Update. * automake.in (condition_negate): Move ... * lib/Automake/Conditional.pm (negate_condition): ... here. Suggested by Raja R Harinath. --- ChangeLog | 11 +++++ automake.in | 24 ++-------- lib/Automake/Conditional.pm | 42 ++++++++++++++++ lib/Automake/ConditionalSet.pm | 72 +++++++++++++++++++++++----- lib/Automake/tests/ConditionalSet.pl | 17 ++++--- 5 files changed, 127 insertions(+), 39 deletions(-) diff --git a/ChangeLog b/ChangeLog index b8ef1d5d..43cc305a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2002-11-20 Alexandre Duret-Lutz + + * lib/Automake/ConditionalSet.pm (conds): Use value() to simplify. + (invert): Rewrite as a product-of-sums to sum-of-products converter. + (_multiply, multiply): New functions. + * lib/Automake/Conditional.pm (not): New function. + * lib/Automake/tests/ConditionalSet.pl (test_invert): Update. + * automake.in (condition_negate): Move ... + * lib/Automake/Conditional.pm (negate_condition): ... here. + Suggested by Raja R Harinath. + 2002-11-19 Alexandre Duret-Lutz * lib/Automake/ConditionalSet.pm (_simplify, simplify): New methods. diff --git a/automake.in b/automake.in index c026a45a..164255ea 100755 --- a/automake.in +++ b/automake.in @@ -5925,21 +5925,6 @@ sub pretty_print_rule ################################################################ -# $NEGATION -# condition_negate ($COND) -# ------------------------ -sub condition_negate ($) -{ - my ($cond) = @_; - - $cond =~ s/TRUE$/TRUEO/; - $cond =~ s/FALSE$/TRUE/; - $cond =~ s/TRUEO$/FALSE/; - - return $cond; -} - - ## ------------------------------ ## ## Handling the condition stack. ## ## ------------------------------ ## @@ -5957,7 +5942,7 @@ sub cond_stack_if ($$$) $cond = "${cond}_TRUE" unless $cond =~ /^TRUE|FALSE$/; - $cond = condition_negate ($cond) + $cond = Automake::Conditional::condition_negate ($cond) if $negate; push (@cond_stack, $cond); @@ -5979,14 +5964,15 @@ sub cond_stack_else ($$$) return; } - $cond_stack[$#cond_stack] = condition_negate ($cond_stack[$#cond_stack]); + $cond_stack[$#cond_stack] = + Automake::Conditional::condition_negate ($cond_stack[$#cond_stack]); # If $COND is given, check against it. if (defined $cond) { $cond = "${cond}_TRUE" unless $cond =~ /^TRUE|FALSE$/; - $cond = condition_negate ($cond) + $cond = Automake::Conditional::condition_negate ($cond) if $negate; err ($where, "else reminder ($negate$cond) incompatible with " @@ -6018,7 +6004,7 @@ sub cond_stack_endif ($$$) { $cond = "${cond}_TRUE" unless $cond =~ /^TRUE|FALSE$/; - $cond = condition_negate ($cond) + $cond = Automake::Conditional::condition_negate ($cond) if $negate; err ($where, "endif reminder ($negate$cond) incompatible with " diff --git a/lib/Automake/Conditional.pm b/lib/Automake/Conditional.pm index cbef6b45..2ce74a6e 100644 --- a/lib/Automake/Conditional.pm +++ b/lib/Automake/Conditional.pm @@ -77,6 +77,9 @@ Automake::Conditional - record a conjunction of conditions # $other and $cond are implied by $both.) @conds = Automake::Conditional::reduce ($other, $both, $cond); + # Invert a Conditional. This returns a ConditionalSet. + $set = $both->not; + =head1 DESCRIPTION A C is a conjunction of atomic conditions. In Automake they @@ -394,6 +397,28 @@ sub implies_any ($@) return 0; } +=item C<$cond-Enot> + +Return a negation of @<$cond> as a list of Cs. +This list should be used to construct a C +(we cannot return a C from C, +because that would make these two packages interdependent). + +=cut + +sub not ($ ) +{ + my ($self) = @_; + return @{$self->{'not'}} if defined $self->{'not'}; + my @res; + for my $cond ($self->conds) + { + push @res, new Automake::Conditional &condition_negate ($cond); + } + $self->{'not'} = [@res]; + return @res; +} + =head2 Other helper functions =over 4 @@ -443,6 +468,23 @@ sub reduce (@) return @ret; } +=item C + +Negate a condition string. + +=cut + +sub condition_negate ($) +{ + my ($cond) = @_; + + $cond =~ s/TRUE$/TRUEO/; + $cond =~ s/FALSE$/TRUE/; + $cond =~ s/TRUEO$/FALSE/; + + return $cond; +} + =head1 SEE ALSO L. diff --git a/lib/Automake/ConditionalSet.pm b/lib/Automake/ConditionalSet.pm index 58b203aa..9ed9b9ba 100644 --- a/lib/Automake/ConditionalSet.pm +++ b/lib/Automake/ConditionalSet.pm @@ -153,7 +153,7 @@ sub conds ($ ) { my ($self) = @_; return @{$self->{'conds'}} if exists $self->{'conds'}; - my @conds = map { $self->{'hash'}{$_} } (keys %{$self->{'hash'}}); + my @conds = values %{$self->{'hash'}}; @conds = sort { $a->string cmp $b->string } @conds; $self->{'conds'} = [@conds]; return @conds; @@ -309,10 +309,53 @@ sub permutations ($ ) return $res; } -=item C<$inv = $res-Einvert> +=item C<$prod = $set1->multiply ($set2)> + +Multiply to conditional sets. + + my $set1 = new Automake::ConditionalSet + (new Automake::Conditional ("A_TRUE"), + new Automake::Conditional ("B_TRUE")); + my $set2 = new Automake::ConditionalSet + (new Automake::Conditional ("C_FALSE"), + new Automake::Conditional ("D_FALSE")); + +C<$set1-Emultiply ($set2)> will return + + new Automake::ConditionalSet + (new Automake::Conditional ("A_TRUE", "C_FALSE"), + new Automake::Conditional ("B_TRUE", "C_FALSE"),; + new Automake::Conditional ("A_TRUE", "D_FALSE"), + new Automake::Conditional ("B_TRUE", "D_FALSE")); + +=cut + +# Same as multiply() but take a list of Conditonal as second argument. +# We use this in invert(). +sub _multiply ($@) +{ + my ($self, @set) = @_; + my @res = (); + foreach my $selfcond ($self->conds) + { + foreach my $setcond (@set) + { + push @res, $selfcond->merge ($setcond); + } + } + return new Automake::ConditionalSet @res; +} + +sub multiply ($$) +{ + my ($self, $set) = @_; + return $self->_multiply ($set->conds); +} + +=item C<$inv = $set-Einvert> Invert a C. Return a C which is true -when C<$res> is false, and vice-versa. +when C<$set> is false, and vice-versa. my $set = new Automake::ConditionalSet (new Automake::Conditional ("A_TRUE", "B_TRUE"), @@ -332,14 +375,21 @@ sub invert($ ) return $self->{'invert'} if defined $self->{'invert'}; - # Generate permutations for all subconditions. - my @perm = $self->permutations->conds; - - # Now remove all conditions which imply one of the input conditions. - my @conds = $self->conds; - my @notconds = - grep { ! $_->implies_any (@conds) } $self->permutations->conds; - my $res = new Automake::ConditionalSet @notconds; + # The invert of an empty ConditionalSet is TRUE. + my $res = new Automake::ConditionalSet TRUE; + + # !((a.b)+(c.d)+(e.f)) + # = (!a+!b).(!c+!d).(!e+!f) + # We develop this into a sum of product iteratively, starting from TRUE: + # 1) TRUE + # 2) TRUE.!a + TRUE.!b + # 3) TRUE.!a.!c + TRUE.!b.!c + TRUE.!a.!d + TRUE.!b.!d + # 4) TRUE.!a.!c.!e + TRUE.!b.!c.!e + TRUE.!a.!d.!e + TRUE.!b.!d.!e + # + TRUE.!a.!c.!f + TRUE.!b.!c.!f + TRUE.!a.!d.!f + TRUE.!b.!d.!f + foreach my $cond ($self->conds) + { + $res = $res->_multiply ($cond->not); + } # Cache result. $self->{'invert'} = $res; diff --git a/lib/Automake/tests/ConditionalSet.pl b/lib/Automake/tests/ConditionalSet.pl index a60d8250..5c815233 100644 --- a/lib/Automake/tests/ConditionalSet.pl +++ b/lib/Automake/tests/ConditionalSet.pl @@ -109,11 +109,10 @@ sub test_invert () [[["COND1_TRUE", "COND2_TRUE"], ["COND3_FALSE", "COND2_TRUE"]], - [["COND1_FALSE","COND2_FALSE","COND3_FALSE"], - ["COND1_TRUE", "COND2_FALSE","COND3_FALSE"], - ["COND1_FALSE","COND2_FALSE","COND3_TRUE"], - ["COND1_TRUE", "COND2_FALSE","COND3_TRUE"], - ["COND1_FALSE","COND2_TRUE", "COND3_TRUE"]]], + [["COND2_FALSE"], + ["COND2_FALSE", "COND3_TRUE"], + ["COND1_FALSE", "COND2_FALSE"], + ["COND1_FALSE", "COND3_TRUE"]]], [[["COND1_TRUE", "COND2_TRUE"], ["TRUE"]], @@ -121,9 +120,8 @@ sub test_invert () [[["COND1_TRUE", "COND2_TRUE"], ["FALSE"]], - [["COND1_FALSE", "COND2_TRUE"], - ["COND1_FALSE", "COND2_FALSE"], - ["COND1_TRUE", "COND2_FALSE"]]], + [["COND1_FALSE"], + ["COND2_FALSE"]]], [[["COND1_TRUE"], ["COND2_FALSE"]], @@ -137,7 +135,8 @@ sub test_invert () my $inv = $set->invert; if ($inv != $res) { - print " (I) " . $inv->string . ' != ' . $res->string . "\n"; + print " (I) " . $set->string . "\n\t" + . $inv->string . ' != ' . $res->string . "\n"; return 1; } } -- 2.43.5