Example #1
0
                    // umagic computes the constants needed to strength reduce unsigned n-bit divides by the constant uint64(c).
                    // The return values satisfy for all 0 <= x < 2^n
                    //  floor(x / uint64(c)) = x * (m + 2^n) >> (n+s)
                    private static umagicData umagic(ulong n, long c) => func((_, panic, __) =>
                    {
                        // Convert from ConstX auxint values to the real uint64 constant they represent.
                        var d = uint64(c) << (int)((64L - n)) >> (int)((64L - n));

                        ptr <object> C = @new <big.Int>().SetUint64(d);
                        var s          = C.BitLen();
                        var M          = big.NewInt(1L);
                        M.Lsh(M, n + uint(s));    // 2^(n+s)
                        M.Add(M, C);              // 2^(n+s)+c
                        M.Sub(M, big.NewInt(1L)); // 2^(n+s)+c-1
                        M.Div(M, C);              // ⎡2^(n+s)/c⎤
                        if (M.Bit(int(n)) != 1L)
                        {
                            panic("n+1st bit isn't set");
                        }

                        M.SetBit(M, int(n), 0L);
                        var m = M.Uint64();
                        return(new umagicData(s: int64(s), m: m));
                    });
Example #2
0
                    // magic computes the constants needed to strength reduce signed n-bit divides by the constant c.
                    // Must have c>0.
                    // The return values satisfy for all -2^(n-1) <= x < 2^(n-1)
                    //  trunc(x / c) = x * m >> (n+s) + (x < 0 ? 1 : 0)
                    private static smagicData smagic(ulong n, long c) => func((_, panic, __) =>
                    {
                        ptr <object> C = @new <big.Int>().SetInt64(c);
                        var s          = C.BitLen() - 1L;
                        var M          = big.NewInt(1L);
                        M.Lsh(M, n + uint(s));    // 2^(n+s)
                        M.Add(M, C);              // 2^(n+s)+c
                        M.Sub(M, big.NewInt(1L)); // 2^(n+s)+c-1
                        M.Div(M, C);              // ⎡2^(n+s)/c⎤
                        if (M.Bit(int(n)) != 0L)
                        {
                            panic("n+1st bit is set");
                        }

                        if (M.Bit(int(n - 1L)) == 0L)
                        {
                            panic("nth bit is not set");
                        }

                        var m = M.Uint64();
                        return(new smagicData(s: int64(s), m: m));
                    });