【笔记】Big Integer - Modular Inverse

本文深入探讨了模逆运算的基本原理及其实现方法,包括大整数的模逆运算和2的幂次方的特例。提供了详细的算法实现,如模逆运算的Shifting算法和针对2的幂次方的模逆运算优化算法。

Modular Inverse

ax + by = gcd(a, b),gcd(a, b) = 1时,ax + by = 1,ax = 1 (mod b),x = a^-1 (mod b),x即a的模逆。

Shifting

/// <summary>
/// <paramref name="value"/> ^ -1 (mod <paramref name="modulo"/>)
/// </summary>
public static BigInteger ModInverse(BigInteger value, BigInteger modulo)
{
    if (modulo.Sign <= 0)
        throw new ArithmeticException("modulo should be positive");
    if (modulo.IsOne)
        return BigInteger.Zero;

    if (value.Sign < 0 || value >= modulo)
        value = Mod(value, modulo);
    if (value.IsOne)
        return BigInteger.One;

    var u = modulo; var v = value;
    var r = BigInteger.Zero; var s = BigInteger.One;

    var vLen = 0;
    while ((vLen = v.BitLength()) > 1)
    {
        var shift = u.BitLength() - vLen;
        if (u.Sign != v.Sign)
        {
            u += (v << shift);
            r += (s << shift);
        }
        else
        {
            u -= (v << shift);
            r -= (s << shift);
        }

        if (u.BitLength() < vLen)
        {
            Swap(ref u, ref v);
            Swap(ref r, ref s);
        }
    }

    if (v.IsZero) return BigInteger.MinusOne;//inverse does not exist
    if (v.Sign < 0) s = -s;
    if (s > modulo) s -= modulo;
    if (s.Sign < 0) s += modulo;

    return s;
}

/// <summary>
/// bit length of <see cref="BigInteger"/>
/// </summary>
public static int BitLength(this BigInteger value)
{
    if (value.Sign < 0) value = -value;
    var byteCount = value.GetByteCount();
    var bitCount = (byteCount - 1) << 3;
    value >>= bitCount;

    return bitCount + 32 - ((uint)value).NumberOfLeadingZeros();
}

/// <summary>
/// <paramref name="value"/> (mod <paramref name="modulo"/>)
/// </summary>
public static BigInteger Mod(BigInteger value, BigInteger modulo)
{
    if (modulo.Sign <= 0)
        throw new ArithmeticException("modulo should be positive");
    if (modulo.IsOne)
        return BigInteger.Zero;

    value = BigInteger.Remainder(value, modulo);

    return value.Sign < 0 ? value + modulo : value;
}

public static void Swap<T>(ref T left, ref T right)
{
    var temp = left;
    left = right;
    right = temp;
}

modular inverse of 2^k

/// <summary>
/// <paramref name="value"/> ^ -1 (mod 2 ^ <paramref name="k"/>)
/// assumes <paramref name="value"/> is odd.
/// </summary>
public static BigInteger ModInversePowerOf2(BigInteger value, int k)
{
    if (value.IsEven)
        throw new ArithmeticException("value should be odd");

    var modulo = BigInteger.One << k;
    var mod = value & (modulo - 1);
    if (mod.Sign < 0) mod += modulo;
    if (mod.IsOne) return 1;

    var bits = new int[k];
    var tmp = BigInteger.One;
    for (var i = 0; i < k; ++i)
    {
        bits[i] = tmp.IsEven ? 0 : 1;
        tmp = (tmp - (bits[i] == 0 ? 0 : mod)) >> 1;
    }

    var bytes = new byte[(k + 8) / 8];
    for (int i = 0, j = 0, t = 0; i < bits.Length; i += 8, ++j)
    {
        t = 0;
        for (var m = i; m < i + 8 && m < bits.Length; ++m)
            t += (bits[m] << (m - i));

        bytes[j] = (byte)(t & 0xFF);
    }

    return new BigInteger(bytes);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值