Workshop o mikrokontrolérech na SKSP 2024.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

104 lines
2.4 KiB

2 months ago
/*
* UCW Library -- Universal Sorter: Two-Way Merge Module
*
* (c) 2007 Martin Mares <mj@ucw.cz>
*
* This software may be freely distributed and used according to the terms
* of the GNU Lesser General Public License.
*/
static void P(twoway_merge)(struct sort_context *ctx UNUSED, struct sort_bucket **ins, struct sort_bucket **outs)
{
struct fastbuf *fin1, *fin2, *fout1, *fout2, *ftmp;
P(key) kbuf1, kbuf2, kbuf3, kbuf4;
P(key) *kin1 = &kbuf1, *kprev1 = &kbuf2, *kin2 = &kbuf3, *kprev2 = &kbuf4;
P(key) *kout = NULL, *ktmp;
int next1, next2, run1, run2;
int comp;
uint run_count = 0;
fin1 = sbuck_read(ins[0]);
next1 = P(read_key)(fin1, kin1);
if (sbuck_have(ins[1]))
{
fin2 = sbuck_read(ins[1]);
next2 = P(read_key)(fin2, kin2);
}
else
{
fin2 = NULL;
next2 = 0;
}
fout1 = fout2 = NULL;
run1 = next1, run2 = next2;
while (next1 || next2)
{
if (!run1)
comp = 1;
else if (!run2)
comp = -1;
else
comp = P(compare)(kin1, kin2);
ktmp = (comp <= 0) ? kin1 : kin2;
if (!kout || !(P(compare)(kout, ktmp) LESS 0))
{
SWAP(fout1, fout2, ftmp);
if (unlikely(!fout1))
{
if (!fout2)
fout1 = sbuck_write(outs[0]);
else if (outs[1])
fout1 = sbuck_write(outs[1]);
else
fout1 = fout2;
}
run_count++;
}
#ifdef SORT_ASSERT_UNIQUE
ASSERT(comp != 0);
#endif
if (comp LESS 0)
{
P(copy_data)(kin1, fin1, fout1);
SWAP(kin1, kprev1, ktmp);
next1 = P(read_key)(fin1, kin1);
run1 = next1 && (P(compare)(kprev1, kin1) LESS 0);
kout = kprev1;
}
#ifdef SORT_UNIFY
else if (comp == 0)
{
P(key) *mkeys[] = { kin1, kin2 };
struct fastbuf *mfb[] = { fin1, fin2 };
P(copy_merged)(mkeys, mfb, 2, fout1);
SWAP(kin1, kprev1, ktmp);
next1 = P(read_key)(fin1, kin1);
run1 = next1 && (P(compare)(kprev1, kin1) LESS 0);
SWAP(kin2, kprev2, ktmp);
next2 = P(read_key)(fin2, kin2);
run2 = next2 && (P(compare)(kprev2, kin2) LESS 0);
kout = kprev2;
}
#endif
else
{
P(copy_data)(kin2, fin2, fout1);
SWAP(kin2, kprev2, ktmp);
next2 = P(read_key)(fin2, kin2);
run2 = next2 && (P(compare)(kprev2, kin2) LESS 0);
kout = kprev2;
}
if (!run1 && !run2)
{
run1 = next1;
run2 = next2;
}
}
if (fout2 && fout2 != fout1)
outs[1]->runs += run_count / 2;
if (fout1)
outs[0]->runs += (run_count+1) / 2;
}