```    1%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2/*	Nan.Numerics.Prime
3	A simple prime number library
4	Copyright 2016 Julio P. Di Egidio
5	<mailto:julio@diegidio.name>
6	<http://julio.diegidio.name/Projects/Nan.Numerics.Prime/>
7
8	This file is part of Nan.Numerics.Prime.
9
10	Nan.Numerics.Prime is free software: you can redistribute it and/or modify
12	the Free Software Foundation, either version 3 of the License, or
13	(at your option) any later version.
14
15	Nan.Numerics.Prime is distributed in the hope that it will be useful,
16	but WITHOUT ANY WARRANTY; without even the implied warranty of
17	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18	GNU General Public License for more details.
19
20	You should have received a copy of the GNU General Public License
21	along with Nan.Numerics.Prime.  If not, see <http://www.gnu.org/licenses/>.
22*/

23%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
24
25% (SWI-Prolog 7.3.25)
26
27% TODO: Implement dynamic wheel with option for level?
28
29:- module(prime_whl, []).
30
31:- public
32	test_/2,		% +N:posint, -Cert:boolean
33	right_/3,		% +N:posint, -P:posint, -Cert:boolean
34	left_/3,		% +N:posint, -P:posint, -Cert:boolean
35	lev_/1.			% -Lev:posint
```

# A simple prime number library :: wheel

Module `prime_whl` provides low-level predicates to test candidate primality of numbers based on a prime wheel of level `4`, i.e. generated by the first `4` consecutive prime numbers.

NOTE: Predicates in this module are not meant for public use.

author
- Julio P. Di Egidio
version
- 1.2.5-beta
- GNU GPLv3
To be done
- Implement dynamic wheel with option for level? */
```   52%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
```
test_(+N:posint, -Cert:boolean) is semidet
True if N is a candidate prime number.

Cert is `true` if N is certainly prime, otherwise it is `false`.

```   60test_(N, true) :-
61	lr_a_(N, _, R), !, N == R.
62test_(N, Cert) :-
63	lro_p_(N, _, 0),
64	cert_(N, Cert).
```
right_(+N:posint, -P:posint, -Cert:boolean) is det
P is the smallest candidate prime number greater than or equal to N.

Cert is `true` if P is certainly prime, otherwise it is `false`.

```   72right_(N, P, true) :-
73	lr_a_(N, _, P), !.
74right_(N, P, Cert) :-
75	lro_p_(N, _, ROff),
76	P is N + ROff,
77	cert_(P, Cert).
```
left_(+N:posint, -P:posint, -Cert:boolean) is semidet
P is the greatest candidate prime number less than or equal to N. Fails if N equals `1`.

Cert is `true` if P is certainly prime, otherwise it is `false`.

```   86left_(1, _, _) :- !, fail.
87left_(N, P, true) :-
88	lr_a_(N, P, _), !.
89left_(N, P, Cert) :-
90	lro_p_(N, LOff, _),
91	P is N - LOff,
92	cert_(P, Cert).
93
94%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
```
lev_(-Lev:posint) is det
Lev is the number of consecutive prime numbers starting from `2` that generate this wheel.
```  101lev_(4/*lev*/).
102
103%	lr_a_(+N:posint, -L:posint, -R:posint) is semidet.
104
105lr_a_(N, L, R) :-
106	N < 11/*la+1*/,
107	whl_a_(N, L, R).
108
109%	lro_p_(+N:posint, -LOff:nonneg, -ROff:nonneg) is det.
110
111lro_p_(N, LOff, ROff) :-
112	N0 is N - 11/*la+1*/,
113	I0 is N0 mod 210/*lp*/,
114	whl_p_(I0, LOff, ROff).
115
116%	cert_(+N:posint, -Cert:boolean) is det.
117
118cert_(N, true) :-
119	N < 121/*(la+1)^2*/, !.
120cert_(_, false).
121
122%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
123
124whl_lev_(4).
125
126whl_la_(10).
127
128whl_lp_(210).
129
130whl_a_(1, 0, 2).
131whl_a_(2, 2, 2).
132whl_a_(3, 3, 3).
133whl_a_(4, 3, 5).
134whl_a_(5, 5, 5).
135whl_a_(6, 5, 7).
136whl_a_(7, 7, 7).
137whl_a_(8, 7, 11).
138whl_a_(9, 7, 11).
139whl_a_(10, 7, 11).
140
141whl_p_(0, 0, 0).
142whl_p_(1, 1, 1).
143whl_p_(2, 0, 0).
144whl_p_(3, 1, 3).
145whl_p_(4, 2, 2).
146whl_p_(5, 3, 1).
147whl_p_(6, 0, 0).
148whl_p_(7, 1, 1).
149whl_p_(8, 0, 0).
150whl_p_(9, 1, 3).
151whl_p_(10, 2, 2).
152whl_p_(11, 3, 1).
153whl_p_(12, 0, 0).
154whl_p_(13, 1, 5).
155whl_p_(14, 2, 4).
156whl_p_(15, 3, 3).
157whl_p_(16, 4, 2).
158whl_p_(17, 5, 1).
159whl_p_(18, 0, 0).
160whl_p_(19, 1, 1).
161whl_p_(20, 0, 0).
162whl_p_(21, 1, 5).
163whl_p_(22, 2, 4).
164whl_p_(23, 3, 3).
165whl_p_(24, 4, 2).
166whl_p_(25, 5, 1).
167whl_p_(26, 0, 0).
168whl_p_(27, 1, 3).
169whl_p_(28, 2, 2).
170whl_p_(29, 3, 1).
171whl_p_(30, 0, 0).
172whl_p_(31, 1, 1).
173whl_p_(32, 0, 0).
174whl_p_(33, 1, 3).
175whl_p_(34, 2, 2).
176whl_p_(35, 3, 1).
177whl_p_(36, 0, 0).
178whl_p_(37, 1, 5).
179whl_p_(38, 2, 4).
180whl_p_(39, 3, 3).
181whl_p_(40, 4, 2).
182whl_p_(41, 5, 1).
183whl_p_(42, 0, 0).
184whl_p_(43, 1, 5).
185whl_p_(44, 2, 4).
186whl_p_(45, 3, 3).
187whl_p_(46, 4, 2).
188whl_p_(47, 5, 1).
189whl_p_(48, 0, 0).
190whl_p_(49, 1, 1).
191whl_p_(50, 0, 0).
192whl_p_(51, 1, 5).
193whl_p_(52, 2, 4).
194whl_p_(53, 3, 3).
195whl_p_(54, 4, 2).
196whl_p_(55, 5, 1).
197whl_p_(56, 0, 0).
198whl_p_(57, 1, 3).
199whl_p_(58, 2, 2).
200whl_p_(59, 3, 1).
201whl_p_(60, 0, 0).
202whl_p_(61, 1, 1).
203whl_p_(62, 0, 0).
204whl_p_(63, 1, 5).
205whl_p_(64, 2, 4).
206whl_p_(65, 3, 3).
207whl_p_(66, 4, 2).
208whl_p_(67, 5, 1).
209whl_p_(68, 0, 0).
210whl_p_(69, 1, 3).
211whl_p_(70, 2, 2).
212whl_p_(71, 3, 1).
213whl_p_(72, 0, 0).
214whl_p_(73, 1, 5).
215whl_p_(74, 2, 4).
216whl_p_(75, 3, 3).
217whl_p_(76, 4, 2).
218whl_p_(77, 5, 1).
219whl_p_(78, 0, 0).
220whl_p_(79, 1, 7).
221whl_p_(80, 2, 6).
222whl_p_(81, 3, 5).
223whl_p_(82, 4, 4).
224whl_p_(83, 5, 3).
225whl_p_(84, 6, 2).
226whl_p_(85, 7, 1).
227whl_p_(86, 0, 0).
228whl_p_(87, 1, 3).
229whl_p_(88, 2, 2).
230whl_p_(89, 3, 1).
231whl_p_(90, 0, 0).
232whl_p_(91, 1, 1).
233whl_p_(92, 0, 0).
234whl_p_(93, 1, 3).
235whl_p_(94, 2, 2).
236whl_p_(95, 3, 1).
237whl_p_(96, 0, 0).
238whl_p_(97, 1, 1).
239whl_p_(98, 0, 0).
240whl_p_(99, 1, 3).
241whl_p_(100, 2, 2).
242whl_p_(101, 3, 1).
243whl_p_(102, 0, 0).
244whl_p_(103, 1, 7).
245whl_p_(104, 2, 6).
246whl_p_(105, 3, 5).
247whl_p_(106, 4, 4).
248whl_p_(107, 5, 3).
249whl_p_(108, 6, 2).
250whl_p_(109, 7, 1).
251whl_p_(110, 0, 0).
252whl_p_(111, 1, 5).
253whl_p_(112, 2, 4).
254whl_p_(113, 3, 3).
255whl_p_(114, 4, 2).
256whl_p_(115, 5, 1).
257whl_p_(116, 0, 0).
258whl_p_(117, 1, 3).
259whl_p_(118, 2, 2).
260whl_p_(119, 3, 1).
261whl_p_(120, 0, 0).
262whl_p_(121, 1, 5).
263whl_p_(122, 2, 4).
264whl_p_(123, 3, 3).
265whl_p_(124, 4, 2).
266whl_p_(125, 5, 1).
267whl_p_(126, 0, 0).
268whl_p_(127, 1, 1).
269whl_p_(128, 0, 0).
270whl_p_(129, 1, 3).
271whl_p_(130, 2, 2).
272whl_p_(131, 3, 1).
273whl_p_(132, 0, 0).
274whl_p_(133, 1, 5).
275whl_p_(134, 2, 4).
276whl_p_(135, 3, 3).
277whl_p_(136, 4, 2).
278whl_p_(137, 5, 1).
279whl_p_(138, 0, 0).
280whl_p_(139, 1, 1).
281whl_p_(140, 0, 0).
282whl_p_(141, 1, 5).
283whl_p_(142, 2, 4).
284whl_p_(143, 3, 3).
285whl_p_(144, 4, 2).
286whl_p_(145, 5, 1).
287whl_p_(146, 0, 0).
288whl_p_(147, 1, 5).
289whl_p_(148, 2, 4).
290whl_p_(149, 3, 3).
291whl_p_(150, 4, 2).
292whl_p_(151, 5, 1).
293whl_p_(152, 0, 0).
294whl_p_(153, 1, 3).
295whl_p_(154, 2, 2).
296whl_p_(155, 3, 1).
297whl_p_(156, 0, 0).
298whl_p_(157, 1, 1).
299whl_p_(158, 0, 0).
300whl_p_(159, 1, 3).
301whl_p_(160, 2, 2).
302whl_p_(161, 3, 1).
303whl_p_(162, 0, 0).
304whl_p_(163, 1, 5).
305whl_p_(164, 2, 4).
306whl_p_(165, 3, 3).
307whl_p_(166, 4, 2).
308whl_p_(167, 5, 1).
309whl_p_(168, 0, 0).
310whl_p_(169, 1, 1).
311whl_p_(170, 0, 0).
312whl_p_(171, 1, 5).
313whl_p_(172, 2, 4).
314whl_p_(173, 3, 3).
315whl_p_(174, 4, 2).
316whl_p_(175, 5, 1).
317whl_p_(176, 0, 0).
318whl_p_(177, 1, 3).
319whl_p_(178, 2, 2).
320whl_p_(179, 3, 1).
321whl_p_(180, 0, 0).
322whl_p_(181, 1, 1).
323whl_p_(182, 0, 0).
324whl_p_(183, 1, 3).
325whl_p_(184, 2, 2).
326whl_p_(185, 3, 1).
327whl_p_(186, 0, 0).
328whl_p_(187, 1, 1).
329whl_p_(188, 0, 0).
330whl_p_(189, 1, 9).
331whl_p_(190, 2, 8).
332whl_p_(191, 3, 7).
333whl_p_(192, 4, 6).
334whl_p_(193, 5, 5).
335whl_p_(194, 6, 4).
336whl_p_(195, 7, 3).
337whl_p_(196, 8, 2).
338whl_p_(197, 9, 1).
339whl_p_(198, 0, 0).
340whl_p_(199, 1, 1).
341whl_p_(200, 0, 0).
342whl_p_(201, 1, 9).
343whl_p_(202, 2, 8).
344whl_p_(203, 3, 7).
345whl_p_(204, 4, 6).
346whl_p_(205, 5, 5).
347whl_p_(206, 6, 4).
348whl_p_(207, 7, 3).
349whl_p_(208, 8, 2).
350whl_p_(209, 9, 1).
351
352%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
```