internal.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 1998-2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include "internal.h"
#define INSERTION_THRESHOLD 12
static void
swap_range(int i, int j, int n, line_rec_t **I)
{
while (n-- > 0) {
line_rec_t *t;
t = I[i];
I[i++] = I[j];
I[j++] = t;
}
}
/*
* offset_is_algorithm() implements a simple insertion sort on line records that
* allows comparison from an offset into the l_collate field (since the subfiles
* should have already been sorted to that depth).
*/
static void
{
ssize_t i;
/*
* Place lowest element in X[0].
*/
for (i = 0; i < n; i++) {
swap((void **)&X[0], (void **)&X[i]);
}
}
/*
* Insertion sort.
*/
for (i = 2; i < n; i++) {
ssize_t j = i;
line_rec_t *t = X[i];
X[j] = X[j - 1];
j--;
ASSERT(j > 0);
}
X[j] = t;
}
}
/*
* tqs_algorithm() is called from rqs_algorithm() when a subpartition is
* encountered whose line records share indistinguishable l_collate fields. It
* implements a semi-iterative ternary quicksort.
*/
static void
{
ssize_t l; /* boundary of left partition */
ssize_t r; /* boundary of right partition */
ssize_t p, q; /* scratch for indices, comparisons */
/*
* completion criteria
*/
if (n <= 1)
return;
if (n <= INSERTION_THRESHOLD) {
return;
}
/*
* selection of partition element
*/
le = l = 1;
r = re = n - 1;
for (;;) {
while (l <= r &&
(p = collate_fcn(X[l], X[0], 0, coll_flags)) <= 0) {
if (p == 0)
l++;
}
while (l <= r &&
(p = collate_fcn(X[r], X[0], 0, coll_flags)) >= 0) {
if (p == 0)
r--;
}
if (l > r)
break;
swap((void **)&X[l++], (void **)&X[r--]);
}
/*
* swap equal partitions into middle
*/
swap_range(0, l - p, p, X);
swap_range(l, n - p, p, X);
/*
* Iterate with larger subpartition, recurse into smaller.
*/
p = l - le;
q = re - r;
if (p > q) {
n = p;
} else {
X = &X[n - q];
n = q;
}
goto tqs_start;
/*NOTREACHED*/
}
/*
* The following semi-iterative radix quicksort is derived from that presented
* in
* J. Bentley and R. Sedgewick, Fast Algorithms for Sorting and Searching
* Strings, in Eighth Annual ACM-SIAM Symposium on Discrete Algorithms,
* 1997 (SODA 1997),
* and
* R. Sedgewick, Algorithms in C, 3rd ed., vol. 1, Addison-Wesley, 1998.
*/
static void
{
uchar_t v; /* partition radix value */
ssize_t l; /* boundary of left partition */
ssize_t r; /* boundary of right partition */
ssize_t p; /* scratch for indices, comparisons */
line_rec_t *t; /* scratch for swaps */
/*
* completion criteria
*/
if (n <= 1)
return;
if (n <= INSERTION_THRESHOLD) {
return;
}
/*
* selection of partition element
*/
le = l = 1;
r = re = n - 1;
for (;;) {
while (l <= r &&
if (p == 0) {
t = X[le];
X[le] = X[l];
X[l] = t;
le++;
}
(l)++;
}
while (l <= r &&
if (p == 0) {
t = X[r];
X[r] = X[re];
X[re] = t;
(re)--;
}
(r)--;
}
if (l > r)
break;
t = X[l];
X[l] = X[r];
X[r] = t;
(l)++;
(r)--;
}
/*
* swap equal partitions into middle
*/
swap_range(0, l - p, p, X);
swap_range(l, n - p, p, X);
/*
* recurse into subpartitions as necessary
*/
p = re - r;
if (p > 0)
p = l - le;
if (p > 0)
return;
/*
* - 1 so that we don't count the final null.
*/
/*
* Equivalent recursion: rqs_algorithm(&X[p], le + n - re - 1,
* depth + 1, collate_fcn, coll_only);
*/
X = &X[p];
depth++;
goto rqs_start;
}
if (!(coll_flags & COLL_UNIQUE)) {
}
}
static void
{
if (C->s_element_size == sizeof (char))
0, collated, coll_flags);
else
0, collated_wide, coll_flags);
}
void
internal_sort(sort_t *S)
{
size_t prev_sort_mem = 0;
void *prev_sort_buf = NULL;
int numerator, denominator;
int memory_left;
int currently_primed;
if (S->m_field_options & FIELD_REVERSE_COMPARISONS)
else
coll_flags = 0;
/*
* For the entire line special case, we can speed comparisons by
* recognizing that the collation vector contains all the information
* required to order the line against other lines of the file.
* COLL_UNIQUE provides such an exit; if we use the standard put-line
* operation for the output stream, we achieve the desired fast path.
*/
if (S->m_entire_line)
cur_stream = S->m_input_streams;
while (cur_stream != NULL) {
}
input_mem = 0;
} else {
S->m_memory_available) / denominator);
}
sizeof (char) : sizeof (wchar_t);
while (memory_left == ST_MEM_AVAIL) {
if (currently_primed == PRIME_SUCCEEDED)
if (SOP_EOS(cur_stream)) {
(void) SOP_FREE(cur_stream);
(void) SOP_CLOSE(cur_stream);
}
if (cur_stream == NULL)
break;
break;
}
}
}
#ifndef DEBUG_NO_CACHE_TEMP
if ((cur_stream == NULL ||
(void) stream_push_to_temporary(&S->m_temporary_streams,
(S->m_single_byte_locale ? 0 : ST_WIDE));
} else {
#endif
(void) stream_push_to_temporary(&S->m_temporary_streams,
(S->m_single_byte_locale ? 0 : ST_WIDE));
#ifdef DEBUG_NO_CACHE_TEMP
if (cur_stream == NULL)
break;
#endif
#ifndef DEBUG_NO_CACHE_TEMP
}
#endif
if (cur_stream == NULL)
break;
SOP_EOS(cur_stream)) {
(void) SOP_FREE(cur_stream);
(void) SOP_CLOSE(cur_stream);
}
}
}
}