bcc32の64ビット演算

今日もbcc32と格闘していました。
Regression Testで発生していた警告は全て潰しました。
http://hamigaki.sourceforge.jp/status/
内2つはどうしようもなかったのでコンパイラオプションで消しました。

W8062
#pragma option pushして、ヘッダ内でpopしなかった場合に発生。仕組み上、<boost/config/abi_prefix.hpp>で常に発生する。同様の理由でabi_suffix.hppでも発生する。
W8092
STLアルゴリズムに渡された反復子の種類を判定して、違っていたら警告する。何を基準に判定しているかよく分からない。関数の名前がSTLアルゴリズムと同じ場合、関係ない関数でも適用される。


数値上はこれで完了ですが、実はwave_file_testで64ビット浮動小数フォーマットの再生で変な音が出ていたので、その修正が残っています。
wave_file_testは、
sine_wave_source→wave_file_sinkで保存→wave_file_sourceで読み込み→pcm_sinkで再生
という手順を踏んでいます。また、浮動小数とバイト列の変換はwide_adaptorが行っています。64ビットの場合のみ発生することから、このwide_adaptorの変換に問題があると考えました。
適当な位置のサンプルをVC8の出力と比較したところ、浮動小数点数のデコード結果が違っていました。

[VC++ 8.0]
-0.00326538

[Borland 5.82]
0.00195312

符号すら違います。符号のチェックをしている箇所を見てみると、

const uint_type sign_mask = static_cast<uint_type>(1) << (bits-1);

uint_type=boost::uint64_t、bits=64なのですが、sign_maskが0になっていました。

uint_type sign_mask = 1;
sign_mask <<= (bits-1);

としたところ、符号が直りました。
数値リテラルをキャストした場合の挙動が怪しいようなので、該当箇所を同様に直しました。
単にキャストのバグというわけでもなく、

unsigned long long foo()
{
    return static_cast<unsigned long long>(1) << 63;
}

だと動くので条件は不明です。
まぁ、これでとりあえず動いたので、ひとまずBorland対応は完了です。