help with prime pairs code

Jabari Zakiya jzakiya at gmail.com
Sun Feb 2 21:17:39 UTC 2025


On Sunday, 2 February 2025 at 10:26:56 UTC, Sergey wrote:
>
> So after those updates the time improved
> ```bash
> [1000000, 5402]
> [17, 999983]
> [499943, 500057]
> 81 ms, 144 μs, and 7 hnsecs
> ```

Here's the D code with the suggested changes, and other updates.
Note, I make the source code look like Ruby|Crystal for my 
esthetics.

```
// Compile with ldc2: $ ldc2 --release -O3 -mcpu native 
prime_pairs_lohi.d
// Run as: echo 100000 | ./prime_pairs_lohi
// Update: 2025/02/02

module prime_pairs;

import std;
import std.datetime.stopwatch : StopWatch;

void prime_pairs_lohi(uint n) {
   if ((n&1) == 1 || n < 4) { return writeln("Input not even n > 
2"); }
   if (n <= 6) { writeln([n, 1]); writeln([n/2, n/2]); 
writeln([n/2, n/2]); return; }

   // generate the low-half-residues (lhr) r < n/2
   auto ndiv2 = n/2;               // llr:hhr midpoint
   auto rhi   = n-2;               // max residue limit
   uint[] lhr = iota(3, ndiv2, 2).filter!(e => gcd(e, n) == 
1).array;

   // store all the powers of the lhr members < n-2
   int[] lhr_mults;                // for lhr values not part of a 
pcp
   foreach(r; lhr) {               // step thru the lhr members
     auto r_pwr = r;               // set to first power of r
     if (r > rhi/r_pwr) break;     // exit if r^2 > n-2, as all 
others are too
     while (r < rhi/r_pwr)         // while r^e < n-2
       lhr_mults ~=(r_pwr *= r);   // store its current power of r
   }

   // store all the cross-products of the lhr members < n-2
   foreach(i, r; lhr) {
     auto ri_max = rhi / r;        // ri can't multiply r with 
values > this
     if (lhr[i+1] > ri_max) break; // exit if product of 
consecutive r’s > n-2
     foreach(ri; lhr[i+1..$]) {    // for each residue in reduced 
list
       if (ri > ri_max) break;     // exit for r if cross-product 
with ri > n-2
       lhr_mults ~= r * ri;        // store value if < n-2
   } }

   // convert lhr_mults vals > n/2 to their lhr complements n-r,
   // store them, those < n/2, in lhr_del; it now holds non-pcp 
lhr vals
   auto lhr_del = lhr_mults.map!((r_del) => r_del > ndiv2 ? n - 
r_del : r_del).array;
   lhr_del.sort!("a < b");
   lhr = setDifference(lhr, lhr_del).array;

   writeln([n,     lhr.length]);   // show n and pcp prime pairs 
count
   writeln([lhr[0],  n-lhr[0]]);   // show first pcp prime pair of 
n
   writeln([lhr[$-1],n-lhr[$-1]]); // show last  pcp prime pair of 
n
}

void main() {
   int n;
   readf("%s", &n);                // get input to n from terminal
   auto timer = StopWatch();       // create execution timer
   timer.start();                  // start it
   prime_pairs_lohi(n);            // run routine
   writeln(timer.peek());          // show timer results
}
```

The D version is now faster than Crystal.
```
D (LDC2 2.40)
➜  ~ echo 100000000 |./prime_pairs_lohi
[100000000, 291400]
[11, 99999989]
[49999757, 50000243]
7 secs, 422 ms, 641 μs, and 9 hnsecs

Crystal (1.15)
➜  ~ ./prime_pairs_lohi 100_000_000
[100000000, 291400]
[11, 99999989]
[49999757, 50000243]
00:00:10.454055301
```

I'll eventually do a Rust version, maybe C++, et al.

I want to think everybody for the help.
If you find more performance improvements please post them.


More information about the Digitalmars-d-learn mailing list