open-source-search-engine/generateSuperMergeCode.cpp
2013-08-02 13:12:24 -07:00

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;
}
}