Plan 9 from Bell Labs’s /usr/web/sources/contrib/fernan/nhc98/tests/nofib/spectral/knights/Sort.lhs

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


\section{Introduction}
This module defines, and tests various sort functions written is Haskell.
I descided to do this rather trivial exercise, to accustom myself with
the prototype Glasgow Haskell compiler, and Glasgows literate programming
system. 

Use of this module is obtained by importing the module, and {\em one} of the
sort functions which will be renamed to {\tt sort} - 
i.e ``{\tt import Sort(lazySort) renaming sort}'' imports {\tt lazySort},
which can be referenced in the current scope as {\tt sort}.

\begin{code}
module Sort(insertSort,mergeSort,quickSort,lazySort)  where

-- import PrelNum( Num(fromInt) )
-- import GlaExts( Num(fromInt) )	-- Shouldn't really use this in a benchmark,
				-- but don't want change wrt old baselines
fromInt = fromInteger . toInteger
\end{code}
%%%%%%%%%%%%%%%%%%%%%%I n s e r t i o n   S o r t%%%%%%%%%%%%%%%%%%%%%%
\section{Insertion Sort}
The following piece of code is taken from the Gofer manual.
%
\begin{code}
insertSort::(Ord a) => [a] -> [a]
insertSort xs = foldr insertion [] xs

insertion :: (Ord a) => a -> [a] -> [a]
insertion x [] = [x]
insertion x (y:ys) 
	| x <= y    = x:y:ys
	| otherwise = y:insertion x ys
\end{code}
%%%%%%%%%%%%%%%%%%%%%%%%%%M e r g e   S o r t%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Merge Sort}
The following code is taken from Keiths ''Functional Programming 2''
lecture notes. 
%
\begin{code}
mergeSort :: (Ord a) => [a] -> [a]
mergeSort xs
	= if (n <=1 ) then xs 
          else 
             (mergeList 
		( mergeSort (take (n `div` 2) xs))
		( mergeSort (drop (n `div` 2) xs)))
	  where
	    	n = length xs

mergeList :: (Ord a) => [a] -> [a] -> [a]
mergeList []   ys = ys
mergeList xs   [] = xs
mergeList (x:xs) (y:ys)
	| x <= y    = x:mergeList xs (y:ys)
	| otherwise = y:mergeList (x:xs) ys
\end{code}
%%%%%%%%%%%%%%%%%%%%%%%%%%Q u i c k   S o r t%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{A not so ``Quick Sort''}
Standard definition of quicksort\cite{turner} using list comprehensions.
\begin{code}
quickSort :: (Ord a) => [a] -> [a]
quickSort []     = []
quickSort (x:xs) = (quickSort [y | y<-xs, y<x]) ++ [x] ++ 
                   (quickSort [y | y<-xs, y>=x])
\end{code}
%%%%%%%%%%%%%%%%%%%%%%L e n n a r t s  S o r t%%%%%%%%%%%%%%%%%%%%%%%
\section{Lennart Augustsson's ``Quick Sort''}
   This module implements a sort function using a variation on
   quicksort.  It is stable, uses no concatenation and compares
   only with {\tt <=}.
%
\begin{rawlatex}
\begin{itemize}
\item {\tt sortLe} sorts with a given predicate 
\item {\tt lazySort} uses the {\tt <=} method
\end{itemize}
\end{rawlatex}
%
\begin{code}
lazySortLe :: (a -> a -> Bool) -> [a] -> [a]
lazySortLe le l = lazyQsort le   l []

lazySort :: (Ord a) => [a] -> [a]
lazySort      l = lazyQsort (<=) l []

-- lazyQsort is stable and does not concatenate.
lazyQsort :: (a -> a -> Bool) -> [a] -> [a] -> [a]
lazyQsort le []     r = r
lazyQsort le [x]    r = x:r
lazyQsort le (x:xs) r = qpart le x xs [] [] r

-- rlazyQsort is as lazyQsort but anti-stable, 
-- i.e. reverses equal elements.
rlazyQsort :: (a -> a -> Bool) -> [a] -> [a] -> [a]
rlazyQsort  le []     r = r
rlazyQsort le [x]    r = x:r
rlazyQsort  le (x:xs) r = rqpart le x xs [] [] r

-- qpart partitions and sorts the sublists
-- rlt and rge are in reverse order and must be sorted with an
-- anti-stable sorting
qpart :: (a -> a -> Bool) -> a -> [a] -> [a] -> [a] -> [a] -> [a]
qpart le x [] rlt rge r =
    rlazyQsort le rlt (x:rlazyQsort le rge r)
qpart le x (y:ys) rlt rge r =
    if le x y then
	qpart le x ys rlt (y:rge) r
    else
	qpart le x ys (y:rlt) rge r

rqpart :: (a -> a -> Bool) -> a -> [a] -> [a] -> [a] -> [a] -> [a]
rqpart le x [] rle rgt r =
    lazyQsort le rle (x:lazyQsort le rgt r)
rqpart le x (y:ys) rle rgt r =
    if le y x then
	rqpart le x ys (y:rle) rgt r
    else
	rqpart le x ys rle (y:rgt) r
\end{code}
%%%%%%%%%%%%%%%%%%%%%%R a n d o m  N u m b e r s%%%%%%%%%%%%%%%%%%%%%%%
\section{Random Number Generator}
   This module implements a (good) random number generator.

   The June 1988 (v31 \#6) issue of the Communications of the ACM has an
   article by Pierre L'Ecuyer called, "Efficient and Portable Combined
   Random Number Generators".  Here is the Portable Combined Generator of
   L'Ecuyer for 32-bit computers.  It has a period of roughly 2.30584e18.

   Transliterator: Lennart Augustsson

Use seeds s1 in 1..2147483562 and s2 in 1..2147483398 to generate
an infinite list of random Ints.

\subsection{Random Integers}
\begin{code}
randomInts :: Int -> Int -> [Int]
randomInts s1 s2 =
    if 1 <= s1 && s1 <= 2147483562 then
	if 1 <= s2 && s2 <= 2147483398 then
	    rands s1 s2
	else
	    error "randomInts: Bad second seed."
    else
	error "randomInts: Bad first seed."

rands :: Int -> Int -> [Int]
rands s1 s2 
   = if z < 1 then z + 2147483562 : rands s1'' s2'' 
     else 
	 z : rands s1'' s2''
     where	  
	k    = s1 `div` 53668
	s1'  = 40014 * (s1 - k * 53668) - k * 12211
	s1'' = if s1' < 0 then s1' + 2147483563 else s1'
    
	k'   = s2 `div` 52774
	s2'  = 40692 * (s2 - k' * 52774) - k' * 3791
	s2'' = if s2' < 0 then s2' + 2147483399 else s2'

	z    = s1'' - s2''
\end{code}

\subsection{Random Doubles}

Same values for s1 and s2 as above, generates an infinite
list of Doubles uniformly distibuted in (0,1).

\begin{code}
randomDoubles :: Int -> Int -> [Double]
randomDoubles s1 s2 = map (\x -> (fromIntegral x * 4.6566130638969828e-10))
			  (randomInts s1 s2)
\end{code}

\section{Test Data}

\begin{code}
test1,test2,test3,test4,test5,test6,test7::[Int]
test1 = [1..10]
test2 = [10,9..1]
test3 = [1..500]
test4 = [500,499..1]

test5 = take 10   (randomInts 123213 342234)
test6 = take 100  (randomInts 123213 342234)
test7 = take 1000 (randomInts 123213 342234)
\end{code}

\section{Results}

\begin{rawlatex}
\begin{tabular}{||c||r|r||r|r||r|r||r|r||}
\hline 
& \multicolumn{2}{c||}{insertSort} &
  \multicolumn{2}{c||}{mergeSort} &
  \multicolumn{2}{c||}{quickSort} &
  \multicolumn{2}{c||}{lazySort} \\
\cline{2-9}
& \multicolumn{1}{c|}{red} &
  \multicolumn{1}{c||}{cell} &
  \multicolumn{1}{c|}{red} &
  \multicolumn{1}{c||}{cell} &
  \multicolumn{1}{c|}{red} &
  \multicolumn{1}{c||}{cell} &
  \multicolumn{1}{c|}{red} &
  \multicolumn{1}{c||}{cell}\\ 
\hline\hline
test1 	&	112 	&	225  	& 
		360	& 	636	& 
		362	& 	640	& 
		140 	& 	501 	\\
\hline
test2 	& 	184  	& 	368   	& 
		367	&	662	& 
		542	& 	910	& 
		140	& 	501	\\
\hline 
test3 	& 	5009 	& 	11406 	& 
		35309	& 	63196	& 
		753002  & 	1135146 &
		252000	&	883637	\\
\hline
test4	&	253517	&	507919	&
		35422	&	63590	&
		1252003	&	1883646	&
		252000	&	883637	\\
\hline 
test5	&	363	&	963	&
		373	&	768	&
		324	&	668	&
	  	367	&	1073	\\
\hline
test6	&	8366	&	19254	&
		6077	&	12273	&
		6002	&	10791	&
		4314	&	13514	\\
\hline 
test7	& 	519754	&	1065013	&
		84228	&	170230	&
		95620	&	161432	&
		25416	&	98789	\\
\hline 
\end{tabular}
\end{rawlatex}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.