public SimpleBigDecimal AdjustScale(int newScale)
        {
            if (newScale < 0)
            {
                throw new ArgumentException("scale may not be negative");
            }

            if (newScale == scale)
            {
                return(this);
            }

            return(new SimpleBigDecimal(bigInt.ShiftLeft(newScale - scale), newScale));
        }
        public void TestShiftLeft()
        {
            for (int i = 0; i < 100; ++i)
            {
                int shift = _random.Next(128);

                IBigInteger a    = new BigInteger(128 + i, _random).Add(one);
                int         bits = a.BitCount;         // Make sure nBits is set

                IBigInteger negA = a.Negate();
                bits = negA.BitCount;                 // Make sure nBits is set

                IBigInteger b = a.ShiftLeft(shift);
                IBigInteger c = negA.ShiftLeft(shift);

                Assert.AreEqual(a.BitCount, b.BitCount);
                Assert.AreEqual(negA.BitCount + shift, c.BitCount);
                Assert.AreEqual(a.BitLength + shift, b.BitLength);
                Assert.AreEqual(negA.BitLength + shift, c.BitLength);

                int j = 0;
                for (; j < shift; ++j)
                {
                    Assert.IsFalse(b.TestBit(j));
                }

                for (; j < b.BitLength; ++j)
                {
                    Assert.AreEqual(a.TestBit(j - shift), b.TestBit(j));
                }
            }
        }
        public void TestClearBit()
        {
            Assert.AreEqual(zero, zero.ClearBit(0));
            Assert.AreEqual(zero, one.ClearBit(0));
            Assert.AreEqual(two, two.ClearBit(0));

            Assert.AreEqual(zero, zero.ClearBit(1));
            Assert.AreEqual(one, one.ClearBit(1));
            Assert.AreEqual(zero, two.ClearBit(1));

            // TODO Tests for clearing bits in negative numbers

            // TODO Tests for clearing extended bits

            for (int i = 0; i < 10; ++i)
            {
                IBigInteger n = new BigInteger(128, _random);

                for (int j = 0; j < 10; ++j)
                {
                    int         pos  = _random.Next(128);
                    IBigInteger m    = n.ClearBit(pos);
                    bool        test = m.ShiftRight(pos).Remainder(two).Equals(one);

                    Assert.IsFalse(test);
                }
            }

            for (int i = 0; i < 100; ++i)
            {
                IBigInteger pow2      = one.ShiftLeft(i);
                IBigInteger minusPow2 = pow2.Negate();

                Assert.AreEqual(zero, pow2.ClearBit(i));
                Assert.AreEqual(minusPow2.ShiftLeft(1), minusPow2.ClearBit(i));

                IBigInteger bigI = BigInteger.ValueOf(i);
                IBigInteger negI = bigI.Negate();

                for (int j = 0; j < 10; ++j)
                {
                    string data = "i=" + i + ", j=" + j;
                    Assert.AreEqual(bigI.AndNot(one.ShiftLeft(j)), bigI.ClearBit(j), data);
                    Assert.AreEqual(negI.AndNot(one.ShiftLeft(j)), negI.ClearBit(j), data);
                }
            }
        }
        public override string ToString()
        {
            if (scale == 0)
            {
                return(bigInt.ToString());
            }

            IBigInteger floorBigInt = Floor();

            IBigInteger fract = bigInt.Subtract(floorBigInt.ShiftLeft(scale));

            if (bigInt.SignValue < 0)
            {
                fract = BigInteger.One.ShiftLeft(scale).Subtract(fract);
            }

            if ((floorBigInt.SignValue == -1) && (!(fract.Equals(BigInteger.Zero))))
            {
                floorBigInt = floorBigInt.Add(BigInteger.One);
            }
            string leftOfPoint = floorBigInt.ToString();

            char[] fractCharArr = new char[scale];
            string fractStr     = fract.ToString(2);
            int    fractLen     = fractStr.Length;
            int    zeroes       = scale - fractLen;

            for (int i = 0; i < zeroes; i++)
            {
                fractCharArr[i] = '0';
            }
            for (int j = 0; j < fractLen; j++)
            {
                fractCharArr[zeroes + j] = fractStr[j];
            }
            string rightOfPoint = new string(fractCharArr);

            StringBuilder sb = new StringBuilder(leftOfPoint);

            sb.Append(".");
            sb.Append(rightOfPoint);

            return(sb.ToString());
        }
        public void TestMultiply()
        {
            IBigInteger one = BigInteger.One;

            Assert.AreEqual(one, one.Negate().Multiply(one.Negate()));

            for (int i = 0; i < 100; ++i)
            {
                int aLen = 64 + _random.Next(64);
                int bLen = 64 + _random.Next(64);

                IBigInteger a = new BigInteger(aLen, _random).SetBit(aLen);
                IBigInteger b = new BigInteger(bLen, _random).SetBit(bLen);
                IBigInteger c = new BigInteger(32, _random);

                IBigInteger ab = a.Multiply(b);
                IBigInteger bc = b.Multiply(c);

                Assert.AreEqual(ab.Add(bc), a.Add(c).Multiply(b));
                Assert.AreEqual(ab.Subtract(bc), a.Subtract(c).Multiply(b));
            }

            // Special tests for power of two since uses different code path internally
            for (int i = 0; i < 100; ++i)
            {
                int         shift  = _random.Next(64);
                IBigInteger a      = one.ShiftLeft(shift);
                IBigInteger b      = new BigInteger(64 + _random.Next(64), _random);
                IBigInteger bShift = b.ShiftLeft(shift);

                Assert.AreEqual(bShift, a.Multiply(b));
                Assert.AreEqual(bShift.Negate(), a.Multiply(b.Negate()));
                Assert.AreEqual(bShift.Negate(), a.Negate().Multiply(b));
                Assert.AreEqual(bShift, a.Negate().Multiply(b.Negate()));

                Assert.AreEqual(bShift, b.Multiply(a));
                Assert.AreEqual(bShift.Negate(), b.Multiply(a.Negate()));
                Assert.AreEqual(bShift.Negate(), b.Negate().Multiply(a));
                Assert.AreEqual(bShift, b.Negate().Multiply(a.Negate()));
            }
        }
        public void TestFlipBit()
        {
            for (int i = 0; i < 10; ++i)
            {
                IBigInteger a = new BigInteger(128, 0, _random);
                IBigInteger b = a;

                for (int x = 0; x < 100; ++x)
                {
                    // Note: Intentionally greater than initial size
                    int pos = _random.Next(256);

                    a = a.FlipBit(pos);
                    b = b.TestBit(pos) ? b.ClearBit(pos) : b.SetBit(pos);
                }

                Assert.AreEqual(a, b);
            }

            for (int i = 0; i < 100; ++i)
            {
                IBigInteger pow2      = one.ShiftLeft(i);
                IBigInteger minusPow2 = pow2.Negate();

                Assert.AreEqual(zero, pow2.FlipBit(i));
                Assert.AreEqual(minusPow2.ShiftLeft(1), minusPow2.FlipBit(i));

                IBigInteger bigI = BigInteger.ValueOf(i);
                IBigInteger negI = bigI.Negate();

                for (int j = 0; j < 10; ++j)
                {
                    string data = "i=" + i + ", j=" + j;
                    Assert.AreEqual(bigI.Xor(one.ShiftLeft(j)), bigI.FlipBit(j), data);
                    Assert.AreEqual(negI.Xor(one.ShiftLeft(j)), negI.FlipBit(j), data);
                }
            }
        }
 public SimpleBigDecimal Add(IBigInteger b)
 {
     return(new SimpleBigDecimal(bigInt.Add(b.ShiftLeft(scale)), scale));
 }
 /**
  * Returns a <code>SimpleBigDecimal</code> representing the same numerical
  * value as <code>value</code>.
  * @param value The value of the <code>SimpleBigDecimal</code> to be
  * created.
  * @param scale The scale of the <code>SimpleBigDecimal</code> to be
  * created.
  * @return The such created <code>SimpleBigDecimal</code>.
  */
 public static SimpleBigDecimal GetInstance(IBigInteger val, int scale)
 {
     return(new SimpleBigDecimal(val.ShiftLeft(scale), scale));
 }
예제 #9
0
        /**
         * Computes the <code>&#964;</code>-adic NAF (non-adjacent form) of an
         * element <code>&#955;</code> of <code><b>Z</b>[&#964;]</code>.
         * @param mu The parameter <code>&#956;</code> of the elliptic curve.
         * @param lambda The element <code>&#955;</code> of
         * <code><b>Z</b>[&#964;]</code>.
         * @return The <code>&#964;</code>-adic NAF of <code>&#955;</code>.
         */
        public static sbyte[] TauAdicNaf(sbyte mu, ZTauElement lambda)
        {
            if (!((mu == 1) || (mu == -1)))
            {
                throw new ArgumentException("mu must be 1 or -1");
            }

            IBigInteger norm = Norm(mu, lambda);

            // Ceiling of log2 of the norm
            int log2Norm = norm.BitLength;

            // If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52
            int maxLength = log2Norm > 30 ? log2Norm + 4 : 34;

            // The array holding the TNAF
            sbyte[] u = new sbyte[maxLength];
            int     i = 0;

            // The actual length of the TNAF
            int length = 0;

            IBigInteger r0 = lambda.u;
            IBigInteger r1 = lambda.v;

            while (!((r0.Equals(BigInteger.Zero)) && (r1.Equals(BigInteger.Zero))))
            {
                // If r0 is odd
                if (r0.TestBit(0))
                {
                    u[i] = (sbyte)BigInteger.Two.Subtract((r0.Subtract(r1.ShiftLeft(1))).Mod(Four)).IntValue;

                    // r0 = r0 - u[i]
                    if (u[i] == 1)
                    {
                        r0 = r0.ClearBit(0);
                    }
                    else
                    {
                        // u[i] == -1
                        r0 = r0.Add(BigInteger.One);
                    }
                    length = i;
                }
                else
                {
                    u[i] = 0;
                }

                IBigInteger t = r0;
                IBigInteger s = r0.ShiftRight(1);
                if (mu == 1)
                {
                    r0 = r1.Add(s);
                }
                else
                {
                    // mu == -1
                    r0 = r1.Subtract(s);
                }

                r1 = t.ShiftRight(1).Negate();
                i++;
            }

            length++;

            // Reduce the TNAF array to its actual length
            sbyte[] tnaf = new sbyte[length];
            Array.Copy(u, 0, tnaf, 0, length);
            return(tnaf);
        }
 /**
 * Returns a <code>SimpleBigDecimal</code> representing the same numerical
 * value as <code>value</code>.
 * @param value The value of the <code>SimpleBigDecimal</code> to be
 * created.
 * @param scale The scale of the <code>SimpleBigDecimal</code> to be
 * created.
 * @return The such created <code>SimpleBigDecimal</code>.
 */
 public static SimpleBigDecimal GetInstance(IBigInteger val, int scale)
 {
     return new SimpleBigDecimal(val.ShiftLeft(scale), scale);
 }
 public int CompareTo(IBigInteger val)
 {
     return bigInt.CompareTo(val.ShiftLeft(scale));
 }
        //Procedure A
        private int procedure_A(int x0, int c, IBigInteger[] 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;
            }

            IBigInteger C        = BigInteger.ValueOf(c);
            IBigInteger constA16 = BigInteger.ValueOf(19381);

            //step1
            IBigInteger[] y = new IBigInteger[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
            IBigInteger[] p = new IBigInteger[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
                    IBigInteger[] 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
                    IBigInteger 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
                    IBigInteger 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
                        IBigInteger 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);
        }
        //Procedure B
        private void procedure_B(int x0, int c, IBigInteger[] 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;
            }

            IBigInteger [] qp = new BigInteger[2];
            IBigInteger    q = null, Q = null, p = null;
            IBigInteger    C        = BigInteger.ValueOf(c);
            IBigInteger    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];

            IBigInteger[] y = new IBigInteger[65];
            y[0] = BigInteger.ValueOf(x0);

            const int tp = 1024;

            IBigInteger 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
                IBigInteger 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
                IBigInteger 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
                    IBigInteger 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);
                }
            }
        }
        public IBigInteger Multiply(
            IBigInteger val)
        {
            if (SignValue == 0 || val.SignValue == 0)
                return Zero;

            if (val.QuickPow2Check()) // val is power of two
            {
                IBigInteger result = this.ShiftLeft(val.Abs().BitLength - 1);
                return val.SignValue > 0 ? result : result.Negate();
            }

            if (this.QuickPow2Check()) // this is power of two
            {
                IBigInteger result = val.ShiftLeft(this.Abs().BitLength - 1);
                return this.SignValue > 0 ? result : result.Negate();
            }

            int resLength = (this.BitLength + val.BitLength)/BitsPerInt + 1;
            var res = new int[resLength];

            if (val == this)
            {
                Square(res, this.Magnitude);
            }
            else
            {
                Multiply(res, this.Magnitude, val.Magnitude);
            }

            return new BigInteger(SignValue*val.SignValue, res, true);
        }
        //Procedure B'
        private void procedure_Bb(long x0, long c, IBigInteger[] pq)
        {
            //Verify and perform condition: 0<x<2^32; 0<c<2^32; c - odd.
            while (x0 < 0 || x0 > 4294967296L)
            {
                x0 = init_random.NextInt() * 2;
            }

            while ((c < 0 || c > 4294967296L) || (c / 2 == 0))
            {
                c = init_random.NextInt() * 2 + 1;
            }

            IBigInteger [] qp = new BigInteger[2];
            IBigInteger    q = null, Q = null, p = null;
            IBigInteger    C        = BigInteger.ValueOf(c);
            IBigInteger    constA32 = BigInteger.ValueOf(97781173);

            //step1
            x0 = procedure_Aa(x0, c, qp, 256);
            q  = qp[0];

            //step2
            x0 = procedure_Aa(x0, c, qp, 512);
            Q  = qp[0];

            IBigInteger[] y = new IBigInteger[33];
            y[0] = BigInteger.ValueOf(x0);

            const int tp = 1024;

            IBigInteger qQ = q.Multiply(Q);

step3:
            for (;;)
            {
                //step 3
                for (int j = 0; j < 32; j++)
                {
                    y[j + 1] = (y[j].Multiply(constA32).Add(C)).Mod(BigInteger.Two.Pow(32));
                }

                //step 4
                IBigInteger Y = BigInteger.Zero;
                for (int j = 0; j < 32; j++)
                {
                    Y = Y.Add(y[j].ShiftLeft(32 * j));
                }

                y[0] = y[32];                 //step 5

                //step 6
                IBigInteger 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
                    IBigInteger 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);
                }
            }
        }
 public SimpleBigDecimal Add(IBigInteger b)
 {
     return new SimpleBigDecimal(bigInt.Add(b.ShiftLeft(scale)), scale);
 }
 public SimpleBigDecimal Subtract(IBigInteger b)
 {
     return(new SimpleBigDecimal(bigInt.Subtract(b.ShiftLeft(scale)), scale));
 }
 public SimpleBigDecimal Subtract(IBigInteger b)
 {
     return new SimpleBigDecimal(bigInt.Subtract(b.ShiftLeft(scale)), scale);
 }
 public int CompareTo(IBigInteger val)
 {
     return(bigInt.CompareTo(val.ShiftLeft(scale)));
 }
        private static string MakeOidStringFromBytes(byte[] bytes)
        {
            var         objId    = new StringBuilder();
            long        value    = 0;
            IBigInteger bigValue = null;
            var         first    = true;

            for (var i = 0; i != bytes.Length; i++)
            {
                int b = bytes[i];

                if (value < 0x80000000000000L)
                {
                    value = value * 128 + (b & 0x7f);
                    if ((b & 0x80) == 0)             // end of number reached
                    {
                        if (first)
                        {
                            switch ((int)value / 40)
                            {
                            case 0:
                                objId.Append('0');
                                break;

                            case 1:
                                objId.Append('1');
                                value -= 40;
                                break;

                            default:
                                objId.Append('2');
                                value -= 80;
                                break;
                            }
                            first = false;
                        }

                        objId.Append('.');
                        objId.Append(value);
                        value = 0;
                    }
                }
                else
                {
                    if (bigValue == null)
                    {
                        bigValue = BigInteger.ValueOf(value);
                    }
                    bigValue = bigValue.ShiftLeft(7);
                    bigValue = bigValue.Or(BigInteger.ValueOf(b & 0x7f));
                    if ((b & 0x80) == 0)
                    {
                        objId.Append('.');
                        objId.Append(bigValue);
                        bigValue = null;
                        value    = 0;
                    }
                }
            }

            return(objId.ToString());
        }
        /**
         * generate suitable parameters for DSA, in line with
         * <i>FIPS 186-3 A.1 Generation of the FFC Primes p and q</i>.
         */
        private DsaParameters GenerateParameters_FIPS186_3()
        {
// A.1.1.2 Generation of the Probable Primes p and q Using an Approved Hash Function
            // FIXME This should be configurable (digest size in bits must be >= N)
            IDigest d      = new Sha256Digest();
            int     outlen = d.GetDigestSize() * 8;

// 1. Check that the (L, N) pair is in the list of acceptable (L, N pairs) (see Section 4.2). If
//    the pair is not in the list, then return INVALID.
            // Note: checked at initialisation

// 2. If (seedlen < N), then return INVALID.
            // FIXME This should be configurable (must be >= N)
            int seedlen = N;

            byte[] seed = new byte[seedlen / 8];

// 3. n = ceiling(L ⁄ outlen) – 1.
            int n = (L - 1) / outlen;

// 4. b = L – 1 – (n ∗ outlen).
            int b = (L - 1) % outlen;

            byte[] output = new byte[d.GetDigestSize()];
            for (;;)
            {
// 5. Get an arbitrary sequence of seedlen bits as the domain_parameter_seed.
                random.NextBytes(seed);

// 6. U = Hash (domain_parameter_seed) mod 2^(N–1).
                Hash(d, seed, output);
                IBigInteger U = new BigInteger(1, output).Mod(BigInteger.One.ShiftLeft(N - 1));

// 7. q = 2^(N–1) + U + 1 – ( U mod 2).
                IBigInteger q = BigInteger.One.ShiftLeft(N - 1).Add(U).Add(BigInteger.One).Subtract(
                    U.Mod(BigInteger.Two));

// 8. Test whether or not q is prime as specified in Appendix C.3.
                // TODO Review C.3 for primality checking
                if (!q.IsProbablePrime(certainty))
                {
// 9. If q is not a prime, then go to step 5.
                    continue;
                }

// 10. offset = 1.
                // Note: 'offset' value managed incrementally
                byte[] offset = Arrays.Clone(seed);

// 11. For counter = 0 to (4L – 1) do
                int counterLimit = 4 * L;
                for (int counter = 0; counter < counterLimit; ++counter)
                {
// 11.1 For j = 0 to n do
//      Vj = Hash ((domain_parameter_seed + offset + j) mod 2^seedlen).
// 11.2 W = V0 + (V1 ∗ 2^outlen) + ... + (V^(n–1) ∗ 2^((n–1) ∗ outlen)) + ((Vn mod 2^b) ∗ 2^(n ∗ outlen)).
                    // TODO Assemble w as a byte array
                    IBigInteger W = BigInteger.Zero;
                    for (int j = 0, exp = 0; j <= n; ++j, exp += outlen)
                    {
                        Inc(offset);
                        Hash(d, offset, output);

                        IBigInteger Vj = new BigInteger(1, output);
                        if (j == n)
                        {
                            Vj = Vj.Mod(BigInteger.One.ShiftLeft(b));
                        }

                        W = W.Add(Vj.ShiftLeft(exp));
                    }

// 11.3 X = W + 2^(L–1). Comment: 0 ≤ W < 2L–1; hence, 2L–1 ≤ X < 2L.
                    IBigInteger X = W.Add(BigInteger.One.ShiftLeft(L - 1));

// 11.4 c = X mod 2q.
                    IBigInteger c = X.Mod(q.ShiftLeft(1));

// 11.5 p = X - (c - 1). Comment: p ≡ 1 (mod 2q).
                    IBigInteger p = X.Subtract(c.Subtract(BigInteger.One));

                    // 11.6 If (p < 2^(L - 1)), then go to step 11.9
                    if (p.BitLength != L)
                    {
                        continue;
                    }

// 11.7 Test whether or not p is prime as specified in Appendix C.3.
                    // TODO Review C.3 for primality checking
                    if (p.IsProbablePrime(certainty))
                    {
// 11.8 If p is determined to be prime, then return VALID and the values of p, q and
//      (optionally) the values of domain_parameter_seed and counter.
                        // TODO Make configurable (8-bit unsigned)?
//	                    int index = 1;
//	                    IBigInteger g = CalculateGenerator_FIPS186_3_Verifiable(d, p, q, seed, index);
//	                    if (g != null)
//	                    {
//	                        // TODO Should 'index' be a part of the validation parameters?
//	                        return new DsaParameters(p, q, g, new DsaValidationParameters(seed, counter));
//	                    }

                        IBigInteger g = CalculateGenerator_FIPS186_3_Unverifiable(p, q, random);
                        return(new DsaParameters(p, q, g, new DsaValidationParameters(seed, counter)));
                    }

// 11.9 offset = offset + n + 1.      Comment: Increment offset; then, as part of
//                                    the loop in step 11, increment counter; if
//                                    counter < 4L, repeat steps 11.1 through 11.8.
                    // Note: 'offset' value already incremented in inner loop
                }
// 12. Go to step 5.
            }
        }