mirror of
https://github.com/gigablast/open-source-search-engine.git
synced 2024-10-04 20:27:43 +03:00
312 lines
8.2 KiB
C++
312 lines
8.2 KiB
C++
#include "gb-include.h"
|
|
|
|
void doit ( long n ) ;
|
|
void printLine ( char *bits , long n , char *lastBits , long removeNegs ) ;
|
|
void setBits ( char *bits , long n , long i ) ;
|
|
|
|
main ( int argc , char *argv[] ) {
|
|
|
|
if ( argc > 2 ) {
|
|
fprintf(stderr,"Usage: gen <# lists to merge>\n");
|
|
exit(-1);
|
|
}
|
|
// merge code for how many lists?
|
|
//long n = atoi ( argv[1] );
|
|
|
|
for ( long i = 3 ; i <= 5 ; i++ )
|
|
doit(i);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void doit ( long n ) {
|
|
|
|
printf ("// This code was auto generated by "
|
|
"generateSuperMergeCode.cpp\n");
|
|
|
|
// print header
|
|
printf ( "void RdbList::superMerge%li ( RdbList *list0 ,\n" , n );
|
|
for ( long i = 1 ; i < n ; i++ )
|
|
printf ("\tRdbList *list%li ,\n", i );
|
|
// then key parms
|
|
printf ( "\tkey_t startKey ,\n\tkey_t endKey ) {\n");
|
|
// set up
|
|
printf ( "\tlong newMax = (m_mergeMinListSize / sizeof(key_t)) * "
|
|
"\tsizeof(key_t);\n"
|
|
"\tkey_t *k = (key_t *) m_listPtr;\n"
|
|
"\tkey_t *keysEnd = (key_t *) (m_listPtr + newMax);\n"
|
|
"\tkey_t *kstart = (key_t *) m_listPtr;\n" );
|
|
// then quick vars
|
|
for ( long i = 0 ; i < n ; i++ )
|
|
printf("\tkey_t *k%li = (key_t *) list%li->m_listPtr;\n",i,i);
|
|
for ( long i = 0 ; i < n ; i++ )
|
|
printf ("\tkey_t *end%li = (key_t *) list%li->m_listEnd;\n",i,i);
|
|
// go forwards
|
|
for ( long i = 0 ; i < n ; i++ )
|
|
printf ("\twhile ( k%li < end%li && *k%li < startKey ) "
|
|
"k%li++;\n",i,i,i,i);
|
|
// pedal backwards
|
|
for ( long i = 0 ; i < n ; i++ )
|
|
printf ("\twhile ( end%li > k%li && *(end%li-1) > endKey ) "
|
|
"end%li--;\n",i,i,i,i);
|
|
|
|
// . begin tree stuff
|
|
// . OUTTER COMPARES
|
|
// . it's a trinary tree
|
|
// . 1st row is (for 5 lists is)
|
|
// . there's ESSENTIALLY 3^(5-1) comparison lines
|
|
// . (k0 < k1, k0 < k2, k0 < k3, k0 < k4) k0,k0,k0,k0
|
|
// . (k0 < k1, k0 < k2, k0 < k3, k0 > k4) k0,k0,k0,k0/k4
|
|
// . (k0 < k1, k0 < k2, k0 < k3, k0 = k4) k0,k0,k0,k4
|
|
|
|
// . (k0 < k1, k0 < k2, k0 > k3, k3 < k4) k0,k0,k3,k3
|
|
// . (k0 < k1, k0 < k2, k0 > k3, k3 > k4) k0,k0,k3,k4
|
|
// . (k0 < k1, k0 < k2, k0 > k3, k3 = k4) k0,k0,k3,k3/k4
|
|
|
|
// . (k0 < k1, k0 > k2, k2 < k3, k2 < k4) k0,k2,k2,k2
|
|
// . (k0 < k1, k0 > k2, k2 < k3, k2 > k4) k0,k2,k2,k4
|
|
// . (k0 < k1, k0 > k2, k2 < k3, k2 = k4) k0,k2,k2,k2/k4
|
|
|
|
// . (k0 < k1, k0 > k2, k2 > k3, k3 < k4) k0,k2,k3,k3
|
|
// . (k0 < k1, k0 > k2, k2 > k3, k3 > k4) k0,k2,k3,k4
|
|
// . (k0 < k1, k0 > k2, k2 > k3, k3 = k4) k0,k2,k3,k3/k4
|
|
|
|
// . so into binary, 1 means leadership is taken away, 2 means shared
|
|
// . # of 0's after first bit on determines nested depth
|
|
|
|
// . 0 0 0 0 if(k0<k1){if(k0<k2){if(k0<k3){if(k0<k4){STORE(k0)}
|
|
// . 0 0 0 1 ei(k4<k0){STORE(k4)}
|
|
// . 0 0 0 2 el{STORE(k0);k0++;k4++}}
|
|
|
|
// . 0 0 1 0 ei(k3<k0){if(k3<k4){STORE(k3)}
|
|
// . 0 0 1 1 ei(k4<k3){STORE(k4)}
|
|
// . 0 0 1 2 el{STORE(k3);k3++;k4++}}
|
|
|
|
// . 0 0 2 0 el {if(k3<k4){STORE(k3)k3+k0+}
|
|
// . 0 0 2 1 ei(k4<k3){STORE(k4)k4+}
|
|
// . 0 0 2 2 el{STORE(k0)k0+k3+k4+}}}
|
|
|
|
|
|
// . 0 1 0 0
|
|
// . 0 1 0 1
|
|
// . 0 1 0 2
|
|
|
|
// . 0 1 1 0
|
|
// . 0 1 1 1
|
|
// . 0 1 1 2
|
|
|
|
// . 0 1 2 0
|
|
// . 0 1 2 1
|
|
// . 0 1 2 2
|
|
|
|
|
|
|
|
// . 0 2 0 0
|
|
// . 0 2 0 1
|
|
// . 0 2 0 2
|
|
|
|
// . 0 2 1 0
|
|
// . 0 2 1 1
|
|
// . 0 2 1 2
|
|
|
|
// . 0 2 2 0
|
|
// . 0 2 2 1
|
|
// . 0 2 2 2
|
|
|
|
|
|
// So there you have it, nice and trinary...
|
|
|
|
// support merges of up to 32 lists
|
|
char bits [ 32 ];
|
|
|
|
// number comparisons, not number of keys
|
|
long numCmps = n - 1;
|
|
|
|
// how many combos do we have?
|
|
// 3 ^ (n-1) where n is # of lists to mer
|
|
long count = 1;
|
|
for ( long i = 0 ; i < numCmps ; i++ ) count *= 2;
|
|
|
|
printf ("\t// %li logic paths\n",count );
|
|
|
|
// we may not need padding
|
|
printf ("\tif ( m_listPtr > m_list ) goto top;\n");
|
|
|
|
printf ("padding:\n");
|
|
|
|
// padding start
|
|
for ( long i = 0 ; i < n ; i++ )
|
|
printf ("\tif ( k%li >= end%li ) goto done;\n",i,i);
|
|
|
|
// init lastBits
|
|
char lastBits[32];
|
|
for ( long i = 0 ; i < 32 ; i++ ) lastBits[i] = -2;
|
|
|
|
// now start counting in trinary
|
|
for ( long i = 0 ; i < count ; i++ ) {
|
|
// set bits for this trinary
|
|
setBits ( bits , numCmps , i );
|
|
// print out a statement
|
|
printLine ( bits , numCmps , lastBits , 0 );
|
|
// copy lastBits
|
|
for ( long i = 0 ; i < 32 ; i++ )
|
|
lastBits[i] = bits[i];
|
|
}
|
|
|
|
// the real part
|
|
printf ("top:\n");
|
|
|
|
printf("\tif ( k >= keysEnd ) goto done;\n");
|
|
|
|
// init lastBits again
|
|
for ( long i = 0 ; i < 32 ; i++ ) lastBits[i] = -2;
|
|
|
|
// print all again
|
|
for ( long i = 0 ; i < count ; i++ ) {
|
|
// set bits for this trinary
|
|
setBits ( bits , numCmps , i );
|
|
// print out a statement
|
|
printLine ( bits , numCmps , lastBits, 1 );
|
|
// copy lastBits
|
|
for ( long i = 0 ; i < 32 ; i++ )
|
|
lastBits[i] = bits[i];
|
|
}
|
|
|
|
// loop command
|
|
printf ( "\tgoto top;\n" );
|
|
|
|
printf ( "\tdone:\n");
|
|
// update list ptrs
|
|
for ( long i = 0 ; i < n ; i++ )
|
|
printf("\tlist%li->m_listPtr = (char *)k%li;\n",i,i);
|
|
|
|
printf ("\tm_mergeMinListSize -= ((char *)k-(char *)kstart);\n");
|
|
// set our stuff
|
|
printf ("\tm_listSize = (char *)k - m_list;\n"
|
|
"\tm_listPtr = (char *)k;\n"
|
|
"\tm_listEnd = m_list + m_listSize;\n");
|
|
|
|
// then re-calls
|
|
for ( long i = 0 ; i < n ; i++ ) {
|
|
printf("\tif ( k%li >= end%li ) {\n",i,i);
|
|
printf ("\t\tsuperMerge%li ( ",n-1);
|
|
// arguments
|
|
for ( long j = 0 ; j < n ; j++ ) {
|
|
if ( j == i ) continue;
|
|
printf("list%li , ",j);
|
|
}
|
|
// rest of args
|
|
//if ( n-1 == 2 ) printf("startKey , endKey , false );\n");
|
|
//else printf("startKey , endKey );\n");
|
|
printf("startKey , endKey );\n");
|
|
printf ("\t\treturn;\n\t}\n");
|
|
}
|
|
// return if no keys set
|
|
printf ("\tif ( k == (key_t *)m_list ) return;\n");
|
|
|
|
printf ("\tkey_t lastKey = *(k - 1);\n");
|
|
|
|
printf ("\tif ( k < keysEnd ) return ;\n");
|
|
|
|
// set endKey of each list if we ran out of room
|
|
for ( long i = 0 ; i < n ; i++ )
|
|
printf ("\tif ( k%li < end%li && *k%li < m_endKey ) "
|
|
"m_endKey = lastKey;\n",i,i,i);
|
|
|
|
printf ("}\n");
|
|
}
|
|
|
|
void printLine ( char *bits , long n , char *lastBits , long removeNegs ) {
|
|
// how many trailing zeroes?
|
|
long nz = 0;
|
|
for ( long i = n - 1 ; i >= 0 ; i-- ) {
|
|
if ( bits[i] == 0 ) nz++;
|
|
}
|
|
// complement to get the ultimate winner
|
|
long winners [ 10 ];
|
|
long numWinners = 1;
|
|
winners[0] = 0;
|
|
|
|
// n tabs
|
|
char tabs[32];
|
|
for ( long i = 0 ; i < n ; i++ ) { tabs[i] = '\t'; tabs[i+1]='\0'; }
|
|
|
|
// call signal
|
|
//printf("CALLED ");
|
|
// print bits out for debug
|
|
//for ( long i = 0 ; i < n ; i++ )
|
|
// printf("%li(%li) ",bits[i],lastBits[i]);
|
|
//printf("\n");
|
|
|
|
for ( long i = 0 ; i < n ; i++ ) {
|
|
// print i tabs
|
|
if ( bits[i] != lastBits[i] )
|
|
for ( long j = 0 ; j < i ; j++ ) printf("\t");
|
|
if ( bits[i] == 0 ) {
|
|
if ( bits[i] != lastBits[i] )
|
|
printf("\tif ( *k%li <= *k%li ) {\n",
|
|
winners[0],i+1);
|
|
//winners[0] = i;
|
|
//numWinners = 1;
|
|
}
|
|
else if ( bits[i] == 1 ) {
|
|
if ( bits[i] != lastBits[i] )
|
|
//printf("\telse if ( *k%li > *k%li ) {\n",
|
|
printf("\telse {\n",
|
|
winners[0],i+1);
|
|
winners[0] = i+1;
|
|
numWinners = 1;
|
|
}
|
|
//else {
|
|
// if ( bits[i] != lastBits[i] )
|
|
// printf("\telse {\n");
|
|
// winners [ numWinners++ ] = i+1;
|
|
//}
|
|
}
|
|
|
|
// if removing negs...
|
|
if ( removeNegs ) {
|
|
printf ("%s\tif ((k-1)->n1==k%li->n1 && "
|
|
"((k-1)->n0|0x01LL)==k%li->n0)"
|
|
"{\n"
|
|
"%s\t\tk%li++; "
|
|
"if ( --k == kstart ) goto padding; }\n"
|
|
"%s\telse { ",
|
|
tabs,winners[0],winners[0],
|
|
tabs,winners[0],
|
|
tabs);
|
|
// then the storage instructions
|
|
printf ("*k++ = *k%li++; }\n",winners[0]);
|
|
// advance 1st winner only
|
|
//printf ("%s\t\tk%li++;\n",tabs,winners[0]);
|
|
// if anything we advanced finished
|
|
printf ("%s\tif ( k%li >= end%li ) goto done;",
|
|
tabs,winners[0],winners[0]);
|
|
}
|
|
else {
|
|
// then the storage instructions
|
|
printf ("%s\t*k++ = *k%li++; \n",tabs,winners[0]);
|
|
// advance 1st winner only
|
|
//printf ("%s\tk%li++;\n",tabs,winners[0]);
|
|
// if anything we advanced finished
|
|
printf ("%s\tif ( k%li >= end%li ) goto done;",
|
|
tabs,winners[0],winners[0]);
|
|
}
|
|
printf ("\n");
|
|
// wrap up
|
|
printf ("%s}",tabs);
|
|
// count consecutive trailing 2's
|
|
for ( long i = n-1 ; i >= 1 ; i-- ) {
|
|
if ( bits[i] == 1 ) printf ("}");
|
|
else break;
|
|
}
|
|
printf ("\n");
|
|
}
|
|
|
|
void setBits ( char *bits , long n , long i ) {
|
|
for ( long j = n - 1 ; j >= 0 ; j-- ) {
|
|
bits[j] = i % 2 ;
|
|
i /= 2;
|
|
}
|
|
}
|