]> git.ipfire.org Git - thirdparty/automake.git/commitdiff
* lib/Automake/ConditionalSet.pm (conds): Use value() to simplify.
authorAlexandre Duret-Lutz <adl@gnu.org>
Wed, 20 Nov 2002 11:10:05 +0000 (11:10 +0000)
committerAlexandre Duret-Lutz <adl@gnu.org>
Wed, 20 Nov 2002 11:10:05 +0000 (11:10 +0000)
(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
automake.in
lib/Automake/Conditional.pm
lib/Automake/ConditionalSet.pm
lib/Automake/tests/ConditionalSet.pl

index b8ef1d5d3883302feb1f5dacb4f16b4d22340f1a..43cc305a0aced16960047019e34dc16f8dc9b378 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2002-11-20  Alexandre Duret-Lutz  <adl@gnu.org>
+
+       * 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  <adl@gnu.org>
 
        * lib/Automake/ConditionalSet.pm (_simplify, simplify): New methods.
index c026a45af68b56d4eb8237349ff8b781971876a1..164255ea51ab1f687b2656b3fd261c3ae478448d 100755 (executable)
@@ -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 "
index cbef6b459153e380bf847bbcee6f49c088a1549f..2ce74a6e0de097fc29f7532ab9e9423099d19e64 100644 (file)
@@ -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<Conditional> is a conjunction of atomic conditions.  In Automake they
@@ -394,6 +397,28 @@ sub implies_any ($@)
   return 0;
 }
 
+=item C<$cond-E<gt>not>
+
+Return a negation of @<$cond> as a list of C<Conditional>s.
+This list should be used to construct a C<ConditionalSet>
+(we cannot return a C<ConditionalSet> from C<Automake::Conditional>,
+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<condition_negate ($condstr)>
+
+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<Automake::ConditionalSet>.
index 58b203aae9f099eb7d29e8f58bdf3ba83a87f106..9ed9b9bad30d8f26f3254c7bd56bc2e444157151 100644 (file)
@@ -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-E<gt>invert>
+=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-E<gt>multiply ($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-E<gt>invert>
 
 Invert a C<ConditionalSet>.  Return a C<ConditionalSet> 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;
index a60d82509bbc29bb0b1c79ce4411062f82a39986..5c8152337cd3047bf158fd18fa59b3f734074bb5 100644 (file)
@@ -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;
        }
     }