Jeśli szukasz wartości, która byłaby propagowana przez operacje arytmetyczne, NaN
jest nadal dostępna z opcją -ffast-math
. Problem leży gdzie indziej. Dzięki -ffast-math
niektóre operacje mogą zostać usunięte z obliczeń z powodu optymalizacji, a następnie nie ma możliwości zagwarantowania, że będą one propagowane.
Na przykład, następujący, z -ffast-math
zestawu spowoduje trudne do pisania 0.0
n
i nie ma szczególny stosunek do n
które chronią przed nim.
float n = NAN;
n *= 0.0;
Jedną rzeczą, jaką można zrobić, jest użycie -fno-finite-math-only -ftrapping-math
z -ffast-math
jak Shafik Yaghmour powiedział. A drugi to, jeśli jest tylko kilka miejsc, w których spodziewasz się złej wartości, możesz sam to sprawdzić, umieszczając testy dokładnie w tych punktach.
Ostatnią opcją, którą mogę pomyśleć - jeśli naprawdę potrzebujesz optymalizacji - jest ręczne wprowadzenie wartości NaN
(i może inf
) do obliczeń i sprawdzenie, jak długo są one propagowane. Następnie w miejscach, w których propagacja się zatrzymuje, należy przetestować wystąpienie. - Jest to niebezpieczna metoda, ponieważ nie jestem w stu procentach pewna, czy mogę wymagać warunkowego przepływu operacji. Jeśli tak, istnieje znaczna szansa, to rozwiązanie będzie nieważne. Jest to ryzykowne i jeśli zostanie wybrane, wymaga bardzo ciężkich testów obejmujących wszystkie gałęzie obliczeń.
Normalnie byłbym raczej przeciw ostatniego rozwiązania, ale w rzeczywistości jest szansa, NaN
(inf
) wartości będą propagowane chociaż cały lub prawie cały obliczeń, więc może dać wydajność Szukasz dla. Więc możesz zaryzykować.
Sprawdzanie NaN
z -ffast-math
można zrobić, jak Shafik Yaghmour powiedział z
inline int isnan(float f)
{
union { float f; uint32_t x; } u = { f };
return (u.x << 1) > 0xff000000u;
}
i double
z
inline int isnan(double d)
{
union { double d; uint64_t x; } u = { d };
return (u.x << 1) > 0xff70000000000000ull;
}
Sprawdzanie inf
byłoby
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;
}
Można również połączyć isnan
i isinf
.
Ten wątek może być pomocny [Mingw32 std :: isnan with -ffast-math] (http://stackoverflow.com/questions/7263404/mingw32-stdisnan-with-ffast-math) –
@ShafikYaghmour Dzięki, że wątek jest pomocny. – stgtscc
Istnieje również opcja użycia '-fno-skończonej-matematyki-tylko-łatającej-matematyki' http://lua-users.org/lists/lua-l/2009-04/msg00091.html –