-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprog.pl
89 lines (67 loc) · 1.9 KB
/
prog.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
#!/usr/bin/perl
# Number of different terms in a period of continued fraction for square root of n-th repunit.
# https://oeis.org/A096488
# a(n) = {2, 3, 2, 8, 2, 37, 2, 76, 2, 217, 2, 870, 2, 583, 2, 5034, 2, 28494, 2, 10058, 2, ...}
#~ a(2) = 2
#~ a(3) = 3
#~ a(4) = 2
#~ a(5) = 8
#~ a(6) = 2
#~ a(7) = 37
#~ a(8) = 2
#~ a(9) = 76
#~ a(10) = 2
#~ a(11) = 217
#~ a(12) = 2
#~ a(13) = 870
#~ a(14) = 2
#~ a(15) = 583
#~ a(16) = 2
#~ a(17) = 5034
#~ a(18) = 2
#~ a(19) = 28494
#~ a(20) = 2
#~ a(21) = 10058
#~ a(22) = 2
# See also: https://oeis.org/A096485
use 5.014;
use strict;
use warnings;
use Math::GMPz;
sub period_length_mpz {
my ($n) = @_;
$n = Math::GMPz->new("$n");
my $x = Math::GMPz::Rmpz_init();
Math::GMPz::Rmpz_sqrt($x, $n);
return ($x) if Math::GMPz::Rmpz_perfect_square_p($n);
my $t = Math::GMPz::Rmpz_init();
my $y = Math::GMPz::Rmpz_init_set($x);
my $z = Math::GMPz::Rmpz_init_set_ui(1);
my $r = Math::GMPz::Rmpz_init();
my %seen;
my $count = 0;
Math::GMPz::Rmpz_add($r, $x, $x); # r = x+x
do {
# y = (r*z - y)
Math::GMPz::Rmpz_submul($y, $r, $z); # y = y - t*z
Math::GMPz::Rmpz_neg($y, $y); # y = -y
# z = ((n - y*y) / z)
Math::GMPz::Rmpz_mul($t, $y, $y); # t = y*y
Math::GMPz::Rmpz_sub($t, $n, $t); # t = n-t
Math::GMPz::Rmpz_divexact($z, $t, $z); # z = t/z
# t = floor((x + y) / z)
Math::GMPz::Rmpz_add($t, $x, $y); # t = x+y
Math::GMPz::Rmpz_tdiv_q($t, $t, $z); # t = floor(t/z)
$r = $t;
++$count
if !$seen{
Math::GMPz::Rmpz_fits_ulong_p($r)
? Math::GMPz::Rmpz_get_ui($r)
: Math::GMPz::Rmpz_get_str($r, 10)
}++;
} until (Math::GMPz::Rmpz_cmp_ui($z, 1) == 0);
return $count;
}
foreach my $n (2 .. 30) {
say "a($n) = ", period_length_mpz('1' x $n);
}