Разрешено ли сокращение выражений с плавающей точкой в ​​C ++?

Выражения с плавающей точкой иногда могут быть сокращены на оборудовании обработки, например использование объединенного умножения-и-сложения в качестве одной аппаратной операции.

По-видимому, используя их, это не просто деталь реализации, а регулируется спецификацией языка программирования. В частности, стандарт C89 не допускает таких сокращений, в то время как в C99 они разрешены при условии, что определен некоторый макрос. Смотрите подробности в этот так ответ.

Но как насчет C ++? Разрешены ли сокращения с плавающей точкой? Разрешено в некоторых стандартах? Разрешено универсально?

6

Решение

Контракты разрешены, но пользователю предоставляется возможность их отключить. Непонятный язык в стандартных облаках вопрос о том, даст ли их отключение желаемые результаты.

Я исследовал это в официальном стандарте C ++ 2003 и в проекте n4659 2017 года. Цитаты C ++ взяты с 2003 года, если не указано иное.

Текст «контракт» не появляется ни в одном документе. Тем не менее, пункт 5 выражений [expr], параграф 10 (тот же текст в 8 [expr] 13 2017 года) гласит:

Значения плавающих операндов и результаты плавающих выражений могут быть представлены с большей точностью и диапазоном, чем требуется типом; типы не изменяются при этом.

Я бы предпочел, чтобы в этом утверждении было четко указано, может ли эта дополнительная точность и диапазон использоваться свободно (реализация может использовать его в некоторых выражениях, включая подвыражения, но не использовать его в других), или должны были использоваться единообразно (если реализация использует дополнительную точность) , он должен использовать его в каждом выражении с плавающей запятой) или в соответствии с некоторыми другими правилами (например, он может использовать одну точность для floatдругое для double).

Если мы интерпретируем это вседозволенно, это означает, что в a*b+c, a*b может оцениваться с бесконечной точностью и дальностью, а затем сложение может оцениваться с любой точностью и дальностью, которые являются нормальными для реализации. Это математически эквивалентно сокращению, так как имеет тот же результат, что и оценка a*b+c с слитой командой умножения-сложения.

Следовательно, с этой интерпретацией реализации могут заключать в себе выражения.

17.4.1.2 [lib.headers] 3 (аналогичный текст в 20.5.1.2 [headers] 3 2017 года) гласит:

Средства библиотеки Standard C представлены в 18 дополнительных заголовках, как показано в таблице 12…

Таблица 12 включает в себя <cmath>и пункт 4 указывает, что это соответствует math.h, Технически, стандарт C ++ 2003 относится к стандарту C 1990, но у меня нет его в электронном виде, и я не знаю, где находится моя бумажная копия, поэтому я буду использовать стандарт C 2011 (но неофициальный проект N1570), который C ++ Проект 2017 года относится к.

Стандарт C определяет, в <math.h>Прагма FP_CONTRACT:

#pragma STDC FP_CONTRACT on-off-switch

где включения-выключения переключателя является on разрешить сокращение выражений или off запретить их. Он также говорит, что состояние по умолчанию для прагмы определяется реализацией.

Стандарт C ++ не определяет «средство» или «средства». Словарное определение «средства» означает «место, удобство или часть оборудования, предоставленные для определенной цели» (Новый Оксфордский Американский Словарь, Приложение Apple Dictionary версии 2.2.2 (203)). Удобство — это «желательная или полезная функция или средство здания или места». Прагма — это полезная функция, предоставляемая для конкретной цели, поэтому она представляется средством, поэтому она включена в <cmath>,

Следовательно, использование этой прагмы должно разрешать или запрещать сокращения.

  • Сокращения разрешены, когда FP_CONTRACT включен и может быть включен по умолчанию.

  • Текст 8 [expr] 13 может быть интерпретирован, чтобы эффективно разрешать сокращения, даже если FP_CONTRACT выключен, но недостаточно ясен для окончательного толкования.

3

Другие решения

Да, это разрешено.

Например, в компиляторе Visual Studio по умолчанию fp_contract включен Это говорит компилятору использовать инструкции сжатия с плавающей точкой, где это возможно. Задавать fp_contract в off сохранить отдельные инструкции с плавающей точкой.

// pragma_directive_fp_contract.cpp
// on x86 and x64 compile with: /O2 /fp:fast /arch:AVX2
// other platforms compile with: /O2

#include <stdio.h>

// remove the following line to enable FP contractions
#pragma fp_contract (off)

int main() {
double z, b, t;

for (int i = 0; i < 10; i++) {
b = i * 5.5;
t = i * 56.025;

z = t * i + b;
printf("out = %.15e\n", z);
}
}

Подробная информация о Укажите поведение с плавающей точкой.

Использование коллекции компиляторов GNU (GCC):

Состояние по умолчанию для FP_CONTRACT прагма (С99 и С11 7.12.2).
Эта прагма не реализована. Выражения в настоящее время только сокращены, если —ffp-contract=fast, -funsafe-math-optimizations или же -ffast-math используются.

1

По вопросам рекламы [email protected]