-------------------------------------------------------------------------------
--
-- Copyright (c) 1999 - 2002 by Thomas Wolf.
--
-- AdaBrowse is free software; you can redistribute it and/or modify it
-- under the terms of the GNU General Public License as published by the
-- Free Software Foundation; either version 2, or (at your option) any
-- later version. AdaBrowse is distributed in the hope that it will be
-- useful, but without any warranty; without even the implied
-- warranty of merchantability or fitness for a particular purpose.
-- See the GNU General Public License for more details. You should have
-- received a copy of the GNU General Public License with this distribution,
-- see file "GPL.txt". If not, write to the Free
-- Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
-- USA.
--
--
-- As a special exception from the GPL, if other files instantiate generics
-- from this unit, or you link this unit with other files to produce an
-- executable, this unit does not by itself cause the resulting executable
-- to be covered by the GPL. This exception does not however invalidate any
-- other reasons why the executable file might be covered by the GPL.
--
--
-- -
-- Author:
-
-- Thomas Wolf (TW)
-- twolf@acm.org
--
-- -
-- Purpose:
-
-- Speed and space optimized quicksort. Actually, an introspective
-- quicksort with a worst-case runtime complexity of
--
O (N * log2 (N))
.
--
-- -
-- Literature:
-
-- Musser, D.R.: "Introspective Sorting and Selection Algorithms",
-- Software -- Practice & Experience (8):983-993; 1997.
--
-- -
-- Tasking semantics:
-
-- N/A. Not abortion-safe.
--
-- -
-- Storage semantics:
-
-- No dynamic storage allocation. Stack space used is
--
O (log2 (N))
.
--
--
-------------------------------------------------------------------------------
pragma License (Modified_GPL);
package GAL.Sorting is
pragma Elaborate_Body;
----------------------------------------------------------------------------
-- A sort with a classic interface:
generic
type Index_Type is (<>);
type Element_Type is private;
type Array_Type is array (Index_Type range <>) of Element_Type;
with function "<" (Left, Right : in Element_Type) return Boolean is <>;
procedure Sort_G
(To_Sort : in out Array_Type);
-- Sorts the array into ascending order according to the given function
-- "<". This is an introspective quicksort with average *and* worst-case
-- performance complexity of O(log2(N)). Stack space usage is bounded by
-- log2(N).
-- If To_Sort'Length >= System.Max_Int, Constraint_Error may be raised.
-- (I didn't test that!) However, System.Max_Int is typically >= 2**31-1,
-- and sorting arrays of 2 Gigabytes or more is not exactly a common case.
----------------------------------------------------------------------------
-- The same with an access parameter and range bounds.
generic
type Index_Type is (<>);
type Element_Type is private;
type Array_Type is array (Index_Type range <>) of Element_Type;
with function "<" (Left, Right : in Element_Type) return Boolean is <>;
procedure Sort_Slice_G
(To_Sort : access Array_Type;
From, To : in Index_Type);
-- A no-op if To_Sort'Length <= 1 or To < From. In both cases, it is
-- irrelevant whether or not 'To' and 'From' are within To_Sort'Range.
-- If both To_Sort'Length > 1 and From <= To, a check is made to ensure
-- that both 'From' and 'To' are within To_Sort'Range, and Constraint_Error
-- will be raised without modifying the array if not. Otherwise, the given
-- slice To_Sort (From .. To) is sorted into ascending order according to
-- '<'.
----------------------------------------------------------------------------
-- A very general sort that can be used to sort whatever you like. As
-- long as you can provide random access in constant time, this will
-- be a logarithmic sort. (It's an introspective quicksort, too.)
generic
with function Is_Smaller (Left, Right : in Integer) return Boolean;
-- Shall return True if the element at index 'Left' is smaller than
-- the element at index 'Right' and Fasle otherwise.
with procedure Copy (To, From : in Integer);
-- Shall copy the element at index 'From' to position 'To'.
procedure Sort_Indexed_G
(Left, Right : in Natural);
-- Sorts range Left .. Right of your data by calling 'Is_Smaller' for
-- comparisons and 'Move' to move elements around. Both 'Is_Smaller'
-- and 'Move' must be prepared to receive indices -1 and -2, which denote
-- two single (and different) temporary locations. Both routines are never
-- called with both indices negative, one index at least is always
-- in the (Left .. Right).
----------------------------------------------------------------------------
-- Same as above, but using access-to-subroutines.
type Comparator is access
function (Left, Right : in Integer) return Boolean;
type Copier is access
procedure (To, From : in Integer);
procedure Sort
(Left, Right : in Natural;
Is_Smaller : in Comparator;
Copy : in Copier);
-- Of course, both 'Is_Smaller' and 'Copy' must not be null or this will
-- raise Constraint_Error!
----------------------------------------------------------------------------
end GAL.Sorting;