NAME: binary_partition - finds an insertion location in an ordered block SYNOPSIS: TYPE *binary_partition(TYPE value, TYPE *begin, TYPE *end); DESCRIPTION: binary_partition returns a location middle in an ordered block such that for any location x in the block middle <= x < end if and only if value < *x. In other words it returns the position of the leftmost element in an ordered block that is greater than value. SEE ALSO: binary_search, insert, set_insert ASSUMPTIONS: Less_than ("<") is defined for the TYPE DEPENDS ON: nothing COMPLEXITY: Logarithmic in the size of the block. If N is the number of locations in the block then at most logN operation less_than are performed. IMPLEMENTATION: TYPE *binary_partition(REGISTER TYPE value, register TYPE *begin, register TYPE *end) { while (5 < end-begin) { register TYPE *index = begin + ((end - begin) >> 1); if (value < *index) end = index; else begin = index + 1; } while (begin < end) if (!(value < *--end)) return end + 1; return end; } NAME: binary_partition - finds an insertion location in an ordered block SYNOPSIS: TYPE *binary_partition(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end); DESCRIPTION: binary_partition returns a location middle in an ordered block such that for any location x in the block middle <= x < end if and only if 0 < relation(*x, value). In other words it returns the position of the leftmost element in an ordered block that is greater than value. relation is the name of the comparison function, which is called with two arguments that point to the elements being compared. As the function must return an integer less than, equal to, or greater than zero, so must the first argument to be considered be less than, equal to, or greater than the second. SEE ALSO: binary_search, insert, set_insert ASSUMPTIONS: none DEPENDS ON: nothing COMPLEXITY: Logarithmic in the size of the block. If N is the number of locations in the block then at most logN calls to the relation are performed. IMPLEMENTATION: TYPE *binary_partition(register int (*relation)(TYPE*, TYPE*), TYPE value, register TYPE *begin, register TYPE *end) { register TYPE *temp = &value; while (5 < end-begin) { register TYPE *index = begin + ((end - begin) >> 1); if ((*relation)(temp, index) < 0) end = index; else begin = index + 1; } while (begin < end) if (!((*relation)(temp, --end) < 0)) return end + 1; return end; } NAME: binary_search - finds an element in an ordered block SYNOPSIS: TYPE *binary_search(TYPE value, TYPE *begin, TYPE *end); DESCRIPTION: binary_search returns the pointer to the rightmost element in an ordered block equal to value if such an element exists and the 0 pointer otherwise. SEE ALSO: binary_partition ASSUMPTIONS: Less_than ("<") is defined for the TYPE DEPENDS ON: TYPE *binary_partition(TYPE value, TYPE *begin, TYPE *end); COMPLEXITY: Logarithmic in the size of the block. If N is the number of locations in the block then at most logN operations less_than are performed. IMPLEMENTATION: TYPE *binary_search(TYPE value, TYPE *begin, TYPE *end) { TYPE *index = binary_partition(value, begin, end); if (begin < index && !(*(index - 1) < value)) return index - 1; else return 0; } NAME: binary_search - finds an element in an ordered block SYNOPSIS: TYPE *binary_search(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end); DESCRIPTION: binary_search returns the pointer to the rightmost element in an ordered block equal to value if such an element exists and the 0 pointer otherwise. relation is the name of the comparison function, which is called with two arguments that point to the elements being compared. As the function must return an integer less than, equal to, or greater than zero, so must the first argument to be considered be less than, equal to, or greater than the second. SEE ALSO: binary_partition ASSUMPTIONS: Assignment ("=") is defined for the TYPE DEPENDS ON: TYPE *binary_partition(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end); COMPLEXITY: Logarithmic in the size of the block. If N is the number of locations in the block then at most logN calls to the relation are performed. IMPLEMENTATION: TYPE *binary_search(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end) { TYPE *index = binary_partition(relation, value, begin, end); if (begin < index && !((*relation)(index - 1, &value) < 0)) return index - 1; else return 0; } NAME: copy - copies a block to a new location SYNOPSIS: void copy(TYPE *begin, TYPE *end, TYPE *result); DESCRIPTION: Copy moves the contents of every location between begin (inclusive) and end (exclusive) into memory locations starting with result, so that for every integer i, 0 <= i < (end - begin), the location result + i gets a value from the location begin + i. NOTE: 1) Copy is the only copying function among the block algorithms that allows the initial block and the resulting block to intersect. In such cases, copy makes certain that every location is copied before it is overwritten. 2) If begin is equal to result no assignments are done. ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N assignments of TYPE are performed. (But see the second note.) IMPLEMENTATION: void copy(register TYPE *begin, register TYPE *end, register TYPE *result) { if (begin < result) { result += end - begin; while (begin < end) *--result = *--end; } else if (result < begin) while (begin < end) *result++ = *begin++; } NAME: count - returns the number of locations in the block that satisfy predicate SYNOPSIS: ptrdiff_t count(int (*predicate)(TYPE*), TYPE *begin, TYPE *end); DESCRIPTION: Count returns the number of locations in the block that satisfy predicate SEE ALSO: other count, position ASSUMPTIONS: none DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block at exactly N calls to predicate are done. IMPLEMENTATION: ptrdiff_t count(register int (*predicate)(TYPE*), register TYPE *begin, register TYPE *end) { register ptrdiff_t n = 0; while (begin < end) if ((*predicate)(begin++)) n++; return n; } NAME: count - counts the number of elements in the block equal to the given value SYNOPSIS: ptrdiff_t count(TYPE value, TYPE *begin, TYPE *end); DESCRIPTION: count returns the number of locations in the block containing values equal to value. SEE ALSO: other count, position ASSUMPTIONS: Equality ("==") is defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N equalities of TYPE are performed. IMPLEMENTATION: ptrdiff_t count(REGISTER TYPE value, register TYPE *begin, register TYPE *end) { register ptrdiff_t n = 0; while (begin < end) if (*begin++ == value) n++; return n; } NAME: count - counts the number of elements in the block satisfying the relation to the given value SYNOPSIS: ptrdiff_t count(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end); DESCRIPTION: count returns the number of locations in the block that satisfy relation with the pointer to value. SEE ALSO: other count, position ASSUMPTIONS: none DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N calls to relation are done. IMPLEMENTATION: ptrdiff_t count(register int (*relation)(TYPE*, TYPE*), TYPE value, register TYPE *begin, register TYPE *end) { register TYPE *temp = &value; register ptrdiff_t n = 0; while (begin < end) if ((*relation)(begin++, temp)) n++; return n; } NAME: difference - collects those elements of two ordered blocks that are in the first, but not in the second SYNOPSIS: TYPE *difference(int (*relation)(TYPE*, TYPE*), TYPE *begin1, TYPE *end1, TYPE *begin2, TYPE *end2, TYPE *result); DESCRIPTION: difference puts elements from two ordered blocks with no repetitions into a new ordered block with no repetitions so that every element which is in the first block but not in the second will be placed in the result The pointer after the last element of the new block is returned. relation is the name of the comparison function, which is called with two arguments that point to the elements being compared. As the function must return an integer less than, equal to, or greater than zero, so must the first argument to be considered be less than, equal to, or greater than the second. NOTE: If begin1 <= result < end1 or begin1 <= result + (end1 - begin1) < end1 or begin2 <= result < end2 or begin2 <= result + (end2 - begin2) < end2 then the effect of difference is not defined. SEE ALSO: intersection, merge, set_union, symmetric_difference, unique ASSUMPTIONS: Assignment ("=") is defined for the TYPE DEPENDS ON: nothing COMPLEXITY: Linear in the size of the blocks. If N and M are the numbers of locations in the blocks then at most N + M - 1 calls to relation and N assignments are performed. IMPLEMENTATION: TYPE *difference(register int (*relation)(TYPE*, TYPE*), register TYPE *begin1, register TYPE *end1, register TYPE *begin2, register TYPE *end2, register TYPE *result) { while (begin1 < end1 && begin2 < end2) { register int c = (*relation)(begin2, begin1); if (0 < c) *result++ = *begin1++; else { if (c == 0) begin1++; begin2++; } } while (begin1 < end1) *result++ = *begin1++; return result; } NAME: difference - collects those elements of two ordered blocks that are in the first, but not in the second SYNOPSIS: TYPE *difference(TYPE *begin1, TYPE *end1, TYPE *begin2, TYPE *end2, TYPE *result); DESCRIPTION: difference puts elements from two ordered blocks with no repetitions into a new ordered block with no repetitions so that every element which is in the first block but not in the second will be placed in the result The pointer after the last element of the new block is returned. NOTE: If begin1 <= result < end1 or begin1 <= result + (end1 - begin1) < end1 or begin2 <= result < end2 or begin2 <= result + (end2 - begin2) < end2 then the effect of difference is not defined. SEE ALSO: intersection, merge, set_union, symmetric_difference ASSUMPTIONS: Less_than ("<") and assignment ("=") are defined for the TYPE DEPENDS ON: nothing COMPLEXITY: Linear in the size of the blocks. If N and M are the numbers of locations in the blocks then at most N + M - 1 less_than operations and N assignments are performed. IMPLEMENTATION: TYPE *difference(register TYPE *begin1, register TYPE *end1, register TYPE *begin2, register TYPE *end2, register TYPE *result) { while (begin1 < end1 && begin2 < end2) if (*begin1 < *begin2) *result++ = *begin1++; else if (!(*begin2++ < *begin1)) begin1++; while (begin1 < end1) *result++ = *begin1++; return result; } NAME: fill - assigns the same value to all locations in a block SYNOPSIS: void fill(TYPE value, TYPE *begin, TYPE *end); DESCRIPTION: fill assigns value to every location between begin (inclusive) and end (exclusive) SEE ALSO: for_each, generate ASSUMPTIONS: assignment ("=") is defined for the TYPE DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N assignments of TYPE are performed. IMPLEMENTATION: void fill(register TYPE value, register TYPE *begin, register TYPE *end) { while (begin < end) *begin++ = value; } NAME: for_each - applies the function to every location in the block SYNOPSIS: void for_each(void (*function)(TYPE*), TYPE *begin, TYPE *end); DESCRIPTION: for_each applies the function to every location in the block from the leftmost to the rightmost. SEE ALSO: generate ASSUMPTIONS: none DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block then exactly N calls to the function are performed. IMPLEMENTATION: void for_each(register void (*function)(TYPE*), register TYPE *begin, register TYPE *end) { while (begin < end) (*function)(begin++); } NAME: generate - applies a function to every location in a block SYNOPSIS: void generate(void (*function)(ptrdiff_t, TYPE*), TYPE *begin, TYPE *end); DESCRIPTION: For every location in a block generate applies a function to the 0-origin index of the location in the block and the pointer to the location. SEE ALSO: fill, for_each ASSUMPTIONS: none DEPENDS ON: none COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N function calls to "function" are performed. EXAMPLE: It is possible to define a function that assigns a consecutive integer starting from 0 to every location in the block (similar to APL iota) by doing: void zap(ptrdiff_t n, ptrdiff_t *address) { *address = n; } void iota(ptrdiff_t *begin, ptrdiff_t *end) { generate(zap, begin, end); } IMPLEMENTATION: void generate(register void (*function)(ptrdiff_t, TYPE*), register TYPE *begin, register TYPE *end) { register TYPE *index = begin; for (; begin < end; begin++) (*function)(begin - index, begin); } NAME: insert - inserts an element in an ordered block SYNOPSIS: TYPE *insert(TYPE value, TYPE *begin, TYPE *end); DESCRIPTION: insert assigns value to the location in the ordered block that contains the leftmost element greater than value. Before the assignment all the elements from that location to the end of the block are moved one location to the right. SEE ALSO: binary_partition, binary_search, set_insert ASSUMPTIONS: Less_than ("<") and assignment ("=") are defined for the TYPE DEPENDS ON: TYPE *binary_partition(TYPE value, TYPE *begin, TYPE *end); void copy(TYPE *begin, TYPE *end, TYPE *result); COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block then at most N assignments and at most logN operations less_than are performed. IMPLEMENTATION: TYPE *insert(TYPE value, TYPE *begin, TYPE *end) { begin = binary_partition(value, begin, end); copy(begin, end, begin + 1); *begin = value; return begin; } NAME: insert - inserts an element in an ordered block SYNOPSIS: TYPE *insert(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end); DESCRIPTION: insert assigns value to the location in the ordered block that contains the leftmost element greater than value. Before the assignment all the elements from that location to the end of the block are moved one location to the right. relation is the name of the comparison function, which is called with two arguments that point to the elements being compared. As the function must return an integer less than, equal to, or greater than zero, so must the first argument to be considered be less than, equal to, or greater than the second. SEE ALSO: binary_partition, binary_search, set_insert ASSUMPTIONS: Assignment ("=") is defined for the TYPE DEPENDS ON: TYPE *binary_partition(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end); void copy(TYPE *begin, TYPE *end, TYPE *result); COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block then at most N assignments and at most logN call to the relation are performed. IMPLEMENTATION: TYPE *insert(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end) { begin = binary_partition(relation, value, begin, end); copy(begin, end, begin + 1); *begin = value; return begin; } NAME: insertion_sort - sorts a block SYNOPSIS: void insertion_sort(TYPE *begin, TYPE *end); DESCRIPTION: insertion_sort sorts a block in place. The sorting is stable, namely, the relative order of equal elements is preserved. It is the sort of choice when: 1) the size of the block is small; or 2) the number of elements out of order is small; or 3) the average distance between original position of an element and its final destination is small. (By small we mean less than 16.) SEE ALSO: merge_sort, sort, stable_sort ASSUMPTIONS: Less_than ("<") and assignment ("=") are defined for the TYPE DEPENDS ON: TYPE *minimum(TYPE *begin, TYPE *end); COMPLEXITY: Quadratic in the size of the block. If N is the number of locations in the block then on the average N^2/4 less_than operations and same number of assignments are performed. IMPLEMENTATION: void insertion_sort(register TYPE *begin, register TYPE *end) { if (end - begin < 2) /* size < 2 */ return; TYPE *r = minimum(begin, end); /* create a sentinel */ TYPE temp = *begin; /* swap */ *begin = *r; *r = temp; begin++; /* there is no need to insert the second element */ while (++begin < end) { REGISTER TYPE value = *begin; register TYPE *index = begin; while (value < *--index) *(index + 1) = *index; *(index + 1) = value; } } NAME: insertion_sort - sorts a block SYNOPSIS: void insertion_sort(int (*relation)(TYPE*, TYPE*), TYPE *begin, TYPE *end); DESCRIPTION: insertion_sort sorts a block in place. The sorting is stable, namely, the relative order of equal elements is preserved. It is the sort of choice when: 1) the size of the block is small; or 2) the number of elements out of order is small; or 3) the average distance between original position of an element and its final destination is small. (By small we mean less than 16.) relation is the name of the comparison function, which is called with two arguments that point to the elements being compared. As the function must return an integer less than, equal to, or greater than zero, so must the first argument to be considered be less than, equal to, or greater than the second. SEE ALSO: merge_sort, sort, stable_sort ASSUMPTIONS: Assignment ("=") is defined for the TYPE DEPENDS ON: nothing COMPLEXITY: Quadratic in the size of the block. If N is the number of locations in the block then on the average N^2/4 less_than operations and same number of assignments are performed. IMPLEMENTATION: void insertion_sort(register int (*relation)(TYPE*, TYPE*), register TYPE *begin, TYPE *end) { register TYPE *index = begin; while (++index < end) { TYPE value = *index; register TYPE *temp = &value; register TYPE *current = index; for (; begin < current && (*relation)(temp , current - 1) < 0; current--) *current = *(current - 1); *current = value; } } NAME: intersection - collects those elements of two ordered blocks that are in both SYNOPSIS: TYPE *intersection(int (*relation)(TYPE*, TYPE*), TYPE *begin1, TYPE *end1, TYPE *begin2, TYPE *end2, TYPE *result); DESCRIPTION: intersection puts elements from two ordered blocks with no repetitions into a new ordered block with no repetitions so that for every element which is in both blocks it will be placed in the result The pointer after the last element of the new block is returned. relation is the name of the comparison function, which is called with two arguments that point to the elements being compared. As the function must return an integer less than, equal to, or greater than zero, so must the first argument to be considered be less than, equal to, or greater than the second. NOTE: If begin1 <= result < end1 or begin1 <= result + (end1 - begin1) < end1 or begin2 <= result < end2 or begin2 <= result + (end2 - begin2) < end2 then the effect of intersection is not defined. SEE ALSO: difference, merge, set_union, symmetric_difference, unique ASSUMPTIONS: Assignment ("=") is defined for the TYPE DEPENDS ON: nothing COMPLEXITY: Linear in the size of the blocks. If N and M are the numbers of locations in the blocks then at most N + M - 1 calls to relation and maximum(N, M) assignments are performed. IMPLEMENTATION: TYPE *intersection(register int (*relation)(TYPE*, TYPE*), register TYPE *begin1, register TYPE *end1, register TYPE *begin2, register TYPE *end2, register TYPE *result) { while (begin1 < end1 && begin2 < end2) { register int c = (*relation)(begin2, begin1); if (c < 0) begin2++; else if (0 < c) begin1++; else { *(result++) = *(begin1++); begin2++; } } return result; } NAME: intersection - collects those elements of two ordered blocks that are in both SYNOPSIS: TYPE *intersection(TYPE *begin1, TYPE *end1, TYPE *begin2, TYPE *end2, TYPE *result); DESCRIPTION: intersection puts elements from two ordered blocks with no repetitions into a new ordered block with no repetitions so that for every element which is in both blocks it will be placed in the result The pointer after the last element of the new block is returned. NOTE: If begin1 <= result < end1 or begin1 <= result + (end1 - begin1) < end1 or begin2 <= result < end2 or begin2 <= result + (end2 - begin2) < end2 then the effect of intersection is not defined. SEE ALSO: difference, merge, set_union, symmetric_difference, unique ASSUMPTIONS: Less_than ("<") and assignment ("=") are defined for the TYPE DEPENDS ON: nothing COMPLEXITY: Linear in the size of the blocks. If N and M are the numbers of locations in the blocks then at most N + M - 1 less_than operations and maximum(N, M) assignments are performed. IMPLEMENTATION: TYPE *intersection(register TYPE *begin1, register TYPE *end1, register TYPE *begin2, register TYPE *end2, register TYPE *result) { while (begin1 < end1 && begin2 < end2) if (*begin2 < *begin1) begin2++; else if (*begin1 < *begin2) begin1++; else { *(result++) = *(begin1++); begin2++; } return result; } NAME: merge - combines two ordered blocks into one SYNOPSIS: void merge(int (*relation)(TYPE*, TYPE*), TYPE *begin1, TYPE *end1, TYPE *begin2, TYPE *end2, TYPE *result); DESCRIPTION: merge combines two ordered blocks into one. merge is stable. That is, equal elements from the first block precede equal elements from the second. relation is the name of the comparison function, which is called with two arguments that point to the elements being compared. As the function must return an integer less than, equal to, or greater than zero, so must the first argument to be considered be less than, equal to, or greater than the second. NOTE: If begin1 <= result < end1 or begin1 <= result + (end1 - begin1) < end1 or begin2 <= result < end2 or begin2 <= result + (end2 - begin2) < end2 than the effect of merge is not defined. SEE ALSO: difference, intersection, symmetric_difference, union ASSUMPTIONS: Assignment ("=") is defined for the TYPE DEPENDS ON: nothing COMPLEXITY: Linear in the size of the blocks. If N and M are the numbers of locations in the blocks then at most N + M - 1 less_than operations and N + M assignments are performed. IMPLEMENTATION: void merge(register int (*relation)(TYPE*, TYPE*), register TYPE *begin1, register TYPE *end1, register TYPE *begin2, register TYPE *end2, register TYPE *result) { while (begin1 < end1 && begin2 < end2) *result++ = ((*relation)(begin2, begin1) < 0 ? *begin2++ : *begin1++); while (begin1 < end1) *result++ = *begin1++; while (begin2 < end2) *result++ = *begin2++; } NAME: merge - combines two ordered blocks into one SYNOPSIS: void merge(TYPE *begin1, TYPE *end1, TYPE *begin2, TYPE *end2, TYPE *result); DESCRIPTION: merge combines two ordered blocks into one. merge is stable. That is, equal elements from the first block precede equal elements from the second. NOTE: If begin1 <= result < end1 or begin1 <= result + (end1 - begin1) < end1 or begin2 <= result < end2 or begin2 <= result + (end2 - begin2) < end2 then the effect of merge is not defined. SEE ALSO: difference, intersection, symmetric_difference, union ASSUMPTIONS: Less_than ("<") and assignment ("=") are defined for the TYPE DEPENDS ON: nothing COMPLEXITY: Linear in the size of the blocks. If N and M are the numbers of locations in the blocks then at most N + M - 1 calls to relation and N + M assignments are performed. IMPLEMENTATION: void merge(register TYPE *begin1, register TYPE *end1, register TYPE *begin2, register TYPE *end2, register TYPE *result) { while (begin1 < end1 && begin2 < end2) *result++ = (*begin2 < *begin1 ? *begin2++ : *begin1++); while (begin1 < end1) *result++ = *begin1++; while (begin2 < end2) *result++ = *begin2++; } NAME: merge_sort - sorts a block SYNOPSIS: TYPE *merge_sort(TYPE *begin, TYPE *end, TYPE *result); DESCRIPTION: merge_sort sorts a block. It is stable, that is the relative order of equal elements is preserved. It does require an auxiliary block of the same size (the address of an auxiliary block is the third argument to merge_sort). It returns the address of the original block or the address of the auxiliary block depending on which one contains the final result of the sort. NOTE: If begin <= result < end or begin <= result + (end - begin) < end then the effect of merge_sort is not defined. SEE ALSO: insertion_sort, sort, stable_sort ASSUMPTIONS: Less_than ("<") and assignment ("=") are defined for the TYPE DEPENDS ON: void insertion_sort(TYPE *begin, TYPE *end); void merge(TYPE *begin1, TYPE *end1, TYPE *begin2, TYPE *end2, TYPE *result); COMPLEXITY: O(NlogN) in the size of the block. If N is the size of the block then at most N*log(N) less_than operations and at most the same number of assignments is performed. IMPLEMENTATION: static void merge_sort_step(ptrdiff_t number, TYPE *begin, TYPE *end, TYPE *result) { ptrdiff_t m = 2 * number; while (begin + m < end) { merge(begin, begin + number, begin + number, begin + m, result); begin += m; result += m; } if (begin + number + 1 < end) merge(begin, begin + number, begin + number, end, result); else while (begin < end) *result++ = *begin++; } static void insertion_sort_chunks(ptrdiff_t number, TYPE *begin, TYPE *end) { for (; begin + number < end; begin += number) insertion_sort(begin, begin + number); insertion_sort(begin, end); } TYPE *merge_sort(TYPE *begin, TYPE *end, TYPE *result) { ptrdiff_t number = 8, length = end - begin; insertion_sort_chunks(number, begin, end); for (; number < length; number += number, end = begin, begin = result, result = end) merge_sort_step(number, begin, begin + length, result); return begin; } NAME: merge_sort - sorts a block SYNOPSIS: TYPE *merge_sort(int (*relation)(TYPE*, TYPE*), TYPE *begin, TYPE *end, TYPE *result); DESCRIPTION: merge_sort sorts a block. It is stable, that is the relative order of equal elements is preserved. It does require an auxiliary block of the same size (the address of an auxiliary block is the third argument to merge_sort). It returns the address of the original block or the address of the auxiliary block depending on which one contains the final result of the sort. relation is the name of the comparison function, which is called with two arguments that point to the elements being compared. As the function must return an integer less than, equal to, or greater than zero, so must the first argument to be considered be less than, equal to, or greater than the second. NOTE: If begin <= result < end or begin <= result + (end - begin) < end then the effect of merge_sort is not defined. SEE ALSO: insertion_sort, sort, stable_sort ASSUMPTIONS: Assignment ("=") is defined for the TYPE DEPENDS ON: void insertion_sort(int (*relation)(TYPE*, TYPE*), TYPE *begin, TYPE *end); void merge(int (*relation)(TYPE*, TYPE*), TYPE *begin1, TYPE *end1, TYPE *begin2, TYPE *end2, TYPE *result); COMPLEXITY: O(NlogN) in the size of the block. If N is the size of the block then at most N*log(N) calls to relation and at most the same number of assignments is performed. IMPLEMENTATION: static void merge_sort_step(int (*relation)(TYPE*, TYPE*), ptrdiff_t number, TYPE *begin, TYPE *end, TYPE *result) { ptrdiff_t m = 2 * number; while (begin + m < end) { merge(relation, begin, begin + number, begin + number, begin + m, result); begin += m; result += m; } if (begin + number + 1 < end) merge(relation, begin, begin + number, begin + number, end, result); else while (begin < end) *result++ = *begin++; } static void insertion_sort_chunks(int (*relation)(TYPE*, TYPE*), ptrdiff_t number, TYPE *begin, TYPE *end) { for (; begin + number < end; begin += number) insertion_sort(relation, begin, begin + number); insertion_sort(relation, begin, end); } TYPE *merge_sort(int (*relation)(TYPE*, TYPE*), TYPE *begin, TYPE *end, TYPE *result) { ptrdiff_t number = 8, length = end - begin; insertion_sort_chunks(relation, number, begin, end); for (; number < length; number += number, end = begin, begin = result, result = end) merge_sort_step(relation, number, begin, begin + length, result); return begin; } NAME: minimum - finds the smallest element in the block SYNOPSIS: TYPE *minimum(TYPE *begin, TYPE *end); DESCRIPTION: minimum returns a pointer to the leftmost smallest element in the block NOTE: If the block is empty then begin is returned. SEE ALSO: select ASSUMPTIONS: Less_than ("<") is defined for the TYPE DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block then exactly N - 1 operation less_than are performed. IMPLEMENTATION: TYPE *minimum(register TYPE *begin, register TYPE *end) { register TYPE *index = begin; while (++begin < end) if (*begin < *index) index = begin; return index; } NAME: minimum - finds the smallest element in the block SYNOPSIS: TYPE *minimum(int (*relation)(TYPE*, TYPE*), TYPE *begin, TYPE *end); DESCRIPTION: minimum returns a pointer to the leftmost smallest element in the block. relation is the name of the comparison function, which is called with two arguments that point to the elements being compared. As the function must return an integer less than, equal to, or greater than zero, so must the first argument to be considered be less than, equal to, or greater than the second. NOTE: If the block is empty then begin is returned. SEE ALSO: select ASSUMPTIONS: none DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block then exactly N - 1 calls to the relation are performed. IMPLEMENTATION: TYPE *minimum(register int (*relation)(TYPE*, TYPE*), register TYPE *begin, register TYPE *end) { register TYPE *index = begin; while (++begin < end) if ((*relation)(begin, index) < 0) index = begin; return index; } NAME: mismatch - finds first mismatch among two blocks SYNOPSIS: TYPE *mismatch(TYPE *begin1, TYPE *end1, TYPE *begin2, TYPE *end2); DESCRIPTION: mismatch returns a pointer to the leftmost element within the first block which is not equal to the corresponding element in the second block. If such an element does not exist then the 0 pointer is returned. SEE ALSO: other mismatch, search ASSUMPTIONS: Equality ("==") is defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the blocks. If N and M are correspondingly the numbers of locations in the first and second blocks then at most minimum(N, M) equality operations on the TYPE are performed. IMPLEMENTATION: TYPE *mismatch(register TYPE *begin1, register TYPE *end1, register TYPE *begin2, register TYPE *end2) { register ptrdiff_t len = end1 - begin1 < end2 - begin2 ? end1 - begin1 : end2 - begin2; while (0 < len--) if (!(*begin1++ == *begin2++)) return begin1; return 0; } NAME: mismatch - finds first mismatch among two blocks SYNOPSIS: TYPE *mismatch(int (*relation)(TYPE*, TYPE*), TYPE *begin1, TYPE *end1, TYPE *begin2, TYPE *end2); DESCRIPTION: mismatch returns a leftmost location within the first block which does not satisfy the relation with the corresponding location in the second block. If such an element does not exist then the 0 pointer is returned. SEE ALSO: other mismatch, search ASSUMPTIONS: none DEPENDS ON: nothing COMPLEXITY: Linear in the size of the blocks. If N and M are correspondingly the numbers of locations in the first and second blocks then at most minimum(N, M) calls to the relation are performed. IMPLEMENTATION: TYPE *mismatch(register int (*relation)(TYPE*, TYPE*), register TYPE *begin1, register TYPE *end1, register TYPE *begin2, register TYPE *end2) { register ptrdiff_t len = end1 - begin1 < end2 - begin2 ? end1 - begin1 : end2 - begin2; while (0 < len--) if (!(*relation)(begin1++, begin2++)) return begin1; return 0; } NAME: partition - separates elements into those that satisfy the predicate and those that do not SYNOPSIS: TYPE *partition(int (*predicate)(TYPE*), TYPE *begin, TYPE *end); DESCRIPTION: partition moves elements in those locations of the block that do satisfy the predicate to the left and those that do not satisfy the predicate to the right and returns the pointer after the last "satisfying" element. NOTE: partition does not preserve the relative order of elements in both groups ("satisfying" and "not-satisfying") that is, it is not stable. If stability is desired then stable_partition should be used. (Actually, at present it is better to use stable_partition_copy - if extra memory is available - and then copy the block back.) SEE ALSO: other partition, partition_copy, remove, remove_copy, stable_partition, stable_partition_copy, stable_remove, stable_remove_copy ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N calls to predicate are done. If P is the number of locations in the block that do satisfy the predicate then at most 3*min(P, N-P) assignments of TYPE are done. IMPLEMENTATION: TYPE *partition(register int (*predicate)(TYPE*), register TYPE *begin, register TYPE *end) { for (;;) { for (;;begin++) if (begin >= end) return end; else if (!(*predicate)(begin)) break; for (;;) if (begin >= --end) return end; else if ((*predicate)(end)) break; { REGISTER TYPE temp = *begin; *begin++ = *end; *end = temp; } } } NAME: partition - separates elements into those that are equal to the value and those that are not SYNOPSIS: TYPE *partition(TYPE value, TYPE *begin, TYPE *end); DESCRIPTION: partition moves elements in the block that are equal to the value to the left and those that are not equal to the right and returns the pointer after the last "equal" element. NOTE: partition does not preserve the relative order of elements in both groups ("equal" and "not-equal") that is, it is not stable. If stability is desired then stable_partition should be used. (Actually, at present it is better to use stable_partition_copy - if extra memory is available - and then copy the block back.) SEE ALSO: other partition, partition_copy, remove, remove_copy, stable_partition, stable_partition_copy, stable_remove, stable_remove_copy ASSUMPTIONS: Assignment ("=") and equality ("==") are defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N equality operations on TYPE are performed. If P is the number of elements in the block that are equal to the value then at most 3*min(P, N-P) assignments of TYPE are done. IMPLEMENTATION: TYPE *partition(REGISTER TYPE value, register TYPE *begin, register TYPE *end) { for (;;) { for (;;begin++) if (begin >= end) return end; else if (!(*begin == value)) break; for (;;) if (begin >= --end) return end; else if (*end == value) break; { REGISTER TYPE temp = *begin; *begin++ = *end; *end = temp; } } } NAME: partition - separates elements into those that relate to the value and those that are not SYNOPSIS: TYPE *partition(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end); DESCRIPTION: partition moves elements in those locations of the block that do satisfy the relation with the pointer to the value to the left and those that do not satisfy the relation to the right and returns the pointer after the last "satisfying" element. NOTE: partition does not preserve the relative order of elements in both groups ("satisfying" and "not-satisfying") that is, it is not stable. If stability is desired then stable_partition should be used. (Actually, at present it is better to use stable_partition_copy - if extra memory is available - and then copy the block back.) SEE ALSO: other partition, partition_copy, remove, remove_copy, stable_partition, stable_partition_copy, stable_remove, stable_remove_copy ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N equality operations on TYPE are performed. If P is the number of locations in the block that satisfy relation with the pointer to the value then at most 3*min(P, N-P) assignments of TYPE are done. IMPLEMENTATION: TYPE *partition(register int (*relation)(TYPE*, TYPE*), TYPE value, register TYPE *begin, register TYPE *end) { register TYPE *temp = &value; for (;;) { for (;;begin++) if (begin >= end) return end; else if (!(*relation)(begin, temp)) break; for (;;) if (begin >= --end) return end; else if ((*relation)(end, temp)) break; { REGISTER TYPE temp = *begin; *begin++ = *end; *end = temp; } } } NAME: partition_copy - copies elements satisfying the predicate before the elements that do not SYNOPSIS: TYPE *partition_copy(int (*predicate)(TYPE*), TYPE *begin, TYPE *end, TYPE *result); DESCRIPTION: partition_copy first copies elements in those locations of the block that do satisfy the predicate and then those that do not satisfy the predicate and returns the pointer after the copy of the last "satisfying" element. NOTE: 1) partition_copy does not preserve the relative order of elements in both groups ("satisfying" and "not-satisfying") that is, it is not stable. If stability is desired then stable_partition_copy should be used. (Actually, the ordering of the "satisfying" group is stable, and the ordering of the "not-satisfying" is the inverse of the stable.) 2) If begin <= result < end or begin <= result + (end - begin) < end then the effect of partition_copy is not defined. SEE ALSO: partition, other partition_copy, remove, remove_copy, stable_partition, stable_partition_copy, stable_remove, stable_remove_copy ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N calls to the predicate and N assignments of TYPE are done. IMPLEMENTATION: TYPE *partition_copy(register int (*predicate)(TYPE*), register TYPE *begin, register TYPE *end, register TYPE *result) { register TYPE *last = result + (end - begin); for (; begin < end; begin++) if ((*predicate)(begin)) *(result++) = *begin; else *--last = *begin; return last; } NAME: partition_copy - copies elements equal to the value before those that are not SYNOPSIS: TYPE *partition_copy(TYPE value, TYPE *begin, TYPE *end, TYPE *result); DESCRIPTION: partition_copy first copies elements in the block that are equal to the value and then those that are not and returns the pointer after the copy of the last "equal" element. NOTE: 1) partition_copy does not preserve the relative order of elements in both groups ("equal" and "not-equal") that is, it is not stable. If stability is desired then stable_partition_copy should be used. (Actually, the ordering of the "equal" group is stable, and the ordering of the "not-equal" is the inverse of the stable.) 2) If begin <= result < end or begin <= result + (end - begin) < end then the effect of partition_copy is not defined. SEE ALSO: partition, other partition_copy, remove, remove_copy, stable_partition, stable_partition_copy, stable_remove, stable_remove_copy ASSUMPTIONS: Assignment ("=") and equality ("==") are defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N equalities of TYPE and N assignments of TYPE are done. IMPLEMENTATION: TYPE *partition_copy(REGISTER TYPE value, TYPE *begin, register TYPE *end, register TYPE *result) { register TYPE *last = result + (end - begin); for (; begin < end; begin++) if (*begin == value) *(result++) = *begin; else *(--last) = *begin; return last; } NAME: partition_copy - copies elements related to the value before those that are not SYNOPSIS: TYPE *partition_copy(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end, TYPE *result); DESCRIPTION: partition_copy first copies those elements in the block locations of which satisfy the relation with the pointer to the value and then those that do not and returns the pointer after the copy of the last "satisfying" element. NOTE: 1) partition_copy does not preserve the relative order of elements in both groups ("satisfying" and "not-satisfying") that is, it is not stable. If stability is desired then stable_partition_copy should be used. (Actually, the ordering of the "satisfying" group is stable, and the ordering of the "not-satisfying" is the inverse of the stable.) 2) If begin <= result < end or begin <= result + (end - begin) < end then the effect of partition_copy is not defined. SEE ALSO: partition, other partition_copy, remove, remove_copy, stable_partition, stable_partition_copy, stable_remove, stable_remove_copy ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N calls to the relation and N assignments of TYPE are done. IMPLEMENTATION: TYPE *partition_copy(register int (*relation)(TYPE*, TYPE*), TYPE value, register TYPE *begin, register TYPE *end, register TYPE *result) { register TYPE *last = result + (end - begin); register TYPE *temp = &value; for (; begin < end; begin++) if ((*relation)(begin, temp)) *(result++) = *begin; else *(--last) = *begin; return last; } NAME: position - finds leftmost location in the block satisfying the predicate SYNOPSIS: TYPE *position(int (*predicate)(TYPE*), TYPE *begin, TYPE *end); DESCRIPTION: Position returns the leftmost pointer in the block that satisfies predicate if such a pointer exists, or 0 if there is no such pointer. SEE ALSO: other position, right_position, search ASSUMPTIONS: none DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block at most N calls to predicate are done. IMPLEMENTATION: TYPE *position(register int (*predicate)(TYPE*), register TYPE *begin, register TYPE *end) { while (begin < end) if ((*predicate)(begin++)) return begin - 1; return 0; } NAME: position - finds leftmost value in the block equal to the given value SYNOPSIS: TYPE *position(TYPE value, TYPE *begin, TYPE *end); DESCRIPTION: Position returns the leftmost pointer in the block that points to an element equal to value if such a pointer exists, or 0 if there is no such pointer. SEE ALSO: other position, right_position, search ASSUMPTIONS: Equality ("==") is defined for the TYPE. DEPENDS ON: Nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block at most N equalities of TYPE are performed. IMPLEMENTATION: TYPE *position(REGISTER TYPE value, register TYPE *begin, register TYPE *end) { while (begin < end) if (*begin++ == value) return begin - 1; return 0; } NAME: position - finds leftmost value in the block satisfying the relation to the given value SYNOPSIS: TYPE *position(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end); DESCRIPTION: position returns the leftmost pointer in the block that satisfies relation with the pointer to value if such a pointer exists, or 0 if there is no such pointer. SEE ALSO: Aother position, right_position, search ASSUMPTIONS: none DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block at most N calls to relation are done. IMPLEMENTATION: TYPE *position(register int (*relation)(TYPE*, TYPE*), TYPE value, register TYPE *begin, register TYPE *end) { register TYPE *temp = &value; while (begin < end) if ((*relation)(begin++, temp)) return begin - 1; return 0; } NAME: random - returns a random pointer to a location in a block SYNOPSIS: TYPE *random(TYPE *begin, TYPE *end); DESCRIPTION: random returns a uniformly distributed random pointer between begin (inclusive) and end (exclusive). Since random uses drand48 it is important that the random number generator is initialized with srand48, seed48, or lcong48 (see drand48(3C)) before random is used. If begin is greater or equal than end 0 pointer is returned. NOTE: random uses drand48, which is UNIX System V specific. In the future, it should be parameterized and use the appropriate random number generator. ASSUMPTIONS: none DEPENDS ON: double drand48(); (in ) COMPLEXITY: constant in the size of the block IMPLEMENTATION: #include TYPE *random(TYPE *begin, TYPE *end) { if (begin < end) return begin + (ptrdiff_t)(drand48() * (end - begin)); else return 0; } NAME: remove - removes elements satisfying the predicate SYNOPSIS: TYPE *remove(int (*predicate)(TYPE*), TYPE *begin, TYPE *end); DESCRIPTION: remove moves all the elements in the block locations of which do not satisfy predicate to the left and returns the pointer pointing after the last such element. NOTE: remove does not preserve the relative order of elements locations of which do not satisfy the predicate, that is, it is not stable. If stability is desired then stable_remove should be used. SEE ALSO: partition, partition_copy, remove_copy, stable_partition, stable_partition_copy, stable_remove, stable_remove_copy ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N calls to predicate are done. If P is the number of locations in the block that do not satisfy predicate then at most P assignments of TYPE are done. IMPLEMENTATION: TYPE *remove(register int (*predicate)(TYPE*), register TYPE *begin, register TYPE *end) { for (;;) { for (;;begin++) if (begin >= end) return end; else if ((*predicate)(begin)) break; for (;;) if (begin >= --end) return end; else if (!(*predicate)(end)) break; *begin++ = *end; } } NAME: remove - removes elements equal to the value SYNOPSIS: TYPE *remove(TYPE value, TYPE *begin, TYPE *end); DESCRIPTION: remove moves all the elements in the block which are not equal to value to the left and returns the pointer pointing after the last such element. NOTE: remove does not preserve the relative order of elements that are not equal to the value, that is, it is not stable. If stability is desired then stable_remove should be used. SEE ALSO: partition, partition_copy, other remove, remove_copy, stable_partition, stable_partition_copy, stable_remove, stable_remove_copy ASSUMPTIONS: Assignment ("=") and equality ("==") are defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N equality operations of the TYPE are performed. If P is the number of locations in the block that are not equal to the value then at most P assignments of TYPE are done. IMPLEMENTATION: TYPE *remove(REGISTER TYPE value, register TYPE *begin, register TYPE *end) { for (;;) { for (;;begin++) if (begin >= end) return end; else if (*begin == value) break; for (;;) if (begin >= --end) return end; else if (!(*end == value)) break; *begin++ = *end; } } NAME: remove - removes elements satisfying the relation with the value SYNOPSIS: TYPE *remove(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end); DESCRIPTION: remove moves all the elements in the block, locations of which do not satisfy the relation with the pointer to the value, to the left and returns the pointer pointing after the last such element. NOTE: remove does not preserve the relative order of elements locations of which do not satisfy the relation with the pointer to the value, that is, it is not stable. If stability is desired then stable_remove should be used. SEE ALSO: partition, partition_copy, other remove, remove_copy, stable_partition, stable_partition_copy, stable_remove, stable_remove_copy ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N calls to the relation are done. If P is the number of locations in the block that do not satisfy the relation with the value then at most P assignments of TYPE are done. IMPLEMENTATION: TYPE *remove(register int (*relation)(TYPE*, TYPE*), TYPE value, register TYPE *begin, register TYPE *end) { register TYPE *temp = &value; for (;;) { for (;;begin++) if (begin >= end) return end; else if ((*relation)(begin, temp)) break; for (;;) if (begin >= --end) return end; else if (!(*relation)(end, temp)) break; *begin++ = *end; } } NAME: remove_copy - copies the elements not satisfying the predicate SYNOPSIS: TYPE *remove_copy(int (*predicate)(TYPE*), TYPE *begin, TYPE *end, TYPE *result); DESCRIPTION: remove_copy copies elements in those locations in the block that do not satisfy the predicate in the consecutive locations starting with result, and returns the pointer past the last of the copies. NOTE: 1) The relative order of the elements not satisfying the predicate IS preserved. (It IS stable.) 2) If begin <= result < end or begin <= result + (end - begin) < end then the effect of remove_copy is not defined. SEE ALSO: partition, partition_copy, remove, other remove_copy, stable_partition, stable_partition_copy, stable_remove, stable_remove_copy ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N calls to predicate are done. If P is the number of locations in the block that do not satisfy predicate then exactly P assignments of TYPE are done. IMPLEMENTATION: TYPE *remove_copy(register int (*predicate)(TYPE*), register TYPE *begin, register TYPE *end, register TYPE *result) { for (; begin < end; begin++) if (!(*predicate)(begin)) *result++ = *begin; return result; } NAME: remove_copy - copies the elments not equal to the value SYNOPSIS: TYPE *remove_copy(TYPE value, TYPE *begin, TYPE *end, TYPE *result); DESCRIPTION: remove_copy copies those elements in the block, that are not equal to the value, in the consecutive locations starting with result, and returns the pointer past the last of the copies. NOTE: 1) The relative order of the elements not satisfying the predicate IS preserved. (It IS stable.) 2) If begin <= result < end or begin <= result + (end - begin) < end then the effect of remove_copy is not defined. SEE ALSO: partition, partition_copy, remove, other remove_copy, stable_partition, stable_partition_copy, stable_remove, stable_remove_copy ASSUMPTIONS: Assignment ("=") and equality ("==") are defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N equality operations of the TYPE are performed. If P is the number of locations in the block that are not equal to the value then exactly P assignments of TYPE are done. IMPLEMENTATION: TYPE *remove_copy(REGISTER TYPE value, register TYPE *begin, register TYPE *end, register TYPE *result) { for (; begin < end; begin++) if (!(*begin == value)) *result++ = *begin; return result; } NAME: remove_copy - copies elements that are not related to the value SYNOPSIS: TYPE *remove_copy(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end, TYPE *result); DESCRIPTION: remove_copy copies those elements in the locations in the block, that do not satisfy the relation with the pointer to the value, in the consecutive locations starting with result, and returns the pointer past the last of the copies. NOTE: 1) The relative order of the elements not satisfying the predicate IS preserved. (It IS stable.) 2) If begin <= result < end or begin <= result + (end - begin) < end then the effect of remove_copy is not defined. SEE ALSO: partition, partition_copy, remove, other remove_copy, stable_partition, stable_partition_copy, stable_remove, stable_remove_copy ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N calls to the relation are done. If P is the number of locations in the block that do not satisfy the relation with the value then exactly P assignments of TYPE are done. IMPLEMENTATION: TYPE *remove_copy(register int (*relation)(TYPE*, TYPE*), TYPE value, register TYPE *begin, register TYPE *end, register TYPE *result) { register TYPE *temp = &value; for (; begin < end; begin++) if (!(*relation)(begin, temp)) *result++ = *begin; return result; } NAME: remove_duplicates - removes duplicate elements SYNOPSIS: TYPE *remove_duplicates(TYPE *begin, TYPE *end); DESCRIPTION: remove_duplicates moves all unique (not equal to each other) elements in the block to the left and returns the pointer after the last unique elements. The relative order of the unique elements is preserved. NOTE: remove_duplicate is quadratic and should not be used with large (more than a hundred or so elements) blocks. Large blocks should be first sorted with sort or stable_sort and then passed through unique. SEE ALSO: other remove_duplicates, remove_duplicates_copy, unique, unique_copy ASSUMPTIONS: Assignment ("=") and equality ("==") are defined for the TYPE. DEPENDS ON: TYPE *position(TYPE value, TYPE *begin, TYPE *end); COMPLEXITY: Quadratic in the size of the block. If N is the number of locations in the block at most N^2/2 equality operations of TYPE and at most N - 2 assignments of TYPE are performed. IMPLEMENTATION: TYPE *remove_duplicates(register TYPE *begin, register TYPE *end) { register TYPE *index = begin; register TYPE *m; for(;index < end; index++) if (position(*index, begin, index) != index) break; m = index; while (++index < end) if (position(*index, begin, m) == m) *m++ = *index; return m; } NAME: remove_duplicates - removes duplicate elements SYNOPSIS: TYPE *remove_duplicates(int (*relation)(TYPE*, TYPE*), TYPE *begin, TYPE *end); DESCRIPTION: remove_duplicates moves all unique (not satisfying the relation to each other) elements in the block to the left and returns the pointer after the last unique elements. The relative order of the unique elements is preserved. NOTE: remove_duplicate is quadratic and should not be used with large (more than a hundred or so elements) blocks. Large blocks should be first sorted with sort or stable_sort and then passed through unique. SEE ALSO: other remove_duplicates, remove_duplicates_copy, unique, unique_copy ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: TYPE *position(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end); COMPLEXITY: Quadratic in the size of the block. If N is the number of locations in the block at most N^2/2 calls to the relation and at most N - 2 assignments of TYPE are performed. IMPLEMENTATION: TYPE *remove_duplicates(int (*relation)(TYPE*, TYPE*), register TYPE *begin, register TYPE *end) { register TYPE *index = begin; register TYPE *m; for(;index < end; index++) if (position(relation, *index, begin, index) != index) break; m = index; while (++index < end) if (!position(relation, *index, begin, m)) *m++ = *index; return m; } NAME: remove_duplicates_copy - copies all unique elements SYNOPSIS: TYPE *remove_duplicates_copy(TYPE *begin, TYPE *end, TYPE *result); DESCRIPTION: remove_duplicates_copy copies all unique (not equal to each other) elements in the block and returns the pointer after the last copied element. The relative order of the unique elements is preserved. NOTE: 1) remove_duplicate_copy is quadratic and should not be used with large (more than a hundred or so elements) blocks. Large blocks should be first copied, then sorted with sort or stable_sort and then passed through unique. 2) If begin <= result < end or begin <= result + (end - begin) < end then the effect of remove_duplicates_copy is not defined. SEE ALSO: remove_duplicates, other remove_duplicates_copy, unique, unique_copy ASSUMPTIONS: Assignment ("=") and equality ("==") are defined for the TYPE. DEPENDS ON: TYPE *position(TYPE value, TYPE *begin, TYPE *end); COMPLEXITY: Quadratic in the size of the block. If N is the number of locations in the block at most N^2/2 equality operations of TYPE and at most N assignments of TYPE are performed. IMPLEMENTATION: TYPE *remove_duplicates_copy(register TYPE *begin, register TYPE *end, register TYPE *result) { register TYPE *m = result; for (; begin < end; begin++) if (!position(*begin, result, m)) *m++ = *begin; return m; } NAME: remove_duplicates_copy - copies all unique elements SYNOPSIS: TYPE *remove_duplicates_copy(int (*relation)(TYPE*, TYPE*), TYPE *begin, TYPE *end, TYPE *result); DESCRIPTION: remove_duplicates_copy copies all unique (not satisfying the relation to each other) elements in the block and returns the pointer after the last copied element. The relative order of the unique elements is preserved. NOTE: 1) remove_duplicate_copy is quadratic and should not be used with large (more than a hundred or so elements) blocks. Large blocks should be first copied, then sorted with sort or stable_sort and then passed through unique. 2) If begin <= result < end or begin <= result + (end - begin) < end then the effect of remove_duplicates_copy is not defined. SEE ALSO: remove_duplicates, other remove_duplicates_copy, unique, unique_copy ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: TYPE *position(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end); COMPLEXITY: Quadratic in the size of the block. If N is the number of locations in the block at most N^2/2 calls to the relation and at most N assignments of TYPE are performed. IMPLEMENTATION: TYPE *remove_duplicates_copy(int (*relation)(TYPE*, TYPE*), register TYPE *begin, register TYPE *end, register TYPE *result) { register TYPE *m = result; for (; begin < end; begin++) if (position(relation, *begin, result, m) == m) *m++ = *begin; return m; } NAME: reverse - reverses a block in place SYNOPSIS: void reverse(TYPE *begin, TYPE *end); DESCRIPTION: Reverse reverses a block in place, namely, for every integer i, 0 <= i < (end - begin), that after the reversal the location end - (i + 1) has the same value as begin + i had before the reversal. SEE ALSO: reverse_copy ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly 3*floor(N/2) assignments of TYPE are performed. IMPLEMENTATION: void reverse(register TYPE *begin, register TYPE *end) { while (begin < --end) { REGISTER TYPE temp = *begin; *begin++ = *end; *end = temp; } } NAME: reverse_copy - copies a block in the reversed order SYNOPSIS: void reverse_copy(TYPE *begin, TYPE *end, TYPE *result); DESCRIPTION: Reverse_copy moves every value in a block into a new location in the reversed order, namely, for every integer i, 0 <= i < (end - begin), that after the reversal the location result + i has the same value as end - (i + 1) had before the reversal. NOTE: If begin <= result < end or begin <= result + (end - begin) < end then the effect of reverse_copy is not defined. SEE ALSO: reverse ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N assignments of TYPE are performed. IMPLEMENTATION: void reverse_copy(register TYPE *begin, register TYPE *end, register TYPE *result) { while (begin < end--) *result++ = *end; } NAME: right_position - finds rightmost location in the block satisfying the predicate SYNOPSIS: TYPE *right_position(int (*predicate)(TYPE*), TYPE *begin, TYPE *end); DESCRIPTION: Right_position returns the rightmost pointer in the block that satisfies predicate if such a pointer exists, or 0 if there is no such pointer. SEE ALSO: position, other right_position, search ASSUMPTIONS: none DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block at most N calls to predicate are done. IMPLEMENTATION: TYPE *right_position(register int (*predicate)(TYPE*), register TYPE *begin, register TYPE *end) { while (begin < end) if ((*predicate)(--end)) return end; return 0; } NAME: right_position - finds rightmost value in the block equal to the given value SYNOPSIS: TYPE *right_position(TYPE value, TYPE *begin, TYPE *end); DESCRIPTION: Position returns the rightmost pointer in the block that points to an element equal to value if such a pointer exists, or 0 if there is no such pointer. SEE ALSO: position, other right_position, search ASSUMPTIONS: Equality ("==") is defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block at most N equalities of TYPE are performed. IMPLEMENTATION: TYPE *right_position(REGISTER TYPE value, register TYPE *begin, register TYPE *end) { while (begin < end) if (*--end == value) return end; return 0; } NAME: right_position - finds rightmost value in the block satisfying relation to the given value SYNOPSIS: TYPE *right_position(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end); DESCRIPTION: Right_position returns the rightmost pointer in the block that satisfies relation with the pointer to value if such a pointer exists, or 0 if there is no such pointer. SEE ALSO: position, other right_position, search ASSUMPTIONS: none DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block at most N calls to relation are done. IMPLEMENTATION: TYPE *right_position(register int (*relation)(TYPE*, TYPE*), TYPE value, register TYPE *begin, register TYPE *end) { register TYPE *temp = &value; while (begin < end) if ((*relation)(--end, temp)) return end; return 0; } NAME: rotate - circularly rotates a block in place SYNOPSIS: void rotate(ptrdiff_t number, TYPE *begin, TYPE *end); DESCRIPTION: If number is non-negative then rotate circularly rotates a block to the right. If number is negative then rotate circularly rotates a block to the left. In both cases, for every i, 0 <= i < (end - begin), the value at the location begin + i before the rotate is equal to the value at the location begin + (i + number)(modulo (end - begin)). NOTE: Rotate is implemented in the usual way with tree calls to reverse. It is possible to speed it up. Rotate_copy is at present almost three times faster than rotate. SEE ALSO: rotate_copy ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: void reverse(TYPE *begin, TYPE *end); COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block approximately 3N assignments of TYPE are performed. IMPLEMENTATION: void rotate(ptrdiff_t number, TYPE *begin, TYPE *end) { if (begin >= end) return; number %= end - begin; if (number == 0) return; if (number < 0) number += (end - begin); reverse(begin, end); reverse(begin, begin + number); reverse(begin + number, end); } NAME: rotate_copy - copies a block while circularly rotating it. SYNOPSIS: void rotate_copy(ptrdiff_t number, TYPE *begin, TYPE *end, TYPE *result); DESCRIPTION: If number is non-negative then rotate_copy copies a block circularly rotating it to the right. If number is negative then rotate_copy copies a block circularly rotating it to the left. In both cases, for every i, 0 <= i < (end - begin), the value at the location begin + i before the rotate is equal to the value at the location result + (i + number)(modulo (end - begin)). NOTE: If begin <= result < end or begin <= result + (end - begin) < end then the effect of rotate_copy is not defined. SEE ALSO: rotate ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: void copy(TYPE *begin, TYPE *end, TYPE *result); COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N assignments of TYPE are performed. IMPLEMENTATION: void rotate_copy(ptrdiff_t number, TYPE *begin, TYPE *end, TYPE *result) { if (begin >= end) return; number %= end - begin; if (number == 0) { copy(begin, end, result); return; } if (number < 0) number += (end - begin); copy(end - number, end, result); copy(begin, end - number, result + number); } NAME: search - finds a matching subblock in a block SYNOPSIS: TYPE *search(TYPE *begin1, TYPE *end1, TYPE *begin2, TYPE *end2); DESCRIPTION: search returns a location in the first block such that such that a subblock of it which starts with this location and is equal in size to the second block such that every element in this subblock is equal to the corresponding element of the second block. If such location does not exist then the 0 pointer is returned. NOTE: At present search is quadratic in the worst case. In the future it may be replaced with a faster one. However, it is quite fast on the average in most practical cases. SEE ALSO: mismatch, other search ASSUMPTIONS: Equality ("==") is defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Quadratic in the size of the blocks. If N and M are correspondingly the numbers of locations in the first and second blocks then at most N*M equality operations of TYPE are performed. (But see the note.) IMPLEMENTATION: TYPE *search(register TYPE *begin1, TYPE *end1, register TYPE *begin2, TYPE *end2) { register ptrdiff_t d1, d2, k; if (begin1 >= end1) return begin2; d1 = end1 - begin1; d2 = end2 - begin2; if (d2 < d1) return 0; k = 0; while (k < d1) if (begin1[k] == begin2[k]) k++; else if (d1 == d2) return 0; else { k = 0; begin2++; d2--; } return begin2; } NAME: search - finds a matching subblock in a block SYNOPSIS: TYPE *search(int (*relation)(TYPE*, TYPE*), TYPE *begin1, TYPE *end1, TYPE *begin2, TYPE *end2); DESCRIPTION: search returns a location in the first block such that such that a subblock of it which starts with this location and is equal in size to the second block such that every element in this subblock is equal to the corresponding element of the second block. If such location does not exist then the 0 pointer is returned. NOTE: At present search is quadratic in the worst case. In the future it may be replaced with a faster one. However, it is quite fast on the average in most practical cases. SEE ALSO: mismatch, other search ASSUMPTIONS: none DEPENDS ON: nothing COMPLEXITY: Quadratic in the size of the blocks. If N and M are correspondingly the numbers of locations in the first and second blocks then at most N*M calls to the relation are performed. (But see the note.) IMPLEMENTATION: TYPE *search(register int (*relation)(TYPE*, TYPE*), register TYPE *begin1, TYPE *end1, register TYPE *begin2, TYPE *end2) { register ptrdiff_t d1, d2, k; if (begin1 >= end1) return begin2; d1 = end1 - begin1; d2 = end2 - begin2; if (d2 < d1) return 0; k = 0; while (k < d1) if ((*relation)(begin1 + k, begin2 + k)) k++; else if (d1 == d2) return 0; else { k = 0; begin2++; d2--; } return begin2; } NAME: select - finds the nth smallest element in the block SYNOPSIS: void select(ptrdiff_t nth, TYPE *begin, TYPE *end); DESCRIPTION: select puts the nth smallest element in the block in the location begin + nth - 1. It also moves first n - 1 smallest elements to the left of this location and the rest of the elements to the right. NOTE: if 0 <= nth = end || nth <= 0 || end - begin < nth) return; for (;;) if (end - begin < 6) { insertion_sort(relation, begin, end); return; } else if (nth < 4) { while (nth--) { register TYPE *r = minimum(relation, begin, end); REGISTER TYPE temp = *begin; *begin++ = *r; *r = temp; } return; } else { TYPE *index = ordered_partition(relation, begin, end); if (index - begin >= nth) end = index; else { nth -= index - begin; begin = index; } } } NAME: set_insert - inserts an element in an ordered block if it is not already in it SYNOPSIS: TYPE *set_insert(TYPE value, TYPE *begin, TYPE *end); DESCRIPTION: set_insert inserts a value into an ordered block if the block does not contain an element equal to the value. If insertion is done then the location at which insertion was done is returned. Otherwise the 0 pointer is returned. SEE ALSO: binary_partition, binary_search, insert, set_union ASSUMPTIONS: Less_than ("<") and assignment ("=") are defined for the TYPE DEPENDS ON: TYPE *binary_partition(TYPE value, TYPE *begin, TYPE *end); void copy(TYPE *begin, TYPE *end, TYPE *result); COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block then at most N assignments and at most logN operations less_than are performed. IMPLEMENTATION: TYPE *set_insert(TYPE value, TYPE *begin, TYPE *end) { TYPE *index = binary_partition(value, begin, end); if (begin < index && !(*(index - 1) < value)) return 0; else { copy(index, end, index + 1); *index = value; return index; } } NAME: set_insert - inserts an element in an ordered block if it is not already in it SYNOPSIS: TYPE *set_insert(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end); DESCRIPTION: set_insert inserts a value into an ordered block if the block does not contain an element equal to the value. If insertion is done then the location at which insertion was done is returned. Otherwise the 0 pointer is returned. relation is the name of the comparison function, which is called with two arguments that point to the elements being compared. As the function must return an integer less than, equal to, or greater than zero, so must the first argument to be considered be less than, equal to, or greater than the second. SEE ALSO: binary_partition, binary_search, insert, set_union ASSUMPTIONS: Assignment ("=") is defined for the TYPE DEPENDS ON: TYPE *binary_partition(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end); void copy(TYPE *begin, TYPE *end, TYPE *result); COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block then at most N assignments and at most logN calls to the relation are performed. IMPLEMENTATION: TYPE *set_insert(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end) { TYPE *index = binary_partition(relation, value, begin, end); if (begin < index && !((*relation)(index - 1, &value) < 0)) return 0; else { copy(index, end, index + 1); *index = value; return index; } } NAME: set_union - combines (with no repetitions) two ordered blocks into one SYNOPSIS: TYPE *set_union(int (*relation)(TYPE*, TYPE*), TYPE *begin1, TYPE *end1, TYPE *begin2, TYPE *end2, TYPE *result); DESCRIPTION: set_union puts elements from two ordered blocks with no repetitions into a new ordered block with no repetitions so that for every element in the original blocks there is an element in the result that is equal to it. The pointer after the last element of the new block is returned. relation is the name of the comparison function, which is called with two arguments that point to the elements being compared. As the function must return an integer less than, equal to, or greater than zero, so must the first argument to be considered be less than, equal to, or greater than the second. NOTE: If begin1 <= result < end1 or begin1 <= result + (end1 - begin1) < end1 or begin2 <= result < end2 or begin2 <= result + (end2 - begin2) < end2 then the effect of set_union is not defined. SEE ALSO: difference, intersection, merge, symmetric_difference, unique ASSUMPTIONS: Assignment ("=") is defined for the TYPE DEPENDS ON: nothing COMPLEXITY: Linear in the size of the blocks. If N and M are the numbers of locations in the blocks then at most N + M - 1 calls to relation and N + M assignments are performed. IMPLEMENTATION: TYPE *set_union(register int (*relation)(TYPE*, TYPE*), register TYPE *begin1, register TYPE *end1, register TYPE *begin2, register TYPE *end2, register TYPE *result) { while (begin1 < end1 && begin2 < end2) { register int c = (*relation)(begin2, begin1); if (c < 0) *result++ = *begin2++; else { *result++ = *begin1++; if (c == 0) begin2++; } } while (begin1 < end1) *result++ = *begin1++; while (begin2 < end2) *result++ = *begin2++; return result; } NAME: set_union - combines (with no repetitions) two ordered blocks into one SYNOPSIS: TYPE *set_union(TYPE *begin1, TYPE *end1, TYPE *begin2, TYPE *end2, TYPE *result); DESCRIPTION: set_union puts elements from two ordered blocks with no repetitions into a new ordered block with no repetitions so that for every element in the original blocks there is an element in the result that is equal to it. The pointer after the last element of the new block is returned. NOTE: If begin1 <= result < end1 or begin1 <= result + (end1 - begin1) < end1 or begin2 <= result < end2 or begin2 <= result + (end2 - begin2) < end2 then the effect of set_union is not defined. SEE ALSO: difference, intersection, merge, symmetric_difference, unique ASSUMPTIONS: Less_than ("<") and assignment ("=") are defined for the TYPE DEPENDS ON: nothing COMPLEXITY: Linear in the size of the blocks. If N and M are the numbers of locations in the blocks then at most N + M - 1 less_than operations and N + M assignments are performed. IMPLEMENTATION: TYPE *set_union(register TYPE *begin1, register TYPE *end1, register TYPE *begin2, register TYPE *end2, register TYPE *result) { while (begin1 < end1 && begin2 < end2) if (*begin2 < *begin1) *result++ = *begin2++; else { *result++ = *begin1++; if (!(*begin1 < *begin2)) begin2++; } while (begin1 < end1) *result++ = *begin1++; while (begin2 < end2) *result++ = *begin2++; return result; } NAME: shuffle - shuffles a block SYNOPSIS: void shuffle(TYPE *begin, TYPE *end); DESCRIPTION: Shuffle randomly permutes a block in place. SEE ALSO: shuffle_copy ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: TYPE *random(TYPE *begin, TYPE *end); COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly 3*(N - 1) assignments of TYPE are performed. IMPLEMENTATION: void shuffle(register TYPE *begin, register TYPE *end) { register TYPE *index = begin + 1; while (index < end) { register TYPE *r = random(begin, index + 1); REGISTER TYPE temp = *index; *index++ = *r; *r = temp; } } NAME: shuffle_copy - copies a block while shuffling it SYNOPSIS: void shuffle_copy(TYPE *begin, TYPE *end, TYPE *result); DESCRIPTION: Shuffle_copy copies a block to a different location while randomly permuting it. NOTE: If begin <= result < end or begin <= result + (end - begin) < end then the effect of shuffle_copy is not defined. SEE ALSO: shuffle ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: TYPE *random(TYPE *begin, TYPE *end); COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly 2*N assignments of TYPE are performed. IMPLEMENTATION: void shuffle_copy(register TYPE *begin, register TYPE *end, register TYPE *result) { register TYPE *result_end = result; while (begin < end) { register TYPE *r = random(result, result_end + 1); *result_end++ = *r; *r = *begin++; } } NAME: sort - sorts the block SYNOPSIS: void sort(TYPE *begin, TYPE *end); DESCRIPTION: sort sorts a block in place. NOTE: sort is not stable. That is, it does not preserve the relative order of equal elements. SEE ALSO: insertion_sort, merge_sort, stable_sort ASSUMPTIONS: Less_than ("<") and assignment ("=") are defined for the TYPE DEPENDS ON: void insertion_sort(TYPE *begin, TYPE *end); TYPE *random(TYPE *begin, TYPE *end); COMPLEXITY: O(NlogN) on the average. Quadratic in the worst case. (Which is highly improbable.) IMPLEMENTATION: static TYPE *ordered_partition(register TYPE *begin, register TYPE *end) { TYPE *old_begin = begin; REGISTER TYPE value = *random(begin, end); begin--; for (;;) { while (*++begin < value); while (value < *--end); if (begin < end) { REGISTER TYPE temp = *begin; *begin = *end; *end = temp; } else return (begin == old_begin) ? begin + 1 : begin; } } static void quicksort_loop(register TYPE *begin, register TYPE *end) { while (10 < end - begin) { register TYPE *index = ordered_partition(begin, end); if (end - index < index - begin) { quicksort_loop(index, end); end = index; } else { quicksort_loop(begin, index); begin = index; } } } void sort(TYPE *begin, TYPE *end) { quicksort_loop(begin, end); insertion_sort(begin, end); } NAME: sort - sorts the block SYNOPSIS: void sort(int (*relation)(TYPE*, TYPE*), TYPE *begin, TYPE *end); DESCRIPTION: sort sorts a block in place. relation is the name of the comparison function, which is called with two arguments that point to the elements being compared. As the function must return an integer less than, equal to, or greater than zero, so must the first argument to be considered be less than, equal to, or greater than the second. NOTE: sort is not stable. That is, it does not preserve the relative order of equal elements. SEE ALSO: insertion_sort, merge_sort, stable_sort ASSUMPTIONS: Assignment ("=") is defined for the TYPE DEPENDS ON: void insertion_sort(int (*relation)(TYPE*, TYPE*), TYPE *begin, TYPE *end); TYPE *random(TYPE *begin, TYPE *end); COMPLEXITY: O(NlogN) on the average. Quadratic in the worst case. (Which is highly improbable.) IMPLEMENTATION: static TYPE *ordered_partition(register int (*relation)(TYPE*, TYPE*), register TYPE *begin, register TYPE *end) { TYPE *old_begin = begin; TYPE value = *random(begin, end); register TYPE *temp = &value; begin--; for (;;) { while ((*relation)(++begin, temp) < 0); while ((*relation)(temp, --end) < 0); if (begin < end) { REGISTER TYPE temp = *begin; *begin = *end; *end = temp; } else return (begin==old_begin) ? begin + 1 : begin; } } static void quicksort_loop(int (*relation)(TYPE*, TYPE*), TYPE *begin, TYPE *end) { while (10 < end - begin) { TYPE *index = ordered_partition(relation, begin, end); if (end - index < index - begin) { quicksort_loop(relation, index, end); end = index; } else { quicksort_loop(relation, begin, index); begin = index; } } } void sort(int (*relation)(TYPE*, TYPE*), TYPE *begin, TYPE *end) { quicksort_loop(relation, begin, end); insertion_sort(relation, begin, end); } NAME: stable_partition - separates elements into those that satisfy the predicate and those that do not SYNOPSIS: TYPE *stable_partition(int (*predicate)(TYPE*), TYPE *begin, TYPE *end); DESCRIPTION: stable_partition moves elements in those locations of the block that do satisfy the predicate to the left and those that do not satisfy the predicate to the right and returns the pointer after the last "satisfying" element. The relative order of elements within both groups is preserved. NOTE: The divide-and-conquer algorithm used in stable_partitioning can be refined and in stead of descending all the way down use all available memory to do those subproblem that can be fitted by using stable_partition_copy and then copy the block back. SEE ALSO: partition, partition_copy, remove, remove_copy, other stable_partition, stable_partition_copy, stable_remove, stable_remove_copy ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: void rotate(ptrdiff_t number, TYPE *begin, TYPE *end); COMPLEXITY: O(NlogN) in the size of the block. If N is the number of locations in the block exactly N calls to the predicate are done. At most 3*N*logN assignments of TYPE are performed. IMPLEMENTATION: TYPE *stable_partition(int (*predicate)(TYPE*), TYPE *begin, TYPE *end) { if (end - begin > 1) { TYPE *middle = begin + ((end - begin) >> 1); TYPE *first_half = stable_partition(predicate, begin, middle); TYPE *second_half = stable_partition(predicate, middle, end); rotate(first_half - middle, first_half, second_half); return first_half + (second_half - middle); } else if (begin < end) return (*predicate)(begin) ? begin + 1 : begin; else return end; } NAME: stable_partition - separates elements into those that are equal to the value and those that are not SYNOPSIS: TYPE *stable_partition(TYPE value, TYPE *begin, TYPE *end); DESCRIPTION: stable_partition moves elements in the block that are equal to the value to the left and those that are not equal to the value to the right and returns the pointer after the last "equal" element. The relative order of elements within both groups is preserved. NOTE: The divide-and-conquer algorithm used in stable_partitioning can be refined and in stead of descending all the way down use all available memory to do those subproblem that can be fitted by using stable_partition_copy and then copy the block back. SEE ALSO: partition, partition_copy, remove, remove_copy, other stable_partition, stable_partition_copy, stable_remove, stable_remove_copy ASSUMPTIONS: Assignment ("=") and equality ("==") are defined for the TYPE. DEPENDS ON: void rotate(ptrdiff_t number, TYPE *begin, TYPE *end); COMPLEXITY: O(NlogN) in the size of the block. If N is the number of locations in the block exactly N equality operations of TYPE are performed. At most 3*N*logN assignments of TYPE are performed. IMPLEMENTATION: TYPE *stable_partition(TYPE value, TYPE *begin, TYPE *end) { if (end - begin > 1) { TYPE *middle = begin + ((end - begin) >> 1); TYPE *first_half = stable_partition(value, begin, middle); TYPE *second_half = stable_partition(value, middle, end); rotate(first_half - middle, first_half, second_half); return first_half + (second_half - middle); } else if (begin < end) return *begin == value ? begin + 1 : begin; else return end; } NAME: stable_partition - separates elements into those that relate to the value and those that are not SYNOPSIS: TYPE *stable_partition(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end); DESCRIPTION: stable_partition moves elements in those locations of the block that do satisfy the relation with the value to the left and those that do not satisfy the relation to the right and returns the pointer after the last "satisfying" element. The relative order of elements within both groups is preserved. NOTE: The divide-and-conquer algorithm used in stable_partitioning can be refined and in stead of descending all the way down use all available memory to do those subproblem that can be fitted by using stable_partition_copy and then copy the block back. SEE ALSO: partition, partition_copy, remove, remove_copy, other stable_partition, stable_partition_copy, stable_remove, stable_remove_copy ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: void rotate(ptrdiff_t number, TYPE *begin, TYPE *end); COMPLEXITY: O(NlogN) in the size of the block. If N is the number of locations in the block exactly N calls to the relation are done. At most 3*N*logN assignments of TYPE are performed. IMPLEMENTATION: TYPE *stable_partition(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end) { if (end - begin > 1) { TYPE *middle = begin + ((end - begin) >> 1); TYPE *first_half = stable_partition(relation, value, begin, middle); TYPE *second_half = stable_partition(relation, value, middle, end); rotate(first_half - middle, first_half, second_half); return first_half + (second_half - middle); } else if (begin < end) return (*relation)(begin, &value) ? begin + 1 : begin; else return end; } NAME: stable_partition_copy - copies elements satisfying the predicate before the elements that do not SYNOPSIS: TYPE *stable_partition_copy(int (*predicate)(TYPE*), TYPE *begin, TYPE *end, TYPE *result); DESCRIPTION: stable_partition_copy first copies elements in those locations of the block that do satisfy the predicate and then those that do not satisfy the predicate and returns the pointer after the copy of the last "satisfying" element. The relative order of elements in both groups ("satisfying" and "not-satisfying") is preserved. NOTE: If begin <= result < end or begin <= result + (end - begin) < end then the effect of stable_partition_copy is not defined. SEE ALSO: partition, partition_copy, remove, remove_copy, stable_partition, other stable_partition_copy, stable_remove, stable_remove_copy ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: TYPE *partition_copy( int (*predicate)(TYPE*), TYPE *begin, TYPE *end, TYPE *result ); void reverse( TYPE *begin, TYPE *end ); COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N calls to predicate are done. If P is the number of locations in the block that do not satisfy the predicate then exactly N + 3*floor(P/2) assignments of TYPE are done. IMPLEMENTATION: TYPE *stable_partition_copy(int (*predicate)(TYPE*), TYPE *begin, TYPE *end, TYPE *result) { TYPE *m = partition_copy(predicate, begin, end, result); reverse(m, result + (end - begin)); return m; } NAME: stable_partition_copy - copies elements equal to the value before those that are not SYNOPSIS: TYPE *stable_partition_copy(TYPE value, TYPE *begin, TYPE *end, TYPE *result); DESCRIPTION: stable_partition_copy first copies elements in the block that are equal to the value and then those that are not and returns the pointer after the copy of the last "equal" element. The relative order of elements in both groups ("equal" and "not-equal") is preserved. NOTE: If begin <= result < end or begin <= result + (end - begin) < end then the effect of stable_partition_copy is not defined. SEE ALSO: partition, partition_copy, remove, remove_copy, stable_partition, other stable_partition_copy, stable_remove, stable_remove_copy ASSUMPTIONS: Assignment ("=") and equality ("==") are defined for the TYPE. DEPENDS ON: TYPE *partition_copy( TYPE value, TYPE *begin, TYPE *end, TYPE *result ); void reverse( TYPE *begin, TYPE *end ); COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N equality operations of TYPE are performed. If P is the number of locations in the block that are not equal to the value then exactly N + 3*floor(P/2) assignments of TYPE are done. IMPLEMENTATION: TYPE *stable_partition_copy(TYPE value, TYPE *begin, TYPE *end, TYPE *result) { TYPE *m = partition_copy(value, begin, end, result); reverse(m, result + (end - begin)); return m; } NAME: stable_partition_copy - copies elements related to the value before those that are not SYNOPSIS: TYPE *stable_partition_copy(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end, TYPE *result); DESCRIPTION: stable_partition_copy first copies those elements in the block locations of which satisfy the relation with the pointer to the value and then those that do not and returns the pointer after the copy of the last "satisfying" element. The relative order of elements in both groups ("satisfying" and "not-satisfying") is preserved. NOTE: If begin <= result < end or begin <= result + (end - begin) < end then the effect of stable_partition_copy is not defined. SEE ALSO: partition, partition_copy, remove, remove_copy, stable_partition, other stable_partition_copy, stable_remove, stable_remove_copy ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: TYPE *partition_copy(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end, TYPE *result); void reverse( TYPE *begin, TYPE *end ); COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N calls to the relation are done. If P is the number of locations in the block that do not satisfy the relation then exactly N + 3*floor(P/2) assignments of TYPE are done. IMPLEMENTATION: TYPE *stable_partition_copy(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end, TYPE *result) { TYPE *m = partition_copy(relation, value, begin, end, result); reverse(m, result + (end - begin)); return m; } NAME: stable_remove - removes elements satisfying the predicate SYNOPSIS: TYPE *stable_remove(int (*predicate)(TYPE*), TYPE *begin, TYPE *end); DESCRIPTION: stable_remove moves all the elements in the block, locations of which do not satisfy the predicate, to the left and returns the pointer pointing after the last such element. The relative order of the elements not satisfying the predicate is preserved. SEE ALSO: partition, partition_copy, remove, remove_copy, stable_partition, stable_partition_copy, other stable_remove, stable_remove_copy ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N calls to predicate are done. If P is the number of locations in the block that do not satisfy predicate then at most P assignments of TYPE are done. IMPLEMENTATION: TYPE *stable_remove(register int (*predicate)(TYPE*), register TYPE *begin, register TYPE *end) { register TYPE *m; while (begin < end && !(*predicate)(begin)) begin++; if (begin >= end) return end; m = begin; while (++begin < end) if (!(*predicate)(begin)) *m++ = *begin; return m; } NAME: stable_remove - removes elements equal to the value SYNOPSIS: TYPE *stable_remove(TYPE value, TYPE *begin, TYPE *end); DESCRIPTION: stable_remove moves all the elements in the block which are not equal to value to the left and returns the pointer pointing after the last such element. The relative order of the elements not satisfying the predicate is preserved. SEE ALSO: partition, partition_copy, remove, remove_copy, stable_partition, stable_partition_copy, other stable_remove, stable_remove_copy ASSUMPTIONS: Assignment ("=") and equality ("==") are defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N equality operations of the TYPE are performed. If P is the number of locations in the block that are not equal to the value then at most P assignments of TYPE are done. IMPLEMENTATION: TYPE *stable_remove(REGISTER TYPE value, register TYPE *begin, register TYPE *end) { register TYPE *m; while (begin < end && !(*begin == value)) begin++; if (begin >= end) return end; m = begin; while (++begin < end) if (!(*begin == value)) *m++ = *begin; return m; } NAME: stable_remove - removes elements satisfying the relation with the value SYNOPSIS: TYPE *stable_remove(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end); DESCRIPTION: stable_remove moves all the elements in the block, locations of which do not satisfy the relation with the pointer to the value, to the left and returns the pointer pointing after the last such element. The relative order of the elements not satisfying the predicate is preserved. SEE ALSO: partition, partition_copy, other remove, remove_copy, stable_partition, stable_partition_copy, stable_remove, stable_remove_copy ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N calls to the relation are done. If P is the number of locations in the block that do not satisfy the relation with the value then at most P assignments of TYPE are done. IMPLEMENTATION: TYPE *stable_remove(register int (*relation)(TYPE*, TYPE*), TYPE value, register TYPE *begin, register TYPE *end) { register TYPE *temp = &value; register TYPE *m; while (begin < end && !(*relation)(begin, temp)) begin++; if (begin >= end) return end; m = begin; while (++begin < end) if (!(*relation)(begin, temp)) *m++ = *begin; return m; } NAME: stable_remove_copy - copies the elements not satisfying the predicate SYNOPSIS: TYPE *stable_remove_copy(int (*predicate)(TYPE*), TYPE *begin, TYPE *end, TYPE *result); DESCRIPTION: stable_remove_copy copies elements in those locations in the block that do not satisfy the predicate in the consecutive locations starting with result, and returns the pointer past the last of the copies. NOTE: 1) Is the same as remove_copy. 2) If begin <= result < end or begin <= result + (end - begin) < end then the effect of stable_remove_copy is not defined. SEE ALSO: partition, partition_copy, remove, remove_copy, stable_partition, stable_partition_copy, stable_remove, other stable_remove_copy ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: ATYPE *remove_copy(int (*predicate)(TYPE*), TYPE *begin, TYPE *end, TYPE *result); COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N calls to predicate are done. If P is the number of locations in the block that do not satisfy predicate then exactly P assignments of TYPE are done. IMPLEMENTATION: TYPE *stable_remove_copy(int (*predicate)(TYPE*), TYPE *begin, TYPE *end, TYPE *result) { return remove_copy(predicate, begin, end, result); } NAME: stable_remove_copy - copies the elments not equal to the value SYNOPSIS: TYPE *stable_remove_copy(TYPE value, TYPE *begin, TYPE *end, TYPE *result); DESCRIPTION: stable_remove_copy copies those elements in the block, that are not equal to the value, in the consecutive locations starting with result, and returns the pointer past the last of the copies. NOTE: 1) Is the same as remove_copy. 2) If begin <= result < end or begin <= result + (end - begin) < end then the effect of stable_remove_copy is not defined. SEE ALSO: partition, partition_copy, remove, remove_copy, stable_partition, stable_partition_copy, stable_remove, other stable_remove_copy ASSUMPTIONS: Assignment ("=") and equality ("==") are defined for the TYPE. DEPENDS ON: TYPE *remove_copy(TYPE value, TYPE *begin, TYPE *end, TYPE *result); COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N equality operations of the TYPE are performed. If P is the number of locations in the block that are not equal to the value then exactly P assignments of TYPE are done. IMPLEMENTATION: TYPE *stable_remove_copy(TYPE value, TYPE *begin, TYPE *end, TYPE *result) { return remove_copy(value, begin, end, result); } NAME: stable_remove_copy - copies elements that are not related to the value SYNOPSIS: TYPE *stable_remove_copy(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end, TYPE *result); DESCRIPTION: stable_remove_copy copies those elements in the locations in the block, that do not satisfy the relation with the pointer to the value, in the consecutive locations starting with result, and returns the pointer past the last of the copies. NOTE: 1) Is the same as remove_copy. 2) If begin <= result < end or begin <= result + (end - begin) < end then the effect of stable_remove_copy is not defined. SEE ALSO: partition, partition_copy, remove, remove_copy, stable_partition, stable_partition_copy, stable_remove, other stable_remove_copy ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: TYPE *remove_copy(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end, TYPE *result); COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block exactly N calls to the relation are done. If P is the number of locations in the block that do not satisfy the relation with the value then exactly P assignments of TYPE are done. IMPLEMENTATION: TYPE *stable_remove_copy(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE *begin, TYPE *end, TYPE *result) { return remove_copy(relation, value, begin, end, result); } NAME: stable_sort - stably sorts a block SYNOPSIS: void stable_sort(int (*relation)(TYPE*, TYPE*), TYPE *begin, TYPE *end); DESCRIPTION: stable_sort sorts a block in place. It is stable, that is, the relative order of equal elements is preserved. relation is the name of the comparison function, which is called with two arguments that point to the elements being compared. As the function must return an integer less than, equal to, or greater than zero, so must the first argument to be considered be less than, equal to, or greater than the second. NOTE: At present stable_sort becomes quadratic if it cannot allocate an auxiliary block. This will be fixed in the future. SEE ALSO: insertion_sort, merge_sort, sort ASSUMPTIONS: Assignment ("=") is defined for the TYPE DEPENDS ON: void insertion_sort(int (*relation)(TYPE*, TYPE*), TYPE *begin, TYPE *end); char *malloc(unsigned); TYPE *merge_sort(int (*relation)(TYPE*, TYPE*), TYPE *begin, TYPE *end, TYPE *result); COMPLEXITY: O(NlogN) if it can obtain an extra memory, O(N^2) otherwise. IMPLEMENTATION: #include void stable_sort(int (*relation)(TYPE*, TYPE*), TYPE *begin, TYPE *end) { TYPE *index = (TYPE*) malloc((unsigned)(sizeof(TYPE) * (end - begin))); if (index == 0) { insertion_sort(relation, begin, end); return; } if (merge_sort(relation, begin, end, index) == index) { TYPE *i = index; while (begin < end) *begin++ = *i++; } free((char*)index); } NAME: stable_sort - stably sorts a block SYNOPSIS: void stable_sort(TYPE *begin, TYPE *end); DESCRIPTION: stable_sort sorts a block in place. It is stable, that is, the relative order of equal elements is preserved. NOTE: At present stable_sort becomes quadratic if it cannot allocate an auxiliary block. That will be fixed in the future. SEE ALSO: insertion_sort, merge_sort, sort ASSUMPTIONS: Less_than ("<") and assignment ("=") are defined for the TYPE DEPENDS ON: void insertion_sort(TYPE *begin, TYPE *end); char *malloc(unsigned); TYPE *merge_sort(TYPE *begin, TYPE *end, TYPE *result); COMPLEXITY: O(NlogN) if it can obtain an extra memory, O(N^2) otherwise. IMPLEMENTATION: #include void stable_sort(TYPE *begin, TYPE *end) { TYPE *index = (TYPE*) malloc((unsigned)(sizeof(TYPE) * (end - begin))); if (index == 0) { insertion_sort(begin, end); return; } if (merge_sort(begin, end, index) == index) { TYPE *i = index; while (begin < end) *begin++ = *i++; } free((char*)index); } NAME: substitute - substitutes value with new_value SYNOPSIS: void substitute(TYPE value, TYPE new_value, TYPE *begin, TYPE *end); DESCRIPTION: substitute assigns new_value to every location in the block the content of which is equal to value. SEE ALSO: other substitute, substitute_copy ASSUMPTIONS: Assignment ("=") and equality ("==") are defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block then exactly N equality operations of TYPE and at most N assignments of TYPE are performed. IMPLEMENTATION: void substitute(REGISTER TYPE value, REGISTER TYPE new_value, register TYPE *begin, register TYPE *end) { for (; begin < end; begin++) if (*begin == value) *begin = new_value; } NAME: substitute - substitutes value with new_value SYNOPSIS: void substitute(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE new_value, TYPE *begin, TYPE *end); DESCRIPTION: substitute assigns new_value to every location in the block which satisfies the relation with the location containing the value. SEE ALSO: other substitute, substitute_copy ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block then exactly N calls to the relation and at most N assignments of TYPE are performed. IMPLEMENTATION: void substitute(register int (*relation)(TYPE*, TYPE*), TYPE value, REGISTER TYPE new_value, register TYPE *begin, register TYPE *end) { register TYPE *temp = &value; for (; begin < end; begin++) if ((*relation)(begin, temp)) *begin = new_value; } NAME: substitute_copy - copies while substituting SYNOPSIS: void substitute_copy(TYPE value, TYPE new_value, TYPE *begin, TYPE *end, TYPE *result); DESCRIPTION: substitute_copy copies the block while replacing every item equal to value with new_value. NOTE: If begin <= result < end or begin <= result + (end - begin) < end then the effect of substitute_copy is not defined. SEE ALSO: substitute, other substitute_copy ASSUMPTIONS: Assignment ("=") and equality ("==") are defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block then exactly N equality operations of TYPE and exactly N assignments of TYPE are performed. IMPLEMENTATION: void substitute_copy(REGISTER TYPE value, REGISTER TYPE new_value, register TYPE *begin, register TYPE *end, register TYPE *result) { for (; begin < end; begin++) *result++ = (*begin == value ? new_value : *begin); } NAME: substitute_copy - copies while substituting SYNOPSIS: void substitute_copy(int (*relation)(TYPE*, TYPE*), TYPE value, TYPE new_value, TYPE *begin, TYPE *end, TYPE *result); DESCRIPTION: substitute_copy copies the block while replacing every item satisfying the relation with value with new_value. NOTE: If begin <= result < end or begin <= result + (end - begin) < end then the effect of substitute_copy is not defined. SEE ALSO: substitute, other substitute_copy ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block then exactly N calls to the relation and exactly N assignments of TYPE are performed. IMPLEMENTATION: void substitute_copy(register int (*relation)(TYPE*, TYPE*), TYPE value, REGISTER TYPE new_value, register TYPE *begin, register TYPE *end, register TYPE *result) { register TYPE *temp = &value; for (; begin < end; begin++) *result++ = ((*relation)(begin, temp) ? new_value : *begin); } NAME: symmetric_difference - collects those elements of two ordered blocks that are only in one of them SYNOPSIS: TYPE *symmetric_difference(int (*relation)(TYPE*, TYPE*), TYPE *begin1, TYPE *end1, TYPE *begin2, TYPE *end2, TYPE *result); DESCRIPTION: symmetric_difference puts elements from two ordered blocks with no repetitions into a new ordered block with no repetitions so that for every element which is in only in one of the original blocks it will be placed in the result The pointer after the last element of the new block is returned. relation is the name of the comparison function, which is called with two arguments that point to the elements being compared. As the function must return an integer less than, equal to, or greater than zero, so must the first argument to be considered be less than, equal to, or greater than the second. NOTE: If begin1 <= result < end1 or begin1 <= result + (end1 - begin1) < end1 or begin2 <= result < end2 or begin2 <= result + (end2 - begin2) < end2 then the effect of symmetric_difference is not defined. SEE ALSO: difference, intersection, merge, set_union, unique ASSUMPTIONS: Assignment ("=") is defined for the TYPE DEPENDS ON: nothing COMPLEXITY: Linear in the size of the blocks. If N and M are the numbers of locations in the blocks then at most N + M - 1 calls to relation and N + M assignments are performed. IMPLEMENTATION: TYPE *symmetric_difference(register int (*relation)(TYPE*, TYPE*), register TYPE *begin1, register TYPE *end1, register TYPE *begin2, register TYPE *end2, register TYPE *result) { while (begin1 < end1 && begin2 < end2) { register int c = (*relation)(begin2, begin1); if (0 < c) *result++ = *begin1++; else if (c < 0) *result++ = *begin2++; else begin1++, begin2++; } while (begin1 < end1) *result++ = *begin1++; while (begin2 < end2) *result++ = *begin2++; return result; } NAME: symmetric_difference - collects those elements of two ordered blocks that are only in one of them SYNOPSIS: TYPE *symmetric_difference(TYPE *begin1, TYPE *end1, TYPE *begin2, TYPE *end2, TYPE *result); DESCRIPTION: symmetric_difference puts elements from two ordered blocks with no repetitions into a new ordered block with no repetitions so that for every element which is in only in one of the original blocks it will be placed in the result The pointer after the last element of the new block is returned. NOTE: If begin1 <= result < end1 or begin1 <= result + (end1 - begin1) < end1 or begin2 <= result < end2 or begin2 <= result + (end2 - begin2) < end2 then the effect of symmetric_difference is not defined. SEE ALSO: difference, intersection, merge, set_union, unique ASSUMPTIONS: Less_than ("<") and assignment ("=") are defined for the TYPE DEPENDS ON: nothing COMPLEXITY: Linear in the size of the blocks. If N and M are the numbers of locations in the blocks then at most N + M - 1 less_than operations and maximum(N, M) assignments are performed. IMPLEMENTATION: TYPE *symmetric_difference(register TYPE *begin1, register TYPE *end1, register TYPE *begin2, register TYPE *end2, register TYPE *result) { while (begin1 < end1 && begin2 < end2) if (*begin1 < *begin2) *result++ = *begin1++; else if (*begin2 < *begin1) *result++ = *begin2++; else begin1++ ,begin2++; while (begin1 < end1) *result++ = *begin1++; while (begin2 < end2) *result++ = *begin2++; return result; } NAME: unique - removes repeated elements SYNOPSIS: TYPE *unique(TYPE *begin, TYPE *end); DESCRIPTION: unique removes all but the first element from every consecutive group of equal elements in the block. SEE ALSO: remove_duplicates, remove_duplicates_copy, other unique, unique_copy ASSUMPTIONS: Assignment ("=") and equality ("==") are defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block then exactly N - 1 equality operations of TYPE and at most N - 2 assignments of TYPE are performed. IMPLEMENTATION: TYPE *unique(register TYPE *begin, register TYPE *end) { register TYPE *m; if (begin >= end) return begin; while (++begin < end) if (*(begin - 1) == *begin) break; if (begin == end) return begin; m = begin - 1; while (++begin < end) if (!(*m == *begin)) *++m = *begin; return m + 1; } NAME: unique - removes repeated elements SYNOPSIS: TYPE *unique(int (*relation)(TYPE*, TYPE*), TYPE *begin, TYPE *end); DESCRIPTION: unique removes all but the first element from every consecutive group of elements, that DO NOT mutually satisfy the relation. NOTE: unique assumes that the relation is non-reflexive (that is, like "!=" and not like "=="). It is done because unique is normally used with sorted blocks and so the same relation may be used both for sorting and removing repeated elements. SEE ALSO: remove_duplicates, remove_duplicates_copy, other unique, unique_copy ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block then exactly N - 1 calls to the relation and at most N - 2 assignments of TYPE are performed. IMPLEMENTATION: TYPE *unique(register int (*relation)(TYPE*, TYPE*), register TYPE *begin, register TYPE *end) { register TYPE *m; if (begin >= end) return begin; while (++begin < end) if (!(*relation)(begin - 1, begin)) break; if (begin == end) return begin; m = begin - 1; while (++begin < end) if ((*relation)(m, begin)) *++m = *begin; return m + 1; } NAME: unique_copy - copies a block while removing repeated elements SYNOPSIS: TYPE *unique_copy(TYPE *begin, TYPE *end, TYPE *result); DESCRIPTION: unique_copy copies only the first element out of any consecutive group of equal elements in the block. NOTE: If begin <= result < end or begin <= result + (end - begin) < end then the effect of unique_copy is not defined. SEE ALSO: remove_duplicates, remove_duplicates_copy, unique, other unique_copy ASSUMPTIONS: Assignment ("=") and equality ("==") are defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block then exactly N - 1 equality operations of TYPE and at most N - 2 assignments of TYPE are performed. IMPLEMENTATION: TYPE *unique_copy(register TYPE *begin, register TYPE *end, register TYPE *result) { if (begin >= end) return result; *result = *begin; while (++begin < end) if (!(*result == *begin)) *++result = *begin; return result + 1; } NAME: unique_copy - copies a block while removing repeated elements SYNOPSIS: TYPE *unique_copy(int (*relation)(TYPE*, TYPE*), TYPE *begin, TYPE *end, TYPE *result); DESCRIPTION: unique_copy copies only the first element out of any consecutive group of elements, that DO NOT mutually satisfy the relation. NOTE: 1) unique_copy assumes that the relation is non-reflexive (that is, like "!=" and not like "=="). It is done because unique_copy is normally used with sorted blocks and so the same relation may be used both for sorting and removing repeated elements. 2) If begin <= result < end or begin <= result + (end - begin) < end then the effect of unique_copy is not defined. SEE ALSO: remove_duplicates, remove_duplicates_copy, unique, other unique_copy ASSUMPTIONS: Assignment ("=") is defined for the TYPE. DEPENDS ON: nothing COMPLEXITY: Linear in the size of the block. If N is the number of locations in the block then exactly N - 1 calls to the relation and at most N assignments of TYPE are performed. IMPLEMENTATION: TYPE *unique_copy(register int (*relation)(TYPE*, TYPE*), register TYPE *begin, register TYPE *end, register TYPE *result) { if (begin >= end) return result; *result = *begin; while (++begin < end) if ((*relation)(result, begin)) *++result = *begin; return result + 1; }