2008-09-02

整数型のビット数

// Xの範囲で1 << Nが算術的に桁あふれするならvalue==1
template <typename X, unsigned N> struct arith_overflow {
// 1<<0は算術的に桁あふれしないと定義する。
// N>0に対しては、1<<(N-1)が算術的に桁あふれしておらず、
// かつ(1<<N)/2 == 1<<(N-1)が成立する場合、
// 1<<Nは算術的に桁あふれしないと定義する。
// なお、Nビット幅の整数Xに対して(X(1)<<N)==0は必ずしも成立しない。
enum { value = arith_overflow<X, N-1>::value
|| X(X(1) << N) / 2 != X(1) << (N - 1) };
};
template <typename X> struct arith_overflow<X, 0> {
enum { value = 0 }; // 定義より、1<<0は算術的に桁あふれしない

};


// 整数型の有効桁のビット数を得る
template <typename X, unsigned N = 0, bool flag = false> struct valid_bits_of {
// X(1)<<Nが桁あふれする場合(flag != false)の定義
enum { value = N };
};
template <typename X, unsigned N> struct valid_bits_of<X, N, false>
{
// X(1)<<Nが桁あふれしない場合(flag == false)の定義
enum {
// N+1〜N+3で桁あふれするか調べ、分からなければN+4で調べる
value = arith_overflow<X, N + 1>::value ? N + 1
: arith_overflow<X, N + 2>::value ? N + 2
: arith_overflow<X, N + 3>::value ? N + 3
: valid_bits_of<X, N + 4,
arith_overflow<X, N + 4>::value>::value
};
};


// 整数型のビット数を得る
template <typename X> struct bits_of {
enum {
value = valid_bits_of<X>::value + is_signed<X>::value
};
};


// MSBのみが立った数を得る
template <typename X> struct msb {
static X value() {
return X(1) << (bits_of<X>::value - 1);
}
};


valid_bits_ofで名前あってるかな?
なんで4つ飛びに調べてるかというと、Sun C++でテンプレートのネストが深すぎると警告がでたため。

0 件のコメント: