Операция Rotate Right на целочисленных данных с использованием операций с плавающей запятой? - PullRequest
1 голос
/ 09 мая 2011

Я бы хотел взять значение с целым представлением без знака и каким-то образом, используя операции с плавающей запятой, выполнить побитовую операцию с поворотом вправо.

Взгляните на ум, используемый здесь: http://en.wikipedia.org/wiki/Fast_inverse_square_root При этом используется магическое значение и некоторые приемы для выполнения операции над числом с плавающей запятой с использованием целочисленных операций.То, что я хочу, является противоположностью;аппаратное обеспечение, которое я использую, сильно оптимизировано для операций с плавающей запятой, но плохо работает с целочисленными операциями.Алгоритм sha256, который интенсивно использует операцию поворота вправо.

1 Ответ

2 голосов
/ 09 мая 2011

На ум приходят два подхода:

  • Возьмите биты, которые содержат целое число, поместите их в переменную, которая должна содержать число с одинаковым количеством битов, и работайте с этими битами, как если бы они были плавающей точкой. Надеюсь, что в оборудовании есть некоторые операции с плавающей запятой, которые работают с этими битами так же, как целочисленные операции, которые использует SHA256.
  • Запишите целое число в переменную с плавающей точкой с большим количеством битов (например, поместите Int32 в Double, который может содержать 53 бита без потери точности), а затем реализуйте операцию поворота вправо с помощью математических операций.

Первый вариант вряд ли сработает. Если ваше оборудование основано на стандарте IEEE 754 (наиболее распространенный стандарт для представлений с плавающей точкой), то значения с плавающей запятой сохраняются как битовые поля; например, double имеет один знаковый бит, 11 битов экспоненты и 53 бита дроби. Не будет никаких операций, которые сдвигают значение знакового бита в один из слотов экспонентного бита. И затем есть битовые шаблоны, которые имеют особое значение и несут это значение в течение всей операции, например, NaN и бесконечности. Так что эта идея, вероятно, не является началом.

Я не уверен, что второй подход тоже подойдет; вам понадобится полный контроль над такими вещами, как поведение округления, и вы захотите убедить себя в том, что у вас есть правильное число битов в ваших значениях с плавающей запятой, и вам абсолютно необходимо будет провести целый ряд тестов, чтобы убедить себя, что ожидаемые результаты для всего диапазона входных данных. Но здесь идет.

Операция поворота вправо - скажем, x ror y - прерывается таким образом. Пусть b будет количеством бит в х. Я предполагаю, что все сделано с использованием беззнаковой арифметики, потому что это делает логику намного проще.

  • Начнем с x ror y.
  • Это может быть выражено как сдвиг вправо, сдвиг влево и ИЛИ, как (x shr y) or (x shl (b - y)).
  • Shr - это то же самое, что делить на степень два. Shr удаляет любые биты, которые падают с нижнего конца, поэтому мы можем эмулировать это, используя функцию floor. Так что теперь у нас есть floor(x / 2^y) or (x shl (b - y)).
  • ЗЫ - это то же самое, что умножение на степень два. Shl отбрасывает все биты, которые выпадают из верхнего конца, который мы можем эмулировать, выполнив умножение по модулю 2 ^ b. Это дает нам floor(x / 2^y) or ((x * 2^(b - y)) mod 2^b).
  • Так как результаты shl и shr не пересекаются (они влияют на разные биты в результате), или можно было бы также сделать с добавлением. Итак, теперь у нас есть математическая запись для всей операции поворота: floor(x / 2^y) + ((x * 2^(b - y)) mod 2^b).

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

...