1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- A D A . C O N T A I N E R S . F O R M A L _ H A S H E D _ S E T S --
9 -- Copyright (C) 2010-2014, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
26 ------------------------------------------------------------------------------
28 with Ada
.Containers
.Hash_Tables
.Generic_Bounded_Operations
;
29 pragma Elaborate_All
(Ada
.Containers
.Hash_Tables
.Generic_Bounded_Operations
);
31 with Ada
.Containers
.Hash_Tables
.Generic_Bounded_Keys
;
32 pragma Elaborate_All
(Ada
.Containers
.Hash_Tables
.Generic_Bounded_Keys
);
34 with Ada
.Containers
.Prime_Numbers
; use Ada
.Containers
.Prime_Numbers
;
36 with System
; use type System
.Address
;
38 package body Ada
.Containers
.Formal_Hashed_Sets
is
39 pragma SPARK_Mode
(Off
);
41 -----------------------
42 -- Local Subprograms --
43 -----------------------
45 -- All need comments ???
51 function Equivalent_Keys
53 Node
: Node_Type
) return Boolean;
54 pragma Inline
(Equivalent_Keys
);
61 with procedure Set_Element
(Node
: in out Node_Type
);
62 procedure Generic_Allocate
64 Node
: out Count_Type
);
66 function Hash_Node
(Node
: Node_Type
) return Hash_Type
;
67 pragma Inline
(Hash_Node
);
70 (Container
: in out Set
;
71 New_Item
: Element_Type
;
72 Node
: out Count_Type
;
73 Inserted
: out Boolean);
75 procedure Intersection
82 Key
: Node_Type
) return Boolean;
83 pragma Inline
(Is_In
);
85 procedure Set_Element
(Node
: in out Node_Type
; Item
: Element_Type
);
86 pragma Inline
(Set_Element
);
88 function Next
(Node
: Node_Type
) return Count_Type
;
91 procedure Set_Next
(Node
: in out Node_Type
; Next
: Count_Type
);
92 pragma Inline
(Set_Next
);
94 function Vet
(Container
: Set
; Position
: Cursor
) return Boolean;
96 --------------------------
97 -- Local Instantiations --
98 --------------------------
100 package HT_Ops
is new Hash_Tables
.Generic_Bounded_Operations
101 (HT_Types
=> HT_Types
,
102 Hash_Node
=> Hash_Node
,
104 Set_Next
=> Set_Next
);
106 package Element_Keys
is new Hash_Tables
.Generic_Bounded_Keys
107 (HT_Types
=> HT_Types
,
109 Set_Next
=> Set_Next
,
110 Key_Type
=> Element_Type
,
112 Equivalent_Keys
=> Equivalent_Keys
);
114 procedure Replace_Element
is
115 new Element_Keys
.Generic_Replace_Element
(Hash_Node
, Set_Element
);
121 function "=" (Left
, Right
: Set
) return Boolean is
123 if Length
(Left
) /= Length
(Right
) then
127 if Length
(Left
) = 0 then
136 Node
:= First
(Left
).Node
;
138 ENode
:= Find
(Container
=> Right
,
139 Item
=> Left
.Nodes
(Node
).Element
).Node
;
141 Right
.Nodes
(ENode
).Element
/= Left
.Nodes
(Node
).Element
146 Node
:= HT_Ops
.Next
(Left
, Node
);
159 procedure Assign
(Target
: in out Set
; Source
: Set
) is
160 procedure Insert_Element
(Source_Node
: Count_Type
);
162 procedure Insert_Elements
is
163 new HT_Ops
.Generic_Iteration
(Insert_Element
);
169 procedure Insert_Element
(Source_Node
: Count_Type
) is
170 N
: Node_Type
renames Source
.Nodes
(Source_Node
);
175 Insert
(Target
, N
.Element
, X
, B
);
179 -- Start of processing for Assign
182 if Target
'Address = Source
'Address then
186 if Target
.Capacity
< Length
(Source
) then
187 raise Storage_Error
with "not enough capacity"; -- SE or CE? ???
190 HT_Ops
.Clear
(Target
);
191 Insert_Elements
(Source
);
198 function Capacity
(Container
: Set
) return Count_Type
is
200 return Container
.Nodes
'Length;
207 procedure Clear
(Container
: in out Set
) is
209 HT_Ops
.Clear
(Container
);
216 function Contains
(Container
: Set
; Item
: Element_Type
) return Boolean is
218 return Find
(Container
, Item
) /= No_Element
;
227 Capacity
: Count_Type
:= 0) return Set
229 C
: constant Count_Type
:=
230 Count_Type
'Max (Capacity
, Source
.Capacity
);
233 Target
: Set
(C
, Source
.Modulus
);
237 if 0 < Capacity
and then Capacity
< Source
.Capacity
then
238 raise Capacity_Error
;
241 Target
.Length
:= Source
.Length
;
242 Target
.Free
:= Source
.Free
;
245 while H
<= Source
.Modulus
loop
246 Target
.Buckets
(H
) := Source
.Buckets
(H
);
251 while N
<= Source
.Capacity
loop
252 Target
.Nodes
(N
) := Source
.Nodes
(N
);
258 Free
(Target
, Cu
.Node
);
265 ---------------------
266 -- Current_To_Last --
267 ---------------------
269 function Current_To_Last
(Container
: Set
; Current
: Cursor
) return Set
is
270 Curs
: Cursor
:= First
(Container
);
271 C
: Set
(Container
.Capacity
, Container
.Modulus
) :=
272 Copy
(Container
, Container
.Capacity
);
276 if Curs
= No_Element
then
280 elsif Current
/= No_Element
and not Has_Element
(Container
, Current
) then
281 raise Constraint_Error
;
284 while Curs
.Node
/= Current
.Node
loop
287 Curs
:= Next
(Container
, (Node
=> Node
));
294 ---------------------
295 -- Default_Modulus --
296 ---------------------
298 function Default_Modulus
(Capacity
: Count_Type
) return Hash_Type
is
300 return To_Prime
(Capacity
);
308 (Container
: in out Set
;
314 Element_Keys
.Delete_Key_Sans_Free
(Container
, Item
, X
);
317 raise Constraint_Error
with "attempt to delete element not in set";
324 (Container
: in out Set
;
325 Position
: in out Cursor
)
328 if not Has_Element
(Container
, Position
) then
329 raise Constraint_Error
with "Position cursor has no element";
332 pragma Assert
(Vet
(Container
, Position
), "bad cursor in Delete");
334 HT_Ops
.Delete_Node_Sans_Free
(Container
, Position
.Node
);
335 Free
(Container
, Position
.Node
);
337 Position
:= No_Element
;
345 (Target
: in out Set
;
348 Tgt_Node
, Src_Node
, Src_Last
, Src_Length
: Count_Type
;
350 TN
: Nodes_Type
renames Target
.Nodes
;
351 SN
: Nodes_Type
renames Source
.Nodes
;
354 if Target
'Address = Source
'Address then
359 Src_Length
:= Source
.Length
;
361 if Src_Length
= 0 then
365 if Src_Length
>= Target
.Length
then
366 Tgt_Node
:= HT_Ops
.First
(Target
);
367 while Tgt_Node
/= 0 loop
368 if Element_Keys
.Find
(Source
, TN
(Tgt_Node
).Element
) /= 0 then
370 X
: constant Count_Type
:= Tgt_Node
;
372 Tgt_Node
:= HT_Ops
.Next
(Target
, Tgt_Node
);
373 HT_Ops
.Delete_Node_Sans_Free
(Target
, X
);
378 Tgt_Node
:= HT_Ops
.Next
(Target
, Tgt_Node
);
384 Src_Node
:= HT_Ops
.First
(Source
);
388 while Src_Node
/= Src_Last
loop
389 Tgt_Node
:= Element_Keys
.Find
(Target
, SN
(Src_Node
).Element
);
391 if Tgt_Node
/= 0 then
392 HT_Ops
.Delete_Node_Sans_Free
(Target
, Tgt_Node
);
393 Free
(Target
, Tgt_Node
);
396 Src_Node
:= HT_Ops
.Next
(Source
, Src_Node
);
404 procedure Process
(L_Node
: Count_Type
);
407 new HT_Ops
.Generic_Iteration
(Process
);
413 procedure Process
(L_Node
: Count_Type
) is
414 E
: Element_Type
renames Left
.Nodes
(L_Node
).Element
;
418 if Find
(Right
, E
).Node
= 0 then
419 Insert
(Target
, E
, X
, B
);
424 -- Start of processing for Difference
430 function Difference
(Left
, Right
: Set
) return Set
is
435 if Left
'Address = Right
'Address then
439 if Length
(Left
) = 0 then
443 if Length
(Right
) = 0 then
448 H
:= Default_Modulus
(C
);
450 return S
: Set
(C
, H
) do
451 Difference
(Left
, Right
, Target
=> S
);
461 Position
: Cursor
) return Element_Type
464 if not Has_Element
(Container
, Position
) then
465 raise Constraint_Error
with "Position cursor equals No_Element";
468 pragma Assert
(Vet
(Container
, Position
),
469 "bad cursor in function Element");
471 return Container
.Nodes
(Position
.Node
).Element
;
474 ---------------------
475 -- Equivalent_Sets --
476 ---------------------
478 function Equivalent_Sets
(Left
, Right
: Set
) return Boolean is
480 function Find_Equivalent_Key
481 (R_HT
: Hash_Table_Type
'Class;
482 L_Node
: Node_Type
) return Boolean;
483 pragma Inline
(Find_Equivalent_Key
);
485 function Is_Equivalent
is
486 new HT_Ops
.Generic_Equal
(Find_Equivalent_Key
);
488 -------------------------
489 -- Find_Equivalent_Key --
490 -------------------------
492 function Find_Equivalent_Key
493 (R_HT
: Hash_Table_Type
'Class;
494 L_Node
: Node_Type
) return Boolean
496 R_Index
: constant Hash_Type
:=
497 Element_Keys
.Index
(R_HT
, L_Node
.Element
);
498 R_Node
: Count_Type
:= R_HT
.Buckets
(R_Index
);
499 RN
: Nodes_Type
renames R_HT
.Nodes
;
507 if Equivalent_Elements
508 (L_Node
.Element
, RN
(R_Node
).Element
)
513 R_Node
:= HT_Ops
.Next
(R_HT
, R_Node
);
515 end Find_Equivalent_Key
;
517 -- Start of processing of Equivalent_Sets
520 return Is_Equivalent
(Left
, Right
);
523 -------------------------
524 -- Equivalent_Elements --
525 -------------------------
527 function Equivalent_Elements
531 CRight
: Cursor
) return Boolean
534 if not Has_Element
(Left
, CLeft
) then
535 raise Constraint_Error
with
536 "Left cursor of Equivalent_Elements has no element";
539 if not Has_Element
(Right
, CRight
) then
540 raise Constraint_Error
with
541 "Right cursor of Equivalent_Elements has no element";
544 pragma Assert
(Vet
(Left
, CLeft
),
545 "bad Left cursor in Equivalent_Elements");
546 pragma Assert
(Vet
(Right
, CRight
),
547 "bad Right cursor in Equivalent_Elements");
550 LN
: Node_Type
renames Left
.Nodes
(CLeft
.Node
);
551 RN
: Node_Type
renames Right
.Nodes
(CRight
.Node
);
553 return Equivalent_Elements
(LN
.Element
, RN
.Element
);
555 end Equivalent_Elements
;
557 function Equivalent_Elements
560 Right
: Element_Type
) return Boolean
563 if not Has_Element
(Left
, CLeft
) then
564 raise Constraint_Error
with
565 "Left cursor of Equivalent_Elements has no element";
568 pragma Assert
(Vet
(Left
, CLeft
),
569 "Left cursor in Equivalent_Elements is bad");
572 LN
: Node_Type
renames Left
.Nodes
(CLeft
.Node
);
574 return Equivalent_Elements
(LN
.Element
, Right
);
576 end Equivalent_Elements
;
578 function Equivalent_Elements
579 (Left
: Element_Type
;
581 CRight
: Cursor
) return Boolean
584 if not Has_Element
(Right
, CRight
) then
585 raise Constraint_Error
with
586 "Right cursor of Equivalent_Elements has no element";
590 (Vet
(Right
, CRight
),
591 "Right cursor of Equivalent_Elements is bad");
594 RN
: Node_Type
renames Right
.Nodes
(CRight
.Node
);
596 return Equivalent_Elements
(Left
, RN
.Element
);
598 end Equivalent_Elements
;
600 ---------------------
601 -- Equivalent_Keys --
602 ---------------------
604 function Equivalent_Keys
606 Node
: Node_Type
) return Boolean
609 return Equivalent_Elements
(Key
, Node
.Element
);
617 (Container
: in out Set
;
622 Element_Keys
.Delete_Key_Sans_Free
(Container
, Item
, X
);
632 Item
: Element_Type
) return Cursor
634 Node
: constant Count_Type
:= Element_Keys
.Find
(Container
, Item
);
641 return (Node
=> Node
);
648 function First
(Container
: Set
) return Cursor
is
649 Node
: constant Count_Type
:= HT_Ops
.First
(Container
);
656 return (Node
=> Node
);
659 -----------------------
660 -- First_To_Previous --
661 -----------------------
663 function First_To_Previous
665 Current
: Cursor
) return Set
667 Curs
: Cursor
:= Current
;
668 C
: Set
(Container
.Capacity
, Container
.Modulus
) :=
669 Copy
(Container
, Container
.Capacity
);
673 if Curs
= No_Element
then
676 elsif not Has_Element
(Container
, Curs
) then
677 raise Constraint_Error
;
680 while Curs
.Node
/= 0 loop
683 Curs
:= Next
(Container
, (Node
=> Node
));
688 end First_To_Previous
;
699 HT
.Nodes
(X
).Has_Element
:= False;
703 ----------------------
704 -- Generic_Allocate --
705 ----------------------
707 procedure Generic_Allocate
709 Node
: out Count_Type
)
711 procedure Allocate
is new HT_Ops
.Generic_Allocate
(Set_Element
);
714 HT
.Nodes
(Node
).Has_Element
:= True;
715 end Generic_Allocate
;
721 function Has_Element
(Container
: Set
; Position
: Cursor
) return Boolean is
724 or else not Container
.Nodes
(Position
.Node
).Has_Element
736 function Hash_Node
(Node
: Node_Type
) return Hash_Type
is
738 return Hash
(Node
.Element
);
746 (Container
: in out Set
;
747 New_Item
: Element_Type
)
753 Insert
(Container
, New_Item
, Position
, Inserted
);
756 Container
.Nodes
(Position
.Node
).Element
:= New_Item
;
765 (Container
: in out Set
;
766 New_Item
: Element_Type
;
767 Position
: out Cursor
;
768 Inserted
: out Boolean)
771 Insert
(Container
, New_Item
, Position
.Node
, Inserted
);
775 (Container
: in out Set
;
776 New_Item
: Element_Type
)
782 Insert
(Container
, New_Item
, Position
, Inserted
);
785 raise Constraint_Error
with
786 "attempt to insert element already in set";
791 (Container
: in out Set
;
792 New_Item
: Element_Type
;
793 Node
: out Count_Type
;
794 Inserted
: out Boolean)
796 procedure Allocate_Set_Element
(Node
: in out Node_Type
);
797 pragma Inline
(Allocate_Set_Element
);
799 function New_Node
return Count_Type
;
800 pragma Inline
(New_Node
);
802 procedure Local_Insert
is
803 new Element_Keys
.Generic_Conditional_Insert
(New_Node
);
805 procedure Allocate
is
806 new Generic_Allocate
(Allocate_Set_Element
);
808 ---------------------------
809 -- Allocate_Set_Element --
810 ---------------------------
812 procedure Allocate_Set_Element
(Node
: in out Node_Type
) is
814 Node
.Element
:= New_Item
;
815 end Allocate_Set_Element
;
821 function New_Node
return Count_Type
is
824 Allocate
(Container
, Result
);
828 -- Start of processing for Insert
831 Local_Insert
(Container
, New_Item
, Node
, Inserted
);
838 procedure Intersection
839 (Target
: in out Set
;
842 Tgt_Node
: Count_Type
;
843 TN
: Nodes_Type
renames Target
.Nodes
;
846 if Target
'Address = Source
'Address then
850 if Source
.Length
= 0 then
855 Tgt_Node
:= HT_Ops
.First
(Target
);
856 while Tgt_Node
/= 0 loop
857 if Find
(Source
, TN
(Tgt_Node
).Element
).Node
/= 0 then
858 Tgt_Node
:= HT_Ops
.Next
(Target
, Tgt_Node
);
862 X
: constant Count_Type
:= Tgt_Node
;
864 Tgt_Node
:= HT_Ops
.Next
(Target
, Tgt_Node
);
865 HT_Ops
.Delete_Node_Sans_Free
(Target
, X
);
872 procedure Intersection
877 procedure Process
(L_Node
: Count_Type
);
880 new HT_Ops
.Generic_Iteration
(Process
);
886 procedure Process
(L_Node
: Count_Type
) is
887 E
: Element_Type
renames Left
.Nodes
(L_Node
).Element
;
892 if Find
(Right
, E
).Node
/= 0 then
893 Insert
(Target
, E
, X
, B
);
898 -- Start of processing for Intersection
904 function Intersection
(Left
, Right
: Set
) return Set
is
909 if Left
'Address = Right
'Address then
913 C
:= Count_Type
'Min (Length
(Left
), Length
(Right
)); -- ???
914 H
:= Default_Modulus
(C
);
916 return S
: Set
(C
, H
) do
917 if Length
(Left
) /= 0 and Length
(Right
) /= 0 then
918 Intersection
(Left
, Right
, Target
=> S
);
927 function Is_Empty
(Container
: Set
) return Boolean is
929 return Length
(Container
) = 0;
936 function Is_In
(HT
: Set
; Key
: Node_Type
) return Boolean is
938 return Element_Keys
.Find
(HT
, Key
.Element
) /= 0;
945 function Is_Subset
(Subset
: Set
; Of_Set
: Set
) return Boolean is
946 Subset_Node
: Count_Type
;
947 Subset_Nodes
: Nodes_Type
renames Subset
.Nodes
;
950 if Subset
'Address = Of_Set
'Address then
954 if Length
(Subset
) > Length
(Of_Set
) then
958 Subset_Node
:= First
(Subset
).Node
;
959 while Subset_Node
/= 0 loop
961 N
: Node_Type
renames Subset_Nodes
(Subset_Node
);
962 E
: Element_Type
renames N
.Element
;
965 if Find
(Of_Set
, E
).Node
= 0 then
970 Subset_Node
:= HT_Ops
.Next
(Subset
, Subset_Node
);
980 function Length
(Container
: Set
) return Count_Type
is
982 return Container
.Length
;
991 procedure Move
(Target
: in out Set
; Source
: in out Set
) is
992 NN
: HT_Types
.Nodes_Type
renames Source
.Nodes
;
996 if Target
'Address = Source
'Address then
1000 if Target
.Capacity
< Length
(Source
) then
1001 raise Constraint_Error
with -- ???
1002 "Source length exceeds Target capacity";
1007 if Source
.Length
= 0 then
1011 X
:= HT_Ops
.First
(Source
);
1013 Insert
(Target
, NN
(X
).Element
); -- optimize???
1015 Y
:= HT_Ops
.Next
(Source
, X
);
1017 HT_Ops
.Delete_Node_Sans_Free
(Source
, X
);
1028 function Next
(Node
: Node_Type
) return Count_Type
is
1033 function Next
(Container
: Set
; Position
: Cursor
) return Cursor
is
1035 if Position
.Node
= 0 then
1039 if not Has_Element
(Container
, Position
) then
1040 raise Constraint_Error
1041 with "Position has no element";
1044 pragma Assert
(Vet
(Container
, Position
), "bad cursor in Next");
1046 return (Node
=> HT_Ops
.Next
(Container
, Position
.Node
));
1049 procedure Next
(Container
: Set
; Position
: in out Cursor
) is
1051 Position
:= Next
(Container
, Position
);
1058 function Overlap
(Left
, Right
: Set
) return Boolean is
1059 Left_Node
: Count_Type
;
1060 Left_Nodes
: Nodes_Type
renames Left
.Nodes
;
1063 if Length
(Right
) = 0 or Length
(Left
) = 0 then
1067 if Left
'Address = Right
'Address then
1071 Left_Node
:= First
(Left
).Node
;
1072 while Left_Node
/= 0 loop
1074 N
: Node_Type
renames Left_Nodes
(Left_Node
);
1075 E
: Element_Type
renames N
.Element
;
1077 if Find
(Right
, E
).Node
/= 0 then
1082 Left_Node
:= HT_Ops
.Next
(Left
, Left_Node
);
1093 (Container
: in out Set
;
1094 New_Item
: Element_Type
)
1096 Node
: constant Count_Type
:= Element_Keys
.Find
(Container
, New_Item
);
1100 raise Constraint_Error
with
1101 "attempt to replace element not in set";
1104 Container
.Nodes
(Node
).Element
:= New_Item
;
1107 ---------------------
1108 -- Replace_Element --
1109 ---------------------
1111 procedure Replace_Element
1112 (Container
: in out Set
;
1114 New_Item
: Element_Type
)
1117 if not Has_Element
(Container
, Position
) then
1118 raise Constraint_Error
with
1119 "Position cursor equals No_Element";
1122 pragma Assert
(Vet
(Container
, Position
),
1123 "bad cursor in Replace_Element");
1125 Replace_Element
(Container
, Position
.Node
, New_Item
);
1126 end Replace_Element
;
1128 ----------------------
1129 -- Reserve_Capacity --
1130 ----------------------
1132 procedure Reserve_Capacity
1133 (Container
: in out Set
;
1134 Capacity
: Count_Type
)
1137 if Capacity
> Container
.Capacity
then
1138 raise Constraint_Error
with "requested capacity is too large";
1140 end Reserve_Capacity
;
1146 procedure Set_Element
(Node
: in out Node_Type
; Item
: Element_Type
) is
1148 Node
.Element
:= Item
;
1155 procedure Set_Next
(Node
: in out Node_Type
; Next
: Count_Type
) is
1164 function Strict_Equal
(Left
, Right
: Set
) return Boolean is
1165 CuL
: Cursor
:= First
(Left
);
1166 CuR
: Cursor
:= First
(Right
);
1169 if Length
(Left
) /= Length
(Right
) then
1173 while CuL
.Node
/= 0 or CuR
.Node
/= 0 loop
1174 if CuL
.Node
/= CuR
.Node
1175 or else Left
.Nodes
(CuL
.Node
).Element
/=
1176 Right
.Nodes
(CuR
.Node
).Element
1181 CuL
:= Next
(Left
, CuL
);
1182 CuR
:= Next
(Right
, CuR
);
1188 --------------------------
1189 -- Symmetric_Difference --
1190 --------------------------
1192 procedure Symmetric_Difference
1193 (Target
: in out Set
;
1196 procedure Process
(Source_Node
: Count_Type
);
1197 pragma Inline
(Process
);
1199 procedure Iterate
is new HT_Ops
.Generic_Iteration
(Process
);
1205 procedure Process
(Source_Node
: Count_Type
) is
1206 N
: Node_Type
renames Source
.Nodes
(Source_Node
);
1210 if Is_In
(Target
, N
) then
1211 Delete
(Target
, N
.Element
);
1213 Insert
(Target
, N
.Element
, X
, B
);
1218 -- Start of processing for Symmetric_Difference
1221 if Target
'Address = Source
'Address then
1226 if Length
(Target
) = 0 then
1227 Assign
(Target
, Source
);
1232 end Symmetric_Difference
;
1234 function Symmetric_Difference
(Left
, Right
: Set
) return Set
is
1239 if Left
'Address = Right
'Address then
1243 if Length
(Right
) = 0 then
1247 if Length
(Left
) = 0 then
1251 C
:= Length
(Left
) + Length
(Right
);
1252 H
:= Default_Modulus
(C
);
1254 return S
: Set
(C
, H
) do
1255 Difference
(Left
, Right
, S
);
1256 Difference
(Right
, Left
, S
);
1258 end Symmetric_Difference
;
1264 function To_Set
(New_Item
: Element_Type
) return Set
is
1269 return S
: Set
(Capacity
=> 1, Modulus
=> 1) do
1270 Insert
(S
, New_Item
, X
, B
);
1280 (Target
: in out Set
;
1283 procedure Process
(Src_Node
: Count_Type
);
1285 procedure Iterate
is
1286 new HT_Ops
.Generic_Iteration
(Process
);
1292 procedure Process
(Src_Node
: Count_Type
) is
1293 N
: Node_Type
renames Source
.Nodes
(Src_Node
);
1294 E
: Element_Type
renames N
.Element
;
1300 Insert
(Target
, E
, X
, B
);
1303 -- Start of processing for Union
1306 if Target
'Address = Source
'Address then
1313 function Union
(Left
, Right
: Set
) return Set
is
1318 if Left
'Address = Right
'Address then
1322 if Length
(Right
) = 0 then
1326 if Length
(Left
) = 0 then
1330 C
:= Length
(Left
) + Length
(Right
);
1331 H
:= Default_Modulus
(C
);
1332 return S
: Set
(C
, H
) do
1333 Assign
(Target
=> S
, Source
=> Left
);
1334 Union
(Target
=> S
, Source
=> Right
);
1342 function Vet
(Container
: Set
; Position
: Cursor
) return Boolean is
1344 if Position
.Node
= 0 then
1349 S
: Set
renames Container
;
1350 N
: Nodes_Type
renames S
.Nodes
;
1354 if S
.Length
= 0 then
1358 if Position
.Node
> N
'Last then
1362 if N
(Position
.Node
).Next
= Position
.Node
then
1366 X
:= S
.Buckets
(Element_Keys
.Index
(S
, N
(Position
.Node
).Element
));
1368 for J
in 1 .. S
.Length
loop
1369 if X
= Position
.Node
then
1377 if X
= N
(X
).Next
then -- to prevent unnecessary looping
1388 package body Generic_Keys
is
1390 -----------------------
1391 -- Local Subprograms --
1392 -----------------------
1394 function Equivalent_Key_Node
1396 Node
: Node_Type
) return Boolean;
1397 pragma Inline
(Equivalent_Key_Node
);
1399 --------------------------
1400 -- Local Instantiations --
1401 --------------------------
1404 new Hash_Tables
.Generic_Bounded_Keys
1405 (HT_Types
=> HT_Types
,
1407 Set_Next
=> Set_Next
,
1408 Key_Type
=> Key_Type
,
1410 Equivalent_Keys
=> Equivalent_Key_Node
);
1418 Key
: Key_Type
) return Boolean
1421 return Find
(Container
, Key
) /= No_Element
;
1429 (Container
: in out Set
;
1435 Key_Keys
.Delete_Key_Sans_Free
(Container
, Key
, X
);
1438 raise Constraint_Error
with "attempt to delete key not in set";
1441 Free
(Container
, X
);
1450 Key
: Key_Type
) return Element_Type
1452 Node
: constant Count_Type
:= Find
(Container
, Key
).Node
;
1456 raise Constraint_Error
with "key not in map";
1459 return Container
.Nodes
(Node
).Element
;
1462 -------------------------
1463 -- Equivalent_Key_Node --
1464 -------------------------
1466 function Equivalent_Key_Node
1468 Node
: Node_Type
) return Boolean
1471 return Equivalent_Keys
(Key
, Generic_Keys
.Key
(Node
.Element
));
1472 end Equivalent_Key_Node
;
1479 (Container
: in out Set
;
1484 Key_Keys
.Delete_Key_Sans_Free
(Container
, Key
, X
);
1485 Free
(Container
, X
);
1494 Key
: Key_Type
) return Cursor
1496 Node
: constant Count_Type
:= Key_Keys
.Find
(Container
, Key
);
1498 return (if Node
= 0 then No_Element
else (Node
=> Node
));
1505 function Key
(Container
: Set
; Position
: Cursor
) return Key_Type
is
1507 if not Has_Element
(Container
, Position
) then
1508 raise Constraint_Error
with
1509 "Position cursor has no element";
1513 (Vet
(Container
, Position
), "bad cursor in function Key");
1516 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
1518 return Key
(N
.Element
);
1527 (Container
: in out Set
;
1529 New_Item
: Element_Type
)
1531 Node
: constant Count_Type
:= Key_Keys
.Find
(Container
, Key
);
1535 raise Constraint_Error
with
1536 "attempt to replace key not in set";
1539 Replace_Element
(Container
, Node
, New_Item
);
1544 end Ada
.Containers
.Formal_Hashed_Sets
;