示例#1
0
            /// <summary>
            /// Returns the first half of the [rootDegree]th roots of unity series in the BigInteger field.
            /// Used in the recursive FFT algorithm in LongInt.Helper class.
            ///
            /// Root degree should be an exact power of two.
            /// </summary>
            /// <param name="rootDegree"></param>
            /// <returns></returns>
            public static BigInteger[] rootsOfUnityHalfGalois(int rootDegree, bool inverted)
            {
                Contract.Requires <ArgumentOutOfRangeException>(rootDegree > 0, "The degree of the root should be a positive power of two.");
                Contract.Ensures(
                    Contract.ForAll(
                        Contract.Result <BigInteger[]>(),
                        (x => WhiteMath <BigInteger, CalcBigInteger> .PowerIntegerModular(x, (ulong)rootDegree, NTT_MODULUS) == 1)));

                BigInteger[] result = new BigInteger[rootDegree / 2];

                // The first root of unity is obviously one.
                // -
                result[0] = 1;

                // Now we will learn what k it is in rootDegree == 2^k
                // -
                int rootDegreeCopy     = rootDegree;
                int rootDegreeExponent = 0;

                while (rootDegreeCopy > 1)
                {
                    rootDegreeCopy /= 2;
                    ++rootDegreeExponent;
                }

                // Now we obtain the principal 2^rootDegreeExponent-th root of unity.
                // -
                BigInteger principalRoot = WhiteMath <BigInteger, CalcBigInteger> .PowerIntegerModular(
                    NTT_MAX_ROOT_OF_UNITY_2_30,
                    WhiteMath <ulong, CalcULong> .PowerInteger(2, NTT_MAX_ROOT_OF_UNITY_DEGREE_EXPONENT - rootDegreeExponent),
                    NTT_MODULUS);

                // Calculate the desired roots of unity.
                // -
                for (int i = 1; i < rootDegree / 2; i++)
                {
                    // All the desired roots of unity are obtained as powers of the principal root.
                    // -
                    result[i] = result[i - 1] * principalRoot % NTT_MODULUS;
                }

                // If performing the inverse NTT, we should invert the roots.
                // -
                if (inverted)
                {
                    for (int i = 0; i < rootDegree / 2; ++i)
                    {
                        result[i] = WhiteMath <BigInteger, CalcBigInteger> .MultiplicativeInverse(result[i], NTT_MODULUS);
                    }
                }

                return(result);
            }
示例#2
0
            /// <summary>
            /// Returns the first half of the [rootDegree]th roots of unity series in the BigInteger field.
            /// Used in the recursive FFT algorithm in LongInt.Helper class.
            ///
            /// Root degree should be an exact power of two.
            /// </summary>
            /// <param name="rootDegree"></param>
            /// <returns></returns>
            internal static BigInteger[] rootsOfUnityHalfGalois(
                NTTFiniteFieldInfo finiteFieldInfo,
                int rootDegree,
                bool inverted)
            {
                Contract.Requires <ArgumentOutOfRangeException>(rootDegree > 0, "The degree of the root should be a positive power of two.");
                Contract.Ensures(
                    Contract.ForAll(
                        Contract.Result <BigInteger[]>(),
                        (x => WhiteMath <BigInteger, CalcBigInteger> .PowerIntegerModular(x, (ulong)rootDegree, finiteFieldInfo.primeModulus) == 1)));

                BigInteger[] result = new BigInteger[rootDegree / 2];

                // The first root of unity is obviously one,
                // but we start with -1 if we need the inverse roots.
                // -
                if (!inverted)
                {
                    result[0] = 1;
                }
                else
                {
                    result[0] = finiteFieldInfo.primeModulus - 1;
                }

                // Calculate the desired roots of unity.
                // -
                for (int i = 1; i < rootDegree / 2; ++i)
                {
                    // All the desired roots of unity are obtained as powers of the principal root.
                    // -
                    result[i] = result[i - 1] * finiteFieldInfo.rootOfUnity % finiteFieldInfo.primeModulus;
                }

                // If performing the inverse NTT, we should reverse the array along
                // with a magic shift by 1 to get the inverted roots in the necessary order.
                //
                if (inverted)
                {
                    result[0] = 1;

                    for (int i = 1; i < rootDegree / 4; ++i)
                    {
                        result.Swap(i, rootDegree / 2 - i);
                    }
                }

                return(result);
            }