-
Notifications
You must be signed in to change notification settings - Fork 33
/
even_fermat_pseudoprimes_in_range.pl
129 lines (92 loc) · 3.59 KB
/
even_fermat_pseudoprimes_in_range.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#!/usr/bin/perl
# Daniel "Trizen" Șuteu
# Date: 22 February 2023
# https://github.com/trizen
# Generate all the k-omega even Fermat pseudoprimes in range [a,b]. (not in sorted order)
# Definition:
# k-omega primes are numbers n such that omega(n) = k.
# See also:
# https://en.wikipedia.org/wiki/Almost_prime
# https://en.wikipedia.org/wiki/Prime_omega_function
# https://trizenx.blogspot.com/2020/08/pseudoprimes-construction-methods-and.html
# OEIS sequences:
# https://oeis.org/A006935 -- Even pseudoprimes to base 2
# https://oeis.org/A130433 -- Even pseudoprimes to base 3
# PARI/GP program:
# even_fermat_psp(A, B, k, base) = A=max(A, vecprod(primes(k))); (f(m, l, p, j) = my(list=List()); forprime(q=p, sqrtnint(B\m, j), if(base%q != 0, my(v=m*q, t=q); while(v <= B, my(L=lcm(l, znorder(Mod(base, t)))); if(gcd(L, v) == 1, if(j==1, if(v>=A && if(k==1, !isprime(v), 1) && (v-1)%L == 0, listput(list, v)), list=concat(list, f(v, L, q+1, j-1))), break); v *= q; t *= q))); list); vecsort(Vec(f(2, 1, 3, k-1)));
# FIXME: it doesn't generate all the terms for bases > 2.
use 5.020;
use warnings;
use ntheory qw(:all);
use experimental qw(signatures);
sub divceil ($x, $y) { # ceil(x/y)
(($x % $y == 0) ? 0 : 1) + divint($x, $y);
}
sub even_fermat_pseudoprimes_in_range ($A, $B, $k, $base) {
if ($k <= 1) {
return;
}
$A = vecmax($A, pn_primorial($k));
my %seen;
my @list;
sub ($m, $L, $lo, $j) {
my $hi = rootint(divint($B, $m), $j);
if ($lo > $hi) {
return;
}
if ($j == 1) {
if ($L == 1) { # optimization
foreach my $p (@{primes($lo, $hi)}) {
$base % $p == 0 and next;
for (my $v = $m * $p ; $v <= $B ; $v *= $p) {
$v >= $A or next;
$k == 1 and is_prime($v) and next;
powmod($base, $v, $v) == $base or next;
push(@list, $v) if !$seen{$v}++;
}
}
return;
}
my $t = invmod($m, $L);
$t > $hi && return;
$t += $L * divceil($lo - $t, $L) if ($t < $lo);
for (my $p = $t ; $p <= $hi ; $p += $L) {
if (is_prime_power($p) and gcd($m, $p) == 1 and gcd($base, $p) == 1) {
my $v = $m * $p;
$v >= $A or next;
$k == 1 and is_prime($v) and next;
#($v - 1) % znorder($base, $p) == 0 or next;
powmod($base, $v, $v) == $base or next;
push(@list, $v) if !$seen{$v}++;
}
}
return;
}
foreach my $p (@{primes($lo, $hi)}) {
$base % $p == 0 and next;
my $z = znorder($base, $p);
gcd($m, $z) == 1 or next;
my $l = lcm($L, $z);
for (my ($q, $v) = ($p, $m * $p) ; $v <= $B ; ($q, $v) = ($q * $p, $v * $p)) {
if ($q > $p) {
powmod($base, $z, $q) == 1 or last;
}
__SUB__->($v, $l, $p + 1, $j - 1);
}
}
}
->(2, 1, 3, $k - 1);
return sort { $a <=> $b } @list;
}
# Generate all the even Fermat pseudoprimes to base 2 in range [1, 10^5]
my $from = 1;
my $upto = 1e7;
my $base = 2;
my @arr;
foreach my $k (1 .. 100) {
last if pn_primorial($k) > $upto;
push @arr, even_fermat_pseudoprimes_in_range($from, $upto, $k, $base);
}
say join(', ', sort { $a <=> $b } @arr);
__END__
161038, 215326, 2568226, 3020626, 7866046, 9115426