Home > Enterprise >  Why is there a loop in this division as multiplication code?
Why is there a loop in this division as multiplication code?

Time:07-01

I got the js code below from an archive of hackers delight (view the source)

The code takes in a value (such as 7) and spits out a magic number to multiply with. Then you bitshift to get the results. I don't remember assembly or any math so I'm sure I'm wrong but I can't find the reason why I'm wrong

From my understanding you could get a magic number by writing ceil(1/divide * 1<<32) (or <<64 for 64bit values, but you'd need bigger ints). If you multiple an integer with imul you'd get the result in one register and the remainder in another. The result register is magically the correct result of a division with this magic number from my formula

I wrote some C code to show what I mean. However I only tested with the values below. It seems correct. The JS code has a loop and more and I was wondering, why? Am I missing something? What values can I use to get an incorrect result that the JS code would get correctly? I'm not very good at math so I didn't understand any of the comments

#include <cstdio>
#include <cassert>
int main(int argc, char *argv[])
{
    auto test_divisor = 7;
    auto test_value = 43;
    auto a = test_value*test_divisor;
    auto b = a-1; //One less test

    auto magic = (1ULL<<32)/test_divisor;
    if (((1ULL<<32)%test_divisor) != 0) {
        magic  ; //Round up
    }
    auto answer1 = (a*magic) >> 32;
    auto answer2 = (b*magic) >> 32;
    assert(answer1 == test_value);
    assert(answer2 == test_value-1);
    printf("%lld %lld\n", answer1, answer2);
}

JS code from hackers delight

var two31 = 0x80000000
var two32 = 0x100000000
function magic_signed(d) { with(Math) {
    if (d >= two31) d = d - two32// Treat large positive as short for negative.
    var ad = abs(d)
    var t = two31   (d >>> 31)
    var anc = t - 1 - t           
  • Related