sofs.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 2,315 行 · 第 1/5 页
ERL
2,315 行
is_no_lists(_T, 0, Sz, L) -> {Sz, L};is_no_lists(T, I, Sz, L) when ?IS_ATOM_TYPE(?REL_TYPE(I, T)) -> is_no_lists(T, I-1, Sz, L);is_no_lists(T, I, Sz, L) -> is_no_lists(T, I-1, Sz, [{I,is_no_lists(?REL_TYPE(I, T))} | L]).create([E | Es], T, T0, L) -> {NT, S} = make_element(E, T, T0), create(Es, NT, T0, [S | L]);create([], T, _T0, L) -> {?SET_OF(T), usort(L)}.make_element(C, ?ANYTYPE, _T0) -> make_element(C);make_element(C, Atom, ?ANYTYPE) when ?IS_ATOM_TYPE(Atom), not is_list(C), not is_tuple(C) -> {Atom, C};make_element(C, Atom, Atom) when ?IS_ATOM_TYPE(Atom) -> {Atom, C};make_element(T, TT, ?ANYTYPE) when is_tuple(T), is_tuple(TT), size(T) =:= size(TT) -> make_tuple(tuple_to_list(T), tuple_to_list(TT), [], [], ?ANYTYPE);make_element(T, TT, T0) when is_tuple(T), is_tuple(TT), size(T) =:= size(TT) -> make_tuple(tuple_to_list(T), tuple_to_list(TT), [], [], tuple_to_list(T0));make_element(L, [LT], ?ANYTYPE) when is_list(L) -> create(L, LT, ?ANYTYPE, []);make_element(L, [LT], [T0]) when is_list(L) -> create(L, LT, T0, []).make_tuple([E | Es], [T | Ts], NT, L, T0) when T0 =:= ?ANYTYPE -> {ET, ES} = make_element(E, T, T0), make_tuple(Es, Ts, [ET | NT], [ES | L], T0);make_tuple([E | Es], [T | Ts], NT, L, [T0 | T0s]) -> {ET, ES} = make_element(E, T, T0), make_tuple(Es, Ts, [ET | NT], [ES | L], T0s);make_tuple([], [], NT, L, _T0s) when NT =/= [] -> {list_to_tuple(reverse(NT)), list_to_tuple(reverse(L))}.%% Derive type.make_element(C) when not is_list(C), not is_tuple(C) -> {?ATOM_TYPE, C};make_element(T) when is_tuple(T) -> make_tuple(tuple_to_list(T), [], []);make_element(L) when is_list(L) -> create(L, ?ANYTYPE, ?ANYTYPE, []).make_tuple([E | Es], T, L) -> {ET, ES} = make_element(E), make_tuple(Es, [ET | T], [ES | L]);make_tuple([], T, L) when T =/= [] -> {list_to_tuple(reverse(T)), list_to_tuple(reverse(L))}.make_oset([T | Ts], Szs, L, Type) -> true = test_oset(Szs, T, T), make_oset(Ts, Szs, L, Type);make_oset([], _Szs, L, Type) -> ?SET(usort(L), Type).%% Optimization. Avoid re-building (nested) tuples.test_oset({Sz,Args}, T, T0) when is_tuple(T), size(T) =:= Sz -> test_oset_args(Args, T, T0);test_oset(Sz, T, _T0) when is_tuple(T), size(T) =:= Sz -> true.test_oset_args([{Arg,Szs} | Ss], T, T0) -> true = test_oset(Szs, ?REL_TYPE(Arg, T), T0), test_oset_args(Ss, T, T0);test_oset_args([], _T, _T0) -> true.list_of_sets([S | Ss], Type, L) -> list_of_sets(Ss, Type, [?SET(S, Type) | L]);list_of_sets([], _Type, L) -> reverse(L).list_of_ordsets([S | Ss], Type, L) -> list_of_ordsets(Ss, Type, [?ORDSET(S, Type) | L]);list_of_ordsets([], _Type, L) -> reverse(L).tuple_of_sets([S | Ss], [?SET_OF(Type) | Types], L) -> tuple_of_sets(Ss, Types, [?SET(S, Type) | L]);tuple_of_sets([S | Ss], [Type | Types], L) -> tuple_of_sets(Ss, Types, [?ORDSET(S, Type) | L]);tuple_of_sets([], [], L) -> list_to_tuple(reverse(L)).spec([E | Es], Fun, Type, L) -> case Fun(term2set(E, Type)) of true -> spec(Es, Fun, Type, [E | L]); false -> spec(Es, Fun, Type, L); _ -> badarg end;spec([], _Fun, _Type, L) -> reverse(L).specification([E | Es], Fun, L) -> case Fun(E) of true -> specification(Es, Fun, [E | L]); false -> specification(Es, Fun, L); _ -> badarg end;specification([], _Fun, L) -> reverse(L).%% Elements from the first list are kept.intersection([H1 | T1], [H2 | T2], L) when H1 < H2 -> intersection1(T1, T2, L, H2);intersection([H1 | T1], [H2 | T2], L) when H1 == H2 -> intersection(T1, T2, [H1 | L]);intersection([H1 | T1], [_H2 | T2], L) -> intersection2(T1, T2, L, H1);intersection(_, _, L) -> reverse(L).intersection1([H1 | T1], T2, L, H2) when H1 < H2 -> intersection1(T1, T2, L, H2);intersection1([H1 | T1], T2, L, H2) when H1 == H2 -> intersection(T1, T2, [H1 | L]);intersection1([H1 | T1], T2, L, _H2) -> intersection2(T1, T2, L, H1);intersection1(_, _, L, _) -> reverse(L).intersection2(T1, [H2 | T2], L, H1) when H1 > H2 -> intersection2(T1, T2, L, H1);intersection2(T1, [H2 | T2], L, H1) when H1 == H2 -> intersection(T1, T2, [H1 | L]);intersection2(T1, [H2 | T2], L, _H1) -> intersection1(T1, T2, L, H2);intersection2(_, _, L, _) -> reverse(L).difference([H1 | T1], [H2 | T2], L) when H1 < H2 -> diff(T1, T2, [H1 | L], H2);difference([H1 | T1], [H2 | T2], L) when H1 == H2 -> difference(T1, T2, L);difference([H1 | T1], [_H2 | T2], L) -> diff2(T1, T2, L, H1);difference(L1, _, L) -> reverse(L, L1).diff([H1 | T1], T2, L, H2) when H1 < H2 -> diff(T1, T2, [H1 | L], H2);diff([H1 | T1], T2, L, H2) when H1 == H2 -> difference(T1, T2, L);diff([H1 | T1], T2, L, _H2) -> diff2(T1, T2, L, H1);diff(_, _, L, _) -> reverse(L).diff2(T1, [H2 | T2], L, H1) when H1 > H2 -> diff2(T1, T2, L, H1);diff2(T1, [H2 | T2], L, H1) when H1 == H2 -> difference(T1, T2, L);diff2(T1, [H2 | T2], L, H1) -> diff(T1, T2, [H1 | L], H2);diff2(T1, _, L, H1) -> reverse(L, [H1 | T1]).symdiff([H1 | T1], T2, L) -> symdiff2(T1, T2, L, H1);symdiff(_, T2, L) -> reverse(L, T2).symdiff1([H1 | T1], T2, L, H2) when H1 < H2 -> symdiff1(T1, T2, [H1 | L], H2);symdiff1([H1 | T1], T2, L, H2) when H1 == H2 -> symdiff(T1, T2, L);symdiff1([H1 | T1], T2, L, H2) -> symdiff2(T1, T2, [H2 | L], H1);symdiff1(_, T2, L, H2) -> reverse(L, [H2 | T2]).symdiff2(T1, [H2 | T2], L, H1) when H1 > H2 -> symdiff2(T1, T2, [H2 | L], H1);symdiff2(T1, [H2 | T2], L, H1) when H1 == H2 -> symdiff(T1, T2, L);symdiff2(T1, [H2 | T2], L, H1) -> symdiff1(T1, T2, [H1 | L], H2);symdiff2(T1, _, L, H1) -> reverse(L, [H1 | T1]).sympart([H1 | T1], [H2 | T2], L1, L12, L2, T) when H1 < H2 -> sympart1(T1, T2, [H1 | L1], L12, L2, T, H2);sympart([H1 | T1], [H2 | T2], L1, L12, L2, T) when H1 == H2 -> sympart(T1, T2, L1, [H1 | L12], L2, T);sympart([H1 | T1], [H2 | T2], L1, L12, L2, T) -> sympart2(T1, T2, L1, L12, [H2 | L2], T, H1);sympart(S1, [], L1, L12, L2, T) -> {?SET(reverse(L1, S1), T), ?SET(reverse(L12), T), ?SET(reverse(L2), T)};sympart(_, S2, L1, L12, L2, T) -> {?SET(reverse(L1), T), ?SET(reverse(L12), T), ?SET(reverse(L2, S2), T)}.sympart1([H1 | T1], T2, L1, L12, L2, T, H2) when H1 < H2 -> sympart1(T1, T2, [H1 | L1], L12, L2, T, H2);sympart1([H1 | T1], T2, L1, L12, L2, T, H2) when H1 == H2 -> sympart(T1, T2, L1, [H1 | L12], L2, T);sympart1([H1 | T1], T2, L1, L12, L2, T, H2) -> sympart2(T1, T2, L1, L12, [H2 | L2], T, H1);sympart1(_, T2, L1, L12, L2, T, H2) -> {?SET(reverse(L1), T), ?SET(reverse(L12), T), ?SET(reverse(L2, [H2 | T2]), T)}.sympart2(T1, [H2 | T2], L1, L12, L2, T, H1) when H1 > H2 -> sympart2(T1, T2, L1, L12, [H2 | L2], T, H1);sympart2(T1, [H2 | T2], L1, L12, L2, T, H1) when H1 == H2 -> sympart(T1, T2, L1, [H1 | L12], L2, T);sympart2(T1, [H2 | T2], L1, L12, L2, T, H1) -> sympart1(T1, T2, [H1 | L1], L12, L2, T, H2);sympart2(T1, _, L1, L12, L2, T, H1) -> {?SET(reverse(L1, [H1 | T1]), T), ?SET(reverse(L12), T), ?SET(reverse(L2), T)}.prod([[E | Es] | Xs], T, L) -> prod(Es, Xs, T, prod(Xs, [E | T], L));prod([], T, L) -> [list_to_tuple(reverse(T)) | L].prod([E | Es], Xs, T, L) -> prod(Es, Xs, T, prod(Xs, [E | T], L));prod([], _Xs, _E, L) -> L.constant_function([E | Es], X, L) -> constant_function(Es, X, [{E,X} | L]);constant_function([], _X, L) -> reverse(L).subset([H1 | T1], [H2 | T2]) when H1 > H2 -> subset(T1, T2, H1);subset([H1 | T1], [H2 | T2]) when H1 == H2 -> subset(T1, T2);subset(L1, _) -> L1 =:= [].subset(T1, [H2 | T2], H1) when H1 > H2 -> subset(T1, T2, H1);subset(T1, [H2 | T2], H1) when H1 == H2 -> subset(T1, T2);subset(_, _, _) -> false.disjoint([B | Bs], A, As) when A < B -> disjoint(As, B, Bs);disjoint([B | _Bs], A, _As) when A == B -> false;disjoint([_B | Bs], A, As) -> disjoint(Bs, A, As);disjoint(_Bs, _A, _As) -> true.%% Append sets that come in order, then "merge".lunion([[_] = S]) -> % optimization S;lunion([[] | Ls]) -> lunion(Ls);lunion([S | Ss]) -> umerge(lunion(Ss, last(S), [S], []));lunion([]) -> [].lunion([[E] = S | Ss], Last, SL, Ls) when E > Last -> % optimization lunion(Ss, E, [S | SL], Ls);lunion([S | Ss], Last, SL, Ls) when hd(S) > Last -> lunion(Ss, last(S), [S | SL], Ls);lunion([S | Ss], _Last, SL, Ls) -> lunion(Ss, last(S), [S], [append(reverse(SL)) | Ls]);lunion([], _Last, SL, Ls) -> [append(reverse(SL)) | Ls].%% The empty list is always the first list, if present.lintersection(_, []) -> [];lintersection([S | Ss], S0) -> lintersection(Ss, intersection(S, S0, []));lintersection([], S) -> S.can_rel([S | Ss], L) -> can_rel(Ss, L, S, S);can_rel([], L) -> sort(L).can_rel(Ss, L, [E | Es], S) -> can_rel(Ss, [{E, S} | L], Es, S);can_rel(Ss, L, _, _S) -> can_rel(Ss, L).rel2family([{X,Y} | S]) -> rel2fam(S, X, [Y], []);rel2family([]) -> [].rel2fam([{X,Y} | S], X0, YL, L) when X0 == X -> rel2fam(S, X0, [Y | YL], L);rel2fam([{X,Y} | S], X0, [A,B | YL], L) -> % optimization rel2fam(S, X, [Y], [{X0,reverse(YL,[B,A])} | L]);rel2fam([{X,Y} | S], X0, YL, L) -> rel2fam(S, X, [Y], [{X0,YL} | L]);rel2fam([], X, YL, L) -> reverse([{X,reverse(YL)} | L]).dom([{X,_} | Es]) -> dom([], X, Es);dom([] = L) -> L.dom(L, X, [{X1,_} | Es]) when X == X1 -> dom(L, X, Es);dom(L, X, [{Y,_} | Es]) -> dom([X | L], Y, Es);dom(L, X, []) -> reverse(L, [X]).ran([{_,Y} | Es], L) -> ran(Es, [Y | L]);ran([], L) -> usort(L).relprod(A, B) -> usort(relprod1(A, B)).relprod1([{Ay,Ax} | A], B) -> relprod1(B, Ay, Ax, A, []);relprod1(_A, _B) -> [].relprod1([{Bx,_By} | B], Ay, Ax, A, L) when Ay > Bx -> relprod1(B, Ay, Ax, A, L);relprod1([{Bx,By} | B], Ay, Ax, A, L) when Ay == Bx -> relprod(B, Bx, By, A, [{Ax,By} | L], Ax, B, Ay);relprod1([{Bx,By} | B], _Ay, _Ax, A, L) -> relprod2(B, Bx, By, A, L);relprod1(_B, _Ay, _Ax, _A, L) -> L.relprod2(B, Bx, By, [{Ay, _Ax} | A], L) when Ay < Bx -> relprod2(B, Bx, By, A, L);relprod2(B, Bx, By, [{Ay, Ax} | A], L) when Ay == Bx -> relprod(B, Bx, By, A, [{Ax,By} | L], Ax, B, Ay);relprod2(B, _Bx, _By, [{Ay, Ax} | A], L) -> relprod1(B, Ay, Ax, A, L);relprod2(_, _, _, _, L) -> L.relprod(B0, Bx0, By0, A0, L, Ax, [{Bx,By} | B], Ay) when Ay == Bx -> relprod(B0, Bx0, By0, A0, [{Ax,By} | L], Ax, B, Ay);relprod(B0, Bx0, By0, A0, L, _Ax, _B, _Ay) -> relprod2(B0, Bx0, By0, A0, L).relprod_n({}, _R, _EmptyG, _IsR) -> {error, badarg};relprod_n(RT, R, EmptyR, IsR) -> RL = tuple_to_list(RT), case domain_type(RL, ?ANYTYPE) of Error = {error, _Reason} -> Error; DType -> Empty = any(fun is_empty_set/1, RL) or EmptyR, RType = range_type(RL, []), Type = ?BINREL(DType, RType), Prod = case Empty of true when DType =:= ?ANYTYPE; RType =:= ?ANYTYPE -> empty_set(); true -> ?SET([], Type); false -> TL = ?LIST((relprod_n(RL))), Sz = size(RT), Fun = fun({X,A}) -> {X, flat(Sz, A, [])} end, ?SET(map(Fun, TL), Type) end, case IsR of true -> relative_product(Prod, R); false -> Prod end end.relprod_n([R | Rs]) -> relprod_n(Rs, R).relprod_n([], R) -> R;relprod_n([R | Rs], R0) -> T = raise_element(R0, 1), R1 = relative_product1(T, R), NR = projection({external, fun({{X,A},AS}) -> {X,{A,AS}} end}, R1), relprod_n(Rs, NR).flat(1, A, L) -> list_to_tuple([A | L]);flat(N, {T,A}, L) -> flat(N-1, T, [A | L]).domain_type([T | Ts], T0) when ?IS_SET(T) -> case ?TYPE(T) of ?BINREL(DT, _RT) -> case unify_types(DT, T0) of [] -> {error, type_mismatch}; T1 -> domain_type(Ts, T1) end; ?ANYTYPE -> domain_type(Ts, T0); _ -> {error, badarg} end;domain_type([], T0) -> T0.range_type([T | Ts], L) -> case ?TYPE(T) of ?BINREL(_DT, RT) -> range_type(Ts, [RT | L]); ?ANYTYPE -> ?ANYTYPE end;range_type([], L) -> list_to_tuple(reverse(L)).converse([{A,B} | X], L) -> converse(X, [{B,A} | L]);converse([], L) -> sort(L).strict([{E1,E2} | Es], L) when E1 == E2 -> strict(Es, L);strict([E | Es], L) -> strict(Es, [E | L]);strict([], L) -> reverse(L).weak(Es) -> %% Not very efficient... weak(Es, ran(Es, []), []).weak(Es=[{X,_} | _], [Y | Ys], L) when X > Y -> weak(Es, Ys, [{Y,Y} | L]);weak(Es=[{X,_} | _], [Y | Ys], L) when X == Y -> weak(Es, Ys, L);weak([E={X,Y} | Es], Ys, L) when X > Y -> weak1(Es, Ys, [E | L], X);weak([E={X,Y} | Es], Ys, L) when X == Y -> weak2(Es, Ys, [E | L], X);weak([E={X,_Y} | Es], Ys, L) -> % when X < _Y weak2(Es, Ys, [E, {X,X} | L], X);weak([], [Y | Ys], L) -> weak([], Ys, [{Y,Y} | L]);weak([], [], L) ->
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?