unsigned add( unsigned a, unsigned b ) { return (unsigned)&((char*)a)[b]; // ignore compiler warnings // (if pointers are bigger than unsigned). it still works. } unsigned umul( unsigned a, unsigned b ) { unsigned res = 0; while( a != 0 ){ if( a & 1) res = add( res, b ); b <<= 1; a >>= 1; } return res; } int mul( int a, int b ){ return (int)umul( (unsigned)a, (unsigned)b ); }
If you consider the a[b] hack to be cheating (since it's really an add) then this works instead. But table lookups involve pointer adds too.
See http://en.wikipedia.org/wiki/IBM_1620 - a conputer that actually did addition using lookup tables...
Something satisfying about using a table mechanism to 'speed up' an operation that could actually be done in one instruction.
static unsigned sumtab[17][16]= { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15}, { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16}, { 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17}, { 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18}, { 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19}, { 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20}, { 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21}, { 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22}, { 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23}, { 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24}, {10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25}, {11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26}, {12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27}, {13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28}, {14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29}, {15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30}, {16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31} }; unsigned add( unsigned a, unsigned b ) { static const int add4hack[8] = {4,8,12,16,20,24,28,32}; unsigned carry = 0; unsigned (*sumtab0)[16] = &sumtab[0]; unsigned (*sumtab1)[16] = &sumtab[1]; unsigned result = 0; int nshift = 0; while( (a|b) != 0 ){ unsigned psum = (carry?sumtab1:sumtab0)[ a & 0xF ][ b & 0xF ]; result = result | ((psum & 0xF)<<nshift); carry = psum >> 4; a = a >> 4 b = b >> 4; nshift= add4hack[nshift>>2]; // add 4 to nshift. } return result; }