private int procedure_A(int x0, int c, BigInteger[] pq, int size)
{
//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 C = BigInteger.ValueOf(c);
BigInteger constA16 = BigInteger.ValueOf(19381);
//step1
BigInteger[] y = new BigInteger[1]; // begin length = 1
y[0] = BigInteger.ValueOf(x0);
//step 2
int[] t = new int[1]; // t - orders; begin length = 1
t[0] = size;
int s = 0;
for (int i=0; t[i]>=17; i++)
{
// extension array t
int[] tmp_t = new int[t.Length + 1]; ///////////////
Array.Copy(t,0,tmp_t,0,t.Length); // extension
t = new int[tmp_t.Length]; // array t
Array.Copy(tmp_t, 0, t, 0, tmp_t.Length); ///////////////
t[i+1] = t[i]/2;
s = i+1;
}
//step3
BigInteger[] p = new BigInteger[s+1];
p[s] = new BigInteger("8003",16); //set min prime number length 16 bit
int m = s-1; //step4
for (int i=0; i<s; i++)
{
int rm = t[m]/16; //step5
step6: for(;;)
{
//step 6
BigInteger[] tmp_y = new BigInteger[y.Length]; ////////////////
Array.Copy(y,0,tmp_y,0,y.Length); // extension
y = new BigInteger[rm+1]; // array y
Array.Copy(tmp_y,0,y,0,tmp_y.Length); ////////////////
for (int j=0; j<rm; j++)
{
y[j+1] = (y[j].Multiply(constA16).Add(C)).Mod(BigInteger.Two.Pow(16));
}
//step 7
BigInteger Ym = BigInteger.Zero;
for (int j=0; j<rm; j++)
{
Ym = Ym.Add(y[j].ShiftLeft(16*j));
}
y[0] = y[rm]; //step 8
//step 9
BigInteger N = BigInteger.One.ShiftLeft(t[m]-1).Divide(p[m+1]).Add(
Ym.ShiftLeft(t[m]-1).Divide(p[m+1].ShiftLeft(16*rm)));
if (N.TestBit(0))
{
N = N.Add(BigInteger.One);
}
//step 10
for(;;)
{
//step 11
BigInteger NByLastP = N.Multiply(p[m+1]);
if (NByLastP.BitLength > t[m])
{
goto step6; //step 12
}
p[m] = NByLastP.Add(BigInteger.One);
//step13
if (BigInteger.Two.ModPow(NByLastP, p[m]).CompareTo(BigInteger.One) == 0
&& BigInteger.Two.ModPow(N, p[m]).CompareTo(BigInteger.One) != 0)
{
break;
}
N = N.Add(BigInteger.Two);
}
if (--m < 0)
{
pq[0] = p[0];
pq[1] = p[1];
return y[0].IntValue; //return for procedure B step 2
}
break; //step 14
}
}
return y[0].IntValue;
}