mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 19:52:31 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			70 lines
		
	
	
	
		
			1.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			70 lines
		
	
	
	
		
			1.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "BigIntegerAlgorithms.hh"
 | |
| 
 | |
| BigUnsigned gcd(BigUnsigned a, BigUnsigned b) {
 | |
| 	BigUnsigned trash;
 | |
| 	// Neat in-place alternating technique.
 | |
| 	for (;;) {
 | |
| 		if (b.isZero())
 | |
| 			return a;
 | |
| 		a.divideWithRemainder(b, trash);
 | |
| 		if (a.isZero())
 | |
| 			return b;
 | |
| 		b.divideWithRemainder(a, trash);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void extendedEuclidean(BigInteger m, BigInteger n,
 | |
| 		BigInteger &g, BigInteger &r, BigInteger &s) {
 | |
| 	if (&g == &r || &g == &s || &r == &s)
 | |
| 		throw "BigInteger extendedEuclidean: Outputs are aliased";
 | |
| 	BigInteger r1(1), s1(0), r2(0), s2(1), q;
 | |
| 	/* Invariants:
 | |
| 	 * r1*m(orig) + s1*n(orig) == m(current)
 | |
| 	 * r2*m(orig) + s2*n(orig) == n(current) */
 | |
| 	for (;;) {
 | |
| 		if (n.isZero()) {
 | |
| 			r = r1; s = s1; g = m;
 | |
| 			return;
 | |
| 		}
 | |
| 		// Subtract q times the second invariant from the first invariant.
 | |
| 		m.divideWithRemainder(n, q);
 | |
| 		r1 -= q*r2; s1 -= q*s2;
 | |
| 
 | |
| 		if (m.isZero()) {
 | |
| 			r = r2; s = s2; g = n;
 | |
| 			return;
 | |
| 		}
 | |
| 		// Subtract q times the first invariant from the second invariant.
 | |
| 		n.divideWithRemainder(m, q);
 | |
| 		r2 -= q*r1; s2 -= q*s1;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| BigUnsigned modinv(const BigInteger &x, const BigUnsigned &n) {
 | |
| 	BigInteger g, r, s;
 | |
| 	extendedEuclidean(x, n, g, r, s);
 | |
| 	if (g == 1)
 | |
| 		// r*x + s*n == 1, so r*x === 1 (mod n), so r is the answer.
 | |
| 		return (r % n).getMagnitude(); // (r % n) will be nonnegative
 | |
| 	else
 | |
| 		throw "BigInteger modinv: x and n have a common factor";
 | |
| }
 | |
| 
 | |
| BigUnsigned modexp(const BigInteger &base, const BigUnsigned &exponent,
 | |
| 		const BigUnsigned &modulus) {
 | |
| 	BigUnsigned ans = 1, base2 = (base % modulus).getMagnitude();
 | |
| 	BigUnsigned::Index i = exponent.bitLength();
 | |
| 	// For each bit of the exponent, most to least significant...
 | |
| 	while (i > 0) {
 | |
| 		i--;
 | |
| 		// Square.
 | |
| 		ans *= ans;
 | |
| 		ans %= modulus;
 | |
| 		// And multiply if the bit is a 1.
 | |
| 		if (exponent.getBit(i)) {
 | |
| 			ans *= base2;
 | |
| 			ans %= modulus;
 | |
| 		}
 | |
| 	}
 | |
| 	return ans;
 | |
| }
 |