The aim of this software is to sum gaps lengths in a gap cycle and output a running tally of the sum of those gap lengths.

Take the gap cycle G(5#) for example. This is the sequence of gaps 64242462. For a gap length of 3 we have the triplets 642, 424, 242, 424, 246, 462... then we continue to wrap around the the start of the cycle to complete the last two triplets 626 and 264.

So, we end up with one triplet that sums to 14, four that sum to 12, two that sum to 10 and one that sums to 8. These final tallys are the results this code will generate.

Key aspects of the implementation are:

A segmented sieve to generate gaps within a Gap Cycle

Parallel processing such that the computation can be split accross multiple threads

Computation of multiple gap lengths concurrently, up to a gap length of 500

Computation Method

Below is G(7#) represented as a ring structure:

10

2

4

2

4

6

2

6

4

2

4

6

6

2

6

4

2

6

4

6

8

4

2

2

4

10

2

4

2

4

6

2

6

4

2

4

6

6

2

6

4

2

6

4

6

8

4

2

Lets look at the required calculation for a gap length of 7 somewhere in the middle of the gap cycle. For the below example we would sum 6+4+2+4+6+6+2 = 30

10

2

4

2

4

6

2

6

4

2

4

6

6

2

6

4

2

6

4

6

8

4

2

2

4

10

2

4

2

4

6

2

6

4

2

4

6

6

2

6

4

2

6

4

6

8

4

2

If we looped around the cycle we would eventually sum the reverse 2+6+6+4+2+4+6 = 30

10

2

4

2

4

6

2

6

4

2

4

6

6

2

6

4

2

6

4

6

8

4

2

2

4

10

2

4

2

4

6

2

6

4

2

4

6

6

2

6

4

2

6

4

6

8

4

2

Importantly, in the context of the required results, we don't care that we're looking at a mirror image, the order of the gaps do not matter. Hence we need only compute the gap length sum for the first instance and incrementing our running tally by 2 instead of 1.

Lets look closely at the end process for our gap length of 7. For our first three below the same mirror image rule applies, we increment our running tally by 2 instead of 1 for all these and save having to look at the other side of the gap cycle.

10

2

4

2

4

6

2

6

4

2

4

6

6

2

6

4

2

6

4

6

8

4

2

2

4

10

2

4

2

4

6

2

6

4

2

4

6

6

2

6

4

2

6

4

6

8

4

2

10

2

4

2

4

6

2

6

4

2

4

6

6

2

6

4

2

6

4

6

8

4

2

2

4

10

2

4

2

4

6

2

6

4

2

4

6

6

2

6

4

2

6

4

6

8

4

2

10

2

4

2

4

6

2

6

4

2

4

6

6

2

6

4

2

6

4

6

8

4

2

2

4

10

2

4

2

4

6

2

6

4

2

4

6

6

2

6

4

2

6

4

6

8

4

2

We have one more to look at. This last one below is a mirror image of itself, so for this one we must only increment our running tally by 1.

10

2

4

2

4

6

2

6

4

2

4

6

6

2

6

4

2

6

4

6

8

4

2

2

4

10

2

4

2

4

6

2

6

4

2

4

6

6

2

6

4

2

6

4

6

8

4

2

Based on the above observations we can compute results by analysing approxiately half the length of the gap cycle, with some special handling at the end points.

The final implementation performs the following sequence for a multi-threaded / parallel process:

Process end point around gap 2

Split remaining range for each thread in our parallel process

Execute a thread for each range

Process end point around gap 4

A gap cycle generator will find gaps, one at a time, over any range (which is required for parallel processing). An analysis array which is the size of the maximum gap length being analysed will compute results as each and every gap found.

The analysis array is not a list of gaps, it is a running sum of the list of gaps. For example, if our maximum analysis length was 7 and we used the first example above, our analysis array would not be [6,4,2,4,6,6,2]... it would be [30,24,20,18,14,8,2]. For each new gap found we then shift each element down our array and add the new gap to the element. So, for the next gap of 6 we perform the operation [24+6,20+6,18+6,14+6,8+6,2+6,6]. This method is more efficient than simply summing each length of gaps along the gap cycle using a buffer of gaps as they are found.

A two dimensional array holds the results generated by the analysis array, each time a gap is found this results array is incremented based on the contents of the analysis array. After the gap cycle range has been computed the results from each thread in the parallel process are merged into a final results array of the same dimensions.

The gap cycle generator is optimised to run over a range of integers, not a range of gaps. A consequence of this is that the ranges that each parallel process runs over must be an integer multiple of the segmented sieve size, otherwise the gap cycle generator will generate more gaps than required. A simpler method that ran over a range of gaps rather than a range of integers in the number line was abandoned as it is less efficient. Having said that, there is a function remaining in the class clsGapCycle which DOES exit the sieve process after a requested number of gaps is found, this is used only while processing the end point around gap 2.

Results can be saved as a CSV file, which will also include information about ratios and asymptotic ratios to gap length 2 as per the discussion in the paper.