-
Notifications
You must be signed in to change notification settings - Fork 0
/
lucas-carmichael_numbers_in_range.pl
83 lines (57 loc) · 2.02 KB
/
lucas-carmichael_numbers_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
#!/usr/bin/perl
# Daniel "Trizen" Șuteu
# Date: 27 August 2022
# https://github.com/trizen
# Generate all the Lucas-Carmichael numbers with n prime factors in a given range [a,b]. (not in sorted order)
# See also:
# https://en.wikipedia.org/wiki/Almost_prime
use 5.020;
use ntheory qw(:all);
use experimental qw(signatures);
sub divceil ($x, $y) { # ceil(x/y)
my $q = divint($x, $y);
($q * $y == $x) ? $q : ($q + 1);
}
sub lucas_carmichael_numbers_in_range ($A, $B, $k, $callback) {
$A = vecmax($A, pn_primorial($k));
sub ($m, $lambda, $p, $k, $u = undef, $v = undef) {
if ($k == 1) {
printf("# $m -> ($u, $v) -> 10^%.3f\n", log($v - $u) / log(10)) if ($v - $u > 2e6);
if ($v - $u > 1e10) {
die "Range too large!\n";
}
foreach my $p (@{primes($u, $v)}) {
my $t = $m * $p;
if (($t + 1) % $lambda == 0 and ($t + 1) % ($p + 1) == 0) {
$callback->($t);
}
}
return;
}
my $s = rootint(divint($B, $m), $k);
for (my $r ; $p <= $s ; $p = $r) {
$r = next_prime($p);
my $L = lcm($lambda, $p + 1);
gcd($L, $m) == 1 or next;
my $t = $m * $p;
my $u = divceil($A, $t);
my $v = divint($B, $t);
if ($u <= $v) {
__SUB__->($t, $L, $r, $k - 1, (($k == 2 && $r > $u) ? $r : $u), $v);
}
}
}
->(1, 1, 3, $k);
}
my $min_k = 10; # mininum number of prime factors
my $max_k = 1e4; # maxinum number of prime factors
#my $from = 1; # generate terms >= this
#my $upto = 196467189590024639; # generate terms <= this
# Generate terms in this range
my $from = 3614740529402519;
my $upto = 20576473996736735;
foreach my $k ($min_k .. $max_k) {
last if pn_primorial($k) > $upto;
say "# Generating with k = $k";
lucas_carmichael_numbers_in_range($from, $upto, $k, sub ($n) { say $n });
}