NaN to Zero
-
Hallo,
kennt jemand eine Möglichkeit, einem x86-kompatiblen Prozessor 'mitzuteilen' (Register-Flag), dass alle NaN's die durch DivByZero entstanden sind, zu 0 geändert werden, so wie es z.B. auf Grafikkarten gemacht wird.
FTZ und DTZ funktioniert leider nicht....
Ich habe es z.B. mit:
...
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
...
versucht; ohne erfolg.Kompiler ist MSVC++ 7.1 und/oder gcc3.3.3; CPU: PentiumM, AthlonXP oder Pentium4.
Stundelanges Googeln hat leider nichts geholfen...
Gruß
-
bei der division durch 0 entstehen unendlichkeiten, keine NaNs (es sei denn, der dividend ist auch 0).
wesentlich ist, dass man mit unendlichkeiten im gegensatz zu NaNs vernünftig (bis auf ein paar ausnahmen) weiterechnenrechnen kann. flush to zero ist teil von SSE und beeinflusst nur operationen, die denormals liefern würden.im zweifelsfalle wird es notwendig sein, die divide_by_zero exception zu demaskieren und den exception handler anzupassen, bzw. das MXCSR register auszuwerten.
-
Stimmt, der Thread sollte besser IND to Zero heissen...
Ich wollte aber gerade auf die Behandlung von Exceptions verzichten; dann werde ich eben DivByZero durch geeignete Inputdaten ausschliessen.
Oder gibt es eine Möglichkeit mit der ich explizit
aus
{-1,#IND, -1,#IND, -1,#IND, -1,#IND}
ein
{0, 0, 0, 0}
machen kann.Gruß
-
es bietet sich an, einen ordered vergleich zu versuchen - da unendlichlichkeiten aber vermutlich nicht als NaNs behandelt werden, müsste man ein bisschen tricksen ( wenn man den operanden von sich selbst abzieht, müsste ein NaN herauskommen, wenn er vorher unendlich war, (habs nicht getestet, es gibt sicher noch andere möglichkeiten) )
etwa so: (alle not finites in xmm0 (ps) auf +0 setzen)
movaps xmm1, xmm0 subps xmm1, xmm0 cmpps xmm1, xmm0, 7 ; ordered andps xmm0, xmm1
das ist nur ein gedanke, getestet hab ich das nicht.
-
Ok, durch den ordered-Vergleich werden alle Infinites auf 0 gesetzt; das ist schon mal gut.
Aber der Vergleich auf ordered setzt dann die nicht-infinites auf quiteNaN.
Es ist natürlich _gut_ möglich, dass ich hier etwas falsch verstanden habe...
Und ich sollte auch dazu sagen, dass ich nicht direkt Assembler benutze, sondern Compiler-Intrinsics für SSE; aber die Befehle sehen genauso aus, wie die Assembler Befehle (subps == _mm_sub_ps).Ein Beispiel(pseudocode):
a={1, 0, 0, 0}
b={1, 1, 1, 1}c=divps(b,a)={1, 1,#INF, 1,#INF, 1,#INF}
d=subps(c,c)={0, -1,#IND, -1,#IND, -1,#IND}e=comp_ordered(d,c)={-1,#QNAN, 0, 0, 0}
Das Ergebniss sollte insgesammt {1,0,0,0} sein.
Aber vielen Dank schon mal für die bisherige Hilfe.
Gruß
Michael
-
Hmm.....
Ich habe wohl das andps vergessen; damit funktioniert es!!
Hätte ich vorher hier nachgefragt, wäre mir tatsächlich _einige Stunden_ Suchen erspart geblieben. Wenigstens habe ich dabei was gelernt.
Allerdemütigsten Dank.
Michael