Using Bhaskara's Chakravala method for solving
Note that we have mixed strategies. In its current form, nres uses the true minimum value for the improving (m,1,dnorm())
while originally we kept less than d. This results in shortening.
Explanation of functions:
dnorm(x,d) : calculates the norm of
for the modulus d.
bhav(x,y,d): calculates the bhavana (product in our field) of x,y with modulus d.
mbh(list,d): multi-bhavana on a list.
res(
) solves
.
nres(
,d) solves as above and reports an answer an optimal answer - the one with smallest norm with modulus d.
The answer is a triple [a,1,c] where c is the dnorm of (a,1).
improve(u,d) uses the nres and combines u with the optimal solution. d is the modulus.
imp(u,d) same as improve, except it skips the multiplication (bhavana). Answer is a new triple with the leftover part of the dnorm at the end.
red(u,a,d) factors out a from u and reports a triple
where c is the new dnorm.
dolist(list,d) keeps on extending the list by improving and reducing the last created (actually the first) term!
dolis is the same, except uses imp and hence leaves the parts unmultiplied.
build(list,d) Finishes the multiplications postponed in dolis.
> |
Functions
> | dnorm:=(x,d)->x[1]^2-d*x[2]^2:# norm w.r.t. d |
> | bhav:=proc(x,y,d) local ans,tmpx,tmpy,var,tmp; #Bhavana of Brahmagupta-Bhaskara tmpx:=x[1]+var*x[2];tmpy:=y[1]+var*y[2]; tmp:=expand(tmpx*tmpy);tmp:=subs(var^2=d,tmp); ans:=[coeff(tmp,var,0),coeff(tmp,var,1)]; ans:=[op(ans),dnorm(ans,d)];end: |
> | mbh:=proc(lis,d) local ans,i;#multiple bhavana ans:=lis[1]; for i from 2 to nops(lis) do; ans:=bhav(ans,lis[i],MD); od; ans; end: |
> | res:=proc(u) local ans,x;#resolution for a suitable unitary sol. ans:=msolve(u[1]+u[2]*x,abs(u[3])); end: |
> | nres:=proc(u,d) local tmp,ans,x,a1,a2;# Same as res, except the answer is a triple. tmp:=msolve(u[1]+u[2]*x,abs(u[3])); ans:=subs(tmp,x);while ans^2<d do; #print(ans); ans:=ans+abs(u[3]); od; a2:=abs(ans^2-d);a1:=abs((ans-abs(u[3]))^2-d); #print(ans,a1,a2); if a1<=a2 then ans:=ans-abs(u[3]);fi; #print([ans,1,dnorm([ans,1],d)]); [ans,1,dnorm([ans,1],d)]; end: |
> | improve:=(u,d)->bhav(u,nres(u,d),d): #combines u with its resolution. imp:=proc(u,d) local tmp,ans; tmp:=nres(u,d); print(tmp[3],u[3]);ans:=[tmp[1],tmp[2],tmp[3]/u[3]]:end: |
> | red:=proc(u,a,d) local ans; #Factors out a from u ans:=[u[1]/a,u[2]/a]; ans:=[op(ans),dnorm(ans,d)];end: |
> | dolist:=proc(l,d) local lis,tmp; # shortcut to improvement in a list! lis:=l; #nres(lis[1],d); tmp:=improve(lis[1],d); tmp:=red(tmp,abs(lis[1][3]),d);lis:=[%,op(lis)]; end: ## dolis:=proc(l,d) local lis,tmp; # shortcut to improvement in a list! lis:=l; #nres(lis[1],d); tmp:=imp(lis[1],d); lis:=[tmp,op(lis)]; end: ## build:=proc(lis,MD) local tmp,ans,i,n; n:=nops(lis); tmp:=[seq([lis[i][1],lis[i][2]],i=1..n)]:print(tmp): tmp:=mbh(tmp,MD); ans:=red(tmp,product(lis[i][3],i=1..n),MD);end: |
> | ; |
> | dolis([[10,1,-3]],103); |
> | dolist(%,103); |
The above is now exclusively used in the worksheet!
> | red([27,6,45],3,19); |
> | nres([4,1,-3],19); |
Case of 11
> | MD:=11;l11:=[[3,1,dnorm([3,1],11)]]; |
> | dolis(l11,MD); |
> | build(%,MD); |
> |
> |
Case of 17
> | MD:=17; |
> | l17:=[[4,1,dnorm([4,1],MD)]]; |
Case of 19
> | MD:=19; #modulus is set to 19 |
> | l19:=[[4,1,dnorm([4,1],MD)]]; |
> | dolis(l19,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | build(%,MD); |
> |
> |
Case of 43
> | MD:=43; |
> | l43:=[[7,1,dnorm([7,1],MD)]]; |
> | dolist(%,MD); |
> | dolist(%,MD); |
> | dolist(%,MD); |
> | dolist(%,MD); |
> | dolist(%,MD); |
> | bhav([59,9],[7,1],MD);red(%,2,MD); |
> | bhav([400,61],[5,1],MD);red(%,3,MD); |
> | bhav([1541,235],[7,1],MD);red(%,6,MD); |
> | dnorm([3482,531],MD); |
> |
> | dolis(l43,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> |
> |
> |
Case of 47
> | MD:=47: #Modulus is 47; |
> | lis47:=[[7,1,dnorm([7,1],MD)]]; |
> | dolis(%,MD); |
> | build(%,MD); |
> |
> |
Case of 57
> | MD:=57:# Modulus=57 |
> | lis57:=[[8,1,dnorm([8,1],MD)]]; |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | build(%,MD); |
> |
> |
> |
> |
> |
Case of 58
> | MD:=58; #modulus is set to 58 |
> | u1:=[8,1];dnorm(u1,MD); |
> | l58:=[[op(u1),dnorm(u1,MD)]]; |
> | dolis(l58,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | build(%,MD); |
> | bhav([99,13],[99,13],MD); |
> |
Case of 67
> |
> | MD:=67; |
Using dolist
> | l67:=[[8,1,dnorm([8,1],MD)]]; |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | build(%,MD); |
> |
> |
> |
> |
Short cut possible!
> | bhav([221,27],[221,27],MD); |
> | red(%,2,MD); |
> |
Case of 61
> | MD:=61; |
> | l61:=[[8,1,dnorm([8,1],MD)]]; |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | build(%,MD); |
> |
> |
> |
Shortcut!
> | bhav([39,5],[39^2+2,39*5],MD); |
> | red(%,4,MD); |
> |
Case of 92
> | MD:=92; |
> | l92:=[[9,1,dnorm([9,1],MD)]]; |
Using dolist
> | dolis(l92,92); |
> | dolis(%,92); |
> | dolis(%,92); |
> | dolis(%,92); |
> | dolis(%,92); |
> | build(%,MD); |
> |
> |
> |
Of course, now the process stops, since norm becomes 1.
Shortcut possible
Alternate treatment using 4.
> | bhav([48,5],[48,5],92); |
> | red(%,4,92); |
> |
Case of 88
> | MD:=88; |
> | l88:=[[9,1,dnorm([9,1],MD)]]; |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | build(%,MD); |
> |
Case of 97
> | MD:=97; |
> | l97:=[[10,1,dnorm([10,1],MD)]]; |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | build(%,MD); |
> |
Case of 103
> | MD:=103; |
Using dolist
> | l103:=[[10,1,dnorm([10,1],MD)]]; |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | w:=mbh([[10,1],[11,1],[7,1],[11,1]],MD); |
> | red(%,sqrt(%[3]),MD); |
> | bhav(%,%,MD); |
> | ifactor(w[3]); |
We could also have cut it short by using the norm 2.
> | dnorm([477,47],MD); |
> | bhav([477,47],[477,47],MD); |
> | red(%,2,MD); |
Case of 107
> | MD:=107; |
> | l107:=[[10,1,dnorm([10,1],MD)]]; |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | build(%,MD); |
> | bhav([31,3],[31,3],MD); |
> | red(%,2,MD); |
Case of 433
> | MD:=433; |
> | l433:=[[21,1,dnorm([21,1],MD)]]; |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | dolis(%,MD); |
> | build(%,MD); |
> | with(numtheory): |
> | cfrac(sqrt(403),'periodic');; |
> | periodic; |
> | ?cfrac |
> |