#include <iostream>

using namespace std;

enum WindingOrder {
	BOTTOM = 0,
	RIGHT,
	TOP,
	LEFT
};

void tester(const int* square, WindingOrder edge, int* output) {
	switch (edge) {
	case BOTTOM:
		output[0] = square[0]; output[1] = square[1]; output[2] = square[2]; output[3] = square[1];
		break;
	case RIGHT:
		output[0] = square[2]; output[1] = square[1]; output[2] = square[2]; output[3] = square[3];
		break;
	case TOP:
		output[0] = square[2]; output[1] = square[3]; output[2] = square[0]; output[3] = square[3];
		break;
	case LEFT:
		output[0] = square[0]; output[1] = square[3]; output[2] = square[0]; output[3] = square[1];
		break;
	}
}

int getIndex(int k, int edge) {
    int A = (k >> 1) & 1;
    int B = k & 1;
    int C = (edge >> 1) & 1;
    int D = edge & 1;
    int P = A&~B&~C | A&~C&D | ~B&~C&D | ~A&B&C | ~A&C&~D | B&C&~D;
    int Q = B;
    return (P << 1) + Q;
}

int main() {
	const int size = 4;
	const int square[size] = { 0, 1, 2, 3 };
	int test[size];
	int output[size];

	for (WindingOrder edge = BOTTOM; edge <= LEFT; edge = static_cast<WindingOrder>(static_cast<int>(edge) + 1)) {
		tester(square, edge, test);

		for (int i = 0; i < size ; ++i) {
			output[i] = square[getIndex(i, static_cast<int>(edge))];
		}

		const bool firstX = output[0] == test[0];
		const bool firstY = output[1] == test[1];
		const bool secondX = output[2] == test[2];
		const bool secondY = output[3] == test[3];

		if (!firstX) {
			cout << "Mismatch at i = 0: test = " << test[0] << " output = " << output[0] << endl;
		} else if (!firstY) {
			cout << "Mismatch at i = 1: test = " << test[1] << " output = " << output[1] << endl;
		} else if (!secondX) {
			cout << "Mismatch at i = 2: test = " << test[2] << " output = " << output[2] << endl;
		} else if (!secondY) {
			cout << "Mismatch at i = 3: test = " << test[3] << " output = " << output[3] << endl;
		} else {
			cout << "Match: " << output[0] << ' ' << output[1] << ' ' << output[2] << ' ' << output[3] << endl;
		}
	}

	return 0;
}