312 lines
8.5 KiB
C++
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;
|
|
}
|
|
}
|