How to find remainder without division or modulo operator in MIPS assembly

余生颓废 提交于 2019-12-04 17:23:33

There's a method described by Granlund & Montgomery that requires the modular / multiplicative inverse of the (odd) divisor modulo 2**b. (Some parts of this paper have been improved recently)

The divisors: (d) = 3, 7 (odd numbers) are an easy case. Assuming 32 bit (unsigned) arithmetic, the inverses modulo 2**32 yield 2863311531 (0xAAAAAAAB) and 3067833783 (0xB6DB6DB7) respectively. There's an online calculator here.

We also need the qmax = (2**32 - 1) / d values: 0x55555555 and 0x24924924 resp.

To test a 32 bit (unsigned) number (n), perform a single word multiply - that is, discard the high word of the full 64 bit result: q = dinv * n

If (n) is divisible by (d), then (q) must satisfy: q * d == n and q <= qmax. e.g.,

int is_divisible_by_3 (uint32_t n)
{
    uint32_t q = n * 0xAAAAAAAB;
    return (q <= 0x55555555 && (q * 3 == n))    
}

Which replaces a division / remainder with a couple of single word multiplications.

And similarly for d = 7. Alternatively, a modern compiler like gcc will perform a similar optimization for a constant divisor / modulus, e.g., if (n % 3 == 0) ... - in the assembly generated for MIPS, etc.

You can sum the remainders for the individual bits. The 2^n mod 3 goes like 1,2,1,2,... and 2^n mod 7 goes like 1,2,4,1,2,4,....

Use a lookup table to make it even faster.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!