public override ECFieldElement Sqrt()
{
if (!q.TestBit(0))
throw Platform.CreateNotImplementedException("even value of q");
// p mod 4 == 3
if (q.TestBit(1))
{
// TODO Can this be optimised (inline the Square?)
// z = g^(u+1) + p, p = 4u + 3
ECFieldElement z = new FpFieldElement(q, x.ModPow(q.ShiftRight(2).Add(BigInteger.One), q));
return z.Square().Equals(this) ? z : null;
}
// p mod 4 == 1
BigInteger qMinusOne = q.Subtract(BigInteger.One);
BigInteger legendreExponent = qMinusOne.ShiftRight(1);
if (!(x.ModPow(legendreExponent, q).Equals(BigInteger.One)))
return null;
BigInteger u = qMinusOne.ShiftRight(2);
BigInteger k = u.ShiftLeft(1).Add(BigInteger.One);
BigInteger Q = this.x;
BigInteger fourQ = Q.ShiftLeft(2).Mod(q);
BigInteger U, V;
do
{
Random rand = new Random();
BigInteger P;
do
{
P = new BigInteger(q.BitLength, rand);
}
while (P.CompareTo(q) >= 0
|| !(P.Multiply(P).Subtract(fourQ).ModPow(legendreExponent, q).Equals(qMinusOne)));
BigInteger[] result = fastLucasSequence(q, P, Q, k);
U = result[0];
V = result[1];
if (V.Multiply(V).Mod(q).Equals(fourQ))
{
// Integer division by 2, mod q
if (V.TestBit(0))
{
V = V.Add(q);
}
V = V.ShiftRight(1);
Debug.Assert(V.Multiply(V).Mod(q).Equals(x));
return new FpFieldElement(q, V);
}
}
while (U.Equals(BigInteger.One) || U.Equals(qMinusOne));
return null;
// BigInteger qMinusOne = q.Subtract(BigInteger.One);
//
// BigInteger legendreExponent = qMinusOne.ShiftRight(1);
// if (!(x.ModPow(legendreExponent, q).Equals(BigInteger.One)))
// return null;
//
// Random rand = new Random();
// BigInteger fourX = x.ShiftLeft(2);
//
// BigInteger r;
// do
// {
// r = new BigInteger(q.BitLength, rand);
// }
// while (r.CompareTo(q) >= 0
// || !(r.Multiply(r).Subtract(fourX).ModPow(legendreExponent, q).Equals(qMinusOne)));
//
// BigInteger n1 = qMinusOne.ShiftRight(2);
// BigInteger n2 = n1.Add(BigInteger.One);
//
// BigInteger wOne = WOne(r, x, q);
// BigInteger wSum = W(n1, wOne, q).Add(W(n2, wOne, q)).Mod(q);
// BigInteger twoR = r.ShiftLeft(1);
//
// BigInteger root = twoR.ModPow(q.Subtract(BigInteger.Two), q)
// .Multiply(x).Mod(q)
// .Multiply(wSum).Mod(q);
//
// return new FpFieldElement(q, root);
}