Сдвиги составлены таким образом, что для подгонки продукта на 63 бита доступна целочисленная арифметика со знаком.
У вас sigA на 24 бита, что означает, что sigA ограничено sigA < 2^24
.
То же самое для sigB: sigB < 2^24
.
Таким образом, у продукта sigA * sigB < 2^48
или, другими словами, у вас есть гарантия, что он уместится в 48 бит
(это самое большее (2^24-1)^2=2^48-2^25+1
).
Следовательно, если вы сдвигаете на 15 бит (8 + 7), у вас есть гарантия, что результаты соответствуют 63 битам
Из-за неявных значений у вас также есть sigA >= 2^23
и sigB >= 2^23
, таким образом sigA*sigB >= 2^46
.Таким образом, он охватывает как минимум 47 битов.
Таким образом, сдвигая на 15 битов, вы уверены, что результаты соответствуют либо 63 битам, либо 62 битам.Неважно, сколько раз вы меняете каждое значение, и 15 + 0 или 1 + 14 будет работать одинаково хорошо.Но при хорошо сбалансированном 8 + 7 каждый из них по-прежнему умещается в 32 бита, что является умным.
В следующей строке вы видите, что продукт всегда настраивается для соответствия наиболее значимому биту в позиции 63 (1на основе):
if ( sigZ < 0x40000000 ) {
--expZ;
sigZ <<= 1;
}
Почему бы не использовать полный 64-битный диапазон с целочисленной арифметикой без знака?Я не знаю, но это будет 8 + 8 смен, а не 7 + 7, как вы предлагаете.