MCPcopy Create free account
hub / github.com/ElementsProject/elements / rsort_ex

Function rsort_ex

src/simplicity/rsort.c:124–233  ·  view source on GitHub ↗

Attempts to (partially) sort an array of pointers to 'sha256_midstate's in place in memcmp order. * If NULL == hasDuplicates then sorting is always run to completion. * Otherwise, if NULL != hasDuplicates and if duplicate entries are found, the sorting is aborted and * *hasDuplicates is set to one of pointers of a duplicate entry. * If NULL != hasDuplicates and no duplicate entries are found,

Source from the content-addressed store, hash-verified

122 * uint32_t stack[(CHAR_COUNT - 1)*(sizeof(*a)->s) + 1];
123 */
124static void rsort_ex(const sha256_midstate** a, uint_fast32_t len, const sha256_midstate** hasDuplicates, uint32_t* stack) {
125 unsigned int depth = 0;
126 size_t bucketCount[sizeof((*a)->s) + 1];
127 size_t totalBucketCount = 1;
128
129 static_assert(sizeof((*a)->s) <= UINT_MAX, "UINT_MAX too small to hold depth.");
130 stack[0]=0;
131 bucketCount[depth] = 1;
132
133 /* This implementation contains a 'stack' of 'totalBucketCount' many subarrays (called buckets)
134 that have been partially sorted up to various prefix length.
135
136 The buckets are disjoint and cover the entire array from 0 up to len.
137 As sorting proceeds, the end of the array will be sorted first.
138 We will decrease len as we go as we find out that items at the end of the array are in their proper, sorted position.
139
140 The 'i'th bucket is the subarray a[stack[i]:stack[i+1]),
141 except for the last bucket which is the subarray a[stack[totalBucketCount-1]:len).
142
143 The depth to which various buckets are sorted increases the further down the stack you go.
144 The 'bucketCount' stores how many buckets are sorted to various depths.
145
146 * for all i <= depth, the subarray a[sum(j < i, bucketCount[i]):end) have their first i characters sorted.
147 * for all i <= depth, the (sum(j < i, bucketCount[i]))th and later buckets have all the first i characters of their entries identical.
148
149 So all buckets are sorted up to a prefix length of 0 many characters.
150 Then, if 1 <= depth, all bucket except for the first bucketCount[0]-many buckets are sorted by their 1 character prefix
151 And then, if 2 <= depth, all bucket except for the first (bucketCount[0] + bucket[1])-many buckets are sorted by their 2 character prefix
152 And so on.
153
154 It is always the case that 'totalBucketCount = sum(i <= depth, bucketCount[i])',
155 and thus the last bucket in the stack is located at stack[totalBucketCount-1].
156 'totalBucketCount' and 'bucketCount' items are always increased and decreased in tandum.
157
158 The loop is initialized with a 'totalBucketCount' of 1 and this one bucket contains the whole array a[0:len).
159 'depth' is initialized to 0, and all the entries are trivialy sorted by the first 0-many characters.
160
161 As we go through the loop, the last bucket is "popped" off the stack and processed, which can go one of two ways.
162
163 If the last bucket is size 2 or greater, we proceed to sort it by its 'depth' character and partition the bucket into 256 sub-buckets
164 which are then pushed onto the stack (notice this causes a net increase of the stack size by 255 items, because one was popped off).
165
166 If ever the depth is beyond the size of the data being sorted,
167 we can immediately halt as we have found 2 or more item that are identical.
168
169 Note: there is an added optimization where by if there is only one non-empty bucket found when attempting to sort,
170 i.e. it happens that every bucket item already has identical 'depth' characters,
171 we skip the subdivision and move onto the next depth immediately.
172 (This is equivalent to pushing the one non-empty bucket onto the stack and immediately popping it back off.)
173
174 If the last bucket is of size 0 or 1, it must be already be sorted.
175 Since this bucket is at the end of the array we decrease 'len'.
176 */
177 while(totalBucketCount) {
178 /* Find the correct "depth" of the last bucket. */
179 while(0 == bucketCount[depth]) {
180 simplicity_assert(depth);
181 depth--;

Callers 2

simplicity_rsortFunction · 0.85
simplicity_hasDuplicatesFunction · 0.85

Calls 3

freqFunction · 0.85
cumulativeFunction · 0.85
sort_bucketsFunction · 0.85

Tested by

no test coverage detected