} //ModularMath.MultiplicativeInverse(long,long) /// <summary> /// Computes the multiplicative inverse of <paramref name="a"/> modulo <paramref name="modulus"/>. /// </summary> /// <param name="a">A non-negative integer less than <paramref name="modulus"/>.</param> /// <param name="modulus">A non-negative integer defining the integer ring in which <paramref name="a"/> resides.</param> /// <returns>The multiplicative inverse of <paramref name="a"/> modulo <paramref name="modulus"/>, /// or null if no such multiplicative inverse exists.</returns> public static MyUInt256 MultiplicativeInverse(MyUInt256 a, MyUInt256 modulus) { if (a.IsMsbSet() || a.Compare(modulus) >= 0) { throw new ArgumentOutOfRangeException("a must be a non-negative integer less than modulus"); } if (a.IsZero()) { return(null); } MyUInt256 mi; ExtendedEuclidean(a, modulus, out mi); return(mi); } //ModularMath.MultiplicativeInverse(MyUInt256,MyUInt256)
} //ModularMath.ExtendedEuclidean(long,long,out ulong) /// <summary> /// Computes the greatest common divisor (GCD) of <paramref name="a"/> and <paramref name="b"/>, /// as well as the multiplicative inverse of <paramref name="a"/> modulo <paramref name="b"/>. /// </summary> /// <param name="a">A positive integer less than <paramref name="b"/>.</param> /// <param name="b">A positive integer greater than <paramref name="a"/>.</param> /// <param name="mulInverse">Receives the multiplicative inverse of <paramref name="a"/> modulo <paramref name="b"/> /// if <paramref name="a"/> and <paramref name="b"/> are coprime, or null otherwise.</param> /// <returns>The greatest common divisor of <paramref name="a"/> and <paramref name="b"/>.</returns> public static MyUInt256 ExtendedEuclidean(MyUInt256 a, MyUInt256 b, out MyUInt256 mulInverse) { if (a.IsZero() || a.Compare(b) >= 0) { throw new ArgumentOutOfRangeException("a must be a positive integer less than b"); } MyUInt256 r0 = new MyUInt256(b), r1 = new MyUInt256(a); // ordered this way because b > a MyUInt256 q = new MyUInt256(), r = new MyUInt256(); MyUInt256 x0 = new MyUInt256(0), x1 = new MyUInt256(1); // x is a's coefficient; we don't maintain b's coefficient MyUInt256 x = new MyUInt256(1); // return multiplicative inverse of 1 if loop breaks before x is assigned and if GCD (q) is 1 MyUInt256 tmp = new MyUInt256(); for (; ;) { r.Set(r0); // r = r0 % r1 r.Modulo(r1); if (r.IsZero()) { break; // break before overwriting previous value of q } q.Set(r0); // q = r0 / r1 q.Divide(r1); x.Set(x0); // x = x0 - q * x1 tmp.Set(q); tmp.Multiply(x1); x.Subtract(tmp); r0.Set(r1); r1.Set(r); x0.Set(x1); x1.Set(x); } if (x.IsMsbSet()) { x.Add(b); } mulInverse = (r1.Compare(1) == 0 ? x : null); return(r1); } //ModularMath.ExtendedEuclidean(MyUInt256,MyUInt256,out MyUInt256)
/// <summary> /// Computes the greatest common divisor (GCD) of <paramref name="a"/> and <paramref name="b"/>, /// as well as the multiplicative inverse of <paramref name="a"/> modulo <paramref name="b"/>. /// </summary> /// <param name="a">A positive integer less than <paramref name="b"/>.</param> /// <param name="b">A positive integer greater than <paramref name="a"/>.</param> /// <param name="mulInverse">Receives the multiplicative inverse of <paramref name="a"/> modulo <paramref name="b"/> /// if <paramref name="a"/> and <paramref name="b"/> are coprime, or null otherwise.</param> /// <returns>The greatest common divisor of <paramref name="a"/> and <paramref name="b"/>.</returns> public static MyUInt256 ExtendedEuclidean(MyUInt256 a, MyUInt256 b, out MyUInt256 mulInverse) { if (a.IsZero() || a.Compare(b) >= 0) throw new ArgumentOutOfRangeException("a must be a positive integer less than b"); MyUInt256 r0 = new MyUInt256(b), r1 = new MyUInt256(a); // ordered this way because b > a MyUInt256 q = new MyUInt256(), r = new MyUInt256(); MyUInt256 x0 = new MyUInt256(0), x1 = new MyUInt256(1); // x is a's coefficient; we don't maintain b's coefficient MyUInt256 x = new MyUInt256(1); // return multiplicative inverse of 1 if loop breaks before x is assigned and if GCD (q) is 1 MyUInt256 tmp = new MyUInt256(); for (; ; ) { r.Set(r0); // r = r0 % r1 r.Modulo(r1); if (r.IsZero()) break; // break before overwriting previous value of q q.Set(r0); // q = r0 / r1 q.Divide(r1); x.Set(x0); // x = x0 - q * x1 tmp.Set(q); tmp.Multiply(x1); x.Subtract(tmp); r0.Set(r1); r1.Set(r); x0.Set(x1); x1.Set(x); } if (x.IsMsbSet()) x.Add(b); mulInverse = (r1.Compare(1) == 0 ? x : null); return r1; }
/// <summary> /// Computes the multiplicative inverse of <paramref name="a"/> modulo <paramref name="modulus"/>. /// </summary> /// <param name="a">A non-negative integer less than <paramref name="modulus"/>.</param> /// <param name="modulus">A non-negative integer defining the integer ring in which <paramref name="a"/> resides.</param> /// <returns>The multiplicative inverse of <paramref name="a"/> modulo <paramref name="modulus"/>, /// or null if no such multiplicative inverse exists.</returns> public static MyUInt256 MultiplicativeInverse(MyUInt256 a, MyUInt256 modulus) { if (a.IsMsbSet() || a.Compare(modulus) >= 0) throw new ArgumentOutOfRangeException("a must be a non-negative integer less than modulus"); if (a.IsZero()) return null; MyUInt256 mi; ExtendedEuclidean(a, modulus, out mi); return mi; }