I found over the weekend a few places in the code giving me arithmetic overflow errors on certain inputs. I’ve updated the code to eliminate the problems, but I don’t see why they existed (I thought I accounted for their possibilities, but guess I didn’t).

Here are the gists again to the updated code.

twinprimes_ssoz

cousinprimes_ssoz

Here’s the nature of the problem.

I was testing for values at the upper 64-bit range, (2^64 -1 = 18446744073709551615)

When running the code with these inputs it gives the correct results (need 16GB of mem).

```
CRYSTAL_WORKERS=16 ./twinprimes_ssoz 18436744073709551615 18436744073709000000
threads = 16
using Prime Generator parameters for P5
segment size = 18388 resgroups for seg bitarray
twinprime candidates = 55167; resgroups = 18389
each of 3 threads has nextp[2 x 331650] array
setup time = 14.445965 secs
perform twinprimes ssoz sieve
3 of 3 twinpairs done
sieve time = 0.00788 secs
total time = 14.453845 secs
last segment = 18389 resgroups; segment slices = 1
total twins = 395; last twin = 18436744073709550662+/-1
```

But when I used values at the absolute upper limit I got arithmetic overflow errors.

```
CRYSTAL_WORKERS=16 ./twinprimes_ssoz 18446744073709551615 18446744073709000000
threads = 16
using Prime Generator parameters for P5
segment size = 18388 resgroups for seg bitarray
twinprime candidates = 55164; resgroups = 18388
prime = 555829Unhandled exception: Arithmetic overflow (OverflowError)
from crystal/share/crystal/src/kernel.cr:25:1 in 'twinprimes_ssoz'
from twinprimes_ssozgist.cr:284:1 in '__crystal_main'
from crystal/share/crystal/src/crystal/main.cr:115:5 in 'main'
from /lib64/libc.so.6 in '??'
from /lib64/libc.so.6 in '__libc_start_main'
from ../sysdeps/x86_64/start.S:117 in '_start'
from ???
```

That error message was of no help, but I eventually placed some `puts`

lines on certain values in places and figured it out.

The first place causing an error was in the routine `sozpg`

, which generates sieving primes.

```
n, rem = start_num.divmod prime
primes << prime if (res_0 <= prime <= val) && (prime &* (n + 1) <= end_num || rem == 0)
^
```

Adding the `&`

eliminated that overflow, but I don’t see why it was occurring, because both `prime`

and `end_num`

are `u64`

values.

The other overflow came in `twins_sieve`

, where again, adding `&`

s fixed the overflows.

```
ki += 1 if ((ki &* modpg) &+ r_hi - 2) < start_num
k_max -= 1 if ((k_max - 1) &* modpg &+ r_hi) > end_num
```

Again `ki`

, `k_max`

, `start|end_num`

are all `u64`

s.

1: Can someone explain why these overflows occur.

2: Will 1.5.0 fix having to explicitly put these `&`

operations in the code?

After the fixes the code runs correctly for these inputs.

```
CRYSTAL_WORKERS=16 ./twinprimes_ssoz 18446744073709551615 18446744073709000000
threads = 16
using Prime Generator parameters for P5
segment size = 18388 resgroups for seg bitarray
twinprime candidates = 55164; resgroups = 18388
each of 3 threads has nextp[2 x 203280218] array
setup time = 18.342097 secs
perform twinprimes ssoz sieve
3 of 3 twinpairs done
sieve time = 5.344191 secs
total time = 23.686288 secs
last segment = 18388 resgroups; segment slices = 1
total twins = 361; last twin = 18446744073709550772+/-1
```

FYI: `18446744073709550772+/-1`

is the largest twin prime within 2^64.