aboutsummaryrefslogtreecommitdiffstats
path: root/libs/bigint/BigIntegerAlgorithms.cc
blob: 7edebda76a8e17de58dcb3476bc02e3d6be5a249 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#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;
}
p">: Context_Acc; Prefix : Sname := No_Sname) return Sname; -- Create a builder for Design. Must be called once. function Build_Builders (Design : Module) return Context_Acc; function Get_Design (Ctxt : Context_Acc) return Module; -- Set the parent for the new instances. procedure Set_Parent (Ctxt : Context_Acc; Parent : Module); function Build_Dyadic (Ctxt : Context_Acc; Id : Dyadic_Module_Id; L, R : Net) return Net; function Build_Shift_Rotate (Ctxt : Context_Acc; Id : Shift_Rotate_Module_Id; L, R : Net) return Net; function Build_Monadic (Ctxt : Context_Acc; Id : Monadic_Module_Id; Op : Net) return Net; function Build_Compare (Ctxt : Context_Acc; Id : Compare_Module_Id; L, R : Net) return Net; function Build_Reduce (Ctxt : Context_Acc; Id : Reduce_Module_Id; Op : Net) return Net; function Build_Const_X (Ctxt : Context_Acc; W : Width) return Net; function Build_Const_Z (Ctxt : Context_Acc; W : Width) return Net; function Build_Const_UB32 (Ctxt : Context_Acc; Val : Uns32; W : Width) return Net; function Build_Const_UL32 (Ctxt : Context_Acc; Val : Uns32; Xz : Uns32; W : Width) return Net; function Build_Const_SB32 (Ctxt : Context_Acc; Val : Int32; W : Width) return Net; -- Large constants. -- Bit means only 0 or 1. -- Log means 0/1/Z/X. Parameters 2N are aval, 2N+1 are bval. function Build_Const_Bit (Ctxt : Context_Acc; W : Width) return Instance; function Build_Const_Log (Ctxt : Context_Acc; W : Width) return Instance; function Build_Posedge (Ctxt : Context_Acc; Src : Net) return Net; function Build_Negedge (Ctxt : Context_Acc; Src : Net) return Net; function Build_Mux2 (Ctxt : Context_Acc; Sel : Net; I0, I1 : Net) return Net; function Build_Mux4 (Ctxt : Context_Acc; Sel : Net; I0, I1, I2, I3 : Net) return Net; -- The width of SEL gives the number of inputs (+ 2). -- The width of DEF (default value) gives the width of the output. function Build_Pmux (Ctxt : Context_Acc; Sel : Net; Def : Net) return Net; -- Build: I0 & I1 [ & I2 [ & I3 ]] function Build_Concat2 (Ctxt : Context_Acc; I0, I1 : Net) return Net; function Build_Concat3 (Ctxt : Context_Acc; I0, I1, I2 : Net) return Net; function Build_Concat4 (Ctxt : Context_Acc; I0, I1, I2, I3 : Net) return Net; -- NBR_INPUTS is the number of inputs ports, W is the width of the -- output. function Build_Concatn (Ctxt : Context_Acc; W : Width; Nbr_Inputs : Uns32) return Net; function Build_Trunc (Ctxt : Context_Acc; Id : Module_Id; I : Net; W : Width) return Net; function Build_Extend (Ctxt : Context_Acc; Id : Module_Id; I : Net; W : Width) return Net; -- Note: OFF is the offset, 0 is LSB. function Build_Extract (Ctxt : Context_Acc; I : Net; Off, W : Width) return Net; function Build_Extract_Bit (Ctxt : Context_Acc; I : Net; Off : Width) return Net; function Build_Dyn_Extract (Ctxt : Context_Acc; Mem : Net; Idx : Net; Off : Uns32; W : Width) return Net; function Build_Dyn_Insert (Ctxt : Context_Acc; Mem : Net; V : Net; Idx : Net; Off : Uns32) return Net; function Build_Dyn_Insert_En (Ctxt : Context_Acc; Mem : Net; V : Net; Idx : Net; En : Net; Off : Uns32) return Net; function Build_Memidx (Ctxt : Context_Acc; I : Net; Step : Uns32; Max : Uns32; W : Width) return Net; function Build_Addidx (Ctxt : Context_Acc; L, R : Net) return Net; function Build_Memory (Ctxt : Context_Acc; Name : Sname; W : Width) return Instance; function Build_Memory_Init (Ctxt : Context_Acc; Name : Sname; W : Width; Init : Net) return Instance; function Build_Mem_Rd (Ctxt : Context_Acc; Pport : Net; Addr : Net; Data_W : Width) return Instance; function Build_Mem_Rd_Sync (Ctxt : Context_Acc; Pport : Net; Addr : Net; Clk : Net; En : Net; Data_W : Width) return Instance; function Build_Mem_Wr_Sync (Ctxt : Context_Acc; Pport : Net; Addr : Net; Clk : Net; En : Net; Data : Net) return Instance; function Build_Mem_Multiport (Ctxt : Context_Acc; I0, I1 : Net) return Net; function Build_Output (Ctxt : Context_Acc; W : Width) return Net; function Build_Ioutput (Ctxt : Context_Acc; Init : Net) return Net; function Build_Inout (Ctxt : Context_Acc; W : Width) return Instance; function Build_Iinout (Ctxt : Context_Acc; W : Width) return Instance; function Build_Signal (Ctxt : Context_Acc; Name : Sname; W : Width) return Net; function Build_Isignal (Ctxt : Context_Acc; Name : Sname; Init : Net) return Net; function Build_Port (Ctxt : Context_Acc; N : Net) return Net; function Build_Enable (Ctxt : Context_Acc) return Net; function Build_Assert (Ctxt : Context_Acc; Name : Sname; Cond : Net) return Instance; function Build_Assume (Ctxt : Context_Acc; Name : Sname; Cond : Net) return Instance; function Build_Cover (Ctxt : Context_Acc; Name : Sname; Cond : Net) return Instance; function Build_Assert_Cover (Ctxt : Context_Acc; Name : Sname; Cond : Net) return Instance; function Build_Formal_Input (Ctxt : Context_Acc; Id : Formal_Module_Id; W : Width) return Net; -- A simple flip-flop. function Build_Dff (Ctxt : Context_Acc; Clk : Net; D : Net) return Net; -- A flip-flop with an initial value (only for fpga) -- The width is derived from INIT and D can be No_Net. function Build_Idff (Ctxt : Context_Acc; Clk : Net; D : Net; Init : Net) return Net; function Build_Adff (Ctxt : Context_Acc; Clk : Net; D : Net; Rst : Net; Rst_Val : Net) return Net; function Build_Iadff (Ctxt : Context_Acc; Clk : Net; D : Net; Rst : Net; Rst_Val : Net; Init : Net) return Net; function Build_Mdff (Ctxt : Context_Acc; Clk : Net; D : Net; Els : Net) return Net; function Build_Midff (Ctxt : Context_Acc; Clk : Net; D : Net; Els : Net; Init : Net) return Net; function Build_Dlatch (Ctxt : Context_Acc; En : Net; D : Net) return Net; function Build_Tri (Ctxt : Context_Acc; En : Net; D : Net) return Net; function Build_Resolver (Ctxt : Context_Acc; L, R : Net) return Net; function Build_Nop (Ctxt : Context_Acc; I : Net) return Net; private type Module_Arr is array (Module_Id range <>) of Module; type Context is record Design : Module; Parent : Module; Num : Uns32; M_Dyadic : Module_Arr (Dyadic_Module_Id); M_Shift_Rotate : Module_Arr (Shift_Rotate_Module_Id); M_Monadic : Module_Arr (Monadic_Module_Id); M_Compare : Module_Arr (Compare_Module_Id); M_Concat : Module_Arr (Concat_Module_Id); M_Concatn : Module; M_Const_UB32 : Module; M_Const_SB32 : Module; M_Const_UL32 : Module; M_Const_X : Module; M_Const_Z : Module; M_Const_Bit : Module; M_Const_Log : Module; M_Posedge : Module; M_Negedge : Module; M_Mux2 : Module; M_Mux4 : Module; M_Pmux : Module; M_Nop : Module; M_Output : Module; M_Ioutput : Module; M_Signal : Module; M_Isignal : Module; M_Port : Module; M_Inout : Module; M_Iinout : Module; M_Enable : Module; M_Dff : Module; M_Idff : Module; M_Adff : Module; M_Iadff : Module; M_Mdff : Module; M_Midff : Module; M_Dlatch : Module; M_Tri : Module; M_Resolver : Module; M_Truncate : Module_Arr (Truncate_Module_Id); M_Extend : Module_Arr (Extend_Module_Id); M_Reduce : Module_Arr (Reduce_Module_Id); M_Extract : Module; M_Dyn_Extract : Module; M_Dyn_Insert : Module; M_Dyn_Insert_En : Module; M_Memidx : Module; M_Addidx : Module; M_Memory : Module; M_Memory_Init : Module; M_Mem_Rd : Module; M_Mem_Rd_Sync : Module; M_Mem_Wr_Sync : Module; M_Mem_Multiport : Module; M_Assert : Module; M_Assume : Module; M_Cover : Module; M_Assert_Cover : Module; M_Formal_Input : Module_Arr (Formal_Module_Id); end record; end Netlists.Builders;