Я размышляю над арифметической библиотекой с фиксированной запятой, и для того, чтобы решить, сколько оптимизации следует выполнить самой библиотеке (с помощью шаблонов выражений), я начал задавать вопрос, сколько уже будет сделано оптимизатором. Возьмите следующий пример, например:
//This is a totally useless function to exemplify my point
void Compare(FixedPoint a, FixedPoint b) {
if(a/b>10) {
... do stuff
}
}
Теперь, в этой функции, типичная реализация FixedPoint
класс вызовет
if( ( (a_<<N) / b_) > (10 <<N) ) {
... do stuff
}
куда N
количество дробных бит Это выражение могло математически быть преобразованным в:
(a_ > 10*b_)
даже если это преобразование не привести к тому же поведению, если учесть целочисленное переполнение. Пользователи моей библиотеки, вероятно, будут заботиться о математической эквивалентности и предпочли бы иметь уменьшенную версию (возможно, предоставленную через шаблоны выражений).
Теперь возникает вопрос: осмелится ли оптимизатор выполнить саму оптимизацию, даже если поведение не является строго таким же? Должен ли я беспокоиться о такой оптимизации? Обратите внимание, что такие оптимизации не являются тривиальными. В действительности вам редко приходится делать какие-либо сдвиги битов, когда вы используете арифметику с фиксированной запятой, если вы действительно делаете эти оптимизации.
Это будет зависеть от того, a_
а также b_
типы подписаны или не подписаны.
В C и C ++ переполнение со знаком является технически неопределенным поведением, в то время как переполнение без знака выполняется с использованием арифметики с двумя дополнениями.
Тем не менее, некоторые компиляторы отказываются оптимизировать этот код, потому что многие программы полагаются на поведение с двумя дополнениями подписанного переполнения.
Хорошие современные компиляторы будут иметь возможность включить / отключить это конкретное предположение: целые числа со знаком не будут переполнены. Какой вариант по умолчанию будет зависеть от компилятора.
Например, с помощью GCC см. Параметры -fstrict-overflow/-fno-strict-overflow
и соответствующее предупреждение -Wstrict-overflow
,
Других решений пока нет …