@@ -4429,6 +4429,9 @@ defmodule Module.Types.Descr do
4429
4429
:bdd_top ->
4430
4430
:bdd_top
4431
4431
4432
+ { _ , _ } ->
4433
+ fun . ( bdd )
4434
+
4432
4435
{ literal , left , union , right } ->
4433
4436
{ fun . ( literal ) , bdd_map ( left , fun ) , bdd_map ( union , fun ) , bdd_map ( right , fun ) }
4434
4437
end
@@ -4448,14 +4451,23 @@ defmodule Module.Types.Descr do
4448
4451
{ bdd , :bdd_bot } ->
4449
4452
bdd
4450
4453
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 }
4453
4458
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
4456
4464
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
4459
4471
end
4460
4472
end
4461
4473
@@ -4473,7 +4485,7 @@ defmodule Module.Types.Descr do
4473
4485
{ :bdd_top , bdd } ->
4474
4486
bdd_negation ( bdd )
4475
4487
4476
- { bdd1 , bdd2 } ->
4488
+ _ ->
4477
4489
case bdd_compare ( bdd1 , bdd2 ) do
4478
4490
{ :lt , { lit1 , c1 , u1 , d1 } , bdd2 } ->
4479
4491
{ lit1 , bdd_difference ( bdd_union ( c1 , u1 ) , bdd2 ) , :bdd_bot ,
@@ -4538,27 +4550,38 @@ defmodule Module.Types.Descr do
4538
4550
{ _ , :bdd_bot } ->
4539
4551
:bdd_bot
4540
4552
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
4562
4585
end
4563
4586
end
4564
4587
0 commit comments