#include <stdint.h>
#include <iostream>
#include <iomanip>
#include <time.h>
#include <stdlib.h>

#define STR_EXPAND(tok) #tok
#define STR(tok) STR_EXPAND(tok)

struct Test1 {
	int a;
#if BITS
	TYPE b0: BITS;
	TYPE b1: BITS;
	TYPE b2: BITS;
#else
	TYPE b0;
	TYPE b1;
	TYPE b2;
#endif
	int c;
};

timespec now()
{
	timespec t = { 0, 0 };
	if (clock_gettime(CLOCK_MONOTONIC, &t) == 0)
		return t;
	abort();
}

double operator -(timespec t1, timespec t2) {
	t1.tv_sec -= t2.tv_sec;
	t1.tv_nsec -= t2.tv_nsec;
	if (t1.tv_nsec < 0) {
		t1.tv_nsec += 1000000000L;
		t1.tv_sec--;
	}

	return t1.tv_sec + t1.tv_nsec / 1e9;
}

int main(int argc, char *argv[])
{
    const int count = atoi(argv[1]);

	Test1 test1 = { 1, false, false, false, 0 };

	const timespec start = now();
    for (int i = 0; i < count; ++i) {
		if (test1.b0)
			test1.a = test1.a + test1.c;
		else
		if (test1.b1)
			test1.a = test1.a - test1.c;
		else
		if (test1.b2)
			test1.c = test1.c - test1.a;
		else
			test1.c = test1.a ^ test1.c;
		test1.b0 = (i % 3) != 0;
		test1.b1 = (i % 5) != 0;
		test1.b2 = (i % 7) != 0;
	}
	const timespec end = now();

	std::cout.precision(3);
	std::cout << std::fixed << std::setw(10) <<
		STR(TYPE) << ':' << BITS <<
		" size: " << sizeof(test1) <<
		" final: " << test1.a << '.' << test1.c <<
		" iterations: " << static_cast<uint64_t>(count/1e6) << 'M' <<
		" time: " << (end-start) << "s" <<
		"\n";

    return 0;
}

