zmodule.red 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. module zmodule;
  2. % Author: James H. Davenport.
  3. fluid '(!*galois
  4. !*tra
  5. !*trfield
  6. !*trmin
  7. basic!-listofallsqrts
  8. basic!-listofnewsqrts
  9. commonden
  10. gaussiani
  11. listofallsqrts
  12. listofnewsqrts
  13. sqrt!-places!-alist
  14. taylorasslist);
  15. exports zmodule;
  16. imports !*multf,sqrtsinsql,sortsqrts,simp,!*q2f,actualsimpsqrt,printsf;
  17. imports prepf,substitutesq,printsq,mapply,!*multsq,mkilist;
  18. imports mkvecf2q,mkvec,mkidenm,invsq,multsq,negsq,addsq,gcdn;
  19. imports !*invsq,prepsq;
  20. symbolic procedure zmodule(w);
  21. begin
  22. scalar reslist,denlist,u,commonden,basis,p1,p2,hcf;
  23. % w is a list of elements (place.residue)=sq.
  24. for each v in w do <<
  25. u:=cdr v;
  26. reslist:=u.reslist;
  27. denlist:=(denr u).denlist >>;
  28. basis:=sqrtsinsql(reslist,nil);
  29. if null u or null cdr u or !*galois
  30. then go to nochange;
  31. reslist:=check!-sqrts!-dependence(reslist,basis);
  32. denlist:=for each u in reslist
  33. collect denr u;
  34. nochange:
  35. commonden:=mapply(function(lambda u,v;
  36. multf(u,quotf(v,gcdf(u,v)))),denlist)./1;
  37. u:=nil;
  38. for each v in reslist do
  39. u:=(numr !*multsq(v,commonden)).u;
  40. reslist:=u;
  41. % We have effectively reversed RESLIST twice, so it is in correct
  42. % order.
  43. u:=bexprn(reslist);
  44. basis:=car u;
  45. reslist:=cdr u;
  46. denlist:=nil;
  47. while basis do <<
  48. p1:=reslist;
  49. p2:=w;
  50. u:=nil;
  51. hcf:=0;
  52. while p1 do <<
  53. if 0 neq caar p1
  54. then <<
  55. u:=((caar p2).(caar p1)).u;
  56. hcf:=gcdn(hcf,caar p1) >>;
  57. p1:=cdr p1;
  58. p2:=cdr p2 >>;
  59. if hcf neq 1
  60. then u:=for each uu in u collect
  61. (car uu). ( (cdr uu) / hcf);
  62. denlist:=(prepsq !*multsq(car basis,
  63. multsq(!*f2q hcf,!*invsq commonden))
  64. .u).denlist;
  65. basis:=cdr basis;
  66. reslist := for each j in reslist collect cdr j>>;
  67. return denlist
  68. end;
  69. symbolic procedure bexprn(wlist);
  70. begin
  71. scalar basis,replist,w,w2,w3,p1,p2;
  72. % wlist is a list of sf.
  73. w:=reverse wlist;
  74. replist:=nil;
  75. while w do <<
  76. w2:=sf2df car w;
  77. % now ensure that all elements of w2 are in the basis.
  78. w3:=w2;
  79. while w3 do <<
  80. % caar is the sf,cdar a its coefficient.
  81. if not member(caar w3,basis)
  82. then <<
  83. basis:=(caar w3).basis;
  84. replist:=mapcons(replist,0) >>;
  85. % adds car w3 to basis.
  86. w3:=cdr w3 >>;
  87. replist:=mkilist(basis,0).replist;
  88. % builds a new zero representation.
  89. w3:=w2;
  90. while w3 do <<
  91. p1:=basis;
  92. p2:=car replist;
  93. %the list for this element.
  94. while p1 do <<
  95. if caar w3 = car p1
  96. then rplaca(p2,cdar w3);
  97. p1:=cdr p1;
  98. p2:=cdr p2 >>;
  99. w3:=cdr w3 >>;
  100. w:=cdr w >>;
  101. return mkbasis(basis,replist)
  102. end;
  103. symbolic procedure mkbasis(basis,reslist);
  104. begin
  105. scalar row,nbasis,nreslist,u,v;
  106. basis:=for each u in basis collect !*f2q u;
  107. % basis is a list of sq's
  108. % reslist is a list of representations in the form
  109. % ( (coeff1 coeff2 ...) ...).
  110. nreslist:=mkilist(reslist,nil);
  111. % initialise our list-of-lists.
  112. trynewloop:
  113. row := mapovercar reslist;
  114. reslist := for each j in reslist collect cdr j;
  115. if obvindep(row,nreslist)
  116. then u:=nil
  117. else u:=lindep(row,nreslist);
  118. if u
  119. then <<
  120. % u contains the numbers with which to add this new item into the
  121. % basis.
  122. v:=nil;
  123. while nbasis do <<
  124. v:=addsq(car nbasis,!*multsq(car basis,car u)).v;
  125. nbasis:=cdr nbasis;
  126. u:=cdr u >>;
  127. nbasis:=reversip v >>
  128. else <<
  129. nreslist:=pair(row,nreslist);
  130. nbasis:=(car basis).nbasis
  131. >>;
  132. basis:=cdr basis;
  133. if basis
  134. then go to trynewloop;
  135. return nbasis.nreslist
  136. end;
  137. symbolic procedure obvindep(row,matrx);
  138. % True if row is obviously linearly independent of the
  139. % Rows of the matrix.
  140. begin scalar u;
  141. if null car matrx
  142. then return t;
  143. % no matrix => no dependence.
  144. nexttry:
  145. if null row
  146. then return nil;
  147. if 0 iequal car row
  148. then go to nouse;
  149. u:=car matrx;
  150. testloop:
  151. if 0 neq car u
  152. then go to nouse;
  153. u:=cdr u;
  154. if u
  155. then go to testloop;
  156. return t;
  157. nouse:
  158. row:=cdr row;
  159. matrx:=cdr matrx;
  160. go to nexttry
  161. end;
  162. symbolic procedure sf2df sf;
  163. if null sf
  164. then nil
  165. else if numberp sf
  166. then (1 . sf).nil
  167. else begin
  168. scalar a,b,c;
  169. a:=sf2df lc sf;
  170. b:=(lpow sf .* 1) .+ nil;
  171. while a do <<
  172. c:=(!*multf(caar a,b).(cdar a)).c;
  173. a :=cdr a >>;
  174. return nconc(c,sf2df red sf)
  175. end;
  176. symbolic procedure check!-sqrts!-dependence(sql,sqrtl);
  177. % Resimplifies the list of SQs SQL,
  178. % allowing for all dependencies among the
  179. % sqrts in SQRTl.
  180. begin
  181. scalar !*galois,sublist,sqrtsavelist,changeflag;
  182. sqrtsavelist:=listofallsqrts.listofnewsqrts;
  183. listofnewsqrts:=list mvar gaussiani;
  184. listofallsqrts:=list((argof mvar gaussiani) . gaussiani);
  185. !*galois:=t;
  186. for each u in sortsqrts(sqrtl,nil) do begin
  187. scalar v,uu;
  188. uu:=!*q2f simp argof u;
  189. v:=actualsimpsqrt uu;
  190. listofallsqrts:=(uu.v).listofallsqrts;
  191. if domainp v or mvar v neq u
  192. then <<
  193. if !*tra or !*trfield then <<
  194. printc u;
  195. printc "re-expressed as";
  196. printsf v >>;
  197. v:=prepf v;
  198. sublist:=(u.v) . sublist;
  199. changeflag:=t >>
  200. end;
  201. if changeflag then <<
  202. sql:=for each u in sql collect
  203. substitutesq(u,sublist);
  204. taylorasslist:=nil;
  205. sqrt!-places!-alist:=nil;
  206. basic!-listofallsqrts:=listofallsqrts;
  207. basic!-listofnewsqrts:=listofnewsqrts;
  208. if !*tra or !*trmin then <<
  209. printc "New set of residues are";
  210. mapc(sql,function printsq) >> >>
  211. else <<
  212. listofallsqrts:=car sqrtsavelist;
  213. listofnewsqrts:=cdr sqrtsavelist >>;
  214. return sql
  215. end;
  216. symbolic procedure lindep(row,matrx);
  217. begin
  218. scalar m,m1,n,u,v,inverse,rowsinuse,failure;
  219. % Inverse is the answer from the "gaussian elimination"
  220. % we are doing.
  221. % Rowsinuse has nil for rows with no "awkward" non-zero entries.
  222. m1:=length car matrx;
  223. m:=isub1 m1;
  224. n:=isub1 length matrx;
  225. % n=length row.
  226. row:=mkvecf2q row;
  227. matrx:=mkvec for each j in matrx collect mkvecf2q j;
  228. inverse:=mkidenm m1;
  229. rowsinuse:=mkvect m;
  230. failure:=t;
  231. % initialisation complete.
  232. for i:=0 step 1 until n do begin
  233. % try to kill off i'th elements in each row.
  234. u:=nil;
  235. for j:=0 step 1 until m do <<
  236. % try to find a pivot element.
  237. if (null u) and
  238. (null getv(rowsinuse,j)) and
  239. (numr getv(getv(matrx,i),j))
  240. then u:=j >>;
  241. if null u
  242. then go to nullu;
  243. putv(rowsinuse,u,t);
  244. % it is no use trying this again ---
  245. % u is our pivot element.
  246. if u iequal m
  247. then go to nonetokill;
  248. for j:=iadd1 u step 1 until m do
  249. if numr getv(getv(matrx,i),j)
  250. then <<
  251. v:=negsq multsq(getv(getv(matrx,i),j),
  252. invsq getv(getv(matrx,i),u));
  253. for k:=0 step 1 until m1 do
  254. putv(getv(inverse,k),j,
  255. addsq(getv(getv(inverse,k),j),
  256. multsq(v,getv(getv(inverse,k),u))));
  257. for k:=0 step 1 until n do
  258. putv(getv(matrx,k),j,
  259. addsq(getv(getv(matrx,k),j),
  260. multsq(v,getv(getv(matrx,k),u)))) >>;
  261. % We have now pivoted throughout matrix.
  262. nonetokill:
  263. % now do the same in row if necessary.
  264. if null numr getv(row,i)
  265. then go to norowop;
  266. v:=negsq multsq(getv(row,i),
  267. invsq getv(getv(matrx,i),u));
  268. for k:=0 step 1 until m1 do
  269. putv(getv(inverse,k),m1,
  270. addsq(getv(getv(inverse,k),m1),
  271. multsq(v,getv(getv(inverse,k),u))));
  272. for k:=0 step 1 until n do
  273. putv(row,k,addsq(getv(row,k),
  274. multsq(v,getv(getv(matrx,k),u))));
  275. u:=nil;
  276. for k:=0 step 1 until n do
  277. if numr getv(row,k)
  278. then u:=t;
  279. % if u is null then row is all 0.
  280. if null u
  281. then <<
  282. n:=-1;
  283. failure:=nil >>;
  284. norowop:
  285. if !*tra then <<
  286. princ "At end of cycle";
  287. printc row;
  288. printc matrx;
  289. printc inverse >>;
  290. return;
  291. nullu:
  292. % there is no pivot for this u.
  293. if numr getv(row,i)
  294. then n:=-1;
  295. % this element cannot be killed.
  296. end;
  297. if failure
  298. then return nil;
  299. v:=nil;
  300. for i:=0 step 1 until m do
  301. v:=(negsq getv(getv(inverse,m-i),m1)).v;
  302. return v
  303. end;
  304. endmodule;
  305. end;