昔,MLS MPM Fluidの最適化をしていた時に(パーティクルの数を増やすだけの目的),一部, float型の値をスレッドセーフに加算する必要があったのですが,提供されている関数(InterlockedAdd)がintにしか対応していなくて,困っていたため, edoさんの記事も参考にしながら,実装しました.
HLSLのfrac関数や,どの数値で割るかによって誤差が発生するので,簡易的なテストもしています.
実際のコードは以下のような感じです.
//
//
//
// example:
// v = 10.25609895412
// (int)10.25609890412 * 10000 -> 102560.989541 -> 102560
// (int)0.989041 * 10000 -> 9895.41 -> 9895
//
// 102560 / 10000 -> 10.256
// 9895 / 100000000 -> 0.00009895
// 10.256 + 0.00009895 -> 10.25609895
//
// BTW max value of int: 2147483647
//
//#define F2I_DIGIT 256
//#define F2I_DIGIT 512
#define F2I_DIGIT 1024 //Must be 2 ^ x
#define F2I_DIGIT_2SQRT F2I_DIGIT * F2I_DIGIT
int2 ConvertFloatToInt2(float v)
{
float f1 = v * F2I_DIGIT;
int i1 = (int)f1;
float f2 = (f1 - i1) * F2I_DIGIT;
//float f2 = frac(f1) * F2I_DIGIT; //This does not work correctly!!
int i2 = (int)f2;
return int2( i1, i2 );
}
float ConvertInt2ToFloat(int2 v)
{
float f1 = ((float)v.x) / F2I_DIGIT;
float f2 = ((float)v.y) / (F2I_DIGIT * F2I_DIGIT);
return f1 + f2;
}