Fastest way to calculate a 128-bit integer modulo a 64-bit integer

后端 未结 13 1844
谎友^
谎友^ 2020-12-01 00:15

I have a 128-bit unsigned integer A and a 64-bit unsigned integer B. What\'s the fastest way to calculate A % B - that is the (64-bit) remainder from dividing A

13条回答
  •  生来不讨喜
    2020-12-01 00:44

    The accepted answer by @caf was real nice and highly rated, yet it contain a bug not seen for years.

    To help test that and other solutions, I am posting a test harness and making it community wiki.

    unsigned cafMod(unsigned A, unsigned B) {
      assert(B);
      unsigned X = B;
      // while (X < A / 2) {  Original code used <
      while (X <= A / 2) {
        X <<= 1;
      }
      while (A >= B) {
        if (A >= X) A -= X;
        X >>= 1;
      }
      return A;
    }
    
    void cafMod_test(unsigned num, unsigned den) {
      if (den == 0) return;
      unsigned y0 = num % den;
      unsigned y1 = mod(num, den);
      if (y0 != y1) {
        printf("FAIL num:%x den:%x %x %x\n", num, den, y0, y1);
        fflush(stdout);
        exit(-1);
      }
    }
    
    unsigned rand_unsigned() {
      unsigned x = (unsigned) rand();
      return x * 2 ^ (unsigned) rand();
    }
    
    void cafMod_tests(void) {
      const unsigned i[] = { 0, 1, 2, 3, 0x7FFFFFFF, 0x80000000, 
          UINT_MAX - 3, UINT_MAX - 2, UINT_MAX - 1, UINT_MAX };
      for (unsigned den = 0; den < sizeof i / sizeof i[0]; den++) {
        if (i[den] == 0) continue;
        for (unsigned num = 0; num < sizeof i / sizeof i[0]; num++) {
          cafMod_test(i[num], i[den]);
        }
      }
      cafMod_test(0x8711dd11, 0x4388ee88);
      cafMod_test(0xf64835a1, 0xf64835a);
    
      time_t t;
      time(&t);
      srand((unsigned) t);
      printf("%u\n", (unsigned) t);fflush(stdout);
      for (long long n = 10000LL * 1000LL * 1000LL; n > 0; n--) {
        cafMod_test(rand_unsigned(), rand_unsigned());
      }
    
      puts("Done");
    }
    
    int main(void) {
      cafMod_tests();
      return 0;
    }
    

提交回复
热议问题