Ejemplo n.º 1
0
        public void TestTwinCoprimeCount(UInt32 n)
        {
            UInt32 CnCount = (UInt32)Coprimes.CalculateQn(n);
            UInt32 BnCount = (UInt32)Coprimes.CalculateQn(n + 1);

            UInt32 PnPlusOne        = PrimeTable.Values[n];
            UInt32 PnPlusOneSquared = PnPlusOne * PnPlusOne;

            DynamicSimpleList <UInt32> CnList = new DynamicSimpleList <UInt32>();
            DynamicSimpleList <UInt32> FnList = new DynamicSimpleList <UInt32>();

            Coprimes.BruteForceCreateCnWithLimit(n, PnPlusOneSquared, CnList, FnList);
            Console.WriteLine("n = {0}, Pn+1 = {1}", n, PnPlusOne);

            UInt32 twinCoprimeCount = 0;

            for (UInt32 i = 2; i + 1 < CnList.Count - 1; i++)
            {
                UInt32 first  = CnList[i];
                UInt32 second = CnList[i + 1];
                if (second - first == 2)
                {
                    //Console.WriteLine("Twin Coprime {0}", first);
                    twinCoprimeCount++;
                }
            }

            Console.WriteLine("Cn,2 = {0}  (times Pn+1) = {1}, twin coprimes {2}",
                              PnPlusOne, PnPlusOneSquared, twinCoprimeCount);
        }
Ejemplo n.º 2
0
        public void TestCnFromCnMinusOne()
        {
            UInt32[] CnMinusOne = new UInt32[] { 1, 3, 5, 7 };
            UInt32[] Cn         = new UInt32[3];

            UInt32 CnLength;

            Coprimes.CnMinusOneToCn(CnMinusOne, (UInt32)CnMinusOne.Length, Cn, out CnLength);

            Assert.AreEqual(3U, CnLength);
            Assert.AreEqual(1U, Cn[0]);
            Assert.AreEqual(5U, Cn[1]);
            Assert.AreEqual(7U, Cn[2]);
        }
Ejemplo n.º 3
0
        public void TestTwinCoprimeCounts(UInt32 n)
        {
            UInt32 CnCount = (UInt32)Coprimes.CalculateQn(n);
            UInt32 BnCount = (UInt32)Coprimes.CalculateQn(n + 1);
            DynamicSimpleList <UInt32> FnList = new DynamicSimpleList <UInt32>();

            UInt32[] Bn        = Coprimes.BruteForceCreateCn(n, BnCount + 1, FnList);
            UInt32   PnPlusOne = Bn[1];

            Console.WriteLine("n = {0}, Pn+1 = {1}", n, PnPlusOne);

            Int32 i;

            for (i = 1; i < CnCount; i++)
            {
                UInt32 coprime = Bn[i];
                UInt32 limit   = coprime * PnPlusOne;

                UInt32 twinCoprimeCount = 0;
                for (int j = i; j + 1 <= BnCount; j++)
                {
                    UInt32 second = Bn[j + 1];
                    if (second >= limit)
                    {
                        break;
                    }
                    UInt32 first = Bn[j];
                    if (second - first == 2)
                    {
                        //Console.WriteLine("Twin Coprime {0}", first);
                        twinCoprimeCount++;
                    }
                }

                Console.WriteLine("Cn,{0} = {1}  (times Pn+1) = {2}, twin coprimes {3}",
                                  i + 1, coprime, limit, twinCoprimeCount);
            }
        }
Ejemplo n.º 4
0
        static Int32 Main(string[] args)
        {
            //
            // Process command line arguments
            //
            Options       options       = new Options();
            List <String> nonOptionArgs = options.Parse(args);

            if (nonOptionArgs.Count <= 0)
            {
                options.PrintUsage();
                return(1);
            }
            if (nonOptionArgs.Count != 1)
            {
                return(options.ErrorAndUsage("Expected {0} non-option arguments but got {1}",
                                             1, nonOptionArgs.Count));
            }

            UInt32 n = UInt32.Parse(nonOptionArgs[0]);

            if (n == 0)
            {
                return(options.ErrorAndUsage("n cannot be 0"));
            }

            UInt32 Pn         = PrimeTable.Values[n - 1];
            UInt32 PnMinusOne = PrimeTable.Values[n - 2];
            UInt32 PnPlusOne  = PrimeTable.Values[n];


            //
            // Find Qn
            //
            UInt32 cnCount;
            UInt64 QnIfSmallEnough = 0; // 0 means a UInt64 is not small enough to hold Qn

            if (options.MaxCnCount.set)
            {
                cnCount = options.MaxCnCount.ArgValue;

                try
                {
                    QnIfSmallEnough = Coprimes.CalculateQn(n);
                    if (QnIfSmallEnough < cnCount)
                    {
                        cnCount = (UInt32)QnIfSmallEnough;
                    }
                }
                catch (ArgumentOutOfRangeException e)
                {
                    Console.WriteLine(e.Message);
                    QnIfSmallEnough = 0;
                }
            }
            else
            {
                QnIfSmallEnough = Coprimes.CalculateQn(n);
                if (QnIfSmallEnough > UInt32.MaxValue)
                {
                    Console.WriteLine("Qn for n={0} is too large for a UInt64, use -m option to only generate the first part of the sequence", n);
                    return(1);
                }
                cnCount = (UInt32)QnIfSmallEnough;
            }

            //
            // Create the GnBuffer
            //
            ISimpleList <UInt32> GnList;

            if (cnCount == QnIfSmallEnough)
            {
                GnList = new FixedSimpleList <UInt32>((UInt32)Coprimes.CalculateQn(n - 1));
            }
            else
            {
                GnList = new DynamicSimpleList <UInt32>();
            }

            //
            // Find Primorial
            //
            UInt64 PrimorialIfSmallEnough = 0; // 0 means a UInt64 is not small enough to hold Primorial

            try
            {
                PrimorialIfSmallEnough = Coprimes.CalculatePrimorial(n);
            }
            catch (ArgumentOutOfRangeException e)
            {
            }


            Console.WriteLine("n = {0}, Pn = {1}, Qn = {2}, Primorial = {3}", n, Pn,
                              (QnIfSmallEnough == 0) ? "TooLargeForUInt64" : QnIfSmallEnough.ToString(),
                              (PrimorialIfSmallEnough == 0) ? "TooLargeForUInt64" : PrimorialIfSmallEnough.ToString());


            if (cnCount != QnIfSmallEnough)
            {
                Console.WriteLine();
                Console.WriteLine("NOTE: You have limited the results to {0}", cnCount);
            }



            //
            // For now just use the slow Cn creator
            //
            UInt32[] Cn = Coprimes.BruteForceCreateCn(n, cnCount + 1, GnList); // Add 1 to the CnCount in order to have Cn intervals


            //
            // Print
            //
            UInt64 maxCoprimeDecimalDigits = DecimalDigitCount(Cn[cnCount - 1]);
            String coprimeNumberFormat     = String.Format("{{0,{0}}}", maxCoprimeDecimalDigits);

            Console.WriteLine();
            if (options.DontPrintSequences.set)
            {
                Console.WriteLine("[Sequences Omitted]");
            }
            else
            {
                Console.Write("Gn:");
                for (UInt32 i = 0; i < GnList.Count; i++)
                {
                    Console.Write(' ');
                    Console.Write(coprimeNumberFormat, GnList[i]);
                }
                Console.WriteLine();
                Console.WriteLine();

                //
                // Print Indices
                //
                Console.Write("i :");
                for (UInt32 i = 1; i <= cnCount; i++)
                {
                    Console.Write(' ');
                    Console.Write(coprimeNumberFormat, i);
                }
                Console.WriteLine();

                //
                // Print Cn
                //
                Console.Write("Cn:");
                UInt32 currentGnIndex = 0;
                for (UInt32 i = 0; i < cnCount; i++)
                {
                    UInt32 coprime = Cn[i];

                    if (currentGnIndex < GnList.Count && coprime > GnList[currentGnIndex])
                    {
                        currentGnIndex++;
                        Console.Write('|');
                    }
                    else
                    {
                        Console.Write(' ');
                    }
                    Console.Write(coprimeNumberFormat, coprime);
                }
                // Print the first coprime of the next sequence
                Console.WriteLine(" ({0})", Cn[cnCount]);
                Console.WriteLine();

                Console.Write("In:");
                // Offset the interval numbers
                for (UInt32 i = 0; i < maxCoprimeDecimalDigits / 2; i++)
                {
                    Console.Write(' ');
                }
                for (UInt32 i = 0; i < cnCount; i++)
                {
                    Console.Write(' ');
                    Console.Write(coprimeNumberFormat, Cn[i + 1] - Cn[i]);
                }
                Console.WriteLine();
            }


            //
            // Generate BPrimes
            //
            UInt64[] bprimes = new UInt64[QnIfSmallEnough * PnPlusOne];
            {
                UInt64 bprimeIndex       = 0;
                UInt64 bprimeValueOffset = 0;
                for (UInt64 i = 0; i < PnPlusOne; i++)
                {
                    for (UInt64 j = 0; j < QnIfSmallEnough; j++)
                    {
                        bprimes[bprimeIndex++] = Cn[j] + bprimeValueOffset;
                    }
                    bprimeValueOffset += PrimorialIfSmallEnough;
                }
            }



            //
            // Analysis
            //
            UInt64 maxBprime = bprimes[bprimes.Length - 1];
            UInt64 maxBprimeDecimalDigits = DecimalDigitCount(maxBprime);
            String bprimeNumberFormat     = String.Format("{{0,{0}}}", maxBprimeDecimalDigits);

            Console.WriteLine();
            Console.WriteLine("Analyzing B_n+1 (B_{0})", n + 1);
            Console.WriteLine("-----------------------------------");

            /*
             * Console.WriteLine();
             * Console.WriteLine("B_{0}", n + 1);
             * Console.WriteLine("-----------------------------------");
             * {
             *  UInt32 bprimeIndex = 0;
             *  for (UInt32 i = 1; i <= PnPlusOne; i++)
             *  {
             *      Console.Write("[{0}]", i);
             *
             *      for (UInt32 j = 0; j < QnIfSmallEnough; j++)
             *      {
             *          Console.Write(' ');
             *          Console.Write(bprimeNumberFormat, bprimes[bprimeIndex]);
             *          bprimeIndex++;
             *      }
             *
             *      Console.WriteLine();
             *  }
             * }
             */

            /*
             * UInt32 maxFilterIndex;
             * {
             *  UInt32 filterIndex = 1;
             *  while (true)
             *  {
             *      //PrintFilterMap(PnPlusOne, (UInt32)QnIfSmallEnough, bprimes, filterIndex);
             *      filterIndex++;
             *      UInt64 bprimeChecker = bprimes[filterIndex];
             *      if (bprimeChecker * bprimeChecker > maxBprime) break;
             *  }
             *  maxFilterIndex = filterIndex - 1;
             *  Console.WriteLine("MaxFilterIndex: {0}, PnPlusOne: {1}", maxFilterIndex, PnPlusOne);
             * }
             */

            //
            // Print Combined Filter Map
            //

            /*
             * UInt32[] bprimeFilterColumnCount = new UInt32[QnIfSmallEnough];
             * UInt32[] bprimeFilterMap = new UInt32[bprimes.Length];
             * UInt32 maxFilter;
             * {
             *  UInt32 bprimeIndex;
             *  for(bprimeIndex = 1; true; bprimeIndex++)
             *  {
             *      UInt64 bprime = bprimes[bprimeIndex];
             *      UInt32 multiplierIndex;
             *      for (multiplierIndex = bprimeIndex; true; multiplierIndex++)
             *      {
             *          UInt64 multipler = bprimes[multiplierIndex];
             *          UInt64 filterNumber = bprime * multipler;
             *          if (filterNumber > maxBprime)
             *          {
             *              break;
             *          }
             *
             *          //
             *          // Mark filter number
             *          //
             *          UInt32 filterIndex = (UInt32)((float)filterNumber / (float)maxBprime * (float)bprimes.Length);
             *          if (filterIndex >= bprimes.Length) filterIndex = (UInt32)bprimes.Length - 1U;
             *
             *          UInt64 guess = bprimes[filterIndex];
             *          if (guess == filterNumber)
             *          UInt32 modQn = 0;
             *          for (UInt32 check = 0; true; check++)
             *          {
             *              //Console.WriteLine("FilterNumber {0} Guess {1} Correct", filterNumber, guess);
             *          }
             *          else if(guess > filterNumber)
             *          {
             *              do
             *              {
             *                  filterIndex--;
             *              } while (bprimes[filterIndex] != filterNumber);
             *              //Console.WriteLine("FilterNumber {0} Guess {1} Over", filterNumber, guess);
             *          }
             *          else
             *          {
             *              do
             *              {
             *                  filterIndex++;
             *              } while (bprimes[filterIndex] != filterNumber);
             *              //Console.WriteLine("FilterNumber {0} Guess {1} Under", filterNumber, guess);
             *          }
             *
             *          if (bprimeFilterMap[filterIndex] == 0)
             *          {
             *              bprimeFilterMap[filterIndex] = bprimeIndex;
             *              //Console.WriteLine("filter[{0}] = {1}", filterNumber, bprimeIndex);
             *              if (bprimeFilterMap[check] == 0)
             *              {
             *                  bprimeFilterMap[check] = bprimeIndex;
             *                  bprimeFilterColumnCount[modQn]++;
             *                  //Console.WriteLine("filter[{0}] = {1}", filterNumber, bprimeIndex);
             *              }
             *              break;
             *              modQn++;
             *              if (modQn == QnIfSmallEnough) modQn = 0;
             *          }
             *
             *      }
             *      if (multiplierIndex == bprimeIndex) break;
             *  }
             *  maxFilter = bprimeIndex;
             * }
             *
             *
             * //
             * // Search for Horizontal Prime Path
             * //
             * for (UInt32 i = 0; i < (UInt32)QnIfSmallEnough - 1; i++)
             * {
             *  UInt32 clearPathIndex = i;
             *  while (true)
             *  {
             *      if (bprimeFilterMap[clearPathIndex] == 0 && bprimeFilterMap[clearPathIndex + 1] == 0)
             *      {
             *          if (clearPathIndex != i)
             *          {
             *              //Console.WriteLine("Column {0} had to use lower row", i);
             *          }
             *          break; // Found clear path
             *      }
             *      clearPathIndex += (UInt32)QnIfSmallEnough;
             *      if (clearPathIndex >= bprimeFilterMap.Length)
             *      {
             *          Console.WriteLine("Column {0} had no prime path", i);
             *          break;
             *      }
             *  }
             * }
             *
             *
             */



            /*
             * UInt64 maxFilterDecimalDigits = DecimalDigitCount(maxFilter);
             * String filterNumberFormat = String.Format("{{0,{0}}}", maxFilterDecimalDigits);
             * Console.WriteLine();
             * Console.WriteLine("FilterMap");
             * Console.WriteLine("-----------------------------------");
             * {
             *  UInt32 filterIndex = 0;
             *  for (UInt32 i = 1; i <= PnPlusOne; i++)
             *  {
             *      Console.Write("[{0,4}]", i);
             *
             *      for (UInt32 j = 0; j < QnIfSmallEnough; j++)
             *      {
             *          Console.Write(' ');
             *          Console.Write(filterNumberFormat, bprimeFilterMap[filterIndex]);
             *          filterIndex++;
             *      }
             *
             *      Console.WriteLine();
             *  }
             * }
             */

            //
            // Write Image File
            //

            /*
             * using(FileStream stream = new FileStream(String.Format(@"C:\temp\CoprimImage{0}.data", n), FileMode.Create, FileAccess.Write))
             * {
             *  FilterMapToImage(stream, bprimeFilterMap, PnPlusOne, (UInt32)QnIfSmallEnough);
             * }
             */



            /*
             * //
             * // Count the number of primes
             * //
             * UInt32 currentCoprimeIndex = 1;
             * UInt32 nextPrimeIndex = n + 1;
             * UInt32 primeCount = 1;
             * //Console.WriteLine("Cn,2 = P{0} = {1}", nextPrimeIndex + 1, Cn[1]);
             * while (true)
             * {
             *  currentCoprimeIndex++;
             *  if (currentCoprimeIndex >= cnCount) break;
             *  UInt32 coprime = Cn[currentCoprimeIndex];
             *
             *  UInt32 nextPrime = PrimeTable.Values[nextPrimeIndex];
             *  while (true)
             *  {
             *      if (coprime == nextPrime)
             *      {
             *          //Console.WriteLine("Cn,{0} = P{1} = {2}", currentCoprimeIndex + 1, nextPrimeIndex + 1, nextPrime);
             *          primeCount++;
             *          nextPrimeIndex++;
             *          break;
             *      }
             *      currentCoprimeIndex++;
             *      if (currentCoprimeIndex >= cnCount) break;
             *      coprime = Cn[currentCoprimeIndex];
             *  }
             * }
             * Console.WriteLine("There are {0} primes in this coprime set", primeCount);
             *
             *
             * //
             * // Count Intervals and get max interval
             * //
             * List<UInt32> intervalCounts = new List<UInt32>();
             * for (int i = 0; i < cnCount; i++)
             * {
             *  UInt32 interval = Cn[i + 1] - Cn[i];
             *  UInt32 intervalIndex = interval / 2 - 1;
             *
             *  //
             *  // Add to the interval index
             *  //
             *  while (intervalIndex >= intervalCounts.Count)
             *  {
             *      intervalCounts.Add(0);
             *  }
             *
             *  intervalCounts[(Int32)intervalIndex]++;
             * }
             *
             * UInt32 maxInterval = (UInt32)intervalCounts.Count * 2;
             * }*/

            /*
             * UInt32 max = 0;
             * for (int i = 0; i < bprimeFilterColumnCount.Length; i++)
             * {
             *  if (Cn[i + 1] - Cn[i] == 2)
             *  {
             *      UInt32 count = bprimeFilterColumnCount[i];
             *      if (count > max) max = count;
             *      Console.Write(count);
             *  }
             *  else if(i > 0 && Cn[i] - Cn[i-1] == 2)
             *  {
             *      UInt32 count = bprimeFilterColumnCount[i];
             *      if (count > max) max = count;
             *      Console.Write('-');
             *      Console.Write(count);
             *      Console.Write("  ");
             *  }
             * }
             * Console.WriteLine();
             * Console.WriteLine("Max: {0}", max);
             */

            return(0);
        }
        static Int32 Main(string[] args)
        {
            //
            // Process command line arguments
            //
            Options       options       = new Options();
            List <String> nonOptionArgs = options.Parse(args);

            if (nonOptionArgs.Count <= 0)
            {
                options.PrintUsage();
                return(1);
            }
            if (nonOptionArgs.Count != 1)
            {
                return(options.ErrorAndUsage("Expected {0} non-option arguments but got {1}",
                                             1, nonOptionArgs.Count));
            }

            UInt32 MaxNumber = UInt32.Parse(nonOptionArgs[0]);

            if (MaxNumber == 0)
            {
                return(options.ErrorAndUsage("MaxNumber cannot be 0"));
            }

            UInt32 C1Length = (MaxNumber + (((MaxNumber % 2) == 1) ? (UInt32)1 : 0)) / 2;

            //
            // Generate the primes
            //
            Console.WriteLine("Allocating two arrays of length {0}...", C1Length);
            UInt32[] coprimes1 = new UInt32[C1Length];
            UInt32[] coprimes2 = new UInt32[C1Length];
            Console.WriteLine("Done allocating memory");


            Int64 sequenceGenerationStartTime = Stopwatch.GetTimestamp();

            //
            // InitializeCoprimes1
            //
            UInt32 sum = 1;

            for (UInt32 i = 0; i < C1Length; i++)
            {
                coprimes1[i] = sum;
                sum         += 2;
            }

            //
            // Generate sequence
            //
            UInt32 coprimes1Length = C1Length, coprimes2Length;
            UInt32 n = 1;
            UInt32 Pn;

            while (true)
            {
                Coprimes.CnMinusOneToCn(coprimes1, coprimes1Length, coprimes2, out coprimes2Length);
                n++;

                Pn = coprimes2[2];
                if (Pn * Pn > coprimes1[coprimes1Length - 1])
                {
                    Console.WriteLine("Pn {0}, coprimes.length = {1}, coprimes[last] = {2}, n = {3}",
                                      Pn, coprimes1Length, coprimes1[coprimes1Length - 1], n);
                    n += coprimes1Length;
                    Pn = coprimes1[coprimes1Length - 1];
                    break;
                }

                Coprimes.CnMinusOneToCn(coprimes2, coprimes2Length, coprimes1, out coprimes1Length);
                n++;

                Pn = coprimes1[2];
                if (Pn * Pn > coprimes2[coprimes2Length - 1])
                {
                    Console.WriteLine("Pn {0}, coprimes.length = {1}, coprimes[last] = {2}, n = {3}",
                                      Pn, coprimes2Length, coprimes2[coprimes2Length - 1], n);
                    n += coprimes2Length;
                    Pn = coprimes2[coprimes2Length - 1];
                    break;
                }
            }

            //
            // Print sequence generation time
            //
            Int64 sequenceGenerationEndTime = Stopwatch.GetTimestamp();

            Console.WriteLine("Sequence Generation Time: {0} milliseconds",
                              (sequenceGenerationEndTime - sequenceGenerationStartTime).StopwatchTicksAsUInt32Milliseconds());

            //
            // Print the nth prime number
            //
            Console.WriteLine("Prime {0} is equal to {1}", n, Pn);

            return(0);
        }
Ejemplo n.º 6
0
        static Int32 Main(string[] args)
        {
            //
            // Process command line arguments
            //
            Options       options       = new Options();
            List <String> nonOptionArgs = options.Parse(args);

            if (nonOptionArgs.Count <= 0)
            {
                options.PrintUsage();
                return(1);
            }
            if (nonOptionArgs.Count != 1)
            {
                return(options.ErrorAndUsage("Expected {0} non-option arguments but got {1}",
                                             1, nonOptionArgs.Count));
            }

            UInt32 n = UInt32.Parse(nonOptionArgs[0]);

            if (n == 0)
            {
                return(options.ErrorAndUsage("n cannot be 0"));
            }

            UInt32 Pn = PrimeTable.Values[n - 1];
            //UInt32 PnMinusOne = PrimeTable.Values[n - 2];
            UInt32 PnPlusOne = PrimeTable.Values[n];

            //
            // Find Qn
            //
            UInt32 cnCount;
            UInt64 QnIfSmallEnough = 0; // 0 means a UInt64 is not big enough to hold Qn

            if (options.MaxCnCount.set)
            {
                cnCount = options.MaxCnCount.ArgValue;

                try
                {
                    QnIfSmallEnough = Coprimes.CalculateQn(n);
                    if (QnIfSmallEnough < cnCount)
                    {
                        cnCount = (UInt32)QnIfSmallEnough;
                    }
                }
                catch (ArgumentOutOfRangeException e)
                {
                    Console.WriteLine(e.Message);
                    QnIfSmallEnough = 0;
                }
            }
            else
            {
                QnIfSmallEnough = Coprimes.CalculateQn(n);
                if (QnIfSmallEnough > UInt32.MaxValue)
                {
                    Console.WriteLine("Qn for n={0} is too large for a UInt64, use -m option to only generate the first part of the sequence", n);
                    return(1);
                }
                cnCount = (UInt32)QnIfSmallEnough;
            }

            //
            // Create the GnBuffer
            //
            ISimpleList <UInt32> GnList;

            if (cnCount == QnIfSmallEnough)
            {
                GnList = new FixedSimpleList <UInt32>((UInt32)Coprimes.CalculateQn(n - 1));
            }
            else
            {
                GnList = new DynamicSimpleList <UInt32>();
            }


            //
            // Find Primorial
            //
            UInt64 PrimorialIfSmallEnough = 0; // 0 means a UInt64 is not small enough to hold Primorial

            try
            {
                PrimorialIfSmallEnough = Coprimes.CalculatePrimorial(n);
            }
            catch (ArgumentOutOfRangeException e)
            {
            }


            Console.WriteLine("n = {0}, Pn = {1}, Qn = {2}, Primorial = {3}", n, Pn,
                              (QnIfSmallEnough == 0) ? "TooLargeForUInt64" : QnIfSmallEnough.ToString(),
                              (PrimorialIfSmallEnough == 0) ? "TooLargeForUInt64" : PrimorialIfSmallEnough.ToString());


            if (cnCount != QnIfSmallEnough)
            {
                Console.WriteLine();
                Console.WriteLine("NOTE: You have limited the results to {0}", cnCount);
            }


            //
            // For now just use the slow Cn creator
            //
            UInt32[] Cn = Coprimes.BruteForceCreateCn(n, cnCount + 1, GnList); // Add 1 to the CnCount in order to have Cn intervals


            //
            // Print
            //
            Console.WriteLine();
            if (options.DontPrintSequences.set)
            {
                Console.WriteLine("[Sequences Omitted]");
            }
            else
            {
                UInt32 maxDecimalDigits = DecimalDigitCount(Cn[cnCount - 1]);
                String numberFormat     = String.Format("{{0,{0}}}", maxDecimalDigits);


                Console.Write("Gn:");
                for (UInt32 i = 0; i < GnList.Count; i++)
                {
                    Console.Write(' ');
                    Console.Write(numberFormat, GnList[i]);
                }
                Console.WriteLine();
                Console.WriteLine();

                //
                // Print Indices
                //
                Console.Write("i :");
                for (UInt32 i = 1; i <= cnCount; i++)
                {
                    Console.Write(' ');
                    Console.Write(numberFormat, i);
                }
                Console.WriteLine();

                //
                // Print Cn
                //
                Console.Write("Cn:");
                UInt32 currentGnIndex = 0;
                for (UInt32 i = 0; i < cnCount; i++)
                {
                    UInt32 coprime = Cn[i];

                    if (currentGnIndex < GnList.Count && coprime > GnList[currentGnIndex])
                    {
                        currentGnIndex++;
                        Console.Write('|');
                    }
                    else
                    {
                        Console.Write(' ');
                    }
                    Console.Write(numberFormat, coprime);
                }
                // Print the first coprime of the next sequence
                Console.WriteLine(" ({0})", Cn[cnCount]);
                Console.WriteLine();

                Console.Write("In:");
                // Offset the interval numbers
                for (UInt32 i = 0; i < maxDecimalDigits / 2; i++)
                {
                    Console.Write(' ');
                }
                for (UInt32 i = 0; i < cnCount; i++)
                {
                    Console.Write(' ');
                    Console.Write(numberFormat, Cn[i + 1] - Cn[i]);
                }
                Console.WriteLine();
            }



            //
            // Analysis
            //

            Console.WriteLine();
            Console.WriteLine("Performing analysis...");
            Console.WriteLine("-----------------------------------");

            //
            // Count the number of primes
            //
            UInt32 currentCoprimeIndex = 1;
            UInt32 nextPrimeIndex      = n + 1;
            UInt32 primeCount          = 1;

            //Console.WriteLine("Cn,2 = P{0} = {1}", nextPrimeIndex + 1, Cn[1]);
            while (true)
            {
                currentCoprimeIndex++;
                if (currentCoprimeIndex >= cnCount)
                {
                    break;
                }
                UInt32 coprime = Cn[currentCoprimeIndex];

                UInt32 nextPrime = PrimeTable.Values[nextPrimeIndex];
                while (true)
                {
                    if (coprime == nextPrime)
                    {
                        //Console.WriteLine("Cn,{0} = P{1} = {2}", currentCoprimeIndex + 1, nextPrimeIndex + 1, nextPrime);
                        primeCount++;
                        nextPrimeIndex++;
                        break;
                    }
                    currentCoprimeIndex++;
                    if (currentCoprimeIndex >= cnCount)
                    {
                        break;
                    }
                    coprime = Cn[currentCoprimeIndex];
                }
            }
            Console.WriteLine("There are {0} primes in this coprime set", primeCount);


            //
            // Count Intervals and get max interval
            //
            List <UInt32> intervalCounts = new List <UInt32>();

            for (int i = 0; i < cnCount; i++)
            {
                UInt32 interval      = Cn[i + 1] - Cn[i];
                UInt32 intervalIndex = interval / 2 - 1;

                //
                // Add to the interval index
                //
                while (intervalIndex >= intervalCounts.Count)
                {
                    intervalCounts.Add(0);
                }

                intervalCounts[(Int32)intervalIndex]++;
            }

            UInt32 maxInterval = (UInt32)intervalCounts.Count * 2;

            Console.WriteLine();
            Console.WriteLine("Maximum interval is {0}", maxInterval);
            Console.WriteLine();

            UInt32 maxIntervalDecimalDigits = DecimalDigitCount(maxInterval);
            String intervalFormat           = String.Format("{{0,{0}}}", maxIntervalDecimalDigits);

            Console.WriteLine("Interval Counts");
            Console.WriteLine("-------------------------");
            UInt32 maxIntervalCount = 0;

            for (UInt32 i = 0; i < intervalCounts.Count; i++)
            {
                UInt32 interval      = (i + 1) * 2;
                UInt32 intervalCount = intervalCounts[(Int32)i];

                if (intervalCount > maxIntervalCount)
                {
                    maxIntervalCount = intervalCount;
                }

                Console.WriteLine("{0} : {1}", String.Format(intervalFormat, interval), intervalCount);
            }


            UInt32 maxIntervalCountDecimalDigits = DecimalDigitCount(maxIntervalCount);
            String intervalCountFormat           = String.Format("{{0,{0}}}", maxIntervalCountDecimalDigits);



            //
            // Count Intervals Pairs
            //
            List <List <UInt32> > intervalPairCountTable = new List <List <UInt32> >();
            UInt32 maxIntervalRowIndex = 0;

            for (int i = 0; i < cnCount - 1; i++)
            {
                UInt32 firstInterval       = Cn[i + 1] - Cn[i];
                UInt32 secondInterval      = Cn[i + 2] - Cn[i + 1];
                UInt32 firstIntervalIndex  = firstInterval / 2 - 1;
                UInt32 secondIntervalIndex = secondInterval / 2 - 1;

                if (secondIntervalIndex > maxIntervalRowIndex)
                {
                    maxIntervalRowIndex = secondIntervalIndex;
                }

                //
                // Add to the interval pair to the table
                //
                while (firstIntervalIndex >= intervalPairCountTable.Count)
                {
                    intervalPairCountTable.Add(new List <UInt32>());
                }

                List <UInt32> intervalRow = intervalPairCountTable[(Int32)firstIntervalIndex];
                while (secondIntervalIndex >= intervalRow.Count)
                {
                    intervalRow.Add(0);
                }
                intervalRow[(Int32)secondIntervalIndex]++;
            }
            Console.WriteLine();
            Console.WriteLine("Interval Pair Map:");
            Console.Write("{0} :", String.Format(intervalFormat, ""));
            for (UInt32 intervalIndex = 0; intervalIndex <= maxIntervalRowIndex; intervalIndex++)
            {
                UInt32 interval = (intervalIndex + 1) * 2;
                Console.Write(" {0}", String.Format(intervalCountFormat, interval));
            }
            Console.WriteLine();
            for (UInt32 i = 0; i < intervalPairCountTable.Count; i++)
            {
                UInt32 firstInterval = (i + 1) * 2;
                Console.Write("{0} :", String.Format(intervalFormat, firstInterval));
                List <UInt32> intervalRow = intervalPairCountTable[(Int32)i];
                UInt32        j;
                for (j = 0; j < intervalRow.Count; j++)
                {
                    UInt32 secondInterval = (j + 1) * 2;
                    Console.Write(" {0}", String.Format(intervalCountFormat, intervalRow[(Int32)j]));
                }
                for (; j <= maxIntervalRowIndex; j++)
                {
                    Console.Write(" {0}", String.Format(intervalCountFormat, 0));
                }
                Console.WriteLine();
            }



            //
            // Check distances between 2s
            //
            //Console.Write("Distances between 2s:");
            Int32 last2Index  = 0;
            Int32 maxDistance = 0;

            for (int i = 0; i < cnCount; i++)
            {
                if (Cn[i + 1] - Cn[i] == 2)
                {
                    Int32 distance = i - last2Index;
                    //Console.Write(" {0}", distance);
                    if (distance > maxDistance)
                    {
                        maxDistance = distance;
                    }
                    last2Index = i;
                }
            }
            Console.WriteLine();
            Console.WriteLine("Max distance between 2s: {0}", maxDistance);

            //
            // Find intervals between Twin Coprimes
            //
            Int32  lastTwinCoprime        = -1;
            UInt32 maxTwinCoprimeDistance = 0;

            for (UInt32 i = 0; i < cnCount - 1; i++)
            {
                UInt32 coprime = Cn[i];
                if (Cn[i + 1] - coprime == 2)
                {
                    UInt32 distance = (UInt32)((Int32)coprime - lastTwinCoprime);
                    //Console.WriteLine("Cn[{0}] = {1} is a twin coprime (distance = {2})", i, coprime, distance);
                    if (distance > maxTwinCoprimeDistance)
                    {
                        maxTwinCoprimeDistance = distance;
                    }
                    lastTwinCoprime = (Int32)coprime;
                }
            }
            Console.WriteLine("Max Twin Coprime Distance: {0}", maxTwinCoprimeDistance);

            //
            // Checks twin coprimes between filter numbers
            //
            Console.WriteLine();
            Console.WriteLine("Twin Coprimes Between Filter Numbers:");
            UInt32 currentFilterNumberIndex = 1;
            UInt32 previousFilterNumber     = GnList[0];
            UInt32 currentFilterNumber      = GnList[1];
            UInt32 currentTwinCoprimeCount  = 0;

            for (UInt32 i = 1; i < cnCount; i++)
            {
                UInt32 coprime = Cn[i];
                if (coprime > currentFilterNumber)
                {
                    //Console.WriteLine("There are {0} twin coprimes between {1} and {2}",
                    //    currentTwinCoprimeCount, previousFilterNumber, currentFilterNumber);
                    currentFilterNumberIndex++;
                    if (currentFilterNumberIndex >= GnList.Count)
                    {
                        break;
                    }
                    previousFilterNumber    = currentFilterNumber;
                    currentFilterNumber     = GnList[currentFilterNumberIndex];
                    currentTwinCoprimeCount = 0;
                }

                if (Cn[i + 1] - coprime == 2)
                {
                    currentTwinCoprimeCount++;
                }
            }

            //
            // Check palindromic
            //
            Console.WriteLine();
            if (cnCount == QnIfSmallEnough)
            {
                Int32 pandoromeMismatches = 0;
                for (int i = 0; i < cnCount - 1; i++)
                {
                    if (Cn[i + 1] - Cn[i] != Cn[cnCount - i - 1] - Cn[cnCount - i - 2])
                    {
                        Console.WriteLine("Palindrome mismatch at {0}", i + 1);
                        pandoromeMismatches++;
                    }
                }
                if (pandoromeMismatches == 0)
                {
                    Console.WriteLine("In is a palindrome");
                }
                else
                {
                    Console.WriteLine("There were {0} palindrome mismatches", pandoromeMismatches);
                }
            }

            //
            // Count filter numbers between 1 and Pn-1#
            //
            UInt32 limitedFilterNumberCount = 0;
            UInt32 filterNumberLimit        = (UInt32)((double)PrimorialIfSmallEnough / (double)PnPlusOne);

            for (UInt32 i = 0; i < QnIfSmallEnough; i++)
            {
                if (Cn[i] > filterNumberLimit)
                {
                    break;
                }
                limitedFilterNumberCount++;
            }
            Console.WriteLine();
            Console.WriteLine("There are {0} coprimes between 1 and {1}",
                              limitedFilterNumberCount, filterNumberLimit);



            //
            // Check mods
            //
            for (UInt32 i = 0; i < cnCount; i++)
            {
                //Console.WriteLine("Cn[{0}] mod {1} = {2}", i + 1, Pn, Cn[i] % Pn);
            }

            Console.WriteLine("Pn = {0}", Pn);
            for (UInt32 i = 0; i < GnList.Count; i++)
            {
                //Console.WriteLine("Gn[{0}] = {1} mod {2} = {3}", i + 1, GnBuffer[i], Pn, GnBuffer[i] % Pn);
            }


            //
            // Generate CnMinusOne
            //

            ISimpleList <UInt32> GnMinusOneList = new DynamicSimpleList <UInt32>();

            UInt32[] CnMinusOne = Coprimes.BruteForceCreateCn((UInt32)(n - 1), (UInt32)(Coprimes.CalculateQn(n - 1) * Pn), GnMinusOneList);


            Console.WriteLine();
            UInt32 QnMinusOne = (UInt32)Coprimes.CalculateQn(n - 1);

            Console.WriteLine("Qn-1 = {0}, Pn = {1}", QnMinusOne, Pn);
            Console.WriteLine();
            Console.WriteLine("The first {0} values", QnMinusOne);
            for (UInt32 i = 0; i < QnMinusOne; i++)
            {
                //Console.WriteLine("Cn-1[{0,3}] = {1,3} mod {2} = {3} (k mod {4} = {5})",
                //    i + 1, CnMinusOne[i], Pn, CnMinusOne[i] % Pn, QnMinusOne, (i % QnMinusOne) + 1);
            }
            Console.WriteLine();
            UInt32 modZeroCount = 0;

            UInt32 lastImportantMod      = 0;
            UInt32 lastImportantModCount = 0;

            List <UInt32> importantMods      = new List <UInt32>();
            List <UInt32> importantModCounts = new List <UInt32>();

            for (UInt32 i = 0; i < CnMinusOne.Length; i++)
            {
                if (CnMinusOne[i] % Pn == 0)
                {
                    modZeroCount++;

                    UInt32 importantMod = CnMinusOne[(i % QnMinusOne)] % Pn;
                    if (importantMod == lastImportantMod)
                    {
                        lastImportantModCount++;
                    }
                    else
                    {
                        Console.WriteLine("{0} Entries with mod {1}", lastImportantModCount, lastImportantMod);
                        importantMods.Add(lastImportantMod);
                        importantModCounts.Add(lastImportantModCount);
                        lastImportantMod      = importantMod;
                        lastImportantModCount = 0;
                    }

                    //Console.WriteLine("Fn[{0,3}] = Cn-1[{1,3}] = {2,4} mod {3} = {4} (k mod {5} = {6,3}) (Cn-1[{6,3}] = {7,3} mod {3,3} = {8})",
                    //    modZeroCount,i + 1, CnMinusOne[i], Pn, CnMinusOne[i] % Pn, QnMinusOne, (i % QnMinusOne) + 1, CnMinusOne[(i % QnMinusOne)], CnMinusOne[(i % QnMinusOne)] % Pn);
                }
            }

            for (int i = 0; i < importantMods.Count; i++)
            {
                Console.WriteLine("Count {0,4} Mod {1}", importantModCounts[i], importantMods[i]);
            }


            return(0);
        }