private void procedure_B(int x0, int c, BigInteger[] pq)
{
//Verify and perform condition: 0<x<2^16; 0<c<2^16; c - odd.
while(x0<0 || x0>65536)
{
x0 = init_random.NextInt()/32768;
}
while((c<0 || c>65536) || (c/2==0))
{
c = init_random.NextInt()/32768 + 1;
}
BigInteger [] qp = new BigInteger[2];
BigInteger q = null, Q = null, p = null;
BigInteger C = BigInteger.ValueOf(c);
BigInteger constA16 = BigInteger.ValueOf(19381);
//step1
x0 = procedure_A(x0, c, qp, 256);
q = qp[0];
//step2
x0 = procedure_A(x0, c, qp, 512);
Q = qp[0];
BigInteger[] y = new BigInteger[65];
y[0] = BigInteger.ValueOf(x0);
const int tp = 1024;
BigInteger qQ = q.Multiply(Q);
step3:
for(;;)
{
//step 3
for (int j=0; j<64; j++)
{
y[j+1] = (y[j].Multiply(constA16).Add(C)).Mod(BigInteger.Two.Pow(16));
}
//step 4
BigInteger Y = BigInteger.Zero;
for (int j=0; j<64; j++)
{
Y = Y.Add(y[j].ShiftLeft(16*j));
}
y[0] = y[64]; //step 5
//step 6
BigInteger N = BigInteger.One.ShiftLeft(tp-1).Divide(qQ).Add(
Y.ShiftLeft(tp-1).Divide(qQ.ShiftLeft(1024)));
if (N.TestBit(0))
{
N = N.Add(BigInteger.One);
}
//step 7
for(;;)
{
//step 11
BigInteger qQN = qQ.Multiply(N);
if (qQN.BitLength > tp)
{
goto step3; //step 9
}
p = qQN.Add(BigInteger.One);
//step10
if (BigInteger.Two.ModPow(qQN, p).CompareTo(BigInteger.One) == 0
&& BigInteger.Two.ModPow(q.Multiply(N), p).CompareTo(BigInteger.One) != 0)
{
pq[0] = p;
pq[1] = q;
return;
}
N = N.Add(BigInteger.Two);
}
}
}