help with prime pairs code
Jabari Zakiya
jzakiya at gmail.com
Sun Feb 2 22:40:41 UTC 2025
On Sunday, 2 February 2025 at 21:17:39 UTC, Jabari Zakiya wrote:
> 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.
I am really impressed!
D is phenomenally memory efficient with this code.
I just ran the D code for some really large n values.
On my older Lenovo Legion 5, using Linux (June 2024) w/16GB
I was able to go up to n = 1,000,000,0000 and it took up ~14.4GB
max, out of ~14.9GB usable.
I got a new, fast TUXEDO Gen 3, w/64GB (Jan 2025), so I'm going
to how high I can go on it.
Here are some results on the Lenovo Legion 5.
```
➜ ~ echo 500000000 |./prime_pairs_lohi3
[500000000, 1219610]
[7, 499999993]
[249999877, 250000123]
43 secs, 402 ms, 950 μs, and 3 hnsecs
➜ ~
➜ ~ echo 900000000 |./prime_pairs_lohi3
[900000000, 4132595]
[37, 899999963]
[449999993, 450000007]
36 secs, 135 ms, 163 μs, and 6 hnsecs
➜ ~
➜ ~ echo 1000000000 |./prime_pairs_lohi3
[1000000000, 2274205]
[71, 999999929]
[499999931, 500000069]
1 minute, 32 secs, 87 ms, 624 μs, and 8 hnsecs
➜ ~
➜ ~ echo 1500000000 |./prime_pairs_lohi3
[1500000000, 6543613]
[43, 1499999957]
[749999927, 750000073]
1 minute, 6 secs, 205 ms, 381 μs, and 5 hnsecs
➜ ~
```
More information about the Digitalmars-d-learn
mailing list