/* version 2007.09.24, D. J. Bernstein; public domain */ #include using namespace std; #include "dagbit.h" static long long nextnode = 1; dagbit::dagbit() { node = 0; flipped = 0; value = 0; } dagbit& dagbit::operator=(int x) { value = x & 1; node = 0; flipped = value; return *this; } dagbit& dagbit::operator=(const dagbit& x) { node = x.node; flipped = x.flipped; value = x.value; return *this; } void dagbit::key(long long b,int x) { node = -(b * 4 + 1); flipped = 0; value = x; } void dagbit::input(long long b,int x) { node = -(b * 4 + 2); flipped = 0; value = x; } void dagbit::output(long long b) { cout << node << ":"; cout << flipped << ":"; cout << value << ":"; cout << "outputbit" << ":"; cout << b << ":"; cout << "\n"; } static struct { const int output[2][2][2]; const char *label; int usex; int usey; int usez; } simpleop[] = { { {{{0,0},{0,0}},{{0,0},{0,0}}}, "zero", 0, 0, 0 } , { {{{0,0},{0,0}},{{1,1},{1,1}}}, "copy", 1, 0, 0 } , { {{{0,0},{1,1}},{{0,0},{1,1}}}, "copy", 0, 1, 0 } , { {{{0,1},{0,1}},{{0,1},{0,1}}}, "copy", 0, 0, 1 } , { {{{0,0},{0,0}},{{0,0},{1,1}}}, "&", 1, 1, 0 } , { {{{0,0},{0,0}},{{0,1},{0,1}}}, "&", 1, 0, 1 } , { {{{0,0},{0,1}},{{0,0},{0,1}}}, "&", 0, 1, 1 } , { {{{0,0},{1,1}},{{1,1},{0,0}}}, "^", 1, 1, 0 } , { {{{0,1},{0,1}},{{1,0},{1,0}}}, "^", 1, 0, 1 } , { {{{0,1},{1,0}},{{0,1},{1,0}}}, "^", 0, 1, 1 } , { {{{0,0},{0,1}},{{0,1},{1,1}}}, "maj", 1, 1, 1 } , { {{{0,1},{1,0}},{{1,0},{0,1}}}, "^^", 1, 1, 1 } } ; dagbit op(dagbit x,dagbit y,dagbit z,const int output[2][2][2]) { for (int i = 0;i < (sizeof simpleop)/(sizeof simpleop[0]);++i) for (int of = 0;of < 2;++of) for (int xf = 0;xf < 2;++xf) for (int yf = 0;yf < 2;++yf) for (int zf = 0;zf < 2;++zf) { int ok = 1; for (int xb = 0;xb < 2;++xb) for (int yb = 0;yb < 2;++yb) for (int zb = 0;zb < 2;++zb) { if (x.node == 0) if (xb != 0) continue; if (y.node == 0) if (yb != 0) continue; if (z.node == 0) if (zb != 0) continue; if (x.node == y.node) if (xb != yb) continue; if (x.node == z.node) if (xb != zb) continue; if (y.node == z.node) if (yb != zb) continue; if (output[xb ^ x.flipped][yb ^ y.flipped][zb ^ z.flipped] != of ^ simpleop[i].output[xb ^ xf][yb ^ yf][zb ^ zf]) ok = 0; } if (ok) { dagbit result; result.value = output[x.value][y.value][z.value]; switch(simpleop[i].usex + simpleop[i].usey + simpleop[i].usez) { case 0: result.node = 0; result.flipped = result.value; return result; case 1: if (simpleop[i].usex) { result.node = x.node; result.flipped = xf ^ of; } if (simpleop[i].usey) { result.node = y.node; result.flipped = zf ^ of; } if (simpleop[i].usez) { result.node = z.node; result.flipped = yf ^ of; } return result; default: result.node = nextnode++; result.flipped = of; cout << result.node << ":"; cout << result.flipped << ":"; cout << result.value << ":"; cout << simpleop[i].label << ":"; if (simpleop[i].usex) cout << x.node << ":" << xf << ":"; if (simpleop[i].usey) cout << y.node << ":" << yf << ":"; if (simpleop[i].usez) cout << z.node << ":" << zf << ":"; cout << "\n"; return result; } } } abort(); } dagbit operator~(dagbit x) { return op(x,x,x,(const int[2][2][2]){{{1,1},{1,1}},{{0,0},{0,0}}}); } dagbit operator&(dagbit x,dagbit y) { return op(x,y,y,(const int[2][2][2]){{{0,0},{0,0}},{{0,0},{1,1}}}); } dagbit operator|(dagbit x,dagbit y) { return op(x,y,y,(const int[2][2][2]){{{0,0},{1,1}},{{1,1},{1,1}}}); } dagbit operator^(dagbit x,dagbit y) { return op(x,y,y,(const int[2][2][2]){{{0,0},{1,1}},{{1,1},{0,0}}}); } dagbit majority(dagbit x,dagbit y,dagbit z) { return op(x,y,z,(const int[2][2][2]){{{0,0},{0,1}},{{0,1},{1,1}}}); } dagbit belowsum(dagbit x,dagbit y,dagbit z) { return op(x,y,z,(const int[2][2][2]){{{0,1},{1,1}},{{0,0},{0,1}}}); } dagbit xorthree(dagbit x,dagbit y,dagbit z) { return op(x,y,z,(const int[2][2][2]){{{0,1},{1,0}},{{1,0},{0,1}}}); }