Std:: isfinite на MSVC

Стандарты С++ 11 и C11 определяют std:: isfinite функция. Visual Studio 2012, похоже, не представляет ее как часть cmath или math.h, но имеет amp_math.h, который кажется, предоставляет эту функцию.

Является ли isfinite взаимозаменяемым с std::isfinite? документация не говорит о поведении при вызове с помощью NAN и у меня нет VS-компилятора, чтобы проверить это.

Ответ 1

Как уже указывал Мариус, isfinite из amp_math.h должен использоваться в С++ AMP, который является расширением MS для параллельных вычислений на многоядерных архитектурах, подобных CUDA или OpenCL. И поскольку эта функция может использоваться только в действительных ограниченных функциях AMP (обычно это ядра GPU), это не будет для вас общего использования.

К сожалению, VS 2012 не поддерживает функции управления математикой и плавающей точкой С++ 11. Но как только вы узнаете, что находитесь на VC и реализуете для него специальный код, вы можете просто использовать _finite (или, скорее, !_finite)) из <float.h>, который является MS-secific функцией, поддерживаемой с по крайней мере VS 2003. Но имейте в виду, что _finite принимает только double и таким образом преобразует любые аргументы не double (хотя VC, похоже, не имеет надлежащего long double в любом случае) со всеми его последствиями (в то время как INF и тихий NaN должен быть преобразован без проблем, я не уверен, что захват в сигнале NaN в преобразовании также был бы результатом прямого вызова std::finite).

Стандартная библиотека VC имеет другие такие функции, чтобы разместить их в отсутствие поддержки С++ 11/C99 (например, _isnan и т.п.). (Почему они отказываются просто удалять это подчеркивание перед этими функциями и класть простую обертку <cfenv> вокруг _controlfp и, таким образом, немного приближаться к завершению поддержки С++ 11, это совсем другой вопрос.)

EDIT: Кроме этого, может работать и прямой подход для проверки INF и NaN:

template<typename T> bool isfinite(T arg)
{
    return arg == arg && 
           arg != std::numeric_limits<T>::infinity() &&
           arg != -std::numeric_limits<T>::infinity();
}

Но, конечно, с теми же последствиями, вероятно, для захвата сигналов для сигнализации NaN (хотя я должен признать, что я не настолько хорошо разбираюсь в тонкостях сигнализации NaN и исключениях с плавающей запятой вообще).

Ответ 2

isfinite from amp_math.h можно вызывать только из функций, отмеченных restrict(amp), что не делает их взаимозаменяемыми, даже если поведение было одинаковым.