aboutsummaryrefslogtreecommitdiff
path: root/sys/vops/lz/asoks.x
blob: a92f401579603855f343d81192f46ce2426285e4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.

include <mach.h>

# ASOK -- Select the Kth smallest element from a vector.  The algorithm used
# is selection by tail recursion (Gonnet 1984).  In each iteration a pivot key
# is selected (somewhat arbitrarily) from the array.  The array is then split
# into two subarrays, those with key values less than or equal to the pivot key
# and those with values greater than the pivot.  The size of the two subarrays
# determines which contains the median value, and the process is repeated
# on that subarray, and so on until all of the elements of the subarray
# are equal, e.g., there is only one element left in the subarray.  For a
# randomly ordered array the expected running time is O(3.38N).  The selection
# is carried out in place, leaving the array in a partially ordered state.
#
# N.B.: Behaviour is O(N) if the input array is sorted.
# N.B.: The cases ksel=1 and ksel=npix, i.e., selection of the minimum and
# maximum values, are more efficiently handled by ALIM which is O(2N).
#
# Jul99 - The above algorithm was found to be pathologically slow in cases
# where many or all elements of the array are equal.  The version of the
# algorithm below, from Wirth, appears to avoid this problem.

short procedure asoks (a, npix, ksel)

short	a[ARB]			# input array
int	npix			# number of pixels
int	ksel			# element to be selected

int	lo, up, i, j, k, dummy
short	temp, wtemp

begin
	lo = 1
	up = npix
	k  = max (lo, min (up, ksel))

	# while (lo < up)
	do dummy = 1, MAX_INT {
	    if (! (lo < up))
		break

	    temp = a[k];  i = lo;  j = up

	    repeat {
		while (a[i] < temp)
		    i = i + 1
		while (temp < a[j])
		    j = j - 1
		if (i <= j) {
		    wtemp = a[i];  a[i] = a[j];  a[j] = wtemp
		    i = i + 1;  j = j - 1
		}
	    } until (i > j)

	    if (j < k)
		lo = i
	    if (k < i)
		up = j
	}

	return (a[k])
end