Сдвиг 1 и умножение против прямого сдвига

#c #arm #integer-arithmetic #cmsis

Вопрос:

Я наткнулся на код, подобный этому, в библиотеке ARM CMSIS-NN:

 int32_t val, shift;

// code that initializes val and shift

int32_t result = val * (1 << shift);
 

которая направлена на умножение val на некоторую степень двух значений x , shift являющуюся показателем степени, т. Е. x=pow(2,shift) . Почему они просто не меняются? Вот так

 int32_t result = val << shift;
 

Есть ли что-то особенное, чего мне не хватает? Может ли компилятор каким-то особым образом оптимизировать предыдущую операцию?

ПРАВКА: Что меня смущает, так это то, что они используют «простые сдвиги» по всему коду. Кроме того, код должен быть сильно оптимизирован. Но я думаю, что современные компиляторы сами поймут, что сдвиг-это правильный путь (вместо умножения)?

Комментарии:

1. Что это за тип q31_t ? Вы уверены, что он поддерживает << оператора? Например, типы с плавающей запятой этого не делают.

2. Сдвиг ограничен количеством битов в машинном слове. Pow () — это не так. [это ограничение, вероятно, было вызвано ограничением в инструкциях x86, где сдвиг рассматривался как (сдвиг 2) ]

3. @Nate Элдридж q31_t -это тип данных с фиксированной точкой (см. Здесь en.wikipedia.org/wiki/Q_(number_format) ). В CMSIS-NN это просто typedef для int32_t-

4. @wildplasser все переменные (включая результат) являются 32-битными. Так что здесь это не должно иметь значения, верно?

5. Кстати: вы всегда должны выполнять такие сдвиги в самом большом доступном типе данных без знака: (1ull <<shift) Да, это может иметь значение, вы можете попытаться сдвинуться на 33, и результат будет неопределенным.

Ответ №1:

Он всегда правильно подписывается и заставляет использовать соответствующие инструкции FPU и работает с любыми типами данных.

Комментарии:

1. Я должен был упомянуть, что все это арифметика с фиксированной точкой. Таким образом, здесь задействованы только целые числа (если быть точным, int32_t). Но сохранение знака может быть причиной. Таким образом, начальный бит не будет смещен, верно? Спасибо, что указали на это. Я должен подумать об этом еще немного.

2. @fabian не только исправил

3. что вы имеете в виду под этим?

4. они хотели быть агностиками типа

5. Но зачем им быть агностиками типов, если все типы привязаны к int32_t?