Эффективное вычисление высокого уровня битов целочисленного умножения на 32 бита

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

10
задан Arnaud 12 June 2018 в 11:19
поделиться

3 ответа

gcc 4.3.2, с оптимизацией -O1 или выше, транслировал вашу функцию точно так, как вы показывали, в сборку IA32, например:

umulhi32:
        pushl   %ebp
        movl    %esp, %ebp
        movl    12(%ebp), %eax
        mull    8(%ebp)
        movl    %edx, %eax
        popl    %ebp
        ret

Это просто выполняет одну 32-битную mull и помещает старшие 32 бита результата (из % edx ) в возвращаемое значение.

Это то, что вы хотели, верно? Похоже, вам просто нужно включить оптимизацию вашего компилятора;) Возможно, вы могли бы подтолкнуть компилятор в правильном направлении, исключив промежуточную переменную:

unsigned int umulhi32(unsigned int x, unsigned int y)
{
  return (unsigned int)(((unsigned long long)x * y)>>32);
}
13
ответ дан 3 December 2019 в 20:43
поделиться

На 32-битном Intel умножение влияет на два регистра вывода. То есть 64 бита полностью доступны, хотите вы этого или нет. Это просто функция от того, достаточно ли умен компилятор, чтобы воспользоваться этим.

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

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

2
ответ дан 3 December 2019 в 20:43
поделиться

Я не думаю, что есть способ сделать это в стандартном C / C ++ лучше, чем то, что у вас уже есть. Я бы написал простую оболочку сборки, которая вернула бы желаемый результат.

Не то, чтобы вы спрашивали о Windows, а в качестве примера, хотя в Windows есть API, который звучит так, как будто он делает то, что вы хотите ( 32-битное умножение на 32-битное с получением полного 64-битного результата), он реализует умножение как макрос, который делает то, что вы делаете:

#define UInt32x32To64( a, b ) (ULONGLONG)((ULONGLONG)(DWORD)(a) * (DWORD)(b))
3
ответ дан 3 December 2019 в 20:43
поделиться