aboutsummaryrefslogtreecommitdiff
path: root/pkg/utilities/nttools/lib/tblsortm.x
blob: 1ece995dac832b35e2a8af030ec7e18ccc93a8a4 (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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
include	"reloperr.h"

.help tbl_sortm
.nf____________________________________________________________________________

This file contains two routines that sort a table on multiple columns. Both
routines put an existing array of row indices into sorted order. The first
routine, tbl_sortm has a simpler interface and is the routine to be used in
a majority of cases. The second routine, tbl_msort, requires that the calling
routine read the table column into an array and handle null elements by
itself. This routine should be used if the table column requires some
special preprocessing before it can be sorted. One example of required
preprocessing is conversion of dates from character strings to julian dates.
Both routines use merge sort to sort the data. Merge sort is fast, though not
as fast as quick sort, and stable, so it can be used to sort on multiple
columns. Its disadvantage is that it requires additional work space to run.

.endhelp_______________________________________________________________________

# TBL_SORTM -- Sort a table on multiple columns
#
# This procedure rearranges an array of row indices into sorted order. The
# order is from smallest to largest value if ascend is true, if ascend is
# false, the order is from largest to smallest. In either case undefined
# elements will be last in the array. For purposes of this routine boolean
# false is considered to be less than true. If character strings are being
# sorted, case can be ignored by setting casesens to false. The array of row
# indices must be created before calling this procedure.
#
# B.Simon	28-Sept-87	First Code
# B.Simon	15-Dec-87	Changed to handle table subsets

procedure tbl_sortm (ascend, casesens, tp, numptr, colptr, nindex, index)

bool	ascend		#  i: Sort in ascending order
bool	casesens	#  i: Sort is case sensitive
pointer	tp		#  i: Table descriptor
int	numptr		#  i: Number of columns to sort on
pointer	colptr[ARB]	#  i: Array of column descriptors
int	nindex		# io: Number of rows
int	index[ARB]	# io: Array of row indices in sorted order
#--
int	dtype, spptype, lendata
int	iptr, nary, iary, nelem, nidx
pointer	cp, idxptr, nulptr, aryptr, curptr

int	movenulls()

begin
	# Allocate storage for index array

	nidx = 2 * nindex
	call malloc (idxptr, nidx, TY_INT)

	# Initialize the array of row indices

	call amovi (index, Memi[idxptr], nindex)

	# Loop over all columns to be sorted

	do iptr = numptr, 1, -1 {

	    cp = colptr(iptr)

	    # Read in the column of table values. Setting dtype to zero
	    # gets the actual column type.

	    dtype = 0
	    call gettabcol (tp, cp, dtype, nary, aryptr, nulptr)

	    if (dtype < 0) {
		lendata = - dtype
	    	spptype = TY_CHAR

		if (! casesens) {
		    curptr = aryptr
		    do iary = 1, nary {
			call strupr (Memc[curptr])
			curptr = curptr + lendata + 1
		    }
		}
	    } else {
		lendata = 1
		spptype = dtype
	    }

	    # Move all null elements to the end of the array

	    nelem = movenulls (nindex, Memb[nulptr], Memi[idxptr])

	    # Perform an indirect sort on the row indices using merge sort

	    call tbl_msort (ascend, dtype, aryptr, nelem, nidx, idxptr)

	    # Free memory used to hold table column and null flags

	    call mfree (aryptr, spptype)
	    call mfree (nulptr, TY_BOOL)
	}

	# Move the row indices into the output array

	call amovi (Memi[idxptr], index, nindex)
	call mfree (idxptr, TY_INT)

end

# TBL_MSORT -- Indirect merge sort of a table column using an index array

procedure tbl_msort (ascend, dtype, aryptr, nelem, nidx, idxptr)

bool	ascend		# i: Sort array in ascending order
int	dtype		# i: Data type of array to be sorted
pointer	aryptr		# i: Pointer to array to be sorted
int	nelem		# i: Number of array elements to be sorted
int	nidx		# i: Size of index array
pointer	idxptr		# o: Pointer to array of indices

include	"compare.com"

int	spptype

extern	compascb, compascd, compasci, compascr, compasct
extern	compdscb, compdscd, compdsci, compdscr, compdsct

begin
	dataptr = aryptr

	if (dtype < 0) {
	    lendata = - dtype
	    spptype = TY_CHAR
	} else {
	    lendata = 1
	    spptype = dtype
	}

	# Convert the type to the SPP format

	# Call the merge sort procedure with the proper comparison routine

	switch (spptype) { 
	case TY_BOOL:
	    if (ascend)
		call msort (Memi[idxptr], nidx, nelem, compascb)
	    else
		call msort (Memi[idxptr], nidx, nelem, compdscb)
	case TY_CHAR:
	    if (ascend)
		call msort (Memi[idxptr], nidx, nelem, compasct)
	    else
		call msort (Memi[idxptr], nidx, nelem, compdsct)
	case TY_SHORT,TY_INT,TY_LONG:
	    if (ascend)
		call msort (Memi[idxptr], nidx, nelem, compasci)
	    else
		call msort (Memi[idxptr], nidx, nelem, compdsci)
	case TY_REAL:
	    if (ascend)
		call msort (Memi[idxptr], nidx, nelem, compascr)
	    else
		call msort (Memi[idxptr], nidx, nelem, compdscr)
	case TY_DOUBLE: 
	    if (ascend)
		call msort (Memi[idxptr], nidx, nelem, compascd)
	    else
		call msort (Memi[idxptr], nidx, nelem, compdscd)
	}
end