Project Euler 46 solution optimized using C++ meta-programming

Continued with last post.. now I'm using C++ meta-programming to solve this problem - all computation moved to compile time.

But there are limitations for G++ to compile template like recursion depth limitation and greediness... Please find comments below to get more details.

/*
	Works with following g++ commands by G++ 4.8.1
	
	g++ -g -c riddle_meta.cpp -std=c++11 -ftemplate-depth=3000
	g++ -o riddle_meta.exe riddle_meta.o -pg
 */
#include <iostream>
using namespace std;

#define MID(a, b) ((a+b)/2)
#define POW(a) (a*a)

//	Calculate Square Root using binary search
//
template <int v, int l, int r>
class SQRT 
{
   static const int mid = MID(r, l);
   static const int mid_pow = POW(mid);
   static const int nl = mid_pow >= v ? l : mid + 1;
   static const int nr = mid_pow >= v ? mid : r;
public:
   static const int value = SQRT<v, nl, nr>::value;
};

template<int v, int l = 1, int r = v>
class SQRT;

template<int v, int r>
class SQRT<v, r, r> 
{
public:
   static const int value = r;
};

//	Perfect Square Checking
//
template<int VAL>
class PSQRT
{
	static const int sqrt = SQRT<VAL>::value;
public:
	static const bool value = (sqrt * sqrt) == VAL;
};

//	Prime Number Checking
//
template<int VAL, int DIV>
class PRIME
{
public:
	static const bool value = (VAL % DIV == 0) ? false : PRIME<VAL, (DIV%2)?(DIV-2):(DIV-1)>::value;
};
template<int VAL>
class PRIME<VAL, 2>
{
public:
	static const bool value = VAL % 2 == 1;
};
template<int VAL>
class PRIME<VAL, 3>
{
public:
	static const bool value = VAL % 3 != 0;
};

//	Goldbach other Conjecture Checking
//
template<int VAL, int P>
class Goldbach
{
	static const int next_odd = (P%2)?(P-2):(P-1);
public:
	static const bool value = (!PRIME<P, SQRT<P>::value>::value) ? 
								Goldbach<VAL, next_odd>::value: // if P is not prime, we try next odd number
								(PSQRT<(VAL-P)/2>::value ? true: (Goldbach<VAL, next_odd>::value)
							  );
};

template<int VAL>
class Goldbach<VAL, 2>
{
public:
	static const bool value = PSQRT<((VAL-2)/2)>::value;
};
template<int VAL>
class Goldbach<VAL, 3>
{
public:
	static const bool value = PSQRT<((VAL-3)/2)>::value;
};
template<>
class Goldbach<3, 1>
{
public:
	static const bool value = true;
};

//	Main Loop: check odd numbers one by one, starting from VAL
//
template<int VAL>
class Driver
{ 
public:
	//	HACK: With primality checking expression enabled, G++ suffers from out of memory error.
	static const int value = ( /*(!PRIME<VAL, VAL - 2>::value) ||*/ Goldbach<VAL, VAL-2>::value) ? (Driver<VAL + 2>::value) : VAL;	 
};
//	HACK: G++ doesn't initialize template lazily, so there must be an ending criteria for upper-bound
template<>
class Driver<5801>
{ 
public:
	static const int value = 5801;
};
//	
int main() 
{   
	//	HACK: there's memory limitation when G++ compiles templates
	std::cout << Driver<5651>::value << endl;	
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章