G
Gianni Mariani
The spirit of this arguably pointless exercise, is that the
numeric_limits<T> class could be replaced with a totally generic
template of compile-time, template computed constants.
The problem is that it takes a *long* time to compile and the "long
double" version instantiates so many classes that gcc runs out of memory
on my 1 gig machine !
So the question is - is there a simple way to reduce the number of
template instantiations from O(N) to O(logN) ?
#include <iostream>
#include <limits>
template <typename T, int N>
struct pow_m
{
static const T value =
( ( pow_m<T, N-1>::value * 2 ) + static_cast<T>( 1 ) ) -
static_cast<T>( 1 )
== ( pow_m<T, N-1>::value * 2 )
? ( pow_m<T, N-1>::value * 2 ) + static_cast<T>( 1 )
: ( pow_m<T, N-1>::value * 2 );
static const T valuep1 = ( value * 2 );
};
template <typename T>
struct pow_m<T, 0>
{
static const T value = static_cast<T>( 1 );
static const T valuep1 = ( value * 2 ) + static_cast<T>( 1 );
};
template <typename T, int N, bool v> struct max_f;
template <typename T, int N>
struct max_f<T,N,true>
{
static const T max_value = pow_m<T,N-1>::value;
static const int max_exponent = N-1;
};
template <typename T, int N, bool v>
struct max_f : max_f<T, N+1, pow_m<T, N+1>::value == pow_m<T,
N+1>::valuep1 >
{
};
template <typename T, int N>
struct pow_nm
{
static const T value =
( ( pow_nm<T, N-1>::value * 2 ) + static_cast<T>( -1 ) ) -
static_cast<T>( -1 )
== ( pow_nm<T, N-1>::value * 2 )
? ( pow_nm<T, N-1>::value * 2 ) + static_cast<T>( -1 )
: ( pow_nm<T, N-1>::value * 2 );
static const T valuep1 = ( value * 2 );
};
template <typename T>
struct pow_nm<T, 0>
{
static const T value = static_cast<T>( -1 );
static const T valuep1 = ( value * 2 ) + static_cast<T>( -1 );
};
template <typename T, int N, bool v> struct max_nm;
template <typename T, int N>
struct max_nm<T,N,true>
{
static const T max_value = pow_nm<T,N-1>::value;
static const int max_exponent = N-1;
};
template <typename T, int N, bool v>
struct max_nm : max_nm<T, N+1, pow_nm<T, N+1>::value == pow_nm<T,
N+1>::valuep1 >
{
};
template<typename T>
struct max_limit
{
static const int max_exponent = max_f<T,0,false>::max_exponent;
static const T max_value = max_f<T,0,false>::max_value;
static const int neg_max_exponent = max_nm<T,0,false>::max_exponent;
static const T neg_max_value = max_nm<T,0,false>::max_value;
};
int main()
{
std::cout << "Positive maximum\n";
std::cout << "Float\n";
std::cout << max_limit< float >::max_exponent << "\n";
std::cout << max_limit< float >::max_value << "\n";
std::cout << "Double\n";
std::cout << max_limit< double >::max_exponent << "\n";
std::cout << max_limit< double >::max_value << "\n";
std::cout << "limits max says " <<
std::numeric_limits<double>::max() << "\n";
std::cout << "limits/template diff " << (
std::numeric_limits<double>::max() - max_limit< double >::max_value ) <<
"\n";
std::cout << "Negative maximum\n";
std::cout << "Float\n";
std::cout << max_limit< float >::neg_max_exponent << "\n";
std::cout << max_limit< float >::neg_max_value << "\n";
std::cout << "Double\n";
std::cout << max_limit< double >::neg_max_exponent << "\n";
std::cout << max_limit< double >::neg_max_value << "\n";
/*
std::cout << "Long Double\n";
std::cout << max_limit< long double >::max_exponent << "\n";
std::cout << max_limit< long double >::max_value << "\n";
*/
}
numeric_limits<T> class could be replaced with a totally generic
template of compile-time, template computed constants.
The problem is that it takes a *long* time to compile and the "long
double" version instantiates so many classes that gcc runs out of memory
on my 1 gig machine !
So the question is - is there a simple way to reduce the number of
template instantiations from O(N) to O(logN) ?
#include <iostream>
#include <limits>
template <typename T, int N>
struct pow_m
{
static const T value =
( ( pow_m<T, N-1>::value * 2 ) + static_cast<T>( 1 ) ) -
static_cast<T>( 1 )
== ( pow_m<T, N-1>::value * 2 )
? ( pow_m<T, N-1>::value * 2 ) + static_cast<T>( 1 )
: ( pow_m<T, N-1>::value * 2 );
static const T valuep1 = ( value * 2 );
};
template <typename T>
struct pow_m<T, 0>
{
static const T value = static_cast<T>( 1 );
static const T valuep1 = ( value * 2 ) + static_cast<T>( 1 );
};
template <typename T, int N, bool v> struct max_f;
template <typename T, int N>
struct max_f<T,N,true>
{
static const T max_value = pow_m<T,N-1>::value;
static const int max_exponent = N-1;
};
template <typename T, int N, bool v>
struct max_f : max_f<T, N+1, pow_m<T, N+1>::value == pow_m<T,
N+1>::valuep1 >
{
};
template <typename T, int N>
struct pow_nm
{
static const T value =
( ( pow_nm<T, N-1>::value * 2 ) + static_cast<T>( -1 ) ) -
static_cast<T>( -1 )
== ( pow_nm<T, N-1>::value * 2 )
? ( pow_nm<T, N-1>::value * 2 ) + static_cast<T>( -1 )
: ( pow_nm<T, N-1>::value * 2 );
static const T valuep1 = ( value * 2 );
};
template <typename T>
struct pow_nm<T, 0>
{
static const T value = static_cast<T>( -1 );
static const T valuep1 = ( value * 2 ) + static_cast<T>( -1 );
};
template <typename T, int N, bool v> struct max_nm;
template <typename T, int N>
struct max_nm<T,N,true>
{
static const T max_value = pow_nm<T,N-1>::value;
static const int max_exponent = N-1;
};
template <typename T, int N, bool v>
struct max_nm : max_nm<T, N+1, pow_nm<T, N+1>::value == pow_nm<T,
N+1>::valuep1 >
{
};
template<typename T>
struct max_limit
{
static const int max_exponent = max_f<T,0,false>::max_exponent;
static const T max_value = max_f<T,0,false>::max_value;
static const int neg_max_exponent = max_nm<T,0,false>::max_exponent;
static const T neg_max_value = max_nm<T,0,false>::max_value;
};
int main()
{
std::cout << "Positive maximum\n";
std::cout << "Float\n";
std::cout << max_limit< float >::max_exponent << "\n";
std::cout << max_limit< float >::max_value << "\n";
std::cout << "Double\n";
std::cout << max_limit< double >::max_exponent << "\n";
std::cout << max_limit< double >::max_value << "\n";
std::cout << "limits max says " <<
std::numeric_limits<double>::max() << "\n";
std::cout << "limits/template diff " << (
std::numeric_limits<double>::max() - max_limit< double >::max_value ) <<
"\n";
std::cout << "Negative maximum\n";
std::cout << "Float\n";
std::cout << max_limit< float >::neg_max_exponent << "\n";
std::cout << max_limit< float >::neg_max_value << "\n";
std::cout << "Double\n";
std::cout << max_limit< double >::neg_max_exponent << "\n";
std::cout << max_limit< double >::neg_max_value << "\n";
/*
std::cout << "Long Double\n";
std::cout << max_limit< long double >::max_exponent << "\n";
std::cout << max_limit< long double >::max_value << "\n";
*/
}