let rec unif_uplet_cmp_f z1 z2 ss = if ss=[] then ss else
match (z1,z2) with
| ([],[]) -> ss
| ((Var(_) as hd)::tl,(Var(_) as hd2)::tl2) ->
(unif_uplet_cmp_g ss hd tl [] z2)@(unif_uplet_cmp_g ss hd2 tl2 [hd] tl)
| ((Var(_) as hd)::tl,_) -> unif_uplet_cmp_g ss hd tl [] z2
| (_,(Var(_) as hd)::tl) -> unif_uplet_cmp_g ss hd tl [] z1
| (t1::zz1,t2::zz2) -> unif_uplet_cmp_f zz1 zz2 (unif_cmp true t1 t2 ss)
| _ -> []
and unif_uplet_cmp_g su d1h d1t d2 = function
| [] -> []
| t::d3 -> (unif_uplet_cmp_f d1t d3 (unif_cmp true d1h
(if d2=[] then t
else Uplet (List.rev (t::d2))) su))
@ (unif_uplet_cmp_g su d1h d1t (t::d2) d3)
and unif_uplet_cmp_h tas lu lv = function
| s::fin ->
let tas =
try
merge tas (unif_uplet_cmp_f (unif_uplet_norm s lu) (unif_uplet_norm s lv) [s])
with
NeedXor -> unif_combi unif_cmp unif_xor true (Uplet lu) (Uplet lv) [s]
in unif_uplet_cmp_h tas lu lv fin
| [] -> tas
and unif_cmp (to_purify : bool) (u : term) (v : term) (subs : t_subst list) : t_subst list =
match (u,v) with
| (Var(n),t) | (t,Var(n)) -> add unif_cmp (unif_combi unif_cmp unif_xor) to_purify n t [] subs
| (Atm(n1),Atm(n2)) -> if n1=n2 then subs else []
| (Uplet(lu),Uplet(lv)) ->
if to_purify then
unif_uplet_cmp_h [] lu lv subs
else
unif_uplet_cmp_f lu lv subs
| (PCrypt(m1,k1),PCrypt(m2,k2))
| (SCrypt(m1,k1),SCrypt(m2,k2)) -> unif_cmp true m1 m2 (unif_cmp to_purify k1 k2 subs)
| (Uplet([t1]),_) -> unif_cmp to_purify t1 v subs
| (_,Uplet([t2])) -> unif_cmp to_purify u t2 subs
| (PInv(t1),t2) | (t2,PInv(t1)) ->
( match (t1,t2) with
| (t1, PInv(t2)) | (PInv(t1), t2)
| (Uplet([t1]),t2) -> unif_cmp to_purify t1 t2 subs
| (Xor(_),_) -> unif_combi unif_cmp unif_xor to_purify t1 (PInv t2) subs
| (_, Xor(_)) -> unif_combi unif_cmp unif_xor to_purify (PInv t1) t2 subs
| (Var(_), _) -> unif_cmp true t1 (PInv t2) subs
| _ -> [] )
| (Xor(_),_) | (_,Xor(_)) ->
unif_combi unif_cmp unif_xor to_purify u v subs
| (Exp(a,l1),Exp(b,l2)) -> unif_exp unif_cmp a l1 b l2 subs
| _ -> []