#include <cmath>
#include <future>
#include <iostream>

union single
{
	single(float num = 0.0f) : f(num) {}
	float f;
	int32_t i;

	struct __attribute__((packed))
	{
		unsigned int mantissa:23;
		unsigned int exponent:8;
		unsigned int sign:1;
	} parts;

	single& operator++()
	{
		this->i+=1;
		return *this;
	}

	single& operator++(int)
	{
		*this = *this + 1;
		return *this;
	}

	single operator-(int i)
	{
		single copy = *this;
		copy.i -= i;
		return copy;
	}

	single operator+(int i)
	{
		return this->operator-(-i);
	}

	std::ostream& print(std::ostream& os) const
	{
		os << "Mantissa: " << this->parts.mantissa << std::endl;
		os << "Exponent: " << this->parts.exponent << std::endl;
		os << "Sign: " << this->parts.sign << std::endl;
		os << "Value: " << this->f << std::endl;
		return os;
	}
};

template<class T>
auto operator<<(std::ostream& os, const T& t) -> decltype(t.print(os), os)
{
	t.print(os);
	return os;
}

double log_2(float a)
{
#define AS_INT(x) *((int*)&(x))
	/* used for scaling */
	static float one = 1.0f;
	static float two = 2.0f;
	return (AS_INT(a) - AS_INT(one)) /
		double(AS_INT(two) - AS_INT(one));
}

int main(int argc, char** argv)
{
	std::cout << log_2(65536) << std::endl;
	return 0;

	float delta;
	single num;
	single max_positive;
	max_positive.i = 0x7F7FFFFF;
	for (int i = 0; i < max_positive.i; i++, num++)
	{
		if (std::isnan(num.f))
		{
			printf("Nan at iteration %d\n", i);
			break;
		}
		float cur_delta = (num + 1).f - num.f;
		if (cur_delta == delta)
		{
			continue;
		}
		delta = cur_delta;
		if (num.f < 0.00000001)
			printf("New delta from %1.8e: %1.8e\n", num.f, delta);
		else
			printf("New delta from %1.8f: %1.8e\n", num.f, delta);
	}
}
