Если вы тщательно профилировали свой код и обнаружили, что оператор по модулю является основной ценой во внутреннем цикле, тогда вам может помочь оптимизация.Возможно, вы уже знакомы с приемом определения знака целого числа с использованием арифметических сдвигов влево (для 32-битных значений):
sign = ( x >> 31 ) | 1;
Это расширяет знаковый бит по слову, поэтому отрицательные значения дают -1и положительные значения 0. Затем бит 0 устанавливается так, что положительные значения приводят к 1.
Если мы увеличиваем значения только на величину, меньшую по модулю, то этот же трюк можно использовать для переносарезультат:
val += inc;
val -= modulo & ( static_cast< int32_t >( ( ( modulo - 1 ) - val ) ) >> 31 );
В качестве альтернативы, если вы уменьшаете значения на значения меньше, чем по модулю, соответствующий код:
int32_t signedVal = static_cast< int32_t >( val - dec );
val = signedVal + ( modulo & ( signedVal >> 31 ) );
Я добавил операторы static_cast, потому что передавалuint32_t, но вы, возможно, не найдете их необходимыми.
Это сильно помогает в отличие от простого оператора%?Это зависит от вашего компилятора и архитектуры процессора.Я обнаружил, что простой цикл работает на 60% быстрее на моем процессоре i3 при компиляции под VS2012, однако на чипе ARM11 в Raspberry Pi и компиляции с GCC я получил улучшение только на 20%.