I was thinking, you should be able to do this at compile-time with appropriate templates too. If you made it a variadic template (to be introduced with C++0x in 2 to 4 years) you could make it perform arbitrary calculations at compile time on bit vectors...
So I set out with my preliminary c++0x compiler for my own OS and tried to make it work. It works, except for me not having a crt0.o to link to, nor an environment to execute in. Since it's in compile time, however, you can see the results in the assembly output since the calculations won't be in there.
The source
Code: Select all
namespace std {
void printf(const char *, ...);
}
template <int... Boolvector>
class bitvector;
template <int B0, int... rest>
struct bitvector<B0, rest...> {
typedef bitvector<rest...> tail;
enum {
head = B0,
value = (B0 << tail::bitcount) + (tail::value),
bitcount = 1 + tail::bitcount
};
template <int Z>
struct add_front {
typedef bitvector<Z, B0, rest...> value;
};
};
template <int c, typename V1, typename V2>
struct add {
private:
typedef add<c, typename V1::tail, typename V2::tail> subchild;
public:
typedef typename add<c, typename V1::tail, typename V2::tail>::value subchildvalue;
typedef typename subchildvalue::template add_front<V1::head ^ V2::head ^ subchild::carry>::value value;
enum {
carry = (V1::head & V2::head) | (V1::head & subchild::carry) | (V2::head & subchild::carry)
};
};
template <int c>
struct add<c, bitvector<>, bitvector<> > {
typedef bitvector<> value;
enum { carry = c };
};
template <>
struct bitvector<> {
enum {
value = 0,
bitcount = 0
};
template <int Z>
struct add_front {
typedef bitvector<Z> value;
};
};
typedef bitvector<0,1,1,0,1,0,0,1> value_105;
typedef bitvector<0,0,1,1,0,0,1,1> value_51;
typedef add<0, value_105, value_51>::value value_result;
int main() {
std::printf("Value of %d + %d = %d\n", value_105::value, value_51::value, value_result::value);
}
The assembly output (per lack of better output, left out a few bits of slack, didn't modify any bit I copied, didn't copy more than one bit):
Code: Select all
.file "bit.cc"
.section .rodata
.LC0:
.string "Value of %d + %d = %d\n"
.text
.align 2
.globl main
.type main, @function
main:
.LFB2:
leal 4(%esp), %ecx
.LCFI0:
andl $-16, %esp
pushl -4(%ecx)
.LCFI1:
pushl %ebp
.LCFI2:
movl %esp, %ebp
.LCFI3:
pushl %ecx
.LCFI4:
subl $20, %esp
.LCFI5:
movl $156, 12(%esp)
movl $51, 8(%esp)
movl $105, 4(%esp)
movl $.LC0, (%esp)
call _ZSt6printfPKcz
movl $0, %eax
addl $20, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.LFE2:
.size main, .-main
<snip exception handling and GNU personality thingy>
.align 4
.LEFDE1:
.ident "GCC: (GNU) 4.3.0 20070427 (experimental)"
As you can see, it'll output (105 + 51 == 156), which is mathematically correct.
If you want to mess with it, you can get the compiler from the GCC CVS/SVN server. Download a 4.3 snapshot (mine is from early this month) or current tip.
Enjoy!