プランクの法則に従って、次のように黒体放射の実装に取り組んできました。
double BlackBody(double T, double wavelength) {
wavelength /= 1e9; // pre-scale wavelength to meters
static const double h = 6.62606957e-34; // Planck constant
static const double c = 299792458.0; // speed of light in vacuum
static const double k = 1.3806488e-23; // Boltzmann constant
double exparg = h*c / (k*wavelength*T);
double exppart = std::exp(exparg) - 1.0;
double constpart = (2.0*h*c*c);
double powpart = pow(wavelength, -5.0);
double v = constpart * powpart / exppart;
return v;
}
float[max-min+1] 配列があり、static const int max=780、static const int min = 380 です。単に配列を反復処理し、BlackBody が波長に対して与えるものを入力します (波長 = array-インデックス + 分)。IntensitySpectrum::BlackBody はこの反復を実行しますが、min と max は両方とも静的メンバー変数であり、配列も IntensitySpectrum 内にあります。
IntensitySpectrum spectrum;
Vec3 rgb = spectrum.ToRGB();
rgb /= std::max(rgb.x, std::max(rgb.y, rgb.z));
for (int xc = 0; xc < grapher.GetWidth(); xc++) {
if (xc % 10 == 0) {
spectrum.BlackBody(200.f + xc * 200.f);
spectrum.Scale(1.0f / 1e+14f);
rgb = spectrum.ToRGB();
rgb /= std::max(rgb.x, std::max(rgb.y, rgb.z));
}
for (int yc = 20; yc < 40; yc++) {
grapher(xc, yc) = grapher.FloatToUint(rgb.x, rgb.y, rgb.z);
}
}
問題は、線スペクトル.BlackBody() が配列の 0 番目の要素を NaN に設定し、0 番目のみを設定することです。また、最初の反復では発生しませんが、xc>=10 である以降の反復ではすべて発生します。
VS デバッガーからのテキスト: Spectrum = {intensity=0x009bec50 {-1.#IND0000, 520718784., 537559104., 554832896., 572547904., 590712128., 609333504., ...} }
エラーを追跡したところ、::BlackBody() 関数の exppart が NaN になり、引数が 2.0 に近いにもかかわらず、基本的に exp() は NaN を返すため、明らかにオーバーフローしません。ただし、配列インデックス 0 のみです。残りの 400 インデックスに対して魔法のように機能し始めます。
メモリオーバーランがそのようなことを引き起こす可能性があることは知っています。そのため、メモリ処理を再確認しました。私は別の自作ライブラリから Vec3 をリンクしていますが、これははるかに大きく、エラーが含まれている可能性がありますが、Vec3 から使用するものはメモリとは何の関係もありません。
何時間も経った後、私は完全に無知です。他に何がこれを引き起こす可能性がありますか? オプティマイザまたは WINAPI が私を騙していませんか? (ええと、はい、プログラムは WINAPI でウィンドウを作成し、WM_PAINT で私のコードを呼び出すほぼ空の WndProc を使用します。)
事前にご協力いただきありがとうございます。
わかりづらくてすみません。これはレイアウトです:
// member
class IntensitySpectrum {
public:
void BlackBody(float temperature) {
// ...
this->intensity[i] = ::BlackBody(temperature, wavelength(i));
// ...
}
private:
static const int min = 380;
static const int max = 780;
float intensity[max-min+1];
}
// global
double BlackBody(double T, double wavelength);