Wenn Sie nach einem Wert suchen, der sich durch arithmetische Operationen ausbreiten würde, steht NaN
immer noch mit der Option -ffast-math
zur Verfügung. Das Problem liegt woanders. Mit -ffast-math
können einige Operationen aufgrund der Optimierung aus der Berechnung entfernt werden, und dann gibt es keine Möglichkeit zu garantieren NaN
oder jeder andere Wert würde propagiert werden.
Zum Beispiel die folgenden, mit -ffast-math
gesetzt, wird dazu führen, hart 0.0
in n
zu schreiben und es gibt keinen besonderen Wert für n
die von ihm schützen würde.
float n = NAN;
n *= 0.0;
Eine Sache, die Sie tun können, ist -fno-finite-math-only -ftrapping-math
mit -ffast-math
zu verwenden, wie Shafik Yaghmour sagte. Und der andere ist, wenn es nur wenige Orte gibt, an denen Sie einen schlechten Wert erwarten, können Sie selbst nachprüfen, indem Sie Tests genau in diese Punkte setzen.
Die letzte Option, die ich denken kann - wenn Sie wirklich dringend Optimierung benötigen - ist manuell injizieren NaN
(und vielleicht inf
) Werte in die Berechnung und prüfen, wie lange es propagiert wird. Dann an den Orten, wo die Ausbreitung stoppt, Test für NaN
(inf
) Auftreten. - Dies ist eine unsichere Methode, da ich mich nicht hundertprozentig sicher bin, kann -ffast-math
bedingten Fluss von Operationen beinhalten. Wenn es möglich ist, besteht eine erhebliche Chance, dass diese Lösung ungültig ist. Es ist also riskant und erfordert, wenn es ausgewählt wird, sehr schwere Tests, die alle Zweige der Berechnung abdecken.
Normalerweise wäre ich eher gegen die letzte Lösung, aber tatsächlich gibt es eine Chance, NaN
(inf
) Werte werden über die gesamte Berechnung oder fast ganz verbreitet, so dass es die Leistung geben kann, die Sie suchen. Sie möchten vielleicht das Risiko eingehen.
Überprüfung auf NaN
mit -ffast-math
Sie tun können, als Shafik Yaghmour sagte mit
inline int isnan(float f)
{
union { float f; uint32_t x; } u = { f };
return (u.x << 1) > 0xff000000u;
}
und für double
mit
inline int isnan(double d)
{
union { double d; uint64_t x; } u = { d };
return (u.x << 1) > 0xff70000000000000ull;
}
Überprüfung auf inf
wäre
inline int isinf(float f)
{
union { float f; uint32_t x; } u = { f };
return (u.x << 1) == 0xff000000u;
}
inline int isinf(double d)
{
union { double d; uint64_t x; } u = { d };
return (u.x << 1) == 0xff70000000000000ull;
}
Sie können auch isnan
und isinf
zusammenführen.
Dieser Thread kann hilfreich sein [Mingw32 std :: isnan mit -ffst-math] (http://stackoverflow.com/questions/7263404/mingw32-stdisnan-with-ffast-math) –
@ShafikYaghhmour Danke, dieser Thread ist hilfreich. – stgtscc
Es gibt auch die Option '-fno-endliche-nur-Mathematik -ftrapping-math' zu verwenden http://lua-users.org/lists/lua-l/2009-04/msg00091.html –