open-source-search-engine/generateSuperMergeCode.cpp
2014-11-10 14:45:11 -08:00

312 lines
8.5 KiB
C++

#include "gb-include.h"
void doit ( int32_t n ) ;
void printLine ( char *bits , int32_t n , char *lastBits , int32_t removeNegs ) ;
void setBits ( char *bits , int32_t n , int32_t 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?
//int32_t n = atoi ( argv[1] );
for ( int32_t i = 3 ; i <= 5 ; i++ )
doit(i);
return 0;
}
void doit ( int32_t n ) {
printf ("// This code was auto generated by "
"generateSuperMergeCode.cpp\n");
// print header
printf ( "void RdbList::superMerge%"INT32" ( RdbList *list0 ,\n" , n );
for ( int32_t i = 1 ; i < n ; i++ )
printf ("\tRdbList *list%"INT32" ,\n", i );
// then key parms
printf ( "\tkey_t startKey ,\n\tkey_t endKey ) {\n");
// set up
printf ( "\tint32_t 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 ( int32_t i = 0 ; i < n ; i++ )
printf("\tkey_t *k%"INT32" = (key_t *) list%"INT32"->m_listPtr;\n",i,i);
for ( int32_t i = 0 ; i < n ; i++ )
printf ("\tkey_t *end%"INT32" = (key_t *) list%"INT32"->m_listEnd;\n",i,i);
// go forwards
for ( int32_t i = 0 ; i < n ; i++ )
printf ("\twhile ( k%"INT32" < end%"INT32" && *k%"INT32" < startKey ) "
"k%"INT32"++;\n",i,i,i,i);
// pedal backwards
for ( int32_t i = 0 ; i < n ; i++ )
printf ("\twhile ( end%"INT32" > k%"INT32" && *(end%"INT32"-1) > endKey ) "
"end%"INT32"--;\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
int32_t numCmps = n - 1;
// how many combos do we have?
// 3 ^ (n-1) where n is # of lists to mer
int32_t count = 1;
for ( int32_t i = 0 ; i < numCmps ; i++ ) count *= 2;
printf ("\t// %"INT32" logic paths\n",count );
// we may not need padding
printf ("\tif ( m_listPtr > m_list ) goto top;\n");
printf ("padding:\n");
// padding start
for ( int32_t i = 0 ; i < n ; i++ )
printf ("\tif ( k%"INT32" >= end%"INT32" ) goto done;\n",i,i);
// init lastBits
char lastBits[32];
for ( int32_t i = 0 ; i < 32 ; i++ ) lastBits[i] = -2;
// now start counting in trinary
for ( int32_t 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 ( int32_t 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 ( int32_t i = 0 ; i < 32 ; i++ ) lastBits[i] = -2;
// print all again
for ( int32_t 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 ( int32_t i = 0 ; i < 32 ; i++ )
lastBits[i] = bits[i];
}
// loop command
printf ( "\tgoto top;\n" );
printf ( "\tdone:\n");
// update list ptrs
for ( int32_t i = 0 ; i < n ; i++ )
printf("\tlist%"INT32"->m_listPtr = (char *)k%"INT32";\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 ( int32_t i = 0 ; i < n ; i++ ) {
printf("\tif ( k%"INT32" >= end%"INT32" ) {\n",i,i);
printf ("\t\tsuperMerge%"INT32" ( ",n-1);
// arguments
for ( int32_t j = 0 ; j < n ; j++ ) {
if ( j == i ) continue;
printf("list%"INT32" , ",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 ( int32_t i = 0 ; i < n ; i++ )
printf ("\tif ( k%"INT32" < end%"INT32" && *k%"INT32" < m_endKey ) "
"m_endKey = lastKey;\n",i,i,i);
printf ("}\n");
}
void printLine ( char *bits , int32_t n , char *lastBits , int32_t removeNegs ) {
// how many trailing zeroes?
int32_t nz = 0;
for ( int32_t i = n - 1 ; i >= 0 ; i-- ) {
if ( bits[i] == 0 ) nz++;
}
// complement to get the ultimate winner
int32_t winners [ 10 ];
int32_t numWinners = 1;
winners[0] = 0;
// n tabs
char tabs[32];
for ( int32_t i = 0 ; i < n ; i++ ) { tabs[i] = '\t'; tabs[i+1]='\0'; }
// call signal
//printf("CALLED ");
// print bits out for debug
//for ( int32_t i = 0 ; i < n ; i++ )
// printf("%"INT32"(%"INT32") ",bits[i],lastBits[i]);
//printf("\n");
for ( int32_t i = 0 ; i < n ; i++ ) {
// print i tabs
if ( bits[i] != lastBits[i] )
for ( int32_t j = 0 ; j < i ; j++ ) printf("\t");
if ( bits[i] == 0 ) {
if ( bits[i] != lastBits[i] )
printf("\tif ( *k%"INT32" <= *k%"INT32" ) {\n",
winners[0],i+1);
//winners[0] = i;
//numWinners = 1;
}
else if ( bits[i] == 1 ) {
if ( bits[i] != lastBits[i] )
//printf("\telse if ( *k%"INT32" > *k%"INT32" ) {\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%"INT32"->n1 && "
"((k-1)->n0|0x01LL)==k%"INT32"->n0)"
"{\n"
"%s\t\tk%"INT32"++; "
"if ( --k == kstart ) goto padding; }\n"
"%s\telse { ",
tabs,winners[0],winners[0],
tabs,winners[0],
tabs);
// then the storage instructions
printf ("*k++ = *k%"INT32"++; }\n",winners[0]);
// advance 1st winner only
//printf ("%s\t\tk%"INT32"++;\n",tabs,winners[0]);
// if anything we advanced finished
printf ("%s\tif ( k%"INT32" >= end%"INT32" ) goto done;",
tabs,winners[0],winners[0]);
}
else {
// then the storage instructions
printf ("%s\t*k++ = *k%"INT32"++; \n",tabs,winners[0]);
// advance 1st winner only
//printf ("%s\tk%"INT32"++;\n",tabs,winners[0]);
// if anything we advanced finished
printf ("%s\tif ( k%"INT32" >= end%"INT32" ) goto done;",
tabs,winners[0],winners[0]);
}
printf ("\n");
// wrap up
printf ("%s}",tabs);
// count consecutive trailing 2's
for ( int32_t i = n-1 ; i >= 1 ; i-- ) {
if ( bits[i] == 1 ) printf ("}");
else break;
}
printf ("\n");
}
void setBits ( char *bits , int32_t n , int32_t i ) {
for ( int32_t j = n - 1 ; j >= 0 ; j-- ) {
bits[j] = i % 2 ;
i /= 2;
}
}