1: %%
    2: %% %CopyrightBegin%
    3: %%
    4: %% Copyright Ericsson AB 2001-2012. All Rights Reserved.
    5: %%
    6: %% The contents of this file are subject to the Erlang Public License,
    7: %% Version 1.1, (the "License"); you may not use this file except in
    8: %% compliance with the License. You should have received a copy of the
    9: %% Erlang Public License along with this software. If not, it can be
   10: %% retrieved online at http://www.erlang.org/.
   11: %%
   12: %% Software distributed under the License is distributed on an "AS IS"
   13: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
   14: %% the License for the specific language governing rights and limitations
   15: %% under the License.
   16: %%
   17: %% %CopyrightEnd%
   18: %%
   19: -module(sofs_SUITE).
   20: 
   21: %-define(debug, true).
   22: 
   23: -ifdef(debug).
   24: -define(format(S, A), io:format(S, A)).
   25: -define(line, put(line, ?LINE), ).
   26: -define(config(X,Y), foo).
   27: -define(t, test_server).
   28: -else.
   29: -include_lib("test_server/include/test_server.hrl").
   30: -define(format(S, A), ok).
   31: -endif.
   32: 
   33: -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 
   34: 	 init_per_group/2,end_per_group/2]).
   35: 
   36: -export([ from_term_1/1, set_1/1, from_sets_1/1, relation_1/1,
   37: 	 a_function_1/1, family_1/1, projection/1,
   38: 	 relation_to_family_1/1, domain_1/1, range_1/1, image/1,
   39: 	 inverse_image/1, inverse_1/1, converse_1/1, no_elements_1/1,
   40: 	 substitution/1, restriction/1, drestriction/1,
   41: 	 strict_relation_1/1, extension/1, weak_relation_1/1,
   42: 	 to_sets_1/1, specification/1, union_1/1, intersection_1/1,
   43: 	 difference/1, symdiff/1, symmetric_partition/1,
   44: 	 is_sofs_set_1/1, is_set_1/1, is_equal/1, is_subset/1,
   45: 	 is_a_function_1/1, is_disjoint/1, join/1, canonical/1,
   46: 	 composite_1/1, relative_product_1/1, relative_product_2/1,
   47: 	 product_1/1, partition_1/1, partition_3/1,
   48: 	 multiple_relative_product/1, digraph/1, constant_function/1,
   49: 	 misc/1]).
   50: 
   51: -export([ family_specification/1,
   52:          family_domain_1/1, family_range_1/1,
   53: 	 family_to_relation_1/1, 
   54:          union_of_family_1/1, intersection_of_family_1/1,
   55:          family_projection/1, family_difference/1, 
   56:          family_intersection_1/1, family_union_1/1,
   57:          family_intersection_2/1, family_union_2/1,
   58:          partition_family/1]).
   59: 
   60: -import(sofs, 
   61: 	[a_function/1, a_function/2, constant_function/2,
   62: 	 canonical_relation/1, composite/2,
   63: 	 converse/1, extension/3, from_term/1, from_term/2,
   64: 	 difference/2, domain/1, empty_set/0, family_difference/2,
   65: 	 family_intersection/1, family_intersection/2, family_union/1,
   66: 	 family_union/2, family/1, family/2, family_specification/2,
   67: 	 family_domain/1, family_range/1, family_field/1,
   68: 	 family_projection/2, family_to_relation/1, union_of_family/1,
   69: 	 field/1, from_external/2, image/2, intersection/1,
   70: 	 intersection/2, intersection_of_family/1, inverse/1,
   71: 	 inverse_image/2, is_disjoint/2, is_empty_set/1, is_equal/2,
   72: 	 is_a_function/1, is_set/1, is_sofs_set/1, is_subset/2,
   73: 	 join/4, from_sets/1, multiple_relative_product/2,
   74: 	 no_elements/1, partition/1, partition/2, partition/3,
   75: 	 partition_family/2, product/1, product/2, projection/2,
   76: 	 range/1, relation/1, relation/2, relation_to_family/1,
   77: 	 relative_product/1, relative_product/2, relative_product1/2,
   78: 	 strict_relation/1, weak_relation/1, restriction/2,
   79: 	 restriction/3, drestriction/2, drestriction/3, to_sets/1,
   80: 	 is_type/1, set/1, set/2, specification/2, substitution/2,
   81: 	 symdiff/2, symmetric_partition/2, to_external/1, type/1,
   82: 	 union/1, union/2, family_to_digraph/1, family_to_digraph/2,
   83: 	 digraph_to_family/1, digraph_to_family/2]).
   84: 
   85: -export([init_per_testcase/2, end_per_testcase/2]).
   86: 
   87: -compile({inline,[{eval,2}]}).
   88: 
   89: suite() -> [{ct_hooks,[ts_install_cth]}].
   90: 
   91: all() -> 
   92:     [{group, sofs}, {group, sofs_family}].
   93: 
   94: groups() -> 
   95:     [{sofs, [],
   96:       [from_term_1, set_1, from_sets_1, relation_1,
   97:        a_function_1, family_1, relation_to_family_1, domain_1,
   98:        range_1, image, inverse_image, inverse_1, converse_1,
   99:        no_elements_1, substitution, restriction, drestriction,
  100:        projection, strict_relation_1, extension,
  101:        weak_relation_1, to_sets_1, specification, union_1,
  102:        intersection_1, difference, symdiff,
  103:        symmetric_partition, is_sofs_set_1, is_set_1, is_equal,
  104:        is_subset, is_a_function_1, is_disjoint, join,
  105:        canonical, composite_1, relative_product_1,
  106:        relative_product_2, product_1, partition_1, partition_3,
  107:        multiple_relative_product, digraph, constant_function,
  108:        misc]},
  109:      {sofs_family, [],
  110:       [family_specification, family_domain_1, family_range_1,
  111:        family_to_relation_1, union_of_family_1,
  112:        intersection_of_family_1, family_projection,
  113:        family_difference, family_intersection_1,
  114:        family_intersection_2, family_union_1, family_union_2,
  115:        partition_family]}].
  116: 
  117: init_per_suite(Config) ->
  118:     Config.
  119: 
  120: end_per_suite(_Config) ->
  121:     ok.
  122: 
  123: init_per_group(_GroupName, Config) ->
  124:     Config.
  125: 
  126: end_per_group(_GroupName, Config) ->
  127:     Config.
  128: 
  129: 
  130: init_per_testcase(_Case, Config) ->
  131:     Dog=?t:timetrap(?t:minutes(2)),
  132:     [{watchdog, Dog}|Config].
  133: 
  134: end_per_testcase(_Case, Config) ->
  135:     Dog=?config(watchdog, Config),
  136:     test_server:timetrap_cancel(Dog),
  137:     ok.
  138: 
  139: %% [{2,b},{1,a,b}] == lists:sort([{2,b},{1,a,b}])
  140: %% [{1,a,b},{2,b}] == lists:keysort(1,[{2,b},{1,a,b}])
  141: 
  142: 
  143: from_term_1(suite) -> [];
  144: from_term_1(doc) -> [""];
  145: from_term_1(Conf) when is_list(Conf) ->
  146:     %% would go wrong: projection(1,from_term([{2,b},{1,a,b}])),
  147: 
  148:     ?line {'EXIT', {badarg, _}} = (catch from_term([], {atom,'_',atom})),
  149:     ?line {'EXIT', {badarg, _}} = (catch from_term([], [])),
  150:     ?line {'EXIT', {badarg, _}} = (catch from_term([], [atom,atom])),
  151: 
  152:     ?line [] = to_external(from_term([])),
  153:     ?line eval(from_term([]), empty_set()),
  154:     ?line [] = to_external(from_term([], ['_'])),
  155:     ?line eval(from_term([], ['_']), empty_set()),
  156:     ?line [[]] = to_external(from_term([[]])),
  157:     ?line [[['_']]] = type(from_term([[],[[]]])),
  158:     ?line [[],[[]]] = to_external(from_term([[],[[]]])),
  159:     ?line [[['_']]] = type(from_term([[],[[]]])),
  160:     ?line eval(from_term([a],['_']), set([a])),
  161:     ?line [[],[a]] = to_external(from_term([[],[a]])),
  162:     ?line [[],[{a}]] = to_external(from_term([[{a}],[]])),
  163:     ?line [{[],[{a,b,[d]}]},{[{a,b}],[]}] =
  164: 	to_external(from_term([{[],[{a,b,[d]}]},{[{a,b}],[]}])),
  165: 
  166:     ?line [{[a,b],[c,d]}] = to_external(from_term([{[a,b],[c,d]}])),
  167:     ?line [{{a,b},[a,b],{{a},{b}}}] =
  168: 	to_external(from_term([{{a,b},[a,b],{{a},{b}}}])),
  169:     ?line [{{a,{[a,b]},a}},{{z,{[y,z]},z}}] =
  170: 	to_external(from_term([{{a,{[a,b,a]},a}},{{z,{[y,y,z]},z}}])),
  171:     ?line {'EXIT', {badarg, _}} = 
  172: 	(catch from_term([{m1,[{m1,f1,1},{m1,f2,2}]},{m2,[]},{m3,[a]}])),
  173:     ?line MS1 = [{m1,[{m1,f1,1},{m1,f2,2}]},{m2,[]},{m3,[{m3,f3,3}]}],
  174:     ?line eval(to_external(from_term(MS1)), MS1),
  175: 
  176:     ?line eval(to_external(from_term(a)), a),
  177:     ?line eval(to_external(from_term({a})), {a}),
  178: 
  179:     ?line eval(to_external(from_term([[a],[{b,c}]],[[atomic]])),
  180: 	       [[a],[{b,c}]]),
  181:     ?line eval(type(from_term([[a],[{b,c}]],[[atomic]])),
  182: 	       [[atomic]]),
  183: 
  184:     ?line {'EXIT', {badarg, _}} = (catch from_term([[],[],a])),
  185:     ?line {'EXIT', {badarg, _}} = (catch from_term([{[a,b],[c,{d}]}])),
  186:     ?line {'EXIT', {badarg, _}} = (catch from_term([[],[a],[{a}]])),
  187:     ?line {'EXIT', {badarg, _}} = (catch from_term([a,{a,b}])),
  188:     ?line {'EXIT', {badarg, _}} = (catch from_term([[a],[{b,c}]],[['_']])),
  189:     ?line {'EXIT', {badarg, _}} = (catch from_term([a | {a,b}])),
  190:     ?line {'EXIT', {badarg, _}} = 
  191: 	(catch from_term([{{a},b,c},{d,e,f}],[{{atom},atom,atom}])),
  192:     ?line {'EXIT', {badarg, _}} = 
  193: 	(catch from_term([{a,{b,c}} | tail], [{atom,{atom,atom}}])),
  194:     ?line {'EXIT', {badarg, _}} = (catch from_term({})),
  195:     ?line {'EXIT', {badarg, _}} = (catch from_term([{}])),
  196: 
  197:     ?line [{foo,bar},[b,a]] = 
  198:         to_external(from_term([[b,a],{foo,bar},[b,a]], [atom])),
  199:     ?line [{[atom],{atom,atom}}] = 
  200: 	type(from_term([{[], {a,b}},{[a,b],{e,f}}])),
  201:     ?line [{[atom],{atom,atom}}] = 
  202: 	type(from_term([{[], {a,b}},{[a,b],{e,f}}], [{[atom],{atom,atom}}])),
  203:     ?line [[atom]] = type(from_term([[a],[{b,c}]],[[atom]])),
  204: 
  205:     ?line {atom, atom} = type(from_term({a,b}, {atom, atom})),
  206:     ?line atom = type(from_term(a, atom)),
  207:     ?line {'EXIT', {badarg, _}} = (catch from_term({a,b},{atom})),
  208:     ?line [{{a},b,c},{{d},e,f}] = 
  209: 	to_external(from_term([{{a},b,c},{{a},b,c},{{d},e,f}],
  210: 			      [{{atom},atom,atom}])),
  211: 
  212:     %% from_external too...
  213:     ?line e = to_external(from_external(e, atom)),
  214:     ?line {e} = to_external(from_external({e}, {atom})),
  215:     ?line [e] = to_external(from_external([e], [atom])),
  216: 
  217:     %% and is_type...
  218:     ?line true = is_type(['_']),
  219:     ?line false = is_type('_'),
  220:     ?line true = is_type([['_']]),
  221:     ?line false = is_type({atom,[],atom}),
  222:     ?line false = is_type({atom,'_',atom}),
  223:     ?line true = is_type({atom,atomic,atom}),
  224:     ?line true = is_type({atom,atom}),
  225:     ?line true = is_type(atom),
  226:     ?line true = is_type([atom]),
  227:     ?line true = is_type(type),
  228: 
  229:     ok.
  230: 
  231: set_1(suite) -> [];
  232: set_1(doc) -> [""];
  233: set_1(Conf) when is_list(Conf) ->
  234:     %% set/1
  235:     ?line {'EXIT', {badarg, _}} = (catch set(a)),
  236:     ?line {'EXIT', {badarg, _}} = (catch set({a})),
  237:     ?line eval(set([]), from_term([],[atom])),
  238:     ?line eval(set([a,b,c]), from_term([a,b,c])),
  239:     ?line eval(set([a,b,a,a,b]), from_term([a,b])),
  240:     ?line eval(set([a,b,c,a,d,d,c,1]), from_term([1,a,b,c,d])),
  241:     ?line eval(set([a,b,d,a,c]), from_term([a,b,c,d])),
  242:     ?line eval(set([f,e,d,c,d]), from_term([c,d,e,f])),
  243:     ?line eval(set([h,f,d,g,g,d,c]), from_term([c,d,f,g,h])),
  244:     ?line eval(set([h,e,d,k,l]), from_term([d,e,h,k,l])),
  245:     ?line eval(set([h,e,c,k,d]), from_term([c,d,e,h,k])),
  246: 
  247:     %% set/2
  248:     ?line {'EXIT', {badarg, _}} = (catch set(a, [a])),
  249:     ?line {'EXIT', {badarg, _}} = (catch set({a}, [a])),
  250:     ?line {'EXIT', {badarg, _}} = (catch set([a], {a})),
  251:     ?line {'EXIT', {badarg, _}} = (catch set([a], a)),
  252:     ?line {'EXIT', {badarg, _}} = (catch set([a], [a,b])),
  253:     ?line {'EXIT', {badarg, _}} = (catch set([a | b],[foo])),
  254:     ?line {'EXIT', {badarg, _}} = (catch set([a | b],['_'])),
  255:     ?line {'EXIT', {badarg, _}} = (catch set([a | b],[[atom]])),
  256:     ?line {'EXIT', {badarg, _}} = (catch set([{}],[{}])),
  257:     ?line eval(set([a],['_']), from_term([a],['_'])),
  258:     ?line eval(set([], ['_']), empty_set()),
  259:     ?line eval(set([a,b,a,b],[foo]), from_term([a,b],[foo])),
  260: 
  261:     ok.
  262: 
  263: from_sets_1(suite) -> [];
  264: from_sets_1(doc) -> [""];
  265: from_sets_1(Conf) when is_list(Conf) ->
  266:     ?line E = empty_set(),
  267: 
  268:     %% unordered
  269:     ?line eval(from_sets([]), E),
  270:     ?line {'EXIT', {type_mismatch, _}} = 
  271: 	(catch from_sets([from_term([{a,b}]), 
  272:                           E,
  273:                           from_term([{a,b,c}])])),
  274:     ?line eval(from_sets([from_term([{a,b}]), E]), 
  275:                from_term([[],[{a,b}]])),
  276: 
  277:     ?line eval(from_sets([from_term({a,b},{atom,atom}), 
  278:                           from_term({b,c},{atom,atom})]),
  279: 	       relation([{a,b}, {b,c}])),
  280:     ?line {'EXIT', {type_mismatch, _}} = 
  281: 	(catch from_sets([from_term({a,b},{atom,atom}), 
  282: 			  from_term({a,b,c},{atom,atom,atom})])),
  283:     ?line {'EXIT', {badarg, _}} = (catch from_sets(foo)),
  284:     ?line eval(from_sets([E]), from_term([[]])),
  285:     ?line eval(from_sets([E,E]), from_term([[]])),
  286:     ?line eval(from_sets([E,set([a])]), from_term([[],[a]])),
  287:     ?line {'EXIT', {badarg, _}} = (catch from_sets([E,{a}])),
  288:     ?line {'EXIT', {type_mismatch, _}} = 
  289: 	(catch from_sets([E,from_term({a}),E])),
  290:     ?line {'EXIT', {type_mismatch, _}} = (catch from_sets([from_term({a}),E])),
  291: 
  292:     %% ordered
  293:     ?line O = {from_term(a,atom), from_term({b}, {atom}), set([c,d])},
  294:     ?line eval(from_sets(O), from_term({a,{b},[c,d]}, {atom,{atom},[atom]})),
  295:     ?line {'EXIT', {badarg, _}} = (catch from_sets([a,b])),
  296:     ?line {'EXIT', {badarg, _}} = (catch from_sets({a,b})),
  297:     ?line eval(from_sets({from_term({a}),E}), from_term({{a},[]})),
  298:     ok.
  299: 
  300: relation_1(suite) -> [];
  301: relation_1(doc) -> [""];
  302: relation_1(Conf) when is_list(Conf) ->
  303:     %% relation/1
  304:     ?line eval(relation([]), from_term([], [{atom,atom}])),
  305:     ?line eval(from_term([{a}]), relation([{a}])),
  306:     ?line {'EXIT', {badarg, _}} = (catch relation(a)),
  307:     ?line {'EXIT', {badarg, _}} = (catch relation([{a} | a])),
  308:     ?line {'EXIT', {badarg, _}} = (catch relation([{}])),
  309:     ?line {'EXIT', {badarg, _}} = (catch relation([],0)),
  310:     ?line {'EXIT', {badarg, _}} = (catch relation([{a}],a)),
  311: 
  312:     %% relation/2
  313:     ?line eval(relation([{a},{b}], 1), from_term([{a},{b}])),
  314:     ?line eval(relation([{1,a},{2,b},{1,a}], [{x,y}]),
  315: 	       from_term([{1,a},{2,b}], [{x,y}])),
  316:     ?line eval(relation([{[1,2],a},{[2,1],b},{[2,1],a}], [{[x],y}]),
  317: 	       from_term([{[1,2],a},{[1,2],b}], [{[x],y}])),
  318:     ?line {'EXIT', {badarg, _}} = (catch relation([{1,a},{2,b}], [{[x],y}])),
  319:     ?line {'EXIT', {badarg, _}} = (catch relation([{1,a},{1,a,b}], [{x,y}])),
  320:     ?line {'EXIT', {badarg, _}} = (catch relation([{a}], 2)),
  321:     ?line {'EXIT', {badarg, _}} = (catch relation([{a},{b},{c,d}], 1)),
  322:     ?line eval(relation([{{a},[{foo,bar}]}], ['_']), 
  323: 	       from_term([{{a},[{foo,bar}]}], ['_'])),
  324:     ?line eval(relation([], ['_']), from_term([], ['_'])),
  325:     ?line {'EXIT', {badarg, _}} = (catch relation([[a]],['_'])),
  326:     ?line eval(relation([{[a,b,a]}], [{[atom]}]), from_term([{[a,b,a]}])),
  327:     ?line eval(relation([{[a,b,a],[[d,e,d]]}], [{[atom],[[atom]]}]), 
  328: 	       from_term([{[a,b,a],[[d,e,d]]}])),
  329:     ?line eval(relation([{[a,b,a],[[d,e,d]]}], [{atom,[[atom]]}]), 
  330: 	       from_term([{[a,b,a],[[d,e,d]]}], [{atom,[[atom]]}])),
  331:     ok.
  332: 
  333: a_function_1(suite) -> [];
  334: a_function_1(doc) -> [""];
  335: a_function_1(Conf) when is_list(Conf) ->
  336:     %% a_function/1
  337:     ?line eval(a_function([]), from_term([], [{atom,atom}])),
  338:     ?line eval(a_function([{a,b},{a,b},{b,c}]), from_term([{a,b},{b,c}])),
  339:     ?line {'EXIT', {badarg, _}} = (catch a_function([{a}])),
  340:     ?line {'EXIT', {badarg, _}} = (catch a_function([{a},{b},{c,d}])),
  341:     ?line {'EXIT', {badarg, _}} = (catch a_function(a)),
  342:     ?line {'EXIT', {badarg, _}} = (catch a_function([{a,b} | a])),
  343:     ?line {'EXIT', {bad_function, _}} = 
  344: 	(catch a_function([{a,b},{b,c},{a,c}])),
  345:     F = 0.0, I = round(F),
  346:     if
  347:         F == I -> % term ordering
  348:             ?line {'EXIT', {bad_function, _}} = 
  349:                 (catch a_function([{I,a},{F,b}])),
  350:             ?line {'EXIT', {bad_function, _}} = 
  351:                  (catch a_function([{[I],a},{[F],b}],[{[a],b}]));
  352:         true -> 
  353:             ?line 2 = no_elements(a_function([{I,a},{F,b}])),
  354:             ?line 2 = no_elements(a_function([{[I],a},{[F],b}],[{[a],b}]))
  355:     end,
  356: 
  357:     %% a_function/2
  358:     FT = [{atom,atom}],
  359:     ?line eval(a_function([], FT), from_term([], FT)),
  360:     ?line eval(a_function([{a,b},{b,c},{b,c}], FT), 
  361: 	       from_term([{a,b},{b,c}], FT)),
  362:     ?line {'EXIT', {badarg, _}} = (catch a_function([{a,b}], [{a}])),
  363:     ?line {'EXIT', {badarg, _}} = (catch a_function([{a,b}], [{a,[b,c]}])),
  364:     ?line {'EXIT', {badarg, _}} = (catch a_function([{a}], FT)),
  365:     ?line {'EXIT', {badarg, _}} = (catch a_function([{a},{b},{c,d}], FT)),
  366:     ?line {'EXIT', {badarg, _}} = (catch a_function(a, FT)),
  367:     ?line {'EXIT', {badarg, _}} = (catch a_function([{a,b} | a], FT)),
  368:     ?line eval(a_function([{{a},[{foo,bar}]}], ['_']),
  369: 	       from_term([{{a},[{foo,bar}]}], ['_'])),
  370:     ?line eval(a_function([], ['_']), from_term([], ['_'])),
  371:     ?line {'EXIT', {badarg, _}} = (catch a_function([[a]],['_'])),
  372:     ?line {'EXIT', {bad_function, _}} = 
  373: 	(catch a_function([{a,b},{b,c},{a,c}], FT)),
  374:     ?line eval(a_function([{a,[a]},{a,[a,a]}], [{atom,[atom]}]),
  375: 	       from_term([{a,[a]}])),
  376:     ?line eval(a_function([{[b,a],c},{[a,b],c}], [{[atom],atom}]),
  377: 	       from_term([{[a,b],c}])),
  378:     ok.
  379: 
  380: family_1(suite) -> [];
  381: family_1(doc) -> [""];
  382: family_1(Conf) when is_list(Conf) ->
  383:     %% family/1
  384:     ?line eval(family([]), from_term([],[{atom,[atom]}])),
  385:     ?line {'EXIT', {badarg, _}} = (catch family(a)),
  386:     ?line {'EXIT', {badarg, _}} = (catch family([a])),
  387:     ?line {'EXIT', {badarg, _}} = (catch family([{a,b}])),
  388:     ?line {'EXIT', {badarg, _}} = (catch family([{a,[]} | a])),
  389:     ?line {'EXIT', {badarg, _}} = (catch family([{a,[a|b]}])),
  390:     ?line {'EXIT', {bad_function, _}} = 
  391:         (catch family([{a,[a]},{a,[]}])),
  392:     ?line {'EXIT', {bad_function, _}} = 
  393: 	(catch family([{a,[]},{b,[]},{a,[a]}])),
  394:     F = 0.0, I = round(F),
  395:     if
  396:         F == I -> % term ordering
  397:             ?line {'EXIT', {bad_function, _}} = 
  398:                 (catch family([{I,[a]},{F,[b]}])),
  399:             ?line true = (1 =:= no_elements(family([{a,[I]},{a,[F]}])));
  400:         true -> 
  401:             ?line {'EXIT', {bad_function, _}} = 
  402:                 (catch family([{a,[I]},{a,[F]}]))
  403:     end,
  404:     ?line eval(family([{a,[]},{b,[b]},{a,[]}]), from_term([{a,[]},{b,[b]}])),
  405:     ?line eval(to_external(family([{b,[{hej,san},tjo]},{a,[]}])),
  406:                [{a,[]},{b,[tjo,{hej,san}]}]),
  407:     ?line eval(family([{a,[a]},{a,[a,a]}]), family([{a,[a]}])),
  408: 
  409:     %% family/2
  410:     FT = [{a,[a]}],
  411:     ?line eval(family([], FT), from_term([],FT)),
  412:     ?line {'EXIT', {badarg, _}} = (catch family(a,FT)),
  413:     ?line {'EXIT', {badarg, _}} = (catch family([a],FT)),
  414:     ?line {'EXIT', {badarg, _}} = (catch family([{a,b}],FT)),
  415:     ?line {'EXIT', {badarg, _}} = (catch family([{a,[]} | a],FT)),
  416:     ?line {'EXIT', {badarg, _}} = (catch family([{a,[a|b]}], FT)),
  417:     ?line {'EXIT', {bad_function, _}} = 
  418:         (catch family([{a,[a]},{a,[]}], FT)),
  419:     ?line {'EXIT', {bad_function, _}} = 
  420: 	(catch family([{a,[]},{b,[]},{a,[a]}], FT)),
  421:     ?line eval(family([{a,[]},{b,[b,b]},{a,[]}], FT), 
  422: 	       from_term([{a,[]},{b,[b]}], FT)),
  423:     ?line eval(to_external(family([{b,[{hej,san},tjo]},{a,[]}], FT)),
  424:                [{a,[]},{b,[tjo,{hej,san}]}]),
  425: 
  426:     ?line eval(family([{{a},[{foo,bar}]}], ['_']),
  427: 	       from_term([{{a},[{foo,bar}]}], ['_'])),
  428:     ?line eval(family([], ['_']), from_term([], ['_'])),
  429:     ?line {'EXIT', {badarg, _}} = (catch family([[a]],['_'])),
  430:     ?line {'EXIT', {badarg, _}} = (catch family([{a,b}],['_'])),
  431:     ?line {'EXIT', {badarg, _}} = 
  432: 	(catch family([{a,[foo]}], [{atom,atom}])),
  433:     ?line eval(family([{{a},[{foo,bar}]}], [{{dt},[{r1,t2}]}]),
  434: 	       from_term([{{a},[{foo,bar}]}], [{{dt},[{r1,t2}]}])),
  435:     ?line eval(family([{a,[a]},{a,[a,a]}],[{atom,[atom]}]),
  436: 	       family([{a,[a]}])),
  437:     ?line eval(family([{[a,b],[a]},{[b,a],[a,a]}],[{[atom],[atom]}]),
  438: 	       from_term([{[a,b],[a]},{[b,a],[a,a]}])),
  439:     ok.
  440: 
  441: projection(suite) -> [];
  442: projection(doc) -> [""];
  443: projection(Conf) when is_list(Conf) ->
  444:     ?line E = empty_set(),
  445:     ?line ER = relation([]),
  446: 
  447:     %% set of ordered sets
  448:     ?line S1 = relation([{a,1},{b,2},{b,22},{c,0}]),
  449:     ?line S2 = relation([{a,1},{a,2},{a,3},{b,4},{b,5},{b,6}]),
  450: 
  451:     ?line eval(projection(1, E), E),
  452:     ?line eval(projection(1, ER), set([])),
  453:     ?line eval(projection(1, relation([{a,1}])), set([a])),
  454:     ?line eval(projection(1, S1), set([a,b,c])),
  455:     ?line eval(projection(1, S2), set([a,b])),
  456:     ?line eval(projection(2, S1), set([0,1,2,22])),
  457:     ?line eval(projection(2, relation([{1,a},{2,a},{3,b}])), set([a,b])),
  458:     ?line eval(projection(1, relation([{a},{b},{c}])), set([a,b,c])),
  459: 
  460:     Fun1 = {external, fun({A,B,C}) -> {A,{B,C}} end},
  461:     ?line eval(projection(Fun1, E), E),
  462:     %% No check here:
  463:     ?line eval(projection(3, projection(Fun1, empty_set())), E),
  464:     ?line E2 = relation([], 3),
  465:     ?line eval(projection(Fun1, E2), from_term([], [{atom,{atom,atom}}])),
  466: 
  467:     Fun2 = {external, fun({A,_B}) -> {A} end},
  468:     ?line eval(projection(Fun2, ER), from_term([], [{atom}])),
  469:     ?line eval(projection(Fun2, relation([{a,1}])), relation([{a}])),
  470:     ?line eval(projection(Fun2, relation([{a,1},{b,3},{a,2}])), 
  471:                relation([{a},{b}])),
  472:     Fun3 = {external, fun({A,_B,C}) -> {C,{A},C} end}, 
  473:     ?line eval(projection(Fun3, relation([{a,1,x},{b,3,y},{a,2,z}])),
  474:                from_term([{x,{a},x},{y,{b},y},{z,{a},z}])),
  475:     Fun4 = {external, fun(A={B,_C,_D}) -> {B, A} end},
  476:     ?line eval(projection(Fun4, relation([{a,1,x},{b,3,y},{a,2,z}])),
  477:                from_term([{a,{a,1,x}},{b,{b,3,y}},{a,{a,2,z}}])),
  478: 
  479:     ?line eval(projection({external, fun({A,B,_C,D}) -> {A,B,A,D} end},
  480: 			  relation([{1,1,1,2}, {1,1,3,1}])),
  481:                relation([{1,1,1,1}, {1,1,1,2}])),
  482: 
  483:     ?line {'EXIT', {badarg, _}} = (catch projection(1, set([]))),
  484:     ?line {'EXIT', {function_clause, _}} = 
  485: 	(catch projection({external, fun({A}) -> A end}, S1)),
  486:     ?line {'EXIT', {badarg, _}} = 
  487: 	(catch projection({external, fun({A,_}) -> {A,0} end}, 
  488: 			  from_term([{1,a}]))),
  489: 
  490:     %% {} is not an ordered set
  491:     ?line {'EXIT', {badarg, _}} = 
  492:         (catch projection({external, fun(_) -> {} end}, ER)),
  493:     ?line {'EXIT', {badarg, _}} = 
  494:         (catch projection({external, fun(_) -> {{}} end}, ER)),
  495:     ?line eval(projection({external, fun({T,_}) -> T end}, 
  496: 			  relation([{{},a},{{},b}])),
  497: 	       set([{}])),
  498:     ?line eval(projection({external, fun({T}) -> T end}, relation([{{}}])),
  499: 	       set([{}])),
  500: 
  501:     ?line eval(projection({external, fun(A) -> {A} end}, 
  502: 			  relation([{1,a},{2,b}])), 
  503: 	       from_term([{{1,a}},{{2,b}}])),
  504:     ?line eval(projection({external, fun({A,B}) -> {B,A} end}, 
  505: 			  relation([{1,a},{2,b}])),
  506: 	       relation([{a,1},{b,2}])),
  507:     ?line eval(projection({external, fun(X=Y=A) -> {X,Y,A} end}, set([a,b,c])),
  508: 	       relation([{a,a,a},{b,b,b},{c,c,c}])),
  509: 
  510:     ?line eval(projection({external, fun({A,{_},B}) -> {A,B} end}, 
  511: 			  from_term([{a,{a},b},{a,{b},c}])),
  512:                relation([{a,b},{a,c}])),
  513:     ?line eval(projection({external, fun({A,_,B}) -> {A,B} end},
  514: 			  relation([{a,{},b},{a,{},c}])),
  515:                relation([{a,b},{a,c}])),
  516:     Fun5 = fun(S) -> from_term({to_external(S),0}, {type(S),atom}) end,
  517:     ?line eval(projection(Fun5, E), E),
  518:     ?line eval(projection(Fun5, set([a,b])), from_term([{a,0},{b,0}])),
  519:     ?line eval(projection(Fun5, relation([{a,1},{b,2}])),
  520: 	       from_term([{{a,1},0},{{b,2},0}])),
  521:     ?line eval(projection(Fun5, from_term([[a],[b]])),
  522: 	       from_term([{[a],0},{[b],0}])),
  523: 
  524:     F = 0.0, I = round(F),
  525:     ?line FR = relation([{I},{F}]),
  526:     if
  527:         F == I -> % term ordering
  528:             true = (no_elements(projection(1, FR)) =:= 1);
  529:         true -> 
  530:             eval(projection(1, FR), set([I,F]))
  531:     end,
  532: 
  533:     %% set of sets
  534:     ?line {'EXIT', {badarg, _}} = 
  535:         (catch projection({external, fun(X) -> X end}, 
  536: 			  from_term([], [[atom]]))),
  537:     ?line {'EXIT', {badarg, _}} = 
  538:         (catch projection({external, fun(X) -> X end}, from_term([[a]]))),
  539:     ?line eval(projection(fun sofs:union/1,
  540: 			  from_term([[[1,2],[2,3]], [[a,b],[b,c]]])),
  541:                from_term([[1,2,3], [a,b,c]])),
  542:     ?line eval(projection(fun(_) -> from_term([a]) end, 
  543: 			  from_term([[b]], [[a]])),
  544:                from_term([[a]])),
  545:     ?line eval(projection(fun(_) -> from_term([a]) end, 
  546: 			  from_term([[1,2],[3,4]])),
  547:                from_term([[a]])),
  548:     Fun10 = fun(S) ->
  549:                    %% Cheating a lot...
  550:                    case to_external(S) of
  551:                        [1] -> from_term({1,1});
  552:                        _ -> S
  553:                    end
  554:            end,
  555:     ?line eval(projection(Fun10, from_term([[1]])), from_term([{1,1}])),
  556:     ?line eval(projection(fun(_) -> from_term({a}) end, from_term([[a]])),
  557: 	       from_term([{a}])),
  558:     ?line {'EXIT', {badarg, _}} = 
  559: 	(catch projection(fun(_) -> {a} end, from_term([[a]]))),
  560: 
  561:     ok.
  562: 
  563: substitution(suite) -> [];
  564: substitution(doc) -> [""];
  565: substitution(Conf) when is_list(Conf) ->
  566:     ?line E = empty_set(),
  567:     ?line ER = relation([]),
  568: 
  569:     %% set of ordered sets
  570:     ?line S1 = relation([{a,1},{b,2},{b,22},{c,0}]),
  571:     ?line S2 = relation([{a,1},{a,2},{a,3},{b,4},{b,5},{b,6}]),
  572: 
  573:     ?line eval(substitution(1, E), E),
  574:     %% No check here:
  575:     Fun0 = {external, fun({A,B,C}) -> {A,{B,C}} end},
  576:     ?line eval(substitution(3, substitution(Fun0, empty_set())), E),
  577:     ?line eval(substitution(1, ER), from_term([],[{{atom,atom},atom}])),
  578:     ?line eval(substitution(1, relation([{a,1}])), from_term([{{a,1},a}])),
  579:     ?line eval(substitution(1, S1), 
  580:                from_term([{{a,1},a},{{b,2},b},{{b,22},b},{{c,0},c}])),
  581:     ?line eval(substitution(1, S2), 
  582:                from_term([{{a,1},a},{{a,2},a},{{a,3},a},{{b,4},b},
  583:                           {{b,5},b},{{b,6},b}])),
  584:     ?line eval(substitution(2, S1), 
  585:                from_term([{{a,1},1},{{b,2},2},{{b,22},22},{{c,0},0}])),
  586:     
  587:     Fun1 = fun({A,_B}) -> {A} end, 
  588:     XFun1 = {external, Fun1},
  589:     ?line eval(substitution(XFun1, E), E),
  590:     ?line eval(substitution(Fun1, E), E),
  591:     ?line eval(substitution(XFun1, ER), from_term([], [{{atom,atom},{atom}}])),
  592:     ?line eval(substitution(XFun1, relation([{a,1}])), 
  593: 	       from_term([{{a,1},{a}}])),
  594:     ?line eval(substitution(XFun1, relation([{a,1},{b,3},{a,2}])), 
  595:                from_term([{{a,1},{a}},{{a,2},{a}},{{b,3},{b}}])),
  596:     ?line eval(substitution({external, fun({A,_B,C}) -> {C,A,C} end}, 
  597: 			    relation([{a,1,x},{b,3,y},{a,2,z}])),
  598:                from_term([{{a,1,x},{x,a,x}},{{a,2,z},{z,a,z}},
  599:                           {{b,3,y},{y,b,y}}])),
  600:     Fun2 = fun(S) -> {A,_B} = to_external(S), from_term({A}) end,
  601:     ?line eval(substitution(Fun2, ER), E),
  602:     ?line eval(substitution(Fun2, relation([{a,1}])), 
  603: 	       from_term([{{a,1},{a}}])),
  604:     Fun3 = fun(S) -> from_term({to_external(S),0}, {type(S),atom}) end,
  605:     ?line eval(substitution(Fun3, E), E),
  606:     ?line eval(substitution(Fun3, set([a,b])),
  607: 	       from_term([{a,{a,0}},{b,{b,0}}])),
  608:     ?line eval(substitution(Fun3, relation([{a,1},{b,2}])),
  609: 	       from_term([{{a,1},{{a,1},0}},{{b,2},{{b,2},0}}])),
  610:     ?line eval(substitution(Fun3, from_term([[a],[b]])),
  611: 	       from_term([{[a],{[a],0}},{[b],{[b],0}}])),
  612:     
  613:     ?line eval(substitution(fun(_) -> E end, from_term([[a],[b]])),
  614: 	       from_term([{[a],[]},{[b],[]}])),
  615: 
  616:     ?line {'EXIT', {badarg, _}} = (catch substitution(1, set([]))),
  617:     ?line eval(substitution(1, ER), from_term([], [{{atom,atom},atom}])),
  618:     ?line {'EXIT', {function_clause, _}} = 
  619: 	(catch substitution({external, fun({A,_}) -> A end}, set([]))),
  620:     ?line {'EXIT', {badarg, _}} = 
  621: 	(catch substitution({external, fun({A,_}) -> {A,0} end}, 
  622: 			    from_term([{1,a}]))),
  623: 
  624:     %% set of sets
  625:     ?line {'EXIT', {badarg, _}} = 
  626:         (catch substitution({external, fun(X) -> X end}, 
  627: 			    from_term([], [[atom]]))),
  628:     ?line {'EXIT', {badarg, _}} = 
  629:         (catch substitution({external, fun(X) -> X end}, from_term([[a]]))),
  630:     ?line eval(substitution(fun(X) -> X end, from_term([], [[atom]])), E),
  631:     ?line eval(substitution(fun sofs:union/1,
  632:                             from_term([[[1,2],[2,3]], [[a,b],[b,c]]])),
  633:                from_term([{[[1,2],[2,3]],[1,2,3]}, {[[a,b],[b,c]],[a,b,c]}])),
  634:     ?line eval(substitution(fun(_) -> from_term([a]) end, 
  635: 			    from_term([[b]], [[a]])),
  636:                from_term([{[b],[a]}], [{[a],[atom]}])),
  637:     ?line eval(substitution(fun(_) -> from_term([a]) end, 
  638: 			    from_term([[1,2],[3,4]])),
  639:                from_term([{[1,2],[a]},{[3,4],[a]}])),
  640:     Fun10 = fun(S) ->
  641:                    %% Cheating a lot...
  642:                    case to_external(S) of
  643:                        [1] -> from_term({1,1});
  644:                        _ -> S
  645:                    end
  646:            end,
  647:     ?line eval(substitution(Fun10, from_term([[1]])), 
  648: 	       from_term([{[1],{1,1}}])),
  649:     ?line {'EXIT', {type_mismatch, _}} =
  650:         (catch substitution(Fun10, from_term([[1],[2]]))),
  651:     ?line {'EXIT', {type_mismatch, _}} =
  652:         (catch substitution(Fun10, from_term([[1],[0]]))),
  653: 
  654:     ?line eval(substitution(fun(_) -> from_term({a}) end, from_term([[a]])),
  655: 	       from_term([{[a],{a}}])),
  656:     ?line {'EXIT', {badarg, _}} = 
  657: 	(catch substitution(fun(_) -> {a} end, from_term([[a]]))),
  658: 
  659:     ok.
  660: 
  661: restriction(suite) -> [];
  662: restriction(doc) -> [""];
  663: restriction(Conf) when is_list(Conf) ->
  664:     ?line E = empty_set(),
  665:     ?line ER = relation([], 2),
  666: 
  667:     %% set of ordered sets
  668:     ?line S1 = relation([{a,1},{b,2},{b,22},{c,0}]),
  669:     ?line eval(restriction(S1, set([a,b])), 
  670:                relation([{a,1},{b,2},{b,22}])),
  671:     ?line eval(restriction(2, S1, set([1,2])),  
  672:                relation([{a,1},{b,2}])),
  673:     ?line eval(restriction(S1, set([a,b,c])), S1),
  674:     ?line eval(restriction(1, S1, set([0,1,d,e])), ER),
  675:     ?line eval(restriction(1, S1, E), ER),
  676:     ?line eval(restriction({external, fun({_A,B,C}) -> {B,C} end}, 
  677:                            relation([{a,aa,1},{b,bb,2},{c,cc,3}]),
  678:                            relation([{bb,2},{cc,3}])),
  679:                relation([{b,bb,2},{c,cc,3}])),
  680:     R1 = relation([],[{a,b}]),
  681:     ?line eval(restriction(2, R1,sofs:set([],[b])), R1),
  682:     Id = fun(X) -> X end,
  683:     XId = {external, Id},
  684:     ?line eval(restriction(XId, relation([{a,b}]), E), ER),
  685:     ?line eval(restriction(XId, E, relation([{b,d}])), E),
  686:     Fun1 = fun(S) -> {_A,B,C} = to_external(S), from_term({B,C}) end,
  687:     ?line eval(restriction(Fun1,
  688:                            relation([{a,aa,1},{b,bb,2},{c,cc,3}]),
  689:                            relation([{bb,2},{cc,3}])),
  690:                relation([{b,bb,2},{c,cc,3}])),
  691:     ?line eval(restriction({external, fun({_,{A},B}) -> {A,B} end},
  692:                            from_term([{a,{aa},1},{b,{bb},2},{c,{cc},3}]), 
  693:                            from_term([{bb,2},{cc,3}])),
  694:                from_term([{b,{bb},2},{c,{cc},3}])),
  695:     S5 = relation([{1,a},{2,b},{3,c}]),
  696:     ?line eval(restriction(2, S5, set([b,c])), relation([{2,b},{3,c}])),
  697:     S4 = relation([{a,1},{b,2},{b,27},{c,0}]),
  698:     ?line eval(restriction(2, S4, E), ER),
  699:     S6 = relation([{1,a},{2,c},{3,b}]),
  700:     ?line eval(restriction(2, S6, set([d,e])), ER),
  701:     ?line eval(restriction(2, 
  702: 			   relation([{1,d},{2,c},{3,b},{4,a},{5,e}]), 
  703: 			   set([c])),
  704: 	       relation([{2,c}])),
  705:     ?line eval(restriction(XId, 
  706: 			   relation([{1,a},{3,b},{4,c},{4,d}]), 
  707: 			   relation([{2,a},{2,c},{4,c}])),
  708: 	       relation([{4,c}])),
  709:     ?line eval(restriction(2, relation([{a,b}]), E), ER),
  710:     ?line eval(restriction(2, E, relation([{b,d}])), E),
  711:     ?line eval(restriction(2, relation([{b,d}]), E), ER),
  712:     ?line eval(restriction(XId, E, set([a])), E),
  713:     ?line eval(restriction(1, S1, E), ER),
  714:     ?line {'EXIT', {badarg, _}} =
  715: 	(catch restriction(3, relation([{a,b}]), E)),
  716:     ?line {'EXIT', {badarg, _}} =
  717: 	(catch restriction(3, relation([{a,b}]), relation([{b,d}]))),
  718:     ?line {'EXIT', {badarg, _}} =
  719: 	(catch restriction(3, relation([{a,b}]), set([{b,d}]))),
  720:     ?line {'EXIT', {type_mismatch, _}} =
  721: 	(catch restriction(2, relation([{a,b}]), relation([{b,d}]))),
  722:     ?line {'EXIT', {type_mismatch, _}} =
  723: 	(catch restriction({external, fun({A,_B}) -> A end}, 
  724: 			   relation([{a,b}]), relation([{b,d}]))),
  725:     ?line {'EXIT', {badarg, _}} = 
  726: 	(catch restriction({external, fun({A,_}) -> {A,0} end}, 
  727: 			   from_term([{1,a}]),
  728: 			   from_term([{1,0}]))),
  729:     ?line eval(restriction(2, relation([{a,d},{b,e},{c,b},{d,c}]), set([b,d])),
  730: 	       relation([{a,d},{c,b}])),
  731:     ?line {'EXIT', {function_clause, _}} =
  732: 	(catch restriction({external, fun({A,_B}) -> A end}, set([]), E)),
  733: 
  734:     Fun3 = fun(S) -> from_term({to_external(S),0}, {type(S),atom}) end,
  735:     ?line eval(restriction(Fun3, set([1,2]), from_term([{1,0}])),
  736: 	       from_term([1])),
  737: 
  738:     %% set of sets
  739:     ?line {'EXIT', {badarg, _}} = 
  740:         (catch restriction({external, fun(X) -> X end}, 
  741: 			   from_term([], [[atom]]), set([a]))),
  742:     S2 = from_term([], [[atom]]),
  743:     ?line eval(restriction(Id, S2, E), E),
  744:     S3 = from_term([[a],[b]], [[atom]]),
  745:     ?line eval(restriction(Id, S3, E), E),
  746:     ?line eval(restriction(Id, from_term([], [[atom]]), set([a])),
  747: 	       from_term([], [[atom]])),
  748:     ?line eval(restriction(fun sofs:union/1,
  749:                            from_term([[[a],[b]], [[b],[c]], 
  750:                                       [[], [a,b]], [[1],[2]]]), 
  751:                            from_term([[a,b],[1,2,3],[b,c]])),
  752:                from_term([[[],[a,b]], [[a],[b]],[[b],[c]]])),
  753:     ?line eval(restriction(fun(_) -> from_term([a]) end, 
  754:                            from_term([], [[atom]]),
  755:                            from_term([], [[a]])),
  756:                from_term([], [[atom]])),
  757:     ?line {'EXIT', {type_mismatch, _}} =
  758:         (catch restriction(fun(_) -> from_term([a]) end, 
  759:                            from_term([[1,2],[3,4]]),
  760:                            from_term([], [atom]))),
  761:     Fun10 = fun(S) ->
  762:                    %% Cheating a lot...
  763:                    case to_external(S) of
  764:                        [1] -> from_term({1,1});
  765:                        _ -> S
  766:                    end
  767:            end,
  768:     ?line {'EXIT', {type_mismatch, _}} =
  769:         (catch restriction(Fun10, from_term([[1]]), from_term([], [[atom]]))),
  770:     ?line {'EXIT', {type_mismatch, _}} = 
  771:         (catch restriction(fun(_) -> from_term({a}) end, 
  772:                            from_term([[a]]),
  773:                            from_term([], [atom]))),
  774:     ?line {'EXIT', {badarg, _}} = 
  775:         (catch restriction(fun(_) -> {a} end, 
  776:                            from_term([[a]]),
  777:                            from_term([], [atom]))),
  778:     ok.
  779: 
  780: drestriction(suite) -> [];
  781: drestriction(doc) -> [""];
  782: drestriction(Conf) when is_list(Conf) ->
  783:     ?line E = empty_set(),
  784:     ?line ER = relation([], 2),
  785: 
  786:     %% set of ordered sets
  787:     ?line S1 = relation([{a,1},{b,2},{b,22},{c,0}]),
  788:     ?line eval(drestriction(S1, set([a,b])), relation([{c,0}])),
  789:     ?line eval(drestriction(2, S1, set([1,2])),  
  790:                relation([{b,22},{c,0}])),
  791:     ?line eval(drestriction(S1, set([a,b,c])), ER),
  792:     ?line eval(drestriction(2, ER, set([a,b])), ER),
  793:     ?line eval(drestriction(1, S1, set([0,1,d,e])), S1),
  794:     ?line eval(drestriction(1, S1, E), S1),
  795:     ?line eval(drestriction({external, fun({_A,B,C}) -> {B,C} end}, 
  796:                             relation([{a,aa,1},{b,bb,2},{c,cc,3}]),
  797:                             relation([{bb,2},{cc,3}])),
  798:                relation([{a,aa,1}])),
  799:     Id = fun(X) -> X end,
  800:     XId = {external, Id},
  801:     ?line eval(drestriction(XId, relation([{a,b}]), E), relation([{a,b}])),
  802:     ?line eval(drestriction(XId, E, relation([{b,d}])), E),
  803:     Fun1 = fun(S) -> {_A,B,C} = to_external(S), from_term({B,C}) end,
  804:     ?line eval(drestriction(Fun1,
  805:                             relation([{a,aa,1},{b,bb,2},{c,cc,3}]),
  806:                             relation([{bb,2},{cc,3}])),
  807:                relation([{a,aa,1}])),
  808:     ?line eval(drestriction({external, fun({_,{A},B}) -> {A,B} end},
  809:                             from_term([{a,{aa},1},{b,{bb},2},{c,{cc},3}]), 
  810:                             from_term([{bb,2},{cc,3}])),
  811:                from_term([{a,{aa},1}])),
  812:     S5 = relation([{1,a},{2,b},{3,c}]),
  813:     ?line eval(drestriction(2, S5, set([b,c])), relation([{1,a}])),
  814:     S4 = relation([{a,1},{b,2},{b,27},{c,0}]),
  815:     ?line eval(drestriction(2, S4, set([])), S4),
  816:     S6 = relation([{1,a},{2,c},{3,b}]),
  817:     ?line eval(drestriction(2, S6, set([d,e])), S6),
  818:     ?line eval(drestriction(2, 
  819: 			    relation([{1,d},{2,c},{3,b},{4,a},{5,e}]), 
  820: 			    set([c])),
  821: 	       relation([{1,d},{3,b},{4,a},{5,e}])),
  822:     ?line eval(drestriction(XId, 
  823: 			    relation([{1,a},{3,b},{4,c},{4,d}]), 
  824: 			    relation([{2,a},{2,c},{4,c}])),
  825: 	       relation([{1,a},{3,b},{4,d}])),
  826:     ?line eval(drestriction(2, relation([{a,b}]), E), relation([{a,b}])),
  827:     ?line eval(drestriction(2, E, relation([{b,d}])), E),
  828:     ?line eval(drestriction(2, relation([{b,d}]), E), relation([{b,d}])),
  829:     ?line eval(drestriction(XId, E, set([a])), E),
  830:     ?line eval(drestriction(1, S1, E), S1),
  831:     ?line {'EXIT', {badarg, _}} =
  832: 	(catch drestriction(3, relation([{a,b}]), E)),
  833:     ?line {'EXIT', {badarg, _}} =
  834: 	(catch drestriction(3, relation([{a,b}]), relation([{b,d}]))),
  835:     ?line {'EXIT', {badarg, _}} =
  836: 	(catch drestriction(3, relation([{a,b}]), set([{b,d}]))),
  837:     ?line {'EXIT', {type_mismatch, _}} =
  838: 	(catch drestriction(2, relation([{a,b}]), relation([{b,d}]))),
  839:     ?line {'EXIT', {type_mismatch, _}} =
  840: 	(catch drestriction({external, fun({A,_B}) -> A end}, 
  841: 			    relation([{a,b}]), relation([{b,d}]))),
  842:     ?line {'EXIT', {badarg, _}} = 
  843: 	(catch drestriction({external, fun({A,_}) -> {A,0} end}, 
  844: 			    from_term([{1,a}]),
  845: 			    from_term([{1,0}]))),
  846:     ?line eval(drestriction(2, relation([{a,d},{b,e},{c,b},{d,c}]), set([b,d])),
  847: 	       relation([{b,e},{d,c}])),
  848:     ?line {'EXIT', {function_clause, _}} =
  849: 	(catch drestriction({external, fun({A,_B}) -> A end}, set([]), E)),
  850: 
  851:     Fun3 = fun(S) -> from_term({to_external(S),0}, {type(S),atom}) end,
  852:     ?line eval(drestriction(Fun3, set([1,2]), from_term([{1,0}])),
  853: 	       from_term([2])),
  854: 
  855:     %% set of sets
  856:     ?line {'EXIT', {badarg, _}} = 
  857:         (catch drestriction({external, fun(X) -> X end}, 
  858: 			    from_term([], [[atom]]), set([a]))),
  859:     S2 = from_term([], [[atom]]),
  860:     ?line eval(drestriction(Id, S2, E), S2),
  861:     S3 = from_term([[a],[b]], [[atom]]),
  862:     ?line eval(drestriction(Id, S3, E), S3),
  863:     ?line eval(drestriction(Id, from_term([], [[atom]]), set([a])),
  864: 	       from_term([], [[atom]])),
  865:     ?line eval(drestriction(fun sofs:union/1,
  866:                             from_term([[[a],[b]], [[b],[c]], 
  867:                                        [[], [a,b]], [[1],[2]]]), 
  868:                             from_term([[a,b],[1,2,3],[b,c]])),
  869:                from_term([[[1],[2]]])),
  870:     ?line eval(drestriction(fun(_) -> from_term([a]) end, 
  871:                             from_term([], [[atom]]),
  872:                             from_term([], [[a]])),
  873:                from_term([], [[atom]])),
  874:     ?line {'EXIT', {type_mismatch, _}} =
  875:         (catch drestriction(fun(_) -> from_term([a]) end, 
  876:                             from_term([[1,2],[3,4]]),
  877:                             from_term([], [atom]))),
  878:     Fun10 = fun(S) ->
  879:                    %% Cheating a lot...
  880:                    case to_external(S) of
  881:                        [1] -> from_term({1,1});
  882:                        _ -> S
  883:                    end
  884:            end,
  885:     ?line {'EXIT', {type_mismatch, _}} =
  886:         (catch drestriction(Fun10, from_term([[1]]), from_term([], [[atom]]))),
  887:     ?line {'EXIT', {type_mismatch, _}} = 
  888:         (catch drestriction(fun(_) -> from_term({a}) end, 
  889:                             from_term([[a]]),
  890:                             from_term([], [atom]))),
  891:     ?line {'EXIT', {badarg, _}} = 
  892:         (catch drestriction(fun(_) -> {a} end, 
  893: 			    from_term([[a]]),
  894: 			    from_term([], [atom]))),
  895:     ok.
  896: 
  897: strict_relation_1(suite) -> [];
  898: strict_relation_1(doc) -> [""];
  899: strict_relation_1(Conf) when is_list(Conf) ->
  900:     ?line E = empty_set(),
  901:     ?line ER = relation([], 2),
  902:     ?line eval(strict_relation(E), E),
  903:     ?line eval(strict_relation(ER), ER),
  904:     ?line eval(strict_relation(relation([{1,a},{a,a},{2,b}])),
  905:                relation([{1,a},{2,b}])),
  906:     ?line {'EXIT', {badarg, _}} = 
  907:         (catch strict_relation(relation([{1,2,3}]))),
  908:     F = 0.0, I = round(F),
  909:     ?line FR = relation([{F,I}]),
  910:     if
  911:         F == I -> % term ordering
  912:             eval(strict_relation(FR), ER);
  913:         true -> 
  914:             eval(strict_relation(FR), FR)
  915:     end,
  916:     ok.
  917: 
  918: extension(suite) -> [];
  919: extension(doc) -> [""];
  920: extension(Conf) when is_list(Conf) ->
  921:     ?line E = empty_set(),
  922:     ?line ER = relation([], 2),
  923:     ?line EF = family([]),
  924:     ?line C1 = from_term(3),
  925:     ?line C2 = from_term([3]),
  926:     ?line {'EXIT', {function_clause, _}} = (catch extension(foo, E, C1)),
  927:     ?line {'EXIT', {function_clause, _}} = (catch extension(ER, foo, C1)),
  928:     ?line {'EXIT', {{case_clause, _},_}} = (catch extension(ER, E, foo)),
  929:     ?line {'EXIT', {type_mismatch, _}} = (catch extension(ER, E, E)),
  930:     ?line {'EXIT', {badarg, _}} = (catch extension(C2, E, E)),
  931:     ?line eval(E, extension(E, E, E)),
  932:     ?line eval(EF, extension(EF, E, E)),
  933:     ?line eval(family([{3,[]}]), extension(EF, set([3]), E)),
  934:     ?line eval(ER, extension(ER, E, C1)),
  935:     ?line eval(E, extension(E, ER, E)),
  936:     ?line eval(from_term([],[{{atom,atom},type(ER)}]), extension(E, ER, ER)),
  937: 
  938:     ?line R1 = relation([{c,7},{c,9},{c,11},{d,17},{f,20}]),
  939:     ?line S1 = set([a,c,d,e]),
  940:     ?line eval(extension(R1, S1, C1), lextension(R1, S1, C1)),
  941: 
  942:     ?line S2 = set([1,2,3]),
  943:     ?line eval(extension(ER, S2, C1), lextension(ER, S2, C1)),
  944: 
  945:     ?line R3 = relation([{4,a},{8,b}]),
  946:     ?line S3 = set([1,2,3,4,5,6,7,8,9,10,11]),
  947:     ?line eval(extension(R3, S3, C1), lextension(R3, S3, C1)),
  948: 
  949:     ?line R4 = relation([{2,b},{4,d},{6,f}]),
  950:     ?line S4 = set([1,3,5,7]),
  951:     ?line eval(extension(R4, S4, C1), lextension(R4, S4, C1)),
  952: 
  953:     ?line F1 = family([{a,[1]},{c,[2]}]),
  954:     ?line S5 = set([a,b,c,d]),
  955:     ?line eval(extension(F1, S5, C2), lextension(F1, S5, C2)),
  956:     ok.
  957: 
  958: lextension(R, S, C) ->
  959:     union(R, drestriction(1, constant_function(S, C), domain(R))).
  960: 
  961: weak_relation_1(suite) -> [];
  962: weak_relation_1(doc) -> [""];
  963: weak_relation_1(Conf) when is_list(Conf) ->
  964:     ?line E = empty_set(),
  965:     ?line ER = relation([], 2),
  966:     ?line eval(weak_relation(E), E),
  967:     ?line eval(weak_relation(ER), ER),
  968:     ?line eval(weak_relation(relation([{a,1},{a,2},{b,2},{c,c}])),
  969:                relation([{1,1},{2,2},{a,1},{a,2},{a,a},{b,2},{b,b},{c,c}])),
  970:     ?line eval(weak_relation(relation([{a,1},{a,a},{a,b}])),
  971:                relation([{1,1},{a,1},{a,a},{a,b},{b,b}])),
  972:     ?line eval(weak_relation(relation([{a,1},{a,b},{7,w}])),
  973:                relation([{1,1},{7,7},{7,w},{a,1},{a,a},{a,b},{b,b},{w,w}])),
  974:     ?line {'EXIT', {badarg, _}} = 
  975: 	(catch weak_relation(from_term([{{a},a}]))),
  976:     ?line {'EXIT', {badarg, _}} = 
  977: 	(catch weak_relation(from_term([{a,a}],[{d,r}]))),
  978:     ?line {'EXIT', {badarg, _}} = (catch weak_relation(relation([{1,2,3}]))),
  979: 
  980:     F = 0.0, I = round(F),
  981:     if
  982:         F == I -> % term ordering
  983:             ?line FR1 = relation([{F,I}]),
  984:             eval(weak_relation(FR1), FR1),
  985:             ?line FR2 = relation([{F,2},{I,1}]),
  986:             true = no_elements(weak_relation(FR2)) =:= 5,
  987:             ?line FR3 = relation([{1,0},{1.0,1}]),
  988:             true = no_elements(weak_relation(FR3)) =:= 3;
  989:         true -> 
  990:             ok
  991:     end,
  992:     ok.
  993: 
  994: to_sets_1(suite) ->  [];
  995: to_sets_1(doc) -> [""];
  996: to_sets_1(Conf) when is_list(Conf) ->
  997:     ?line {'EXIT', {badarg, _}} = (catch to_sets(from_term(a))),
  998:     ?line {'EXIT', {function_clause, _}} = (catch to_sets(a)),
  999:     %% unordered
 1000:     ?line [] = to_sets(empty_set()),
 1001:     ?line eval(to_sets(from_term([a])), [from_term(a)]),
 1002:     ?line eval(to_sets(from_term([[]],[[atom]])), [set([])]),
 1003: 
 1004:     ?line L = [from_term([a,b]),from_term([c,d])],
 1005:     ?line eval(to_sets(from_sets(L)), L),
 1006: 
 1007:     ?line eval(to_sets(relation([{a,1},{b,2}])),
 1008:                [from_term({a,1},{atom,atom}), from_term({b,2},{atom,atom})]),
 1009: 
 1010:     %% ordered
 1011:     ?line O = {from_term(a,atom), from_term({b}, {atom}), set([c,d])},
 1012:     ?line eval(to_sets(from_sets(O)), O),
 1013:     ok.
 1014: 
 1015: 
 1016: specification(suite) -> [];
 1017: specification(doc) -> [""];
 1018: specification(Conf) when is_list(Conf) ->
 1019:     Fun = {external, fun(I) when is_integer(I) -> true; (_) -> false end},
 1020:     ?line [1,2,3] = to_external(specification(Fun, set([a,1,b,2,c,3]))),
 1021: 
 1022:     Fun2 = fun(S) -> is_subset(S, set([1,3,5,7,9])) end,
 1023:     S2 = from_term([[1],[2],[3],[4],[5],[6],[7]]),
 1024:     ?line eval(specification(Fun2, S2), from_term([[1],[3],[5],[7]])),
 1025:     Fun2x = fun([1]) -> true;
 1026: 	       ([3]) -> true;
 1027: 	       (_) -> false 
 1028: 	    end,
 1029:     ?line eval(specification({external,Fun2x}, S2), from_term([[1],[3]])),
 1030: 
 1031:     Fun3 = fun(_) -> neither_true_nor_false end,
 1032:     ?line {'EXIT', {badarg, _}} = 
 1033: 	(catch specification(Fun3, set([a]))),
 1034:     ?line {'EXIT', {badarg, _}} = 
 1035: 	(catch specification({external, Fun3}, set([a]))),
 1036:     ?line {'EXIT', {badarg, _}} = 
 1037: 	(catch specification(Fun3, from_term([[a]]))),
 1038:     ?line {'EXIT', {function_clause, _}} = 
 1039: 	(catch specification(Fun, a)),
 1040:     ok.
 1041: 
 1042: union_1(suite) -> [];
 1043: union_1(doc) -> [""];
 1044: union_1(Conf) when is_list(Conf) ->
 1045:     ?line E = empty_set(),
 1046:     ?line ER = relation([], 2),
 1047:     ?line {'EXIT', {badarg, _}} = (catch union(ER)),
 1048:     ?line {'EXIT', {type_mismatch, _}} =
 1049: 	(catch union(relation([{a,b}]), relation([{a,b,c}]))),
 1050:     ?line {'EXIT', {type_mismatch, _}} =
 1051: 	(catch union(from_term([{a,b}]), from_term([{c,[x]}]))),
 1052:     ?line {'EXIT', {type_mismatch, _}} =
 1053: 	(catch union(from_term([{a,b}]), from_term([{c,d}], [{d,r}]))),
 1054:     ?line {'EXIT', {badarg, _}} = (catch union(set([a,b,c]))),
 1055:     ?line eval(union(E), E),
 1056:     ?line eval(union(from_term([[]],[[atom]])), set([])),
 1057:     ?line eval(union(from_term([[{a,b},{b,c}],[{b,c}]])), 
 1058:                relation([{a,b},{b,c}])),
 1059:     ?line eval(union(from_term([[1,2,3],[2,3,4],[3,4,5]])), 
 1060:                set([1,2,3,4,5])),
 1061: 
 1062:     ?line eval(union(from_term([{[a],[],c}]), from_term([{[],[],q}])),
 1063: 	       from_term([{[a],[],c},{[],[],q}])),
 1064: 
 1065:     ?line eval(union(E, E), E),
 1066:     ?line eval(union(set([a,b]), E), set([a,b])),
 1067:     ?line eval(union(E, set([a,b])), set([a,b])),
 1068: 
 1069:     ?line eval(union(from_term([[a,b]])), from_term([a,b])),
 1070:     ok.
 1071: 
 1072: intersection_1(suite) -> [];
 1073: intersection_1(doc) -> [""];
 1074: intersection_1(Conf) when is_list(Conf) ->
 1075:     ?line E = empty_set(),
 1076:     ?line {'EXIT', {badarg, _}} = (catch intersection(from_term([a,b]))),
 1077:     ?line {'EXIT', {badarg, _}} = (catch intersection(E)),
 1078:     ?line {'EXIT', {type_mismatch, _}} =
 1079: 	(catch intersection(relation([{a,b}]), relation([{a,b,c}]))),
 1080:     ?line {'EXIT', {type_mismatch, _}} =
 1081: 	(catch intersection(relation([{a,b}]), from_term([{a,b}],[{d,r}]))),
 1082: 
 1083:     ?line eval(intersection(from_term([[a,b,c],[d,e,f],[g,h,i]])), set([])),
 1084: 
 1085:     ?line eval(intersection(E, E), E),
 1086:     ?line eval(intersection(set([a,b,c]),set([0,b,q])), 
 1087:                set([b])),
 1088:     ?line eval(intersection(set([0,b,q]),set([a,b,c])), 
 1089:                set([b])),
 1090:     ?line eval(intersection(set([a,b,c]),set([a,b,c])), 
 1091:                set([a,b,c])),
 1092:     ?line eval(intersection(set([a,b,d]),set([c,d])), 
 1093:                set([d])),
 1094:     ok.
 1095: 
 1096: difference(suite) -> [];
 1097: difference(doc) -> [""];
 1098: difference(Conf) when is_list(Conf) ->
 1099:     ?line E = empty_set(),
 1100:     ?line {'EXIT', {type_mismatch, _}} =
 1101: 	(catch difference(relation([{a,b}]), relation([{a,b,c}]))),
 1102:     ?line eval(difference(E, E), E),
 1103:     ?line {'EXIT', {type_mismatch, _}} =
 1104: 	(catch difference(relation([{a,b}]), from_term([{a,c}],[{d,r}]))),
 1105:     ?line eval(difference(set([a,b,c,d,f]), set([a,d,e,g])), 
 1106:                set([b,c,f])),
 1107:     ?line eval(difference(set([a,b,c]), set([d,e,f])), 
 1108:                set([a,b,c])),
 1109:     ?line eval(difference(set([a,b,c]), set([a,b,c,d,e,f])), 
 1110:                set([])),
 1111:     ?line eval(difference(set([e,f,g]), set([a,b,c,e])), 
 1112:                set([f,g])),
 1113:     ?line eval(difference(set([a,b,d,e,f]), set([c])), 
 1114:                set([a,b,d,e,f])),
 1115:     ok.
 1116: 
 1117: symdiff(suite) -> [];
 1118: symdiff(doc) -> [""];
 1119: symdiff(Conf) when is_list(Conf) ->
 1120:     ?line E = empty_set(),
 1121:     ?line {'EXIT', {type_mismatch, _}} =
 1122: 	(catch symdiff(relation([{a,b}]), relation([{a,b,c}]))),
 1123:     ?line {'EXIT', {type_mismatch, _}} =
 1124: 	(catch symdiff(relation([{a,b}]), from_term([{a,b}], [{d,r}]))),
 1125:     ?line eval(symdiff(E, E), E),
 1126:     ?line eval(symdiff(set([a,b,c,d,e,f]), set([0,1,a,c])),
 1127:                union(set([b,d,e,f]), set([0,1]))),
 1128:     ?line eval(symdiff(set([a,b,c]), set([q,v,w,x,y])),
 1129:                union(set([a,b,c]), set([q,v,w,x,y]))),
 1130:     ?line eval(symdiff(set([a,b,c,d,e,f]), set([a,b,c])),
 1131:                set([d,e,f])),
 1132:     ?line eval(symdiff(set([c,e,g,h,i]), set([b,d,f])),
 1133:                union(set([c,e,g,h,i]), set([b,d,f]))),
 1134:     ?line eval(symdiff(set([c,d,g,h,k,l]), 
 1135:                        set([a,b,e,f,i,j,m,n])),
 1136:                union(set([c,d,g,h,k,l]), set([a,b,e,f,i,j,m,n]))),
 1137:     ?line eval(symdiff(set([c,d,g,h,k,l]), 
 1138:                        set([d,e,h,i,l,m,n,o,p])),
 1139:                union(set([c,g,k]), set([e,i,m,n,o,p]))),
 1140:     ok.
 1141: 
 1142: symmetric_partition(suite) -> [];
 1143: symmetric_partition(doc) -> [""];
 1144: symmetric_partition(Conf) when is_list(Conf) ->
 1145:     ?line E = set([]),
 1146:     ?line S1 = set([1,2,3,4]),
 1147:     ?line S2 = set([3,4,5,6]),
 1148:     ?line S3 = set([3,4]),
 1149:     ?line S4 = set([1,2,3,4,5,6]),
 1150:     ?line T1 = set([1,2]),
 1151:     ?line T2 = set([3,4]),
 1152:     ?line T3 = set([5,6]),
 1153:     ?line T4 = set([1,2,5,6]),
 1154:     ?line {'EXIT', {type_mismatch, _}} =
 1155: 	(catch symmetric_partition(relation([{a,b}]), relation([{a,b,c}]))),
 1156:     ?line {E, E, E} = symmetric_partition(E, E),
 1157:     ?line {'EXIT', {type_mismatch, _}} =
 1158: 	(catch symmetric_partition(relation([{a,b}]), 
 1159:                                    from_term([{a,c}],[{d,r}]))),
 1160:     ?line {E, E, S1} = symmetric_partition(E, S1),
 1161:     ?line {S1, E, E} = symmetric_partition(S1, E),
 1162:     ?line {T1, T2, T3} = symmetric_partition(S1, S2),
 1163:     ?line {T3, T2, T1} = symmetric_partition(S2, S1),
 1164:     ?line {E, T2, T4} = symmetric_partition(S3, S4),
 1165:     ?line {T4, T2, E} = symmetric_partition(S4, S3),
 1166: 
 1167:     ?line S5 = set([1,3,5]),
 1168:     ?line S6 = set([2,4,6,7,8]),
 1169:     ?line {S5, E, S6} = symmetric_partition(S5, S6),
 1170:     ?line {S6, E, S5} = symmetric_partition(S6, S5),
 1171:     ?line EE = empty_set(),
 1172:     ?line {EE, EE, EE} = symmetric_partition(EE, EE),
 1173: 
 1174:     ok.
 1175: 
 1176: is_sofs_set_1(suite) -> [];
 1177: is_sofs_set_1(doc) -> [""];
 1178: is_sofs_set_1(Conf) when is_list(Conf) ->
 1179:     ?line E = empty_set(),
 1180:     ?line true = is_sofs_set(E),
 1181:     ?line true = is_sofs_set(from_term([a])),
 1182:     ?line true = is_sofs_set(from_term({a})),
 1183:     ?line true = is_sofs_set(from_term(a)),
 1184:     ?line false = is_sofs_set(a),
 1185:     ok.
 1186: 
 1187: is_set_1(suite) -> [];
 1188: is_set_1(doc) -> [""];
 1189: is_set_1(Conf) when is_list(Conf) ->
 1190:     ?line E = empty_set(),
 1191:     ?line true = is_set(E),
 1192:     ?line true = is_set(from_term([a])),
 1193:     ?line false = is_set(from_term({a})),
 1194:     ?line false = is_set(from_term(a)),
 1195:     ?line {'EXIT', _} = (catch is_set(a)),
 1196: 
 1197:     ?line true = is_empty_set(E),
 1198:     ?line false = is_empty_set(from_term([a])),
 1199:     ?line false = is_empty_set(from_term({a})),
 1200:     ?line false = is_empty_set(from_term(a)),
 1201:     ?line {'EXIT', _} = (catch is_empty_set(a)),
 1202: 
 1203:     ok.
 1204: 
 1205: is_equal(suite) -> [];
 1206: is_equal(doc) -> [""];
 1207: is_equal(Conf) when is_list(Conf) ->
 1208:     ?line E = empty_set(),
 1209:     ?line true = is_equal(E, E),
 1210:     ?line false = is_equal(from_term([a]), E),
 1211:     ?line {'EXIT', {type_mismatch, _}} =
 1212: 	(catch is_equal(intersection(set([a]), set([b])),
 1213: 			intersection(from_term([{a}]), from_term([{b}])))),
 1214:     ?line {'EXIT', {type_mismatch, _}} =
 1215: 	(catch is_equal(from_term([],[{[atom],atom,[atom]}]), 
 1216: 			from_term([],[{[atom],{atom},[atom]}]))),
 1217:     ?line {'EXIT', {type_mismatch, _}} =
 1218: 	(catch is_equal(set([a]), from_term([a],[type]))),
 1219: 
 1220:     ?line E2 = from_sets({from_term(a,atom)}),
 1221:     ?line true = is_equal(E2, E2),
 1222:     ?line true = is_equal(from_term({a}, {atom}), E2),
 1223:     ?line false = is_equal(from_term([{[a],[],c}]), 
 1224: 			   from_term([{[],[],q}])),
 1225: 
 1226:     ?line {'EXIT', {type_mismatch, _}} =
 1227:         (catch is_equal(E, E2)),
 1228:     ?line {'EXIT', {type_mismatch, _}} =
 1229:         (catch is_equal(E2, E)),
 1230:     ?line true = is_equal(from_term({[],a,[]},{[atom],atom,[atom]}), 
 1231:                           from_term({[],a,[]},{[atom],atom,[atom]})),
 1232:     ?line {'EXIT', {type_mismatch, _}} =
 1233: 	(catch is_equal(from_term({[],a,[]},{[atom],atom,[atom]}), 
 1234: 			from_term({[],{a},[]},{[atom],{atom},[atom]}))),
 1235:     ?line {'EXIT', {type_mismatch, _}} =
 1236: 	(catch is_equal(from_term({a}), from_term({a},{type}))),
 1237: 
 1238:     ok.
 1239: 
 1240: is_subset(suite) -> [];
 1241: is_subset(doc) -> [""];
 1242: is_subset(Conf) when is_list(Conf) ->
 1243:     ?line E = empty_set(),
 1244:     ?line true = is_subset(E, E),
 1245:     ?line true = is_subset(set([a,c,e]), set([a,b,c,d,e])),
 1246:     ?line false = is_subset(set([a,b]), E),
 1247:     ?line false = is_subset(set([d,e,f]), set([b,c,d,e])),
 1248:     ?line false = is_subset(set([a,b,c]), set([b,c])),
 1249:     ?line false = is_subset(set([b,c]), set([a,c])),
 1250:     ?line false = is_subset(set([d,e]), set([a,b])),
 1251:     ?line {'EXIT', {type_mismatch, _}} =
 1252: 	(catch is_subset(intersection(set([a]), set([b])),
 1253: 			 intersection(from_term([{a}]), from_term([{b}])))),
 1254:     ?line {'EXIT', {type_mismatch, _}} =
 1255:         (catch is_subset(set([a]), from_term([a,b], [at]))),
 1256:     ok.
 1257: 
 1258: is_a_function_1(suite) -> [];
 1259: is_a_function_1(doc) -> [""];
 1260: is_a_function_1(Conf) when is_list(Conf) ->
 1261:     ?line E = empty_set(),
 1262:     ?line ER = relation([], 2),
 1263:     ?line {'EXIT', {badarg, _}} = (catch is_a_function(set([a,b]))),
 1264:     ?line true = is_a_function(E),
 1265:     ?line true = is_a_function(ER),
 1266:     ?line true = is_a_function(relation([])),
 1267:     ?line true = is_a_function(relation([],2)),
 1268:     ?line true = is_a_function(relation([{a,b},{b,c}])),
 1269:     ?line false = is_a_function(relation([{a,b},{b,c},{b,d},{e,f}])),
 1270:     ?line IS = relation([{{a,b},c},{{a,b},d}]),
 1271:     ?line false = is_a_function(IS),
 1272:     F = 0.0, I = round(F),
 1273:     ?line FR = relation([{I,F},{F,1}]),
 1274:     if
 1275:         F == I -> % term ordering
 1276:             false = is_a_function(FR);
 1277:         true -> 
 1278:             true = is_a_function(FR)
 1279:     end,
 1280:     ok.
 1281: 
 1282: is_disjoint(suite) -> [];
 1283: is_disjoint(doc) -> [""];
 1284: is_disjoint(Conf) when is_list(Conf) ->
 1285:     ?line E = empty_set(),
 1286:     ?line {'EXIT', {type_mismatch, _}} = 
 1287: 	(catch is_disjoint(relation([{a,1}]), set([a,b]))),
 1288:     ?line {'EXIT', {type_mismatch, _}} = 
 1289: 	(catch is_disjoint(set([a]), from_term([a],[mota]))),
 1290:     ?line true = is_disjoint(E, E),
 1291:     ?line false = is_disjoint(set([a,b,c]),set([b,c,d])),
 1292:     ?line false = is_disjoint(set([b,c,d]),set([a,b,c])),
 1293:     ?line true = is_disjoint(set([a,c,e]),set([b,d,f])),
 1294:     ok.
 1295: 
 1296: join(suite) -> [];
 1297: join(doc) -> [""];
 1298: join(Conf) when is_list(Conf) ->
 1299:     ?line E = empty_set(),
 1300: 
 1301:     ?line {'EXIT', {badarg, _}} = (catch join(relation([{a,1}]), 3, E, 5)),
 1302:     ?line {'EXIT', {badarg, _}} = (catch join(E, 1, relation([{a,1}]), 3)),
 1303:     ?line {'EXIT', {badarg, _}} = (catch join(E, 1, from_term([a]), 1)),
 1304: 
 1305:     ?line eval(join(E, 1, E, 2), E),
 1306:     ?line eval(join(E, 1, from_term([{{a},b}]), 2), E),
 1307:     ?line eval(join(from_term([{{a},b}]), 2, E, 1), E),
 1308:     ?line eval(join(from_term([{{a},b,e}]), 2, from_term([{c,{d}}]), 1),
 1309:                from_term([], [{{atom},atom,atom,{atom}}])),
 1310:     ?line eval(join(relation([{a}]), 1, relation([{1,a},{2,a}]), 2),
 1311:                relation([{a,1},{a,2}])),
 1312:     ?line eval(join(relation([{a,b,c},{b,c,d}]), 2, 
 1313:                     relation([{1,b},{2,a},{3,c}]), 2),
 1314:                relation([{a,b,c,1},{b,c,d,3}])),
 1315:     ?line eval(join(relation([{1,a,aa},{1,b,bb},{1,c,cc},{2,a,aa},{2,b,bb}]), 
 1316:                     1,
 1317:                     relation([{1,c,cc},{1,d,dd},{1,e,ee},{2,c,cc},{2,d,dd}]),
 1318:                     1),
 1319:              relation([{1,a,aa,c,cc},{1,a,aa,d,dd},{1,a,aa,e,ee},{1,b,bb,c,cc},
 1320: 		       {1,b,bb,d,dd},{1,b,bb,e,ee},{1,c,cc,c,cc},{1,c,cc,d,dd},
 1321: 		       {1,c,cc,e,ee},{2,a,aa,c,cc},{2,a,aa,d,dd},{2,b,bb,c,cc},
 1322: 		       {2,b,bb,d,dd}])),
 1323: 
 1324:     R1 = relation([{a,b},{b,c}]),
 1325:     R2 = relation([{b,1},{a,2},{c,3},{c,4}]),
 1326:     ?line eval(join(R1, 1, R2, 1), from_term([{a,b,2},{b,c,1}])),
 1327:     ?line eval(join(R1, 2, R2, 1), from_term([{a,b,1},{b,c,3},{b,c,4}])),
 1328:     ?line eval(join(R1, 1, converse(R2), 2),
 1329: 	       from_term([{a,b,2},{b,c,1}])),
 1330:     ?line eval(join(R1, 2, converse(R2), 2),
 1331: 	       from_term([{a,b,1},{b,c,3},{b,c,4}])),
 1332:     ok.
 1333: 
 1334: canonical(suite) -> [];
 1335: canonical(doc) -> [""];
 1336: canonical(Conf) when is_list(Conf) ->
 1337:     ?line E = empty_set(),    
 1338:     ?line {'EXIT', {badarg, _}} = 
 1339:         (catch canonical_relation(set([a,b]))),
 1340:     ?line eval(canonical_relation(E), E),
 1341:     ?line eval(canonical_relation(from_term([[]])), E),
 1342:     ?line eval(canonical_relation(from_term([[a,b,c]])),
 1343:                from_term([{a,[a,b,c]},{b,[a,b,c]},{c,[a,b,c]}])),
 1344:     ok.
 1345: 
 1346: relation_to_family_1(suite) -> [];
 1347: relation_to_family_1(doc) -> [""];
 1348: relation_to_family_1(Conf) when is_list(Conf) ->
 1349:     ?line E = empty_set(),
 1350:     ?line EF = family([]),
 1351:     ?line eval(relation_to_family(E), E),
 1352:     ?line eval(relation_to_family(relation([])), EF),
 1353:     ?line eval(relation_to_family(relation([], 2)), EF),
 1354:     ?line R = relation([{b,1},{c,7},{c,9},{c,11}]),
 1355:     ?line F = family([{b,[1]},{c,[7,9,11]}]),
 1356:     ?line eval(relation_to_family(R), F),
 1357:     ?line eval(sofs:rel2fam(R), F),
 1358:     ?line {'EXIT', {badarg, _}} = (catch relation_to_family(set([a]))),
 1359:     ok.
 1360: 
 1361: domain_1(suite) -> [];
 1362: domain_1(doc) -> [""];
 1363: domain_1(Conf) when is_list(Conf) ->
 1364:     ?line E = empty_set(),
 1365:     ?line ER = relation([]),
 1366:     ?line {'EXIT', {badarg, _}} = (catch domain(relation([],3))),
 1367:     ?line eval(domain(E), E),
 1368:     ?line eval(domain(ER), set([])),
 1369:     ?line eval(domain(relation([{1,a},{1,b},{2,a},{2,b}])), set([1,2])),
 1370:     ?line eval(domain(relation([{a,1},{b,2},{c,3}])), set([a,b,c])),
 1371:     ?line eval(field(relation([{a,1},{b,2},{c,3}])), 
 1372:                set([a,b,c,1,2,3])),
 1373:     F = 0.0, I = round(F),
 1374:     ?line FR = relation([{I,a},{F,b}]),
 1375:     if
 1376:         F == I -> % term ordering
 1377:             ?line true = (1 =:= no_elements(domain(FR)));
 1378:         true -> 
 1379:             ?line true = (2 =:= no_elements(domain(FR)))
 1380:     end,
 1381:     ok.
 1382: 
 1383: range_1(suite) -> [];
 1384: range_1(doc) -> [""];
 1385: range_1(Conf) when is_list(Conf) ->
 1386:     ?line E = empty_set(),
 1387:     ?line ER = relation([]),
 1388:     ?line {'EXIT', {badarg, _}} = (catch range(relation([],3))),
 1389:     ?line eval(range(E), E),
 1390:     ?line eval(range(ER), set([])),
 1391:     ?line eval(range(relation([{1,a},{1,b},{2,a},{2,b}])), set([a,b])),
 1392:     ?line eval(range(relation([{a,1},{b,2},{c,3}])), set([1,2,3])),
 1393:     ok.
 1394:     
 1395: inverse_1(suite) -> [];
 1396: inverse_1(doc) -> [""];
 1397: inverse_1(Conf) when is_list(Conf) ->
 1398:     ?line E = empty_set(),
 1399:     ?line ER = relation([]),
 1400:     ?line {'EXIT', {badarg, _}} = (catch inverse(relation([],3))),
 1401:     ?line {'EXIT', {bad_function, _}} = 
 1402: 	(catch inverse(relation([{1,a},{1,b}]))),
 1403:     ?line {'EXIT', {bad_function, _}} = 
 1404: 	(catch inverse(relation([{1,a},{2,a}]))),
 1405:     ?line eval(inverse(E), E),
 1406:     ?line eval(inverse(ER), ER),
 1407:     ?line eval(inverse(relation([{a,1},{b,2},{c,3}])),
 1408:                relation([{1,a},{2,b},{3,c}])),
 1409:     F = 0.0, I = round(F),
 1410:     ?line FR = relation([{I,a},{F,b}]),
 1411:     if
 1412:         F == I -> % term ordering
 1413:             ?line {'EXIT', {bad_function, _}} = (catch inverse(FR));
 1414:         true -> 
 1415:             ?line eval(inverse(FR), relation([{a,I},{b,F}]))
 1416:     end,
 1417:     ok.
 1418:     
 1419: converse_1(suite) -> [];
 1420: converse_1(doc) -> [""];
 1421: converse_1(Conf) when is_list(Conf) ->
 1422:     ?line E = empty_set(),
 1423:     ?line ER = relation([]),
 1424:     ?line {'EXIT', {badarg, _}} = (catch converse(relation([],3))),
 1425:     ?line eval(converse(ER), ER),
 1426:     ?line eval(converse(E), E),
 1427:     ?line eval(converse(relation([{a,1},{b,2},{c,3}])),
 1428:                relation([{1,a},{2,b},{3,c}])),
 1429:     ?line eval(converse(relation([{1,a},{1,b}])),
 1430: 	       relation([{a,1},{b,1}])),
 1431:     ?line eval(converse(relation([{1,a},{2,a}])),
 1432: 	       relation([{a,1},{a,2}])),
 1433:     ok.
 1434:     
 1435: no_elements_1(suite) -> [];
 1436: no_elements_1(doc) -> [""];
 1437: no_elements_1(Conf) when is_list(Conf) ->
 1438:     ?line 0 = no_elements(empty_set()),
 1439:     ?line 0 = no_elements(set([])),
 1440:     ?line 1 = no_elements(from_term([a])),
 1441:     ?line 10 = no_elements(from_term(lists:seq(1,10))),
 1442:     ?line 3 = no_elements(from_term({a,b,c},{atom,atom,atom})),
 1443:     ?line {'EXIT', {badarg, _}} = (catch no_elements(from_term(a))),
 1444:     ?line {'EXIT', {function_clause, _}} = (catch no_elements(a)),
 1445:     ok.
 1446: 
 1447: image(suite) -> [];
 1448: image(doc) -> [""];
 1449: image(Conf) when is_list(Conf) ->
 1450:     ?line E = empty_set(),
 1451:     ?line ER = relation([]),
 1452:     ?line eval(image(E, E), E),
 1453:     ?line eval(image(ER, E), set([])),
 1454:     ?line eval(image(relation([{a,1},{b,2},{c,3},{f,6}]), set([a,b,c,d,f])), 
 1455:                set([1,2,3,6])),
 1456:     ?line eval(image(relation([{a,1},{b,2},{c,3},{d,4},{r,17}]), 
 1457: 		     set([b,c,q,r])), 
 1458:                set([2,3,17])),
 1459:     ?line eval(image(from_term([{[a],{1}},{[b],{2}}]), from_term([[a]])),
 1460: 	       from_term([{1}])),
 1461:     ?line eval(image(relation([{1,a},{2,a},{3,a},{4,b},{2,b}]), set([1,2,4])),
 1462: 	       set([a,b])),
 1463:     ?line {'EXIT', {badarg, _}} =
 1464: 	(catch image(from_term([a,b]), E)),
 1465:     ?line {'EXIT', {type_mismatch, _}} =
 1466: 	(catch image(from_term([{[a],1}]), set([[a]]))),
 1467:     ok.
 1468: 
 1469: inverse_image(suite) -> [];
 1470: inverse_image(doc) -> [""];
 1471: inverse_image(Conf) when is_list(Conf) ->
 1472:     ?line E = empty_set(),
 1473:     ?line ER = relation([]),
 1474:     ?line eval(inverse_image(E, E), E),
 1475:     ?line eval(inverse_image(ER, E), set([])),
 1476:     ?line eval(inverse_image(converse(relation([{a,1},{b,2},{c,3},{f,6}])), 
 1477: 			     set([a,b,c,d,f])), 
 1478:                set([1,2,3,6])),
 1479:     ?line eval(inverse_image(converse(relation([{a,1},{b,2},{c,3},
 1480: 						{d,4},{r,17}])), 
 1481: 			     set([b,c,q,r])), 
 1482:                set([2,3,17])),
 1483:     ?line eval(inverse_image(converse(from_term([{[a],{1}},{[b],{2}}])), 
 1484: 			     from_term([[a]])),
 1485: 	       from_term([{1}])),
 1486:     ?line eval(inverse_image(converse(relation([{1,a},{2,a},
 1487: 						{3,a},{4,b},{2,b}])), 
 1488: 			     set([1,2,4])),
 1489: 	       set([a,b])),
 1490:     ?line {'EXIT', {badarg, _}} =
 1491: 	(catch inverse_image(from_term([a,b]), E)),
 1492:     ?line {'EXIT', {type_mismatch, _}} =
 1493: 	(catch inverse_image(converse(from_term([{[a],1}])), set([[a]]))),
 1494:     ok.
 1495: 
 1496: composite_1(suite) -> [];
 1497: composite_1(doc) -> [""];
 1498: composite_1(Conf) when is_list(Conf) ->
 1499:     ?line E = empty_set(),
 1500:     ?line EF = a_function([]),
 1501:     ?line eval(composite(E, E), E),
 1502:     ?line eval(composite(E, a_function([{a,b}])), E),
 1503:     ?line eval(composite(relation([{a,b}]), E), E),
 1504:     ?line {'EXIT', {bad_function, _}} = 
 1505: 	(catch composite(EF, relation([{a,b},{a,c}]))),
 1506:     ?line {'EXIT', {bad_function, _}} = 
 1507: 	(catch composite(a_function([{b,a}]), EF)),
 1508:     ?line {'EXIT', {bad_function, _}} = 
 1509: 	(catch composite(relation([{1,a},{2,b},{2,a}]), 
 1510: 			 a_function([{a,1},{b,3}]))),
 1511:     ?line {'EXIT', {bad_function, _}} = 
 1512: 	 (catch composite(a_function([{1,a},{2,b}]), a_function([{b,3}]))),
 1513:     ?line eval(composite(EF, EF), EF),
 1514:     ?line eval(composite(a_function([{b,a}]), from_term([{a,{b,c}}])),
 1515:                from_term([{b,{b,c}}])),
 1516:     ?line eval(composite(a_function([{q,1},{z,2}]), 
 1517: 			 a_function([{1,a},{2,a}])),
 1518:                a_function([{q,a},{z,a}])),
 1519:     ?line eval(composite(a_function([{a,0},{b,0},{c,1},{d,1},{e,2},{f,3}]), 
 1520: 			 a_function([{0,p},{1,q},{2,r},{3,w},{4,aa}])),
 1521:                a_function([{c,q},{d,q},{f,w},{e,r},{a,p},{b,p}])),
 1522:     ?line eval(composite(a_function([{1,c}]), 
 1523: 			 a_function([{a,1},{b,3},{c,4}])),
 1524: 	       a_function([{1,4}])),
 1525:     ?line {'EXIT', {bad_function, _}} = 
 1526: 	(catch composite(a_function([{1,a},{2,b}]), 
 1527: 			 a_function([{a,1},{c,3}]))),
 1528:     ?line {'EXIT', {badarg, _}} = 
 1529: 	(catch composite(from_term([a,b]), E)),
 1530:     ?line {'EXIT', {badarg, _}} = 
 1531: 	(catch composite(E, from_term([a,b]))),
 1532:     ?line {'EXIT', {type_mismatch, _}} = 
 1533:         (catch composite(from_term([{a,b}]), from_term([{{a},b}]))),
 1534:     ?line {'EXIT', {type_mismatch, _}} = 
 1535:         (catch composite(from_term([{a,b}]), 
 1536: 			 from_term([{b,c}], [{d,r}]))),
 1537:     F = 0.0, I = round(F),
 1538:     ?line FR1 = relation([{1,c}]),
 1539:     ?line FR2 = relation([{I,1},{F,3},{c,4}]),
 1540:     if
 1541:         F == I -> % term ordering
 1542:             ?line {'EXIT', {bad_function, _}} = (catch composite(FR1, FR2));
 1543:         true -> 
 1544:             ?line eval(composite(FR1, FR2), a_function([{1,4}]))
 1545:     end,
 1546:     ok.
 1547: 
 1548: relative_product_1(suite) -> [];
 1549: relative_product_1(doc) -> [""];
 1550: relative_product_1(Conf) when is_list(Conf) ->
 1551:     ?line E = empty_set(),
 1552:     ?line ER = relation([]),
 1553:     ?line eval(relative_product1(E, E), E),
 1554:     ?line eval(relative_product1(E, relation([{a,b}])), E),
 1555:     ?line eval(relative_product1(relation([{a,b}]), E), E),
 1556:     ?line eval(relative_product1(relation([{a,b}]), from_term([{a,{b,c}}])),
 1557:                from_term([{b,{b,c}}])),
 1558:     ?line eval(relative_product1(relation([{1,z},{1,q},{2,z}]), 
 1559: 				 relation([{1,a},{1,b},{2,a}])),
 1560:                relation([{q,a},{q,b},{z,a},{z,b}])),
 1561:     ?line eval(relative_product1(relation([{0,a},{0,b},{1,c},
 1562: 					   {1,d},{2,e},{3,f}]), 
 1563: 				 relation([{1,q},{3,w}])),
 1564:                relation([{c,q},{d,q},{f,w}])),
 1565:     ?line {'EXIT', {badarg, _}} = 
 1566: 	(catch relative_product1(from_term([a,b]), ER)),
 1567:     ?line {'EXIT', {badarg, _}} = 
 1568: 	(catch relative_product1(ER, from_term([a,b]))),
 1569:     ?line {'EXIT', {type_mismatch, _}} = 
 1570:         (catch relative_product1(from_term([{a,b}]), from_term([{{a},b}]))),
 1571:     ?line {'EXIT', {type_mismatch, _}} = 
 1572:         (catch relative_product1(from_term([{a,b}]), 
 1573: 				 from_term([{b,c}], [{d,r}]))),
 1574:     ok.
 1575: 
 1576: relative_product_2(suite) -> [];
 1577: relative_product_2(doc) -> [""];
 1578: relative_product_2(Conf) when is_list(Conf) ->
 1579:     ?line E = empty_set(),
 1580:     ?line ER = relation([]),
 1581: 
 1582:     ?line {'EXIT', {badarg, _}} = (catch relative_product({from_term([a,b])})),
 1583:     ?line {'EXIT', {type_mismatch, _}} =
 1584: 	(catch relative_product({from_term([{a,b}]), from_term([{{a},b}])})),
 1585:     ?line {'EXIT', {badarg, _}} = (catch relative_product({})), 
 1586:     ?line true = is_equal(relative_product({ER}), 
 1587: 			  from_term([], [{atom,{atom}}])),
 1588:     ?line eval(relative_product({relation([{a,b},{c,a}]),
 1589: 				 relation([{a,1},{a,2}]),
 1590: 				 relation([{a,aa},{c,1}])}),
 1591:                from_term([{a,{b,1,aa}},{a,{b,2,aa}}])),
 1592:     ?line eval(relative_product({relation([{a,b}])}, E), E),
 1593:     ?line eval(relative_product({E}, relation([{a,b}])), E),
 1594:     ?line eval(relative_product({E,from_term([], [{{atom,atom,atom},atom}])}),
 1595: 	       E),
 1596:     ?line {'EXIT', {badarg, _}} = 
 1597:         (catch relative_product({from_term([a,b])}, E)),
 1598:     ?line {'EXIT', {badarg, _}} = 
 1599: 	(catch relative_product({relation([])}, set([]))),
 1600:     ?line {'EXIT', {type_mismatch, _}} =
 1601: 	(catch relative_product({from_term([{a,b}]), 
 1602: 				 from_term([{{a},b}])}, ER)),
 1603: 
 1604:     ?line {'EXIT', {badarg, _}} = (catch relative_product({}, ER)),
 1605:     ?line relprod2({relation([{a,b}])}, from_term([],[{{atom},atom}]), ER),
 1606:     ?line relprod2({relation([{a,b}]),relation([{a,1}])},
 1607:                    from_term([{{b,1},{tjo,hej,sa}}]),
 1608:                    from_term([{a,{tjo,hej,sa}}])),
 1609:     ?line relprod2({relation([{a,b}]), ER}, from_term([{{a,b},b}]), ER),
 1610:     ?line relprod2({relation([{a,b},{c,a}]),
 1611:                     relation([{a,1},{a,2}])},
 1612:                    from_term([{{b,1},b1},{{b,2},b2}]),
 1613:                    relation([{a,b1},{a,b2}])),
 1614:     ?line eval(relative_product({relation([{a,b}]), ER}), 
 1615:                from_term([],[{atom,{atom,atom}}])),
 1616:     ?line eval(relative_product({from_term([{{a,[a,b]},[a]}]),
 1617: 				 from_term([{{a,[a,b]},[[a,b]]}])}),
 1618:                from_term([{{a,[a,b]},{[a],[[a,b]]}}])),
 1619:     ok.
 1620: 
 1621: relprod2(A1T, A2, R) ->
 1622:     %% A tuple as first argument is the old interface:
 1623:     eval(relative_product(A1T, A2), R),
 1624:     eval(relative_product(tuple_to_list(A1T), A2), R).
 1625: 
 1626: product_1(suite) -> [];
 1627: product_1(doc) -> [""];
 1628: product_1(Conf) when is_list(Conf) ->
 1629:     ?line E = empty_set(),
 1630:     ?line eval(product(E, E), E),
 1631:     ?line eval(product(relation([]), E), E),
 1632:     ?line eval(product(E, relation([])), E),
 1633:     ?line eval(product(relation([{a,b}]),relation([{c,d}])),
 1634:                from_term([{{a,b},{c,d}}],[{{atom,atom},{atom,atom}}])),
 1635: 
 1636:     ?line eval(product({E, set([a,b,c])}), E),
 1637:     ?line eval(product({set([a,b,c]), E}), E),
 1638:     ?line eval(product({set([a,b,c]), E, E}), E),
 1639:     ?line eval(product({E,E}), E),
 1640:     ?line eval(product({set([a,b]),set([1,2])}), 
 1641:                relation([{a,1},{a,2},{b,1},{b,2}])),
 1642:     ?line eval(product({from_term([a,b]), from_term([{a,b},{c,d}]),
 1643:                         from_term([1])}),
 1644:                from_term([{a,{a,b},1},{a,{c,d},1},{b,{a,b},1},{b,{c,d},1}])),
 1645:     ?line {'EXIT', {badarg, _}} = (catch product({})),
 1646:     ?line {'EXIT', {badarg, _}} = (catch product({foo})),
 1647:     ?line eval(product({E}), E),
 1648:     ?line eval(product({E, E}), E),
 1649:     ?line eval(product(set([a,b]), set([1,2])),
 1650:                relation([{a,1},{a,2},{b,1},{b,2}])),
 1651:     ?line eval(product({relation([]), E}), E),
 1652:     ok.
 1653: 
 1654: partition_1(suite) -> [];
 1655: partition_1(doc) -> [""];
 1656: partition_1(Conf) when is_list(Conf) ->
 1657:     ?line E = empty_set(),
 1658:     ?line ER = relation([]),
 1659:     ?line Id = fun(A) -> A end,
 1660:     ?line S1 = relation([{a,1},{b,2},{b,22},{c,0}]),
 1661:     ?line eval(partition(1, E), E),
 1662:     ?line eval(partition(2, E), E),
 1663:     ?line eval(partition(1, ER), from_term([], [type(ER)])),
 1664:     ?line eval(partition(2, ER), from_term([], [type(ER)])),
 1665:     ?line eval(partition(1, relation([{1,a},{1,b},{2,c},{2,d}])), 
 1666: 	       from_term([[{1,a},{1,b}],[{2,c},{2,d}]])),
 1667:     ?line eval(partition(2, relation([{1,a},{1,b},{2,a},{2,b},{3,c}])), 
 1668: 	       from_term([[{1,a},{2,a}],[{1,b},{2,b}],[{3,c}]])),
 1669:     ?line eval(partition(2, relation([{1,a}])), from_term([[{1,a}]])),
 1670:     ?line eval(partition(2, relation([{1,a},{2,b}])),
 1671: 			 from_term([[{1,a}],[{2,b}]])),
 1672:     ?line eval(partition(2, relation([{1,a},{2,a},{3,a}])), 
 1673: 	       from_term([[{1,a},{2,a},{3,a}]])),
 1674:     ?line eval(partition(2, relation([{1,b},{2,a}])), % OTP-4516
 1675: 	       from_term([[{1,b}],[{2,a}]])),
 1676:     ?line eval(union(partition(Id, S1)), S1),
 1677:     ?line eval(partition({external, fun({A,{B,_}}) -> {A,B} end}, 
 1678:                          from_term([{a,{b,c}},{b,{c,d}},{a,{b,f}}])),
 1679:                from_term([[{a,{b,c}},{a,{b,f}}],[{b,{c,d}}]])),
 1680:     F = 0.0, I = round(F),
 1681:     ?line FR = relation([{I,a},{F,b}]),
 1682:     if
 1683:         F == I -> % term ordering
 1684:             ?line eval(partition(1, FR), from_term([[{I,a},{F,b}]]));
 1685:         true -> 
 1686:             ?line eval(partition(1, FR), from_term([[{I,a}],[{F,b}]]))
 1687:     end,
 1688:     ?line {'EXIT', {badarg, _}} = (catch partition(2, set([a]))),
 1689:     ?line {'EXIT', {badarg, _}} = (catch partition(1, set([a]))),
 1690:     ?line eval(partition(Id, set([a])), from_term([[a]])),
 1691: 
 1692:     ?line eval(partition(E), E),
 1693:     ?line P1 = from_term([[a,b,c],[d,e,f],[g,h]]),
 1694:     ?line P2 = from_term([[a,d],[b,c,e,f,q,v]]),
 1695:     ?line eval(partition(union(P1, P2)), 
 1696:                from_term([[a],[b,c],[d],[e,f],[g,h],[q,v]])),
 1697:     ?line {'EXIT', {badarg, _}} = (catch partition(from_term([a]))),
 1698:     ok.
 1699: 
 1700: partition_3(suite) -> [];
 1701: partition_3(doc) -> [""];
 1702: partition_3(Conf) when is_list(Conf) ->
 1703:     ?line E = empty_set(),
 1704:     ?line ER = relation([]),
 1705: 
 1706:     %% set of ordered sets
 1707:     ?line S1 = relation([{a,1},{b,2},{b,22},{c,0}]),
 1708:     ?line eval(partition(1, S1, set([0,1,d,e])),
 1709: 	       lpartition(1, S1, set([0,1,d,e]))),
 1710:     ?line eval(partition(1, S1, E), lpartition(1, S1, E)),
 1711:     ?line eval(partition(2, ER, set([a,b])), lpartition(2, ER, set([a,b]))),
 1712: 
 1713:     XFun1 = {external, fun({_A,B,C}) -> {B,C} end},
 1714:     R1a = relation([{a,aa,1},{b,bb,2},{c,cc,3}]),
 1715:     R1b = relation([{bb,2},{cc,3}]),
 1716:     ?line eval(partition(XFun1, R1a, R1b), lpartition(XFun1, R1a, R1b)),
 1717: 
 1718:     Id = fun(X) -> X end,
 1719:     XId = {external, Id},
 1720:     R2 = relation([{a,b}]),
 1721:     ?line eval(partition(XId, R2, E), lpartition(XId, R2, E)),
 1722: 
 1723:     R3 = relation([{b,d}]),
 1724:     ?line eval(partition(XId, E, R3), lpartition(XId, E, R3)),
 1725: 
 1726:     Fun1 = fun(S) -> {_A,B,C} = to_external(S), from_term({B,C}) end,
 1727:     R4a = relation([{a,aa,1},{b,bb,2},{c,cc,3}]),
 1728:     R4b = relation([{bb,2},{cc,3}]),
 1729:     ?line eval(partition(Fun1,R4a,R4b), lpartition(Fun1,R4a,R4b)),
 1730: 
 1731:     XFun2 = {external, fun({_,{A},B}) -> {A,B} end},
 1732:     R5a = from_term([{a,{aa},1},{b,{bb},2},{c,{cc},3}]),
 1733:     R5b = from_term([{bb,2},{cc,3}]),
 1734:     ?line eval(partition(XFun2,R5a, R5b), lpartition(XFun2,R5a, R5b)),
 1735: 
 1736:     R6 = relation([{a,b}]),
 1737:     ?line eval(partition(2, R6, E), lpartition(2, R6, E)),
 1738: 
 1739:     R7 = relation([{b,d}]),
 1740:     ?line eval(partition(2, E, R7), lpartition(2, E, R7)),
 1741: 
 1742:     S2 = set([a]),
 1743:     ?line eval(partition(XId, E, S2), lpartition(XId, E, S2)),
 1744:     ?line eval(partition(XId, S1, E), lpartition(XId, S1, E)),
 1745:     ?line {'EXIT', {badarg, _}} =
 1746: 	(catch partition(3, relation([{a,b}]), E)),
 1747:     ?line {'EXIT', {badarg, _}} =
 1748: 	(catch partition(3, relation([{a,b}]), relation([{b,d}]))),
 1749:     ?line {'EXIT', {badarg, _}} =
 1750: 	(catch partition(3, relation([{a,b}]), set([{b,d}]))),
 1751:     ?line {'EXIT', {type_mismatch, _}} =
 1752: 	(catch partition(2, relation([{a,b}]), relation([{b,d}]))),
 1753:     ?line {'EXIT', {type_mismatch, _}} =
 1754: 	(catch partition({external, fun({A,_B}) -> A end}, 
 1755: 			 relation([{a,b}]), relation([{b,d}]))),
 1756:     ?line {'EXIT', {badarg, _}} = 
 1757: 	(catch partition({external, fun({A,_}) -> {A,0} end}, 
 1758: 			 from_term([{1,a}]),
 1759: 			 from_term([{1,0}]))),
 1760: 
 1761:     S18a = relation([{1,e},{2,b},{3,c},{4,b},{5,a},{6,0}]),
 1762:     S18b = set([b,d,f]),
 1763:     ?line eval(partition({external,fun({_,X}) -> X end}, S18a, S18b),
 1764: 	       lpartition({external,fun({_,X}) -> X end}, S18a, S18b)),
 1765:     S19a = sofs:relation([{3,a},{8,b}]),
 1766:     S19b = set([2,6,7]),
 1767:     ?line eval(partition({external,fun({X,_}) -> X end}, S19a, S19b),
 1768: 	       lpartition({external,fun({X,_}) -> X end}, S19a, S19b)),
 1769: 
 1770:     R8a = relation([{a,d},{b,e},{c,b},{d,c}]),
 1771:     S8 = set([b,d]),
 1772:     ?line eval(partition(2, R8a, S8), lpartition(2, R8a, S8)),
 1773: 
 1774:     S16a = relation([{1,e},{2,b},{3,c},{4,b},{5,a},{6,0}]),
 1775:     S16b = set([b,c,d]),
 1776:     ?line eval(partition(2, S16a, S16b), lpartition(2, S16a, S16b)),
 1777:     S17a = relation([{e,1},{b,2},{c,3},{b,4},{a,5},{0,6}]),
 1778:     S17b = set([b,c,d]),
 1779:     ?line eval(partition(1, S17a, S17b), lpartition(1, S17a, S17b)),
 1780: 
 1781:     ?line {'EXIT', {function_clause, _}} =
 1782: 	(catch partition({external, fun({A,_B}) -> A end}, set([]), E)),
 1783: 
 1784:     Fun3 = fun(S) -> from_term({to_external(S),0}, {type(S),atom}) end,
 1785:     S9a = set([1,2]),
 1786:     S9b = from_term([{1,0}]),
 1787:     ?line eval(partition(Fun3, S9a, S9b), lpartition(Fun3, S9a, S9b)),
 1788: 
 1789:     S14a = relation([{1,a},{2,b},{3,c},{0,0}]),
 1790:     S14b = set([b,c]),
 1791:     ?line eval(partition(2, S14a, S14b), lpartition(2, S14a, S14b)),
 1792:     S15a = relation([{a,1},{b,2},{c,3},{0,0}]),
 1793:     S15b = set([b,c]),
 1794:     ?line eval(partition(1, S15a, S15b), lpartition(1, S15a, S15b)),
 1795: 
 1796:     %% set of sets
 1797:     ?line {'EXIT', {badarg, _}} = 
 1798:         (catch partition({external, fun(X) -> X end}, 
 1799: 			 from_term([], [[atom]]), set([a]))),
 1800: 
 1801:     S10 = from_term([], [[atom]]),
 1802:     ?line eval(partition(Id, S10, E), lpartition(Id, S10, E)),
 1803: 
 1804:     S10e = from_term([[a],[b]], [[atom]]),
 1805:     ?line eval(partition(Id, S10e, E), lpartition(Id, S10e, E)),
 1806: 
 1807:     S11a = from_term([], [[atom]]),
 1808:     S11b = set([a]),
 1809:     ?line eval(partition(Id, S11a, S11b), lpartition(Id, S11a, S11b)),
 1810: 
 1811:     S12a = from_term([[[a],[b]], [[b],[c]], [[], [a,b]], [[1],[2]]]),
 1812:     S12b = from_term([[a,b],[1,2,3],[b,c]]),
 1813:     ?line eval(partition(fun sofs:union/1, S12a, S12b),
 1814: 	       lpartition(fun sofs:union/1, S12a, S12b)),
 1815: 
 1816:     Fun13 = fun(_) -> from_term([a]) end,
 1817:     S13a = from_term([], [[atom]]),
 1818:     S13b = from_term([], [[a]]),
 1819:     ?line eval(partition(Fun13, S13a, S13b), lpartition(Fun13, S13a, S13b)),
 1820: 
 1821:     ?line {'EXIT', {type_mismatch, _}} =
 1822:         (catch partition(fun(_) -> from_term([a]) end, 
 1823: 			 from_term([[1,2],[3,4]]),
 1824: 			 from_term([], [atom]))),
 1825:     Fun10 = fun(S) ->
 1826:                    %% Cheating a lot...
 1827:                    case to_external(S) of
 1828:                        [1] -> from_term({1,1});
 1829:                        _ -> S
 1830:                    end
 1831:            end,
 1832:     ?line {'EXIT', {type_mismatch, _}} =
 1833:         (catch partition(Fun10, from_term([[1]]), from_term([], [[atom]]))),
 1834:     ?line {'EXIT', {type_mismatch, _}} = 
 1835:         (catch partition(fun(_) -> from_term({a}) end, 
 1836: 			 from_term([[a]]),
 1837: 			 from_term([], [atom]))),
 1838:     ?line {'EXIT', {badarg, _}} = 
 1839:         (catch partition(fun(_) -> {a} end, 
 1840: 			 from_term([[a]]),
 1841: 			 from_term([], [atom]))),
 1842:     ok.
 1843: 
 1844: lpartition(F, S1, S2) ->
 1845:     {restriction(F, S1, S2), drestriction(F, S1, S2)}.
 1846: 
 1847: multiple_relative_product(suite) -> [];
 1848: multiple_relative_product(doc) -> [""];
 1849: multiple_relative_product(Conf) when is_list(Conf) ->
 1850:     ?line E = empty_set(),
 1851:     ?line ER = relation([]),
 1852:     ?line T = relation([{a,1},{a,11},{b,2},{c,3},{c,33},{d,4}]), 
 1853:     ?line {'EXIT', {badarg, _}} = 
 1854:         (catch multiple_relative_product({}, ER)),
 1855:     ?line {'EXIT', {badarg, _}} = 
 1856: 	(catch multiple_relative_product({}, relation([{a,b}]))),
 1857:     ?line eval(multiple_relative_product({E,T,T}, relation([], 3)), E),
 1858:     ?line eval(multiple_relative_product({T,T,T}, E), E),
 1859:     ?line eval(multiple_relative_product({T,T,T}, relation([],3)), 
 1860:                from_term([],[{{atom,atom,atom},{atom,atom,atom}}])),
 1861:     ?line eval(multiple_relative_product({T,T,T}, 
 1862:                                    relation([{a,b,c},{c,d,a}])),
 1863:                from_term([{{a,b,c},{1,2,3}}, {{a,b,c},{1,2,33}},
 1864:                           {{a,b,c},{11,2,3}}, {{a,b,c},{11,2,33}},
 1865:                           {{c,d,a},{3,4,1}}, {{c,d,a},{3,4,11}},
 1866:                           {{c,d,a},{33,4,1}}, {{c,d,a},{33,4,11}}])),
 1867:     ?line {'EXIT', {type_mismatch, _}} =
 1868: 	(catch multiple_relative_product({T}, from_term([{{a}}]))), 
 1869:     ok.
 1870: 
 1871: digraph(suite) -> [];
 1872: digraph(doc) -> [""];
 1873: digraph(Conf) when is_list(Conf) ->
 1874:     ?line T0 = ets:all(),
 1875:     ?line E = empty_set(),
 1876:     ?line R = relation([{a,b},{b,c},{c,d},{d,a}]),
 1877:     ?line F = relation_to_family(R),
 1878:     Type = type(F),
 1879: 
 1880:     ?line {'EXIT', {badarg, _}} = 
 1881:         (catch family_to_digraph(set([a]))),
 1882:     digraph_fail(badarg, catch family_to_digraph(set([a]), [foo])),
 1883:     digraph_fail(badarg, catch family_to_digraph(F, [foo])),
 1884:     digraph_fail(cyclic, catch family_to_digraph(family([{a,[a]}]),[acyclic])),
 1885: 
 1886:     ?line G1 = family_to_digraph(E),
 1887:     ?line {'EXIT', {badarg, _}} = (catch digraph_to_family(G1, foo)),
 1888:     ?line {'EXIT', {badarg, _}} = (catch digraph_to_family(G1, atom)),
 1889:     ?line true = [] == to_external(digraph_to_family(G1)),
 1890:     ?line true = [] == to_external(digraph_to_family(G1, Type)),
 1891:     ?line true = digraph:delete(G1),
 1892: 
 1893:     ?line G1a = family_to_digraph(E, [protected]),
 1894:     ?line true = [] == to_external(digraph_to_family(G1a)),
 1895:     ?line true = [] == to_external(digraph_to_family(G1a, Type)),
 1896:     ?line true = digraph:delete(G1a),
 1897: 
 1898:     ?line G2 = family_to_digraph(F),
 1899:     ?line true = F == digraph_to_family(G2),
 1900:     ?line true = F == digraph_to_family(G2, type(F)),
 1901:     ?line true = digraph:delete(G2),
 1902: 
 1903:     ?line R2 = from_term([{{a},b},{{c},d}]),
 1904:     ?line F2 = relation_to_family(R2),
 1905:     ?line Type2 = type(F2),
 1906:     ?line G3 = family_to_digraph(F2, [protected]),
 1907:     ?line true = is_subset(F2, digraph_to_family(G3, Type2)),
 1908:     ?line true = digraph:delete(G3),
 1909: 
 1910:     Fl = 0.0, I = round(Fl),
 1911:     if
 1912:         Fl == I -> % term ordering
 1913:             ?line G4 = digraph:new(),
 1914:             digraph:add_vertex(G4, Fl),
 1915:             digraph:add_vertex(G4, I),
 1916:             ?line {'EXIT', {badarg, _}} = 
 1917:                 (catch digraph_to_family(G4, Type)),
 1918:             ?line {'EXIT', {badarg, _}} = 
 1919:                 (catch digraph_to_family(G4)),
 1920:             ?line true = digraph:delete(G4);
 1921:         true -> ok
 1922:     end,
 1923:     
 1924:     ?line true = T0 == ets:all(),
 1925:     ok.
 1926: 
 1927: digraph_fail(ExitReason, Fail) ->
 1928:     {'EXIT', {ExitReason, [{sofs,family_to_digraph,A,_}|_]}} = Fail,
 1929:     case {test_server:is_native(sofs),A} of
 1930: 	{false,[_,_]} -> ok;
 1931: 	{true,2} -> ok
 1932:     end.
 1933: 
 1934: constant_function(suite) -> [];
 1935: constant_function(doc) -> [""];
 1936: constant_function(Conf) when is_list(Conf) ->
 1937:     ?line E = empty_set(),
 1938:     ?line C = from_term(3),
 1939:     ?line eval(constant_function(E, C), E),
 1940:     ?line eval(constant_function(set([a,b]), E), from_term([{a,[]},{b,[]}])),
 1941:     ?line eval(constant_function(set([a,b]), C), from_term([{a,3},{b,3}])),
 1942:     ?line {'EXIT', {badarg, _}} = (catch constant_function(C, C)),
 1943:     ?line {'EXIT', {badarg, _}} = (catch constant_function(set([]), foo)),
 1944:     ok.
 1945: 
 1946: misc(suite) -> [];
 1947: misc(doc) -> [""];
 1948: misc(Conf) when is_list(Conf) ->
 1949:     % find "relational" part of relation:
 1950:     ?line S = relation([{a,b},{b,c},{b,d},{c,d}]),
 1951:     Id = fun(A) -> A end,
 1952:     ?line RR = relational_restriction(S),
 1953:     ?line eval(union(difference(partition(Id,S), partition(1,S))), RR),
 1954:     ?line eval(union(difference(partition(1,S), partition(Id,S))), RR),
 1955: 
 1956:     % the "functional" part:
 1957:     ?line eval(union(intersection(partition(1,S), partition(Id,S))),
 1958:                difference(S, RR)),
 1959:     ?line {'EXIT', {undef, _}} =    
 1960:         (catch projection(fun external:foo/1, set([a,b,c]))),
 1961:     ok.
 1962: 
 1963: relational_restriction(R) ->
 1964:     Fun = fun(S) -> no_elements(S) > 1 end,
 1965:     family_to_relation(family_specification(Fun, relation_to_family(R))).
 1966: 
 1967: 
 1968: family_specification(suite) -> [];
 1969: family_specification(doc) -> [""];
 1970: family_specification(Conf) when is_list(Conf) ->
 1971:     E = empty_set(),
 1972:     %% internal
 1973:     ?line eval(family_specification(fun sofs:is_set/1, E), E),
 1974:     ?line {'EXIT', {badarg, _}} =    
 1975:        (catch family_specification(fun sofs:is_set/1, set([]))),
 1976:     ?line F1 = from_term([{1,[1]}]),
 1977:     ?line eval(family_specification(fun sofs:is_set/1, F1), F1),
 1978:     Fun = fun(S) -> is_subset(S, set([0,1,2,3,4])) end,
 1979:     ?line F2 = family([{a,[1,2]},{b,[3,4,5]}]),
 1980:     ?line eval(family_specification(Fun, F2), family([{a,[1,2]}])),
 1981:     ?line F3 = from_term([{a,[]},{b,[]}]),
 1982:     ?line eval(family_specification(fun sofs:is_set/1, F3), F3),
 1983:     Fun2 = fun(_) -> throw(fippla) end, 
 1984:     ?line fippla = (catch family_specification(Fun2, family([{a,[1]}]))),
 1985:     Fun3 = fun(_) -> neither_true_nor_false end,
 1986:     ?line {'EXIT', {badarg, _}} = 
 1987: 	(catch family_specification(Fun3, F3)),
 1988: 
 1989:     %% external
 1990:     IsList = {external, fun(L) when is_list(L) -> true; (_) -> false end},
 1991:     ?line eval(family_specification(IsList, E), E),
 1992:     ?line eval(family_specification(IsList, F1), F1),
 1993:     MF = {external, fun(L) -> lists:member(3, L) end},
 1994:     ?line eval(family_specification(MF, F2), family([{b,[3,4,5]}])),
 1995:     ?line fippla = (catch family_specification(Fun2, family([{a,[1]}]))),
 1996:     ?line {'EXIT', {badarg, _}} = 
 1997: 	(catch family_specification({external, Fun3}, F3)),
 1998:     ok.
 1999: 
 2000: family_domain_1(suite) -> [];
 2001: family_domain_1(doc) -> [""];
 2002: family_domain_1(Conf) when is_list(Conf) ->
 2003:     ?line E = empty_set(),
 2004:     ?line ER = from_term([{a,[]},{b,[]}],[{atom,[{atom,atom}]}]),
 2005:     ?line EF = from_term([{a,[]},{b,[]}],[{atom,[atom]}]),
 2006:     ?line eval(family_domain(E), E),
 2007:     ?line eval(family_domain(ER), EF),
 2008:     ?line FR = from_term([{a,[{1,a},{2,b},{3,c}]},{b,[]},{c,[{4,d},{5,e}]}]),
 2009:     ?line eval(family_domain(FR), from_term([{a,[1,2,3]},{b,[]},{c,[4,5]}])),
 2010:     ?line eval(family_field(E), E),
 2011:     ?line eval(family_field(FR), 
 2012:                from_term([{a,[a,b,c,1,2,3]},{b,[]},{c,[d,e,4,5]}])),
 2013:     ?line eval(family_domain(from_term([{{a},[{{1,[]},c}]}])),
 2014:                from_term([{{a},[{1,[]}]}])),
 2015:     ?line eval(family_domain(from_term([{{a},[{{1,[a]},c}]}])),
 2016:                from_term([{{a},[{1,[a]}]}])),
 2017:     ?line eval(family_domain(from_term([{{a},[]}])),
 2018: 	       from_term([{{a},[]}])),
 2019:     ?line eval(family_domain(from_term([], type(FR))), 
 2020:                from_term([], [{atom,[atom]}])),
 2021:     ?line {'EXIT', {badarg, _}} = (catch family_domain(set([a]))),
 2022:     ?line {'EXIT', {badarg, _}} = (catch family_field(set([a]))),
 2023:     ?line {'EXIT', {badarg, _}} = (catch family_domain(set([{a,[b]}]))),
 2024:     ok.
 2025: 
 2026: family_range_1(suite) -> [];
 2027: family_range_1(doc) -> [""];
 2028: family_range_1(Conf) when is_list(Conf) ->
 2029:     ?line E = empty_set(),
 2030:     ?line ER = from_term([{a,[]},{b,[]}],[{atom,[{atom,atom}]}]),
 2031:     ?line EF = from_term([{a,[]},{b,[]}],[{atom,[atom]}]),
 2032:     ?line eval(family_range(E), E),
 2033:     ?line eval(family_range(ER), EF),
 2034:     ?line FR = from_term([{a,[{1,a},{2,b},{3,c}]},{b,[]},{c,[{4,d},{5,e}]}]),
 2035:     ?line eval(family_range(FR), from_term([{a,[a,b,c]},{b,[]},{c,[d,e]}])),
 2036:     ?line eval(family_range(from_term([{{a},[{c,{1,[a]}}]}])),
 2037:                from_term([{{a},[{1,[a]}]}])),
 2038:     ?line eval(family_range(from_term([{{a},[{c,{1,[]}}]}])),
 2039:                from_term([{{a},[{1,[]}]}])),
 2040:     ?line eval(family_range(from_term([{{a},[]}])),
 2041: 	       from_term([{{a},[]}])),
 2042:     ?line eval(family_range(from_term([], type(FR))), 
 2043:                from_term([], [{atom,[atom]}])),
 2044:     ?line {'EXIT', {badarg, _}} = (catch family_range(set([a]))),
 2045:     ?line {'EXIT', {badarg, _}} = (catch family_range(set([{a,[b]}]))),
 2046:     ok.
 2047: 
 2048: family_to_relation_1(suite) -> [];
 2049: family_to_relation_1(doc) -> [""];
 2050: family_to_relation_1(Conf) when is_list(Conf) ->
 2051:     ?line E = empty_set(),
 2052:     ?line ER = relation([]),
 2053:     ?line EF = family([]),
 2054:     ?line eval(family_to_relation(E), E),
 2055:     ?line eval(family_to_relation(EF), ER),
 2056:     ?line eval(sofs:fam2rel(EF), ER),
 2057:     ?line F = family([{a,[]},{b,[1]},{c,[7,9,11]}]),
 2058:     ?line eval(family_to_relation(F), relation([{b,1},{c,7},{c,9},{c,11}])),
 2059:     ?line {'EXIT', {badarg, _}} = (catch family_to_relation(set([a]))),
 2060:     ok.
 2061: 
 2062: union_of_family_1(suite) -> [];
 2063: union_of_family_1(doc) -> [""];
 2064: union_of_family_1(Conf) when is_list(Conf) ->
 2065:     ?line E = empty_set(),
 2066:     ?line EF = from_term([{a,[]},{b,[]}],[{atom,[atom]}]),
 2067:     ?line eval(union_of_family(E), E),
 2068:     ?line eval(union_of_family(EF), set([])),
 2069:     ?line eval(union_of_family(family([])), set([])),
 2070:     ?line FR = from_term([{a,[1,2,3]},{b,[]},{c,[4,5]}]),
 2071:     ?line eval(union_of_family(FR), set([1,2,3,4,5])),
 2072:     ?line eval(union_of_family(sofs:family([{a,[1,2]},{b,[1,2]}])),
 2073: 	       set([1,2])),
 2074:     ?line {'EXIT', {badarg, _}} = (catch union_of_family(set([a]))),
 2075:     ok.
 2076: 
 2077: intersection_of_family_1(suite) -> [];
 2078: intersection_of_family_1(doc) -> [""];
 2079: intersection_of_family_1(Conf) when is_list(Conf) ->
 2080:     ?line EF = from_term([{a,[]},{b,[]}],[{atom,[atom]}]),
 2081:     ?line eval(intersection_of_family(EF), set([])),
 2082:     ?line FR = from_term([{a,[1,2,3]},{b,[2,3]},{c,[3,4,5]}]),
 2083:     ?line eval(intersection_of_family(FR), set([3])),
 2084:     ?line {'EXIT', {badarg, _}} = 
 2085:         (catch intersection_of_family(family([]))),
 2086:     ?line EE = from_term([], [[atom]]),
 2087:     ?line {'EXIT', {badarg, _}} = (catch intersection_of_family(EE)),
 2088:     ?line {'EXIT', {badarg, _}} = (catch intersection_of_family(set([a]))),
 2089:     ok.
 2090: 
 2091: family_projection(suite) -> [];
 2092: family_projection(doc) -> [""];
 2093: family_projection(Conf) when is_list(Conf) ->
 2094:     SSType = [{atom,[[atom]]}],
 2095:     SRType = [{atom,[{atom,atom}]}],
 2096:     ?line E = empty_set(),
 2097: 
 2098:     ?line eval(family_projection(fun(X) -> X end, family([])), E),
 2099:     ?line L1 = [{a,[]}],
 2100:     ?line eval(family_projection(fun sofs:union/1, E), E),
 2101:     ?line eval(family_projection(fun sofs:union/1, from_term(L1, SSType)),
 2102:                family(L1)),
 2103:     ?line {'EXIT', {badarg, _}} =    
 2104:         (catch family_projection(fun sofs:union/1, set([]))),
 2105:     ?line {'EXIT', {badarg, _}} =
 2106:         (catch family_projection(fun sofs:union/1, from_term([{1,[1]}]))),
 2107: 
 2108:     ?line F2 = from_term([{a,[[1],[2]]},{b,[[3,4],[5]]}], SSType),
 2109:     ?line eval(family_projection(fun sofs:union/1, F2),
 2110:                family_union(F2)),
 2111: 
 2112:     ?line F3 = from_term([{1,[{a,b},{b,c},{c,d}]},{3,[]},{5,[{3,5}]}],
 2113:                          SRType),
 2114:     ?line eval(family_projection(fun sofs:domain/1, F3), family_domain(F3)),
 2115:     ?line eval(family_projection(fun sofs:range/1, F3), family_range(F3)),
 2116: 
 2117:     ?line eval(family_projection(fun(_) -> E end, family([{a,[b,c]}])),
 2118: 	       from_term([{a,[]}])),
 2119: 
 2120:     Fun1 = fun(S) ->
 2121:                    case to_external(S) of
 2122:                        [1] -> from_term({1,1});
 2123:                        _ -> S
 2124:                    end
 2125:            end,
 2126:     ?line eval(family_projection(Fun1, family([{a,[1]}])), 
 2127: 	       from_term([{a,{1,1}}])),
 2128:     Fun2 = fun(_) -> throw(fippla) end, 
 2129:     ?line fippla = 
 2130:         (catch family_projection(Fun2, family([{a,[1]}]))),
 2131:     ?line {'EXIT', {type_mismatch, _}} =
 2132:         (catch family_projection(Fun1, from_term([{1,[1]},{2,[2]}]))),
 2133:     ?line {'EXIT', {type_mismatch, _}} =
 2134:         (catch family_projection(Fun1, from_term([{1,[1]},{0,[0]}]))),
 2135: 
 2136:     ?line eval(family_projection(fun(_) -> E end, from_term([{a,[]}])),
 2137: 	       from_term([{a,[]}])),
 2138:     F4 = from_term([{a,[{1,2,3}]},{b,[{4,5,6}]},{c,[]},{m3,[]}]),
 2139:     Z = from_term(0),
 2140:     ?line eval(family_projection(fun(S) -> local_adjoin(S, Z) end, F4),
 2141: 	      from_term([{a,[{{1,2,3},0}]},{b,[{{4,5,6},0}]},{c,[]},{m3,[]}])),
 2142:     ?line {'EXIT', {badarg, _}} =
 2143:         (catch family_projection({external, fun(X) -> X end}, 
 2144: 				 from_term([{1,[1]}]))),
 2145: 
 2146:     %% ordered set element
 2147:     ?line eval(family_projection(fun(_) -> from_term(a, atom) end, 
 2148: 				 from_term([{1,[a]}])),
 2149: 	       from_term([{1,a}])),
 2150:     ok.
 2151: 
 2152: family_difference(suite) -> [];
 2153: family_difference(doc) -> [""];
 2154: family_difference(Conf) when is_list(Conf) ->
 2155:     ?line E = empty_set(),
 2156:     ?line EF = family([]),
 2157:     ?line F9 = from_term([{b,[b,c]}]),
 2158:     ?line F10 = from_term([{a,[b,c]}]),
 2159:     ?line eval(family_difference(E, E), E),
 2160:     ?line eval(family_difference(E, F10), from_term([], type(F10))),
 2161:     ?line eval(family_difference(F10, E), F10),
 2162:     ?line eval(family_difference(F9, F10), F9),
 2163:     ?line eval(family_difference(F10, F10), family([{a,[]}])),
 2164:     ?line F20 = from_term([{a,[1,2,3]},{b,[1,2,3]},{c,[1,2,3]}]),
 2165:     ?line F21 = from_term([{b,[1,2,3]},{c,[1,2,3]}]),
 2166:     ?line eval(family_difference(F20, from_term([{a,[2]}])),
 2167:                from_term([{a,[1,3]},{b,[1,2,3]},{c,[1,2,3]}])),
 2168:     ?line eval(family_difference(F20, from_term([{0,[2]},{q,[1,2]}])), F20),
 2169:     ?line eval(family_difference(F20, F21),
 2170:                from_term([{a,[1,2,3]},{b,[]},{c,[]}])),
 2171: 
 2172:     ?line eval(family_difference(from_term([{e,[f,g]}]), family([])),
 2173:                from_term([{e,[f,g]}])),
 2174:     ?line eval(family_difference(from_term([{e,[f,g]}]), EF),
 2175:                from_term([{e,[f,g]}])),
 2176:     ?line eval(family_difference(from_term([{a,[a,b,c,d]},{c,[b,c]}]),
 2177:                                  from_term([{a,[b,c]},{b,[d]},{d,[e,f]}])),
 2178:                from_term([{a,[a,d]},{c,[b,c]}])),
 2179:     ?line {'EXIT', {badarg, _}} = 
 2180: 	(catch family_difference(set([]), set([]))),
 2181:     ?line {'EXIT', {type_mismatch, _}} =    
 2182: 	(catch family_difference(from_term([{a,[b,c]}]),
 2183:                                  from_term([{e,[{f}]}]))),
 2184:     ?line {'EXIT', {type_mismatch, _}} =    
 2185: 	(catch family_difference(from_term([{a,[b]}]),
 2186:                                  from_term([{c,[d]}], [{i,[s]}]))),
 2187:     ok.
 2188: 
 2189: family_intersection_1(suite) -> [];
 2190: family_intersection_1(doc) -> [""];
 2191: family_intersection_1(Conf) when is_list(Conf) ->
 2192:     ?line E = empty_set(),
 2193:     ?line EF = family([]),
 2194:     ?line ES = from_term([], [{atom,[[atom]]}]),
 2195:     ?line eval(family_intersection(E), E),
 2196:     ?line {'EXIT', {badarg, _}} = (catch family_intersection(EF)),
 2197:     ?line eval(family_intersection(ES), EF),
 2198:     ?line {'EXIT', {badarg, _}} = (catch family_intersection(set([]))),
 2199:     ?line {'EXIT', {badarg, _}} = 
 2200:         (catch family_intersection(from_term([{a,[1,2]}]))),
 2201:     ?line F1 = from_term([{a,[[1],[2],[2,3]]},{b,[]},{c,[[4]]}]),
 2202:     ?line {'EXIT', {badarg, _}} = (catch family_intersection(F1)),
 2203:     ?line F2 = from_term([{b,[[1],[2],[2,3]]},{a,[]},{c,[[4]]}]),
 2204:     ?line {'EXIT', {badarg, _}} = (catch family_intersection(F2)),
 2205:     ?line F3 = from_term([{a,[[1,2,3],[2],[2,3]]},{c,[[4,5,6],[5,6,7]]}]),
 2206:     ?line eval(family_intersection(F3), family([{a,[2]},{c,[5,6]}])),
 2207:     ok.
 2208: 
 2209: family_intersection_2(suite) -> [];
 2210: family_intersection_2(doc) -> [""];
 2211: family_intersection_2(Conf) when is_list(Conf) ->
 2212:     ?line E = empty_set(),
 2213:     ?line EF = family([]),
 2214:     ?line F1 = from_term([{a,[1,2]},{b,[4,5]},{c,[7,8]},{d,[10,11]}]),
 2215:     ?line F2 = from_term([{c,[6,7]},{d,[9,10,11]},{q,[1]}]),
 2216:     ?line F3 = from_term([{a,[1,2]},{b,[4,5]},{c,[6,7,8]},{d,[9,10,11]},
 2217:                           {q,[1]}]),
 2218: 
 2219:     ?line eval(family_intersection(E, E), E),
 2220:     ?line eval(family_intersection(EF, EF), EF),
 2221:     ?line eval(family_intersection(F1, F2), 
 2222:                from_term([{c,[7]},{d,[10,11]}])),
 2223:     ?line eval(family_intersection(F1, F3), F1),
 2224:     ?line eval(family_intersection(F2, F3), F2),
 2225: 
 2226:     ?line eval(family_intersection(EF, from_term([{e,[f,g]}])), EF),
 2227:     ?line eval(family_intersection(E, from_term([{e,[f,g]}])), EF),
 2228:     ?line eval(family_intersection(from_term([{e,[f,g]}]), EF), EF),
 2229:     ?line eval(family_intersection(from_term([{e,[f,g]}]), E), EF),
 2230:     ?line {'EXIT', {type_mismatch, _}} =    
 2231: 	(catch family_intersection(from_term([{a,[b,c]}]),
 2232:                                    from_term([{e,[{f}]}]))),
 2233: 
 2234:     ?line F11 = family([{a,[1,2,3]},{b,[0,2,4]},{c,[0,3,6,9]}]),
 2235:     ?line eval(union_of_family(F11), set([0,1,2,3,4,6,9])),
 2236:     ?line F12 = from_term([{a,[1,2,3,4]},{b,[0,2,4]},{c,[2,3,4,5]}]),
 2237:     ?line eval(intersection_of_family(F12), set([2,4])),
 2238:     ok.
 2239: 
 2240: family_union_1(suite) -> [];
 2241: family_union_1(doc) -> [""];
 2242: family_union_1(Conf) when is_list(Conf) ->
 2243:     ?line E = empty_set(),
 2244:     ?line EF = family([]),
 2245:     ?line ES = from_term([], [{atom,[[atom]]}]),
 2246:     ?line eval(family_union(E), E),
 2247:     ?line eval(family_union(ES), EF),
 2248:     ?line {'EXIT', {badarg, _}} = (catch family_union(set([]))),
 2249:     ?line {'EXIT', {badarg, _}} = 
 2250:         (catch family_union(from_term([{a,[1,2]}]))),
 2251:     ?line eval(family_union(from_term([{a,[[1],[2],[2,3]]},{b,[]},{c,[[4]]}])),
 2252:                family([{a,[1,2,3]},{b,[]},{c,[4]}])),
 2253:     ok.
 2254: 
 2255: family_union_2(suite) -> [];
 2256: family_union_2(doc) -> [""];
 2257: family_union_2(Conf) when is_list(Conf) ->
 2258:     ?line E = empty_set(),
 2259:     ?line EF = family([]),
 2260:     ?line F1 = from_term([{a,[1,2]},{b,[4,5]},{c,[7,8]},{d,[10,11]}]),
 2261:     ?line F2 = from_term([{c,[6,7]},{d,[9,10,11]},{q,[1]}]),
 2262:     ?line F3 = from_term([{a,[1,2]},{b,[4,5]},{c,[6,7,8]},{d,[9,10,11]},
 2263:                           {q,[1]}]),
 2264: 
 2265:     ?line eval(family_union(E, E), E),
 2266:     ?line eval(family_union(F1, E), F1),
 2267:     ?line eval(family_union(E, F2), F2),
 2268:     ?line eval(family_union(F1, F2), F3),
 2269:     ?line eval(family_union(F2, F1), F3),
 2270: 
 2271:     ?line eval(family_union(E, from_term([{e,[f,g]}])),
 2272:                from_term([{e,[f,g]}])),
 2273:     ?line eval(family_union(EF, from_term([{e,[f,g]}])),
 2274:                from_term([{e,[f,g]}])),
 2275:     ?line eval(family_union(from_term([{e,[f,g]}]), E), 
 2276:                from_term([{e,[f,g]}])),
 2277:     ?line {'EXIT', {badarg, _}} = 
 2278: 	(catch family_union(set([]),set([]))),
 2279:     ?line {'EXIT', {type_mismatch, _}} =    
 2280: 	(catch family_union(from_term([{a,[b,c]}]), 
 2281:                             from_term([{e,[{f}]}]))),
 2282:     ok.
 2283: 
 2284: partition_family(suite) -> [];
 2285: partition_family(doc) -> [""];
 2286: partition_family(Conf) when is_list(Conf) ->
 2287:     ?line E = empty_set(),
 2288: 
 2289:     %% set of ordered sets
 2290:     ?line ER = relation([]),
 2291:     ?line EF = from_term([], [{atom,[{atom,atom}]}]),
 2292: 
 2293:     ?line eval(partition_family(1, E), E),
 2294:     ?line eval(partition_family(2, E), E),
 2295:     ?line eval(partition_family(fun sofs:union/1, E), E),
 2296:     ?line eval(partition_family(1, ER), EF),
 2297:     ?line eval(partition_family(2, ER), EF),
 2298:     ?line {'EXIT', {badarg, _}} = (catch partition_family(1, set([]))),
 2299:     ?line {'EXIT', {badarg, _}} = (catch partition_family(2, set([]))),
 2300:     ?line {'EXIT', {function_clause, _}} =
 2301: 	(catch partition_family(fun({_A,B}) -> {B} end, from_term([{1}]))),
 2302:     ?line eval(partition_family(1, relation([{1,a},{1,b},{2,c},{2,d}])), 
 2303: 	       from_term([{1,[{1,a},{1,b}]},{2,[{2,c},{2,d}]}])),
 2304:     ?line eval(partition_family(1, relation([{1,a},{2,b}])),
 2305: 	       from_term([{1,[{1,a}]},{2,[{2,b}]}])),
 2306:     ?line eval(partition_family(2, relation([{1,a},{1,b},{2,a},{2,b},{3,c}])), 
 2307: 	       from_term([{a,[{1,a},{2,a}]},{b,[{1,b},{2,b}]},{c,[{3,c}]}])),
 2308:     ?line eval(partition_family(2, relation([{1,a}])), 
 2309: 	       from_term([{a,[{1,a}]}])),
 2310:     ?line eval(partition_family(2, relation([{1,a},{2,a},{3,a}])), 
 2311: 	       from_term([{a,[{1,a},{2,a},{3,a}]}])),
 2312:     ?line eval(partition_family(2, relation([{1,a},{2,b}])),
 2313: 	       from_term([{a,[{1,a}]},{b,[{2,b}]}])),
 2314:     ?line F13 = from_term([{a,b,c},{a,b,d},{b,b,c},{a,c,c},{a,c,d},{b,c,c}]),
 2315:     ?line eval(partition_family(2, F13),
 2316:                from_term([{b,[{a,b,c},{a,b,d},{b,b,c}]},
 2317:                           {c,[{a,c,c},{a,c,d},{b,c,c}]}])),
 2318: 
 2319:     Fun1 = {external, fun({A,_B}) -> {A} end}, 
 2320:     ?line eval(partition_family(Fun1, relation([{a,1},{a,2},{b,3}])),
 2321: 	       from_term([{{a},[{a,1},{a,2}]},{{b},[{b,3}]}])),
 2322:     Fun2 = fun(S) -> {A,_B} = to_external(S), from_term({A}) end,
 2323:     ?line eval(partition_family(Fun2, relation([{a,1},{a,2},{b,3}])),
 2324: 	       from_term([{{a},[{a,1},{a,2}]},{{b},[{b,3}]}])),
 2325: 
 2326:     ?line {'EXIT', {badarg, _}} = 
 2327: 	(catch partition_family({external, fun({A,_}) -> {A,0} end}, 
 2328: 				from_term([{1,a}]))),
 2329:     ?line [{{atom,atom},[{atom,atom,atom,atom}]}] = 
 2330: 	type(partition_family({external, fun({A,_B,C,_D}) -> {C,A} end}, 
 2331: 			      relation([],4))),
 2332: 
 2333:     Fun3 = fun(S) -> from_term({to_external(S),0}, {type(S),atom}) end,
 2334:     ?line eval(partition_family(Fun3, E), E),
 2335:     ?line eval(partition_family(Fun3, set([a,b])),
 2336: 	       from_term([{{a,0},[a]}, {{b,0},[b]}])),
 2337:     ?line eval(partition_family(Fun3, relation([{a,1},{b,2}])),
 2338: 	       from_term([{{{a,1},0},[{a,1}]},{{{b,2},0},[{b,2}]}])),
 2339:     ?line eval(partition_family(Fun3, from_term([[a],[b]])),
 2340: 	       from_term([{{[a],0},[[a]]}, {{[b],0},[[b]]}])),
 2341:     ?line partition_family({external, fun(X) -> X end}, E),
 2342: 
 2343:     F = 0.0, I = round(F),
 2344:     ?line FR = relation([{I,a},{F,b}]),
 2345:     if
 2346:         F == I -> % term ordering
 2347:             ?line true = (1 =:= no_elements(partition_family(1, FR)));
 2348:         true -> 
 2349:             ?line eval(partition_family(1, FR), 
 2350:                        from_term([{I,[{I,a}]},{F,[{F,b}]}]))
 2351:     end,
 2352:     %% set of sets
 2353:     ?line {'EXIT', {badarg, _}} = 
 2354:         (catch partition_family({external, fun(X) -> X end}, 
 2355: 				from_term([], [[atom]]))),
 2356:     ?line {'EXIT', {badarg, _}} = 
 2357:         (catch partition_family({external, fun(X) -> X end}, 
 2358: 				from_term([[a]]))),
 2359:     ?line eval(partition_family(fun sofs:union/1,
 2360: 				from_term([[[1],[1,2]], [[1,2]]])),
 2361: 	       from_term([{[1,2], [[[1],[1,2]],[[1,2]]]}])),
 2362:     ?line eval(partition_family(fun(X) -> X end, 
 2363: 				from_term([[1],[1,2],[1,2,3]])),
 2364: 	       from_term([{[1],[[1]]},{[1,2],[[1,2]]},{[1,2,3],[[1,2,3]]}])),
 2365: 
 2366:     ?line eval(partition_family(fun(_) -> from_term([a]) end, 
 2367:                                 from_term([], [[atom]])),
 2368: 	       E),
 2369:     Fun10 = fun(S) ->
 2370:                    %% Cheating a lot...
 2371:                    case to_external(S) of
 2372:                        [1] -> from_term({1,1});
 2373:                        _ -> S
 2374:                    end
 2375:            end,
 2376: 
 2377:     ?line eval(partition_family(Fun10, from_term([[1]])),
 2378: 	       from_term([{{1,1},[[1]]}])),
 2379:     ?line eval(partition_family(fun(_) -> from_term({a}) end, 
 2380:                                 from_term([[a]])),
 2381: 	       from_term([{{a},[[a]]}])),
 2382:     ?line {'EXIT', {badarg, _}} = 
 2383:          (catch partition_family(fun(_) -> {a} end, from_term([[a]]))),
 2384:     ok.
 2385: 
 2386: %% Not meant to be efficient...
 2387: local_adjoin(S, C) ->
 2388:     X = to_external(C),
 2389:     T = type(C),
 2390:     F = fun(Y) -> from_term({to_external(Y),X}, {type(Y),T}) end,
 2391:     projection(F, S).
 2392: 
 2393: eval(R, E) when R == E ->
 2394:     R;
 2395: eval(R, E) ->
 2396:     io:format("expected ~p~n got ~p~n", [E, R]),
 2397:     exit({R,E}).
 2398: