By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,502 Members | 1,204 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,502 IT Pros & Developers. It's quick & easy.

template computed alternative to numeric_limits<T>

P: n/a

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";
*/
}
Jul 22 '05 #1
Share this Question
Share on Google+
5 Replies


P: n/a

"Gianni Mariani" <gi*******@mariani.ws> wrote in message news:O9********************@speakeasy.net...

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

[snip]

I don't know anything about templates (yet) but this DMC
(Digital Mars) compiler complains that static members should
initialised outside of the structures. I may not be the smartest
of C++ programers but I seem to remember that this is also
the way with 'ordinary' classes ;-)

Alan

Jul 22 '05 #2

P: n/a
Alan wrote:
"Gianni Mariani" <gi*******@mariani.ws> wrote in message news:O9********************@speakeasy.net...
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


[snip]

I don't know anything about templates (yet) but this DMC
(Digital Mars) compiler complains that static members should
initialised outside of the structures. I may not be the smartest
of C++ programers but I seem to remember that this is also
the way with 'ordinary' classes ;-)


OK - here is a version that might work for you:
#include <iostream>
#include <limits>
template <typename T, int N>
struct pow_m
{
static const T value;

static const T valuep1;
};

template <typename T, int N>
const T pow_m<T,N>::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 );

template <typename T, int N>
const T pow_m<T,N>::valuep1 = ( value * 2 );

template <typename T>
struct pow_m<T, 0>
{
static const T value;
static const T valuep1;
};

template <typename T>
const T pow_m<T, 0>::value = static_cast<T>( 1 );
template <typename T>
const T pow_m<T, 0>::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;

static const int max_exponent;
};
template <typename T, int N>
const T max_f<T,N,true>::max_value = pow_m<T,N-1>::value;

template <typename T, int N>
const int max_f<T,N,true>::max_exponent = N-1;

template <typename T, int N>
struct eval_f
{
static const bool at_limit = ( pow_m<T, N+1>::value == pow_m<T,
N+1>::valuep1 );
};

template <typename T, int N, bool v>
struct max_f : max_f<T, N+1, eval_f<T,N>::at_limit >
{
};

template <typename T, int N>
struct pow_nm
{
static const T value;

static const T valuep1;

};

template <typename T, int N>
const T pow_nm<T,N>::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 );

template <typename T, int N>
const T pow_nm<T,N>::valuep1 = ( value * 2 );

template <typename T>
struct pow_nm<T, 0>
{
static const T value;
static const T valuep1;
};
template <typename T>
const T pow_nm<T, 0>::value = static_cast<T>( -1 );
template <typename T>
const T pow_nm<T, 0>::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;

static const int max_exponent;
};

template <typename T, int N>
const T max_nm<T,N,true>::max_value = pow_nm<T,N-1>::value;

template <typename T, int N>
const int max_nm<T,N,true>::max_exponent = N-1;

template <typename T, int N>
struct eval_nm
{
static const bool at_limit = ( pow_nm<T, N+1>::value == pow_nm<T,
N+1>::valuep1 );
};

template <typename T, int N, bool v>
struct max_nm : max_nm<T, N+1, eval_nm<T,N>::at_limit >
{
};

template<typename T>
struct max_limit
{
static const int max_exponent;
static const T max_value;

static const int neg_max_exponent;
static const T neg_max_value;

};

template<typename T>
const int max_limit<T>::max_exponent = max_f<T,0,false>::max_exponent;
template<typename T>
const T max_limit<T>::max_value = max_f<T,0,false>::max_value;

template<typename T>
const int max_limit<T>::neg_max_exponent =
max_nm<T,0,false>::max_exponent;
template<typename T>
const T max_limit<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";
*/
}
Jul 22 '05 #3

P: n/a

"Gianni Mariani" <gi*******@mariani.ws> wrote in message news:J7********************@speakeasy.net...
Alan wrote:
"Gianni Mariani" <gi*******@mariani.ws> wrote in message news:O9********************@speakeasy.net...
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
[snip]

I don't know anything about templates (yet) but this DMC
(Digital Mars) compiler complains that static members should
initialised outside of the structures. I may not be the smartest
of C++ programers but I seem to remember that this is also
the way with 'ordinary' classes ;-)


OK - here is a version that might work for you:
#include <iostream>
#include <limits>
template <typename T, int N>
struct pow_m
{
static const T value;

static const T valuep1;
};

template <typename T, int N>
const T pow_m<T,N>::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 );

template <typename T, int N>
const T pow_m<T,N>::valuep1 = ( value * 2 );

template <typename T>
struct pow_m<T, 0>
{
static const T value;
static const T valuep1;
};

template <typename T>
const T pow_m<T, 0>::value = static_cast<T>( 1 );
template <typename T>
const T pow_m<T, 0>::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;

static const int max_exponent;
};
template <typename T, int N>
const T max_f<T,N,true>::max_value = pow_m<T,N-1>::value;

template <typename T, int N>
const int max_f<T,N,true>::max_exponent = N-1;

template <typename T, int N>
struct eval_f
{
static const bool at_limit = ( pow_m<T, N+1>::value == pow_m<T,
N+1>::valuep1 );
};

template <typename T, int N, bool v>
struct max_f : max_f<T, N+1, eval_f<T,N>::at_limit >
{
};

template <typename T, int N>
struct pow_nm
{
static const T value;

static const T valuep1;

};

template <typename T, int N>
const T pow_nm<T,N>::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 );

template <typename T, int N>
const T pow_nm<T,N>::valuep1 = ( value * 2 );

template <typename T>
struct pow_nm<T, 0>
{
static const T value;
static const T valuep1;
};
template <typename T>
const T pow_nm<T, 0>::value = static_cast<T>( -1 );
template <typename T>
const T pow_nm<T, 0>::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;

static const int max_exponent;
};

template <typename T, int N>
const T max_nm<T,N,true>::max_value = pow_nm<T,N-1>::value;

template <typename T, int N>
const int max_nm<T,N,true>::max_exponent = N-1;

template <typename T, int N>
struct eval_nm
{
static const bool at_limit = ( pow_nm<T, N+1>::value == pow_nm<T,
N+1>::valuep1 );
};

template <typename T, int N, bool v>
struct max_nm : max_nm<T, N+1, eval_nm<T,N>::at_limit >
{
};

template<typename T>
struct max_limit
{
static const int max_exponent;
static const T max_value;

static const int neg_max_exponent;
static const T neg_max_value;

};

template<typename T>
const int max_limit<T>::max_exponent = max_f<T,0,false>::max_exponent;
template<typename T>
const T max_limit<T>::max_value = max_f<T,0,false>::max_value;

template<typename T>
const int max_limit<T>::neg_max_exponent =
max_nm<T,0,false>::max_exponent;
template<typename T>
const T max_limit<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";

}


Complains:
Line 55: in-class initializer for const at_limit not constant
Line 59: constant initializer expected

Alan
Jul 22 '05 #4

P: n/a
Alan wrote:
Complains:
Line 55: in-class initializer for const at_limit not constant
Line 59: constant initializer expected


Now the question is, it that legal ?

GCC compiles it just fine.
Jul 22 '05 #5

P: n/a

"Gianni Mariani" <gi*******@mariani.ws> wrote in message news:7b********************@speakeasy.net...
Alan wrote:
Complains:
Line 55: in-class initializer for const at_limit not constant
Line 59: constant initializer expected
Now the question is, it that legal ?

GCC compiles it just fine.


I'm not the person to answer your question.

But does it still "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 !" ?
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 !



Jul 22 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.