File Coverage

goldbach.c
Criterion Covered Total %
statement 58 59 98.3
branch 74 80 92.5
condition n/a
subroutine n/a
pod n/a
total 132 139 94.9


line stmt bran cond sub pod time code
1             #include
2             #include
3             #include
4              
5             #include "ptypes.h"
6             #include "goldbach.h"
7             #define FUNC_is_prime_in_sieve 1
8             #include "sieve.h"
9             #include "cache.h"
10             #include "primality.h"
11             #include "util.h"
12              
13             /* TODO: Consider adding Waring-Goldbach(n,k,t) */
14              
15              
16 41           UV minimal_goldbach_pair(UV n)
17             {
18             UV p;
19 41 100         if (n < 4) return 0;
20 37 100         if (n & 1 || n == 4)
    100          
21 15 100         return (is_prime(n-2)) ? 2 : 0;
22             /* Maybe this could be faster using a sieve. Max p < 4*10^18 is 9781 */
23 1720 50         for (p=3; p <= n/2; p = next_prime(p))
24 1720 100         if (is_prime(n-p))
25 22           return p;
26 0           return 0;
27             }
28              
29             #if 0
30             /* Some ways for finding Goldbach pairs */
31              
32             /* 1. Simple */
33             START_DO_FOR_EACH_PRIME(3,n/2) {
34             if (is_prob_prime(n-p))
35             L[s++] = p;
36             } END_DO_FOR_EACH_PRIME
37             Renew(L, s, UV); *size=s; return L;
38              
39             /* 2. Get a full list then walk from the edges. Not bad for small sizes. */
40             if (n >= 22 && n < 4294967295U) {
41             uint32_t *pr;
42             UV nprimes = range_prime_sieve_32(&pr, n, 0); /* pr[0]=2, pr[1]=3, */
43             UV i = 4, j = nprimes-1;
44             while (i <= j) {
45             UV sum = pr[i] + pr[j];
46             if (sum > n) {
47             j--;
48             } else {
49             if (sum == n)
50             L[s++] = pr[i];
51             i++;
52             }
53             }
54             Safefree(pr);
55             }
56              
57             /* 3. Single sieve */
58             if (n >= 22) {
59             unsigned char* segment;
60             UV seg_base, seg_low, seg_high;
61             void* ctx = start_segment_primes(n/2, n-11, &segment);
62             while (next_segment_primes(ctx, &seg_base, &seg_low, &seg_high)) {
63             START_DO_FOR_EACH_SIEVE_PRIME( segment, seg_base, seg_low, seg_high )
64             UV q = n-p;
65             if (is_prob_prime(q))
66             L[s++] = q;
67             END_DO_FOR_EACH_SIEVE_PRIME
68             }
69             end_segment_primes(ctx);
70             sort_uv_array(L, s);
71             }
72              
73             /* The double sieve, low as inner, comes out fastest. */
74             #endif
75              
76 38           static UV sieve_pairs(UV* L, UV n) {
77 38           size_t s = 0;
78 38 100         if (n >= 22) {
79             unsigned char* segment;
80             UV seg_base, seg_low, seg_high;
81 22           void* ctx = start_segment_primes(n/2, n-11, &segment);
82 44 100         while (next_segment_primes(ctx, &seg_base, &seg_low, &seg_high)) {
83 22           size_t qbeg = n-seg_high, qend = n-seg_low;
84 22           UV qdbeg = qbeg/30, qdend = (qend+29)/30;
85             unsigned char* lowsieve;
86 22           New(0, lowsieve, qdend-qdbeg+1, unsigned char);
87 22           sieve_segment(lowsieve, qdbeg, qdend);
88 704 50         START_DO_FOR_EACH_SIEVE_PRIME( segment, seg_base, seg_low, seg_high )
    100          
    100          
    100          
    100          
89 598           UV q = n-p;
90 598 100         if (L) {
91 299 100         if (is_prime_in_sieve(lowsieve, q-qdbeg*30))
92 74           L[s++] = q;
93             } else {
94 299 100         if (is_prime_in_sieve(lowsieve, q-qdbeg*30))
95 74           s++;
96             }
97 38           END_DO_FOR_EACH_SIEVE_PRIME
98 22           Safefree(lowsieve);
99             }
100 22           end_segment_primes(ctx);
101 22 100         if (L && s > 1) { /* Reverse the list */
    100          
102 6           size_t i = 0, j = s-1;
103 40 100         while (i < j) { UV t=L[i]; L[i]=L[j]; L[j]=t; i++; j--; }
104             }
105             }
106 38           return s;
107             }
108              
109 38           UV* goldbach_pairs(size_t *size, UV n)
110             {
111             UV *L;
112 38           size_t s = 0;
113 38 100         if (n < 4) return 0;
114 34 100         if (n & 1 || n == 4) {
    100          
115 15 100         if (!is_prime(n-2))
116 5           return 0;
117 10           New(0, L, 1, UV);
118 10           L[0] = 2;
119 10           *size = 1;
120 10           return L;
121             }
122             /* Overestimate */
123 19 50         New(0, L, max_nprimes(n/2) >> (n > 30030 ? 1 : 0), UV);
124              
125 19 50         if (n >= 6 && is_prime(n-3)) L[s++] = 3;
    100          
126 19 100         if (n >= 10 && is_prime(n-5)) L[s++] = 5;
    100          
127 19 100         if (n >= 14 && is_prime(n-7)) L[s++] = 7;
    100          
128              
129 19           s += sieve_pairs(L+s, n);
130              
131 19 50         Renew(L, s, UV); /* Possibly reduce storage */
132 19           *size = s;
133 19           return L;
134             }
135              
136 38           UV goldbach_pair_count(UV n)
137             {
138 38           size_t s = 0;
139 38 100         if (n < 4) return 0;
140 34 100         if (n & 1 || n == 4)
    100          
141 15           return (is_prime(n-2)) ? 1 : 0;
142              
143 19 50         if (n >= 6 && is_prime(n-3)) s++;
    100          
144 19 100         if (n >= 10 && is_prime(n-5)) s++;
    100          
145 19 100         if (n >= 14 && is_prime(n-7)) s++;
    100          
146              
147 19           s += sieve_pairs(0, n);
148              
149 19           return s;
150             }
151              
152             /* See https://arxiv.org/pdf/2601.16193 for ideas on upper,lower,approx. */