1------------------------------------------------------------------------------ 2-- -- 3-- GNAT LIBRARY COMPONENTS -- 4-- -- 5-- ADA.CONTAINERS.GENERIC_CONSTRAINED_ARRAY_SORT -- 6-- -- 7-- B o d y -- 8-- -- 9-- Copyright (C) 2004-2019, Free Software Foundation, Inc. -- 10-- -- 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. -- 17-- -- 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. -- 21-- -- 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-- -- 27-- This unit was originally developed by Matthew J Heaney. -- 28------------------------------------------------------------------------------ 29 30-- This algorithm was adapted from GNAT.Heap_Sort_G (see g-hesorg.ad[sb]) 31 32with System; 33 34procedure Ada.Containers.Generic_Constrained_Array_Sort 35 (Container : in out Array_Type) 36is 37 type T is range System.Min_Int .. System.Max_Int; 38 39 function To_Index (J : T) return Index_Type; 40 pragma Inline (To_Index); 41 42 procedure Sift (S : T); 43 44 A : Array_Type renames Container; 45 46 -------------- 47 -- To_Index -- 48 -------------- 49 50 function To_Index (J : T) return Index_Type is 51 K : constant T'Base := Index_Type'Pos (A'First) + J - T'(1); 52 begin 53 return Index_Type'Val (K); 54 end To_Index; 55 56 Max : T := A'Length; 57 Temp : Element_Type; 58 59 ---------- 60 -- Sift -- 61 ---------- 62 63 procedure Sift (S : T) is 64 C : T := S; 65 Son : T; 66 67 begin 68 loop 69 Son := 2 * C; 70 71 exit when Son > Max; 72 73 declare 74 Son_Index : Index_Type := To_Index (Son); 75 76 begin 77 if Son < Max then 78 if A (Son_Index) < A (Index_Type'Succ (Son_Index)) then 79 Son := Son + 1; 80 Son_Index := Index_Type'Succ (Son_Index); 81 end if; 82 end if; 83 84 A (To_Index (C)) := A (Son_Index); -- Move (Son, C); 85 end; 86 87 C := Son; 88 end loop; 89 90 while C /= S loop 91 declare 92 Father : constant T := C / 2; 93 begin 94 if A (To_Index (Father)) < Temp then -- Lt (Father, 0) 95 A (To_Index (C)) := A (To_Index (Father)); -- Move (Father, C) 96 C := Father; 97 else 98 exit; 99 end if; 100 end; 101 end loop; 102 103 A (To_Index (C)) := Temp; -- Move (0, C); 104 end Sift; 105 106-- Start of processing for Generic_Constrained_Array_Sort 107 108begin 109 for J in reverse 1 .. Max / 2 loop 110 Temp := Container (To_Index (J)); -- Move (J, 0); 111 Sift (J); 112 end loop; 113 114 while Max > 1 loop 115 Temp := A (To_Index (Max)); -- Move (Max, 0); 116 A (To_Index (Max)) := A (A'First); -- Move (1, Max); 117 118 Max := Max - 1; 119 Sift (1); 120 end loop; 121end Ada.Containers.Generic_Constrained_Array_Sort; 122