Skip to content

Commit 9c0f19f

Browse files
committed
Implement bdd leafs for unions and intersections
1 parent 78e0398 commit 9c0f19f

File tree

1 file changed

+51
-28
lines changed

1 file changed

+51
-28
lines changed

lib/elixir/lib/module/types/descr.ex

Lines changed: 51 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4429,6 +4429,9 @@ defmodule Module.Types.Descr do
44294429
:bdd_top ->
44304430
:bdd_top
44314431

4432+
{_, _} ->
4433+
fun.(bdd)
4434+
44324435
{literal, left, union, right} ->
44334436
{fun.(literal), bdd_map(left, fun), bdd_map(union, fun), bdd_map(right, fun)}
44344437
end
@@ -4448,14 +4451,23 @@ defmodule Module.Types.Descr do
44484451
{bdd, :bdd_bot} ->
44494452
bdd
44504453

4451-
{{lit, l1, u1, r1}, {lit, l2, u2, r2}} ->
4452-
{lit, bdd_union(l1, l2), bdd_union(u1, u2), bdd_union(r1, r2)}
4454+
_ ->
4455+
case bdd_compare(bdd1, bdd2) do
4456+
{:lt, {lit1, c1, u1, d1}, bdd2} ->
4457+
{lit1, c1, bdd_union(u1, bdd2), d1}
44534458

4454-
{{lit1, l1, u1, r1}, {lit2, _, _, _} = bdd2} when lit1 < lit2 ->
4455-
{lit1, l1, bdd_union(u1, bdd2), r1}
4459+
{:gt, bdd1, {lit2, c2, u2, d2}} ->
4460+
{lit2, c2, bdd_union(bdd1, u2), d2}
4461+
4462+
{:eq, {_, _}, bdd2} ->
4463+
bdd2
44564464

4457-
{bdd1, {lit2, l2, u2, r2}} ->
4458-
{lit2, l2, bdd_union(bdd1, u2), r2}
4465+
{:eq, bdd1, {_, _}} ->
4466+
bdd1
4467+
4468+
{:eq, {lit, c1, u1, d1}, {_, c2, u2, d2}} ->
4469+
{lit, bdd_union(c1, c2), bdd_union(u1, u2), bdd_union(d1, d2)}
4470+
end
44594471
end
44604472
end
44614473

@@ -4473,7 +4485,7 @@ defmodule Module.Types.Descr do
44734485
{:bdd_top, bdd} ->
44744486
bdd_negation(bdd)
44754487

4476-
{bdd1, bdd2} ->
4488+
_ ->
44774489
case bdd_compare(bdd1, bdd2) do
44784490
{:lt, {lit1, c1, u1, d1}, bdd2} ->
44794491
{lit1, bdd_difference(bdd_union(c1, u1), bdd2), :bdd_bot,
@@ -4538,27 +4550,38 @@ defmodule Module.Types.Descr do
45384550
{_, :bdd_bot} ->
45394551
:bdd_bot
45404552

4541-
# Notice that (l ? c1, u1, d1) and (l ? c2, u2, d2) is, on paper, equivalent to
4542-
# [(l /\ c1) \/ u1 \/ (not l /\ d1)] and [(l /\ c2) \/ u2 \/ (not l /\ d2)]
4543-
# which is equivalent, by distributivity of intersection over union, to
4544-
# l /\ [(c1 /\ c2) \/ (c1 /\ u2) \/ (u1 /\ c2)]
4545-
# \/ (u1 /\ u2)
4546-
# \/ [(not l) /\ ((d1 /\ u2) \/ (d1 /\ d2) \/ (u1 /\ d2))]
4547-
# which is equivalent, by factoring out c1 in the first disjunct, and d1 in the third, to
4548-
# l /\ [c1 /\ (c2 \/ u2)] \/ (u1 /\ c2)
4549-
# \/ (u1 /\ u2)
4550-
# \/ (not l) /\ [d1 /\ (u2 \/ d2) \/ (u1 /\ d2)]
4551-
# This last expression gives the following implementation:
4552-
{{lit, c1, u1, d1}, {lit, c2, u2, d2}} ->
4553-
{lit, bdd_union(bdd_intersection_union(c1, c2, u2), bdd_intersection(u1, c2)),
4554-
bdd_intersection(u1, u2),
4555-
bdd_union(bdd_intersection_union(d1, u2, d2), bdd_intersection(u1, d2))}
4556-
4557-
{{lit1, c1, u1, d1}, {lit2, _, _, _} = bdd2} when lit1 < lit2 ->
4558-
{lit1, bdd_intersection(c1, bdd2), bdd_intersection(u1, bdd2), bdd_intersection(d1, bdd2)}
4559-
4560-
{bdd1, {lit2, c2, u2, d2}} ->
4561-
{lit2, bdd_intersection(bdd1, c2), bdd_intersection(bdd1, u2), bdd_intersection(bdd1, d2)}
4553+
_ ->
4554+
case bdd_compare(bdd1, bdd2) do
4555+
{:lt, {lit1, c1, u1, d1}, bdd2} ->
4556+
{lit1, bdd_intersection(c1, bdd2), bdd_intersection(u1, bdd2),
4557+
bdd_intersection(d1, bdd2)}
4558+
4559+
{:gt, bdd1, {lit2, c2, u2, d2}} ->
4560+
{lit2, bdd_intersection(bdd1, c2), bdd_intersection(bdd1, u2),
4561+
bdd_intersection(bdd1, d2)}
4562+
4563+
{:eq, {_, _} = bdd1, _} ->
4564+
bdd1
4565+
4566+
{:eq, _, {_, _} = bdd2} ->
4567+
bdd2
4568+
4569+
# Notice that (l ? c1, u1, d1) and (l ? c2, u2, d2) is, on paper, equivalent to
4570+
# [(l /\ c1) \/ u1 \/ (not l /\ d1)] and [(l /\ c2) \/ u2 \/ (not l /\ d2)]
4571+
# which is equivalent, by distributivity of intersection over union, to
4572+
# l /\ [(c1 /\ c2) \/ (c1 /\ u2) \/ (u1 /\ c2)]
4573+
# \/ (u1 /\ u2)
4574+
# \/ [(not l) /\ ((d1 /\ u2) \/ (d1 /\ d2) \/ (u1 /\ d2))]
4575+
# which is equivalent, by factoring out c1 in the first disjunct, and d1 in the third, to
4576+
# l /\ [c1 /\ (c2 \/ u2)] \/ (u1 /\ c2)
4577+
# \/ (u1 /\ u2)
4578+
# \/ (not l) /\ [d1 /\ (u2 \/ d2) \/ (u1 /\ d2)]
4579+
# This last expression gives the following implementation:
4580+
{:eq, {lit, c1, u1, d1}, {_, c2, u2, d2}} ->
4581+
{lit, bdd_union(bdd_intersection_union(c1, c2, u2), bdd_intersection(u1, c2)),
4582+
bdd_intersection(u1, u2),
4583+
bdd_union(bdd_intersection_union(d1, u2, d2), bdd_intersection(u1, d2))}
4584+
end
45624585
end
45634586
end
45644587

0 commit comments

Comments
 (0)