May 2, 2025

Hardy Littlewood (C++)

Patterns of primes continue forever.

DownloadOpen

The Hardy-Littlewood conjecture essentially says that even though primes grow sparse as numbers grow large; they will continue to appear in pairs or other patterns forever. That should not really be true because they are in general thinning out as the numbers grow large. So it is a key feature we can explore.

They use something called Prime Tuples which are sets of primes arranged in certain ways. One example is 'Twin Primes' {3,5}, {5,7}, {11,13}

There are lots of examples:

'Prime Cousins'; numbers 4 apart {3,7}, {7,11}

'Prime Quadruplets: {5,7,11,13}.

The highest known prime quadruplet p = 667,674,063,382,677 × 2^{33,608} − 1

Anyway. For our interest the patterns continue forever according to Hardy and Littlewood and because that is the case it probably means something helpful.

In English I would characterise it as because they do not escape from each other at Large N; there is something causing them to come back as pairs, and cousins. That's thing is Riemann's Zeta.

I wrote some code which is insufficient really because n isn't large enough to make the point. The idea is that you can see as the prime pairs get larger the gaps do not always get larger. This isn't strictly reflecting Hardy Littlewood either but just making a point that the whole thing is not infinitely divergent.

#include <iostream>
#include <vector>
#include <iomanip> // For formatting

void generateTwinPrimeSpacings(int limit) {
    // Sieve of Eratosthenes
    std::vector<bool> isPrime(limit + 1, true);
    isPrime[0] = isPrime[1] = false;
    
    for (int i = 2; i * i <= limit; ++i) {
        if (isPrime[i]) {
            for (int j = i * i; j <= limit; j += i) {
                isPrime[j] = false;
            }
        }
    }
    
    // Store twin prime pairs and their starting points
    std::vector<int> twinPrimeStarts;
    for (int i = 2; i <= limit - 2; ++i) {
        if (isPrime[i] && isPrime[i + 2]) {
            twinPrimeStarts.push_back(i);
        }
    }
    
    // Print table header
    std::cout << "Twin Prime Pairs and Spacings up to " << limit << ":\n";
    std::cout << "--------------------------------------------\n";
    std::cout << "Prime 1 | Prime 2 | Spacing | Change\n";
    std::cout << "--------|---------|---------|-------\n";
    
    // Print first pair without spacing or change
    if (!twinPrimeStarts.empty()) {
        std::cout << std::setw(7) << twinPrimeStarts[0] << " | "
                  << std::setw(7) << twinPrimeStarts[0] + 2 << " | "
                  << std::setw(7) << "-" << " | "
                  << std::setw(5) << "-" << "\n";
    }
    
    // Print subsequent pairs with spacing and change
    for (size_t i = 1; i < twinPrimeStarts.size(); ++i) {
        int currentSpacing = twinPrimeStarts[i] - twinPrimeStarts[i - 1];
        std::string change = "-";
        
        // Calculate change in spacing (skip for first comparison)
        if (i > 1) {
            int prevSpacing = twinPrimeStarts[i - 1] - twinPrimeStarts[i - 2];
            if (currentSpacing > prevSpacing) {
                change = "+";
            } else if (currentSpacing < prevSpacing) {
                change = "-";
            } else {
                change = "="; // Equal spacing
            }
        }
        
        std::cout << std::setw(7) << twinPrimeStarts[i] << " | "
                  << std::setw(7) << twinPrimeStarts[i] + 2 << " | "
                  << std::setw(7) << currentSpacing << " | "
                  << std::setw(5) << change << "\n";
    }
}

int main() {
    int limit = 1000; // Adjustable limit
    generateTwinPrimeSpacings(limit);
    return 0;
}