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ß


  • Mod

    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ß


  • Mod

    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


Anmelden zum Antworten