@@ -4631,18 +4631,27 @@ defmodule Module.Types.Descr do
46314631 { _ , :bdd_bot } ->
46324632 :bdd_bot
46334633
4634- { { lit , c1 , u1 , d1 } = bdd1 , { lit , c2 , u2 , d2 } = bdd2 } ->
4635- # If possible, keep unions without dematerializing them down.
4636- # We rely on the fact that (t1 ∨ t2) ∧ t3 is the same as (t1 ∧ t3) ∨ (t2 ∧ t3).
4637- if u1 != :bdd_bot do
4638- { lit , lazy_bdd_intersection_union ( c1 , c2 , u2 ) , :bdd_bot ,
4639- lazy_bdd_intersection_union ( d1 , d2 , u2 ) }
4640- |> lazy_bdd_union ( lazy_bdd_intersection ( u1 , bdd2 ) )
4641- else
4642- { lit , lazy_bdd_intersection_union ( c2 , c1 , u1 ) , :bdd_bot ,
4643- lazy_bdd_intersection_union ( d2 , d1 , u1 ) }
4644- |> lazy_bdd_union ( lazy_bdd_intersection ( u2 , bdd1 ) )
4645- end
4634+ # Notice that (l ? c1, u1, d1) and (l ? c2, u2, d2) is, on paper, equivalent to
4635+ # [(l /\ c1) \/ u1 \/ (not l /\ d1)] and [(l /\ c2) \/ u2 \/ (not l /\ d2)]
4636+ # which is equivalent, by distributivity of intersection over union, to
4637+ # l /\ [(c1 /\ c2) \/ (c1 /\ u2) \/ (u1 /\ c2)]
4638+ # \/ (u1 /\ u2)
4639+ # \/ [(not l) /\ ((d1 /\ u2) \/ (d1 /\ d2) \/ (u1 /\ d2))]
4640+ # which is equivalent, by factoring out c1 in the first disjunct, and d1 in the third, to
4641+ # l /\ [c1 /\ (c2 \/ u2)] \/ (u1 /\ c2)
4642+ # \/ (u1 /\ u2)
4643+ # \/ (not l) /\ [d1 /\ (u2 \/ d2) \/ (u1 /\ d2)]
4644+ # This last expression gives the following implementation:
4645+ { { lit , c1 , u1 , d1 } , { lit , c2 , u2 , d2 } } ->
4646+ { lit ,
4647+ lazy_bdd_union (
4648+ lazy_bdd_intersection_union ( c1 , c2 , u2 ) ,
4649+ lazy_bdd_intersection ( u1 , c2 )
4650+ ) , lazy_bdd_intersection ( u1 , u2 ) ,
4651+ lazy_bdd_union (
4652+ lazy_bdd_intersection_union ( d1 , u2 , d2 ) ,
4653+ lazy_bdd_intersection ( u1 , d2 )
4654+ ) }
46464655
46474656 { { lit1 , c1 , u1 , d1 } , { lit2 , _ , _ , _ } = bdd2 } when lit1 < lit2 ->
46484657 { lit1 , lazy_bdd_intersection ( c1 , bdd2 ) , lazy_bdd_intersection ( u1 , bdd2 ) ,
0 commit comments