Karim Belabas on Thu, 03 Aug 2017 08:23:47 +0200 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
Re: Continued fractions for square roots |
* Charles Greathouse [2017-08-02 22:29]: > I'm working on a project where I compute the periodic part of the continued > fraction of the square root of a (nonsquare) positive integer. > > The obvious approach is to take the numerical square root, compute the > continued fraction (dropping the last, say, two terms), and see if it ends > in a periodic part with enough members to feel confident in the pattern, > maybe three. If not, increase precision and try again. > > But I was concerned about the possibility of numerical error, so I rolled > my own implementation which avoids t_REALs. I think the algorithm is > classic; I modified it slightly from Beceanu 2003 > > cf(D)={ > my(a0=sqrtint(D\1),a=List(),b=List([a0]),c=List([D-a0^2]),n=1); > if(D<0 || issquare(D), error("D must be a positive rational nonsquare")); > while(1, > \\ Set a[n], b[n+1], and c[n+1] > listput(a, (a0+b[n])\c[n]); > listput(b, a[n]*c[n]-b[n]); > listput(c, (D-b[n+1]^2)\c[n]); > \\ Check if a loop is formed > for(i=1,n-1, > if(a[i]==a[n] && b[i+1]==b[n+1] && c[i+1]==c[n+1], This last loop is going to kill you ( O(n^2), where n ~ D^(1/2) is expected ). You should use a map (or a hashtable in C...) Something like this [ completely untested :-) ] cf(D)={ my(a0=sqrtint(D\1), a=List(a0), b=List(a0), c=List(D-a0^2), n=1); if(D<0 || issquare(D), error("D must be a positive rational nonsquare")); my(M=Map()); mapput(M,[a0,a0,c[1]], n); while(1, my (A,B,C); \\ Set a[n+1], b[n+1], and c[n+1] listput(a, A = (a0+b[n])\c[n]); listput(b, B = A*c[n]-b[n]); listput(c, C = (D-B^2)\c[n]); if (!mapisdefined(M, [A,B,C]), n++; mapput(M, [A,B,C], n); next); \\ a loop is formed i = mapget(M,[A,B,C]); my(k=n+1-i,loop=vector(k,j,a[n+1-k+j])); fordiv(k,d, for(j=1,k-d, if(loop[j]!=loop[j+d], next(2))); \\ Least period is of length d a=Vec(a); forstep(j=n-k,1,-1, if(a[j]!=a[j+d], return([a[1..j], a[j+1..j+d]])) ); return([[],[a[1..d]]]) \\ Unlikely to happen, but possible I suppose ) ); } Cheers, K.B. -- Karim Belabas, IMB (UMR 5251) Tel: (+33) (0)5 40 00 26 17 Universite de Bordeaux Fax: (+33) (0)5 40 00 21 23 351, cours de la Liberation http://www.math.u-bordeaux.fr/~kbelabas/ F-33405 Talence (France) http://pari.math.u-bordeaux.fr/ [PARI/GP] `