/*
	float x; に対し *(int *)&x を返すtemplate
*/

/**
	[log2(x)]を返す
	@note x >= 0 を仮定
*/
template<int x>
struct ilog2 {
	enum {
		value = (ilog2<x / 2>::value) + 1
	};
};

template<>
struct ilog2<0> {
	enum {
		value = -1
	};
};

/**
	float型整数のfloatとしてのbinary表現
	@note x > 0 を仮定
*/
template<int x, int adj_e = 0>
struct positive_float_int2binary {
	enum {
		log2_x = ilog2<x>::value,
		exponent = (log2_x + 127 - adj_e) << 23,
		f = x - (1 << log2_x),
		mantissa = (log2_x <= 23) ? (f << (23 - log2_x)) : (unsigned(f) >> (log2_x - 23)),
		value = exponent | mantissa
	};
};

/**
	float型整数のfloatとしてのbinary表現
*/
template<int x, int adj_e = 0>
struct float_int2binary {
	enum {
		value = (x > 0) ? positive_float_int2binary<x, adj_e>::value : (x < 0) ? (positive_float_int2binary<-x, adj_e>::value | 0x80000000) : 0
	};
};

/**
	10^xを求める
*/
template<int x>
struct pow10 {
	enum {
		value = (pow10<x - 1>::value) * 10
	};
};

template<>
struct pow10<0> {
	enum {
		value = 1
	};
};

#define CALC_E(a, b) (24 + (b * 1661) / 500/*log2(10)*/ - ilog2<a>::value)
//#define CALC_E(a, b) (24 + (b * 70777) / 21306/*log2(10)*/ - ilog2<a>::value)

/**
	a*10^(-b)の数のbinary表現
*/
template<int a, int b = 0>
struct float2binary {
	enum {
		e = CALC_E(a, b),
		x = ((a * (1 << e)) + pow10<b>::value / 2) / pow10<b>::value,
		value = float_int2binary<x, e>::value
	};
};
/**
	max{s: a*10^(-b)*2^s < 2^24 }を求める
*/

#include <stdio.h>
#include <math.h>

#define P1(x, y) f = x / pow(10, y); printf("%9.3f, %0X:%0X:%c\n", f, float2binary<x, y>::value, *(int *)&f, (float2binary<x, y>::value == *(int *)&f) ? 'o' : 'x');
#define P2(x) f = x; printf("%8d:%0X:%0X:%c\n", x, float2binary<x>::value, *(int *)&f, (float2binary<x>::value == *(int *)&f) ? 'o' : 'x');


int main()
{
	float f;

	P1(1, 1); // 0.1
	P1(-2, 1); // -0.2
	P1(3, 1);
	P1(-4, 1);
	P1(5, 1); // 0.5
	P1(12, 1);

	puts("----------------------");
	P2(-10);
	P2(-3);
	P2(-1);
	P2(0);
	P2(1);
	P2(2);
	P2(3);
	P2(4);
	P2(5);
	P2(6);
	P2(7);
	P2(15);
	P2(16);
	P2(17);
	P2(8193);
	P2((1<<22)-2);
	P2((1<<22)-1);
	P2(1<<22);
	P2((1<<22)+1);
	P2((1<<22)+2);

	P2((1<<23)-2);
	P2((1<<23)-1);
	P2(1<<23);
	P2((1<<23)+1);
	P2((1<<23)+2);

	P2((1<<24)-2);
	P2((1<<24)-1);
	P2(1<<24);
	P2((1<<24)+1);
	P2((1<<24)+2);
	P2((1<<24)+3);

	P2((1<<25)-3);
	P2((1<<25)-2);
	P2((1<<25)-1);
	P2(1<<25);
	P2((1<<25)+1);
	P2((1<<25)+2);

	P2((1<<26)-2);
	P2((1<<26)-1);
	P2(1<<26);
	P2((1<<26)+1);
	P2((1<<26)+2);
	return 0;
}
