/* * Insert one heap pointer. * * Since the entries are being inserted into a balanced binary tree, you * might think that the order of insertion wouldn't be critical, but it turns * out that inserting the entries in sorted order results in a lot of * rebalancing operations and is slow. To prevent this, we attempt to insert * the nodes in an order that will produce a nearly-balanced tree if the input * is in fact sorted. * * We do this as follows. First, we imagine that we have an array whose size * is the smallest power of two greater than or equal to the actual array * size. Second, we insert the middle entry of our virtual array into the * tree; then, we insert the middles of each half of out virtual array, then * middles of quarters, etc. */ void ginInsertRecordBA(BuildAccumulator *accum, ItemPointer heapptr, OffsetNumber attnum, Datum *entries, int32 nentry) { uint32 step = nentry; if (nentry <= 0) return; Assert(ItemPointerIsValid(heapptr) && attnum >= FirstOffsetNumber); /* * step will contain largest power of 2 and <= nentry */ step |= (step >> 1); step |= (step >> 2); step |= (step >> 4); step |= (step >> 8); step |= (step >> 16); step >>= 1; step++; while (step > 0) { int i; for (i = step - 1; i < nentry && i >= 0; i += step << 1 /* *2 */ ) ginInsertEntry(accum, heapptr, attnum, entries[i]); step >>= 1; /* /2 */ } }
/* * insert middle of left part the middle of right one, * then calls itself for each parts */ static void ginChooseElem(BuildAccumulator *accum, ItemPointer heapptr, Datum *entries, uint32 nentry, uint32 low, uint32 high, uint32 offset) { uint32 pos; uint32 middle = (low + high) >> 1; pos = (low + middle) >> 1; if (low != middle && pos >= offset && pos - offset < nentry) ginInsertEntry(accum, heapptr, entries[pos - offset]); pos = (high + middle + 1) >> 1; if (middle + 1 != high && pos >= offset && pos - offset < nentry) ginInsertEntry(accum, heapptr, entries[pos - offset]); if (low != middle) ginChooseElem(accum, heapptr, entries, nentry, low, middle, offset); if (high != middle + 1) ginChooseElem(accum, heapptr, entries, nentry, middle + 1, high, offset); }