Чтобы сделать этот расчет в сборке, но если бы он вызывался из Python, я бы
попробуйте встроенную сборку из
Модуль Python, написанный на C .
Оба GCC и
MSVC
компиляторы имеют встроенную сборку, только с разным синтаксисом.
Обратите внимание, что наш модуль p = 1000000007
просто умещается в 30 бит. Результат
желаемый (a*b)%p
может быть вычислен в регистрах Intel 80x86 с учетом некоторых слабых
ограничения на a,b
не намного больше, чем p
.
Ограничения по размеру a,b
(1) a,b
- 32-разрядные целые числа без знака
(2) a*b
меньше p << 32
, то есть p
раз 2 ^ 32
В частности, если a,b
меньше 2*p
, переполнение будет предотвращено.
Учитывая (1), также достаточно, чтобы любой из них был меньше p
.
В инструкции Intel 80x86 MUL можно умножить два 32-разрядных целых числа без знака.
и сохранить 64-битный результат в паре регистров аккумулятора EDX: EAX. Немного
детали и особенности MUL обсуждаются в разделе 10.2.1 этого полезного
Резюме .
Команда DIV может затем разделить этот 64-битный результат на 32-битную константу.
(модуль p
), сохраняя частное в EAX и остаток в EDX.
См. Раздел 10.2.2 последней ссылки. Результат, который мы хотим получить, - это остаток.
Именно эта инструкция деления DIV влечет за собой риск переполнения, если
64-разрядное произведение в числителе EDX: EAX дает коэффициент больше 32-разрядного
не выполнив (2) выше.
Я работаю над фрагментом кода в C / inline сборке для «доказательства концепции».
Однако максимальный выигрыш в скорости будет зависеть от группирования массивов
данные a,b
для обработки, амортизации накладных расходов на вызовы функций и т. д. в
Python (если это целевая платформа).