coatesid.red 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. module coatesid;
  2. % Author: James H. Davenport.
  3. fluid '(!*tra intvar magiclist taylorasslist taylorvariable);
  4. exports coatessolve,vecprod,coates!-lineq;
  5. imports !*invsq,!*multsq,negsq,!*addsq,swap,check!-lineq,non!-null!-vec,
  6. printsq,sqrt2top,mapvec,mksp,vecsort,addsq,mkilist,mkvec,mapply,
  7. taylorformp,xsubstitutesq,taylorform,taylorevaluate,multsq,
  8. invsq,removecmsq;
  9. symbolic procedure coatessolve(mzero,pzero,basis,normals);
  10. begin scalar m,n,rightside,nnn;
  11. % The following is needed in int(-4x^3/(sqrt(4x^4+1)-4x^4-1),x).
  12. if null mzero then return 'failed;
  13. % if null normals
  14. % then normals:=list mkilist(basis,1 ./ 1);
  15. % This provides the default normalisation,
  16. % viz merely a de-homogenising constraint;
  17. % No it doesn't - JHD May 1983 and August 1986.
  18. % This may be precisely the wrong constraint, as can be seen from
  19. % the example of SQRT(X**2-1). Fixed 19/8/86 to amend COATESMATRIX
  20. % to insert a normalising constraint if none is provided.
  21. nnn:=max(length normals,1);
  22. basis:=mkvec basis;
  23. m:=coatesmatrix(mzero,pzero,basis,normals);
  24. n:=upbv m;
  25. rightside:=mkvect n;
  26. for i:=0:n do putv(rightside,n-i,(if i<nnn then 1 else nil) ./ 1);
  27. n:=coates!-lineq(m,rightside);
  28. if n eq 'failed then return 'failed;
  29. n:=removecmsq vecprod(n,basis);
  30. if !*tra then <<
  31. printc "Answer from linear equation solving is ";
  32. printsq n >>;
  33. return n
  34. end;
  35. symbolic procedure coatesmatrix(mzero,pzero,basis,normals);
  36. % NORMALS is a list of the normalising constraints
  37. % that we must apply. Thypically, this is NIL, and we have to
  38. % invent one - see the code IF NULL NORMALS ...
  39. begin
  40. scalar ans,n1,n2,j,w,save,nextflag,save!-taylors,x!-factors,
  41. normals!-ok,temp;
  42. save!-taylors:=mkvect isub1 length pzero;
  43. save:=taylorasslist;
  44. normals!-ok:=nil;
  45. n1:=upbv basis;
  46. n2:=isub1 mapply(function plus2,mzero) + max(length normals,1);
  47. % the number of constaints in all (counting from 0).
  48. taylorvariable:=intvar;
  49. if !*tra then <<
  50. printc "Basis for the functions with precisely the correct poles";
  51. mapvec(basis,function printsq) >>;
  52. ans:=mkvect n2;
  53. for i:=0:n2 do
  54. putv(ans,i,mkvect n1);
  55. for i:=0:n1 do begin
  56. scalar xmz,xpz,k;
  57. xmz:=mzero;
  58. k:=j:=0;
  59. xpz:=pzero;
  60. while xpz do <<
  61. newplace basicplace car xpz;
  62. if nextflag
  63. then w:=taylorformp list('binarytimes,
  64. getv(save!-taylors,k),
  65. getv(x!-factors,k))
  66. else if not !*tra
  67. then w:=taylorform xsubstitutesq(getv(basis,i),car xpz)
  68. else begin
  69. scalar flg,u,slists;
  70. u:=xsubstitutesq(getv(basis,i),basicplace car xpz);
  71. slists:=extenplace car xpz;
  72. for each w in sqrtsinsq(u,intvar) do
  73. if not assoc(w,slists)
  74. then flg:=w.flg;
  75. if flg then <<
  76. printc "The following square roots were not expected";
  77. mapc(flg,function superprint);
  78. printc "in the substitution";
  79. superprint car xpz;
  80. printsq getv(basis,i) >>;
  81. w:=taylorform xsubstitutesq(u,slists)
  82. end;
  83. putv(save!-taylors,k,w);
  84. k:=iadd1 k;
  85. for l:=0 step 1 until isub1 car xmz do <<
  86. astore(ans,j,i,taylorevaluate(w,l));
  87. j:=iadd1 j >>;
  88. if null normals and j=n2 then <<
  89. temp:=taylorevaluate(w,car xmz);
  90. astore(ans,j,i,temp);
  91. % The defaults normalising condition is that the coefficient
  92. % after the last zero be a non-zero.
  93. % Unfortunately this too may fail (JHD 21.3.87) - check for it later
  94. normals!-ok:=normals!-ok or numr temp >>;
  95. xpz:=cdr xpz;
  96. xmz:=cdr xmz >>;
  97. nextflag:=(i < n1) and
  98. (getv(basis,i) = multsq(!*kk2q intvar,getv(basis,i+1)));
  99. if nextflag and null x!-factors then <<
  100. x!-factors:=mkvect upbv save!-taylors;
  101. xpz:=pzero;
  102. k:=0;
  103. xmz:=invsq !*kk2q intvar;
  104. while xpz do <<
  105. putv(x!-factors,k,taylorform xsubstitutesq(xmz,car xpz));
  106. xpz:=cdr xpz;
  107. k:=iadd1 k >> >>
  108. end;
  109. if null normals and null normals!-ok then <<
  110. if !*tra
  111. then printc "Our default normalisation condition was vacuous";
  112. astore(ans,n2,n1,1 ./ 1)>>;
  113. while normals do <<
  114. w:=car normals;
  115. for k:=0:n1 do <<
  116. astore(ans,j,k,car w);
  117. w:=cdr w >>;
  118. j:=iadd1 j;
  119. normals:=cdr normals >>;
  120. tayshorten save;
  121. return ans
  122. end;
  123. symbolic procedure printmatrix(ans,n2,n1);
  124. if !*tra
  125. then <<
  126. printc "Equations to be solved:";
  127. for i:=0:n2 do begin
  128. if null getv(ans,i)
  129. then return;
  130. princ "Row number ";
  131. princ i;
  132. for j:=0:n1 do
  133. printsq getv(getv(ans,i),j)
  134. end >>;
  135. symbolic procedure vecprod(u,v);
  136. begin
  137. scalar w,n;
  138. w:=nil ./ 1;
  139. n:=upbv u;
  140. for i:=0:n do
  141. w:=!*addsq(w,!*multsq(getv(u,i),getv(v,i)));
  142. return w
  143. end;
  144. symbolic procedure coates!-lineq(m,rightside);
  145. begin
  146. scalar nnn,n;
  147. nnn:=desparse(m,rightside);
  148. if nnn eq 'failed
  149. then return 'failed;
  150. m:=car nnn;
  151. if null m
  152. then <<
  153. n:=cddr nnn;
  154. goto vecprod >>;
  155. rightside:=cadr nnn;
  156. nnn:=cddr nnn;
  157. n:=check!-lineq(m,rightside);
  158. if n eq 'failed
  159. then return n;
  160. n:=jhdsolve(m,rightside,non!-null!-vec nnn);
  161. if n eq 'failed
  162. then return n;
  163. for i:=0:upbv n do
  164. if (m:=getv(nnn,i))
  165. then putv(n,i,m);
  166. vecprod:
  167. for i:=0:upbv n do
  168. if null getv(n,i) then putv(n,i,nil ./ 1);
  169. return n
  170. end;
  171. symbolic procedure jhdsolve(m,rightside,ignore);
  172. % Returns answer to m.answer=rightside.
  173. % Matrix m not necessarily square.
  174. begin
  175. scalar ii,n1,n2,ans,u,row,swapflg,swaps;
  176. % The SWAPFLG is true if we have changed the order of the
  177. % columns and need later to invert this via SWAPS.
  178. n1:=upbv m;
  179. for i:=0:n1 do
  180. if (u:=getv(m,i))
  181. then (n2:=upbv u);
  182. printmatrix(m,n1,n2);
  183. swaps:=mkvect n2;
  184. for i:=0:n2 do
  185. putv(swaps,i,n2-i);
  186. % We have the SWAPS vector, which should be a vector of indices,
  187. % arranged like this because VECSORT sorts in decreasing order.
  188. for i:=0:isub1 n1 do begin
  189. scalar k,v,pivot;
  190. tryagain:
  191. row:=getv(m,i);
  192. if null row
  193. then go to interchange;
  194. % look for a pivot in row.
  195. k:=-1;
  196. for j:=0:n2 do
  197. if numr (pivot:=getv(row,j))
  198. then <<
  199. k:=j;
  200. j:=n2 >>;
  201. if k neq -1
  202. then goto newrow;
  203. if numr getv(rightside,i)
  204. then <<
  205. m:='failed;
  206. i:=sub1 n1; %Force end of loop.
  207. go to finished >>;
  208. % now interchange i and last element.
  209. interchange:
  210. swap(m,i,n1);
  211. swap(rightside,i,n1);
  212. n1:=isub1 n1;
  213. if i iequal n1
  214. then goto finished
  215. else goto tryagain;
  216. newrow:
  217. if i neq k
  218. then <<
  219. swapflg:=t;
  220. swap(swaps,i,k);
  221. % record what we have done.
  222. for l:=0:n1 do
  223. swap(getv(m,l),i,k) >>;
  224. % place pivot on diagonal.
  225. pivot:=sqrt2top negsq !*invsq pivot;
  226. for j:=iadd1 i:n1 do begin
  227. u:=getv(m,j);
  228. if null u
  229. then return;
  230. v:=!*multsq(getv(u,i),pivot);
  231. if numr v then <<
  232. putv(rightside,j,
  233. !*addsq(getv(rightside,j),!*multsq(v,getv(rightside,i))));
  234. for l:=0:n2 do
  235. putv(u,l,!*addsq(getv(u,l),!*multsq(v,getv(row,l)))) >>
  236. end;
  237. finished:
  238. end;
  239. if m eq 'failed
  240. then go to failed;
  241. % Equations were inconsistent.
  242. while null (row:=getv(m,n1)) do
  243. n1:=isub1 n1;
  244. u:=nil;
  245. for i:=0:n2 do
  246. if numr getv(row,i)
  247. then u:='t;
  248. if null u
  249. then if numr getv(rightside,n1)
  250. then go to failed
  251. else n1:=isub1 n1;
  252. % Deals with a last equation which is all zero.
  253. if n1 > n2
  254. then go to failed;
  255. % Too many equations to satisfy.
  256. ans:=mkvect n2;
  257. n2:=n2 - ignore;
  258. ii:=n1;
  259. for i:=0 step 1 until n1 do
  260. if null getv(m,i)
  261. then ii:=iadd1 ii;
  262. if ii < n2 then <<
  263. if !*tra then <<
  264. printc "The equations do not completely determine the functions";
  265. printc "Matrix:";
  266. mapvec(m,function superprint);
  267. printc "Right-hand side:";
  268. superprint rightside;
  269. printc list("Adding new symbols for ", iadd1 ii," ... ",n2) >>;
  270. % FOR I:=IADD1 ii:N2 DO <<
  271. % U:=GENSYM();
  272. % MAGICLIST:=U.MAGICLIST;
  273. % PUTV(ANS,I,!*KK2Q U) >>;
  274. if !*tra then printc "If in doubt consult an expert">>;
  275. % now to do the back-substitution.
  276. % Note that the matrix is not necessarily square,
  277. % but that we have ensured that the non-square (underdetermiined)
  278. % parts are at the right
  279. for i:=n1 step -1 until 0 do begin
  280. row:=getv(m,i);
  281. if null row
  282. then return;
  283. % WHILE NULL NUMR GETV(ROW,II) DO II:=ISUB1 II;
  284. ii:=0;
  285. while null numr getv(row,ii) do ii:=iadd1 ii;
  286. u:=getv(rightside,i);
  287. for j:=iadd1 ii:n2 do <<
  288. if null getv(ans,j) then <<
  289. magiclist:=gensym().magiclist;
  290. putv(ans,j,!*kk2q car magiclist) >>;
  291. u:=!*addsq(u,!*multsq(getv(row,j),negsq getv(ans,j)))
  292. >>;
  293. putv(ans,ii,!*multsq(u,sqrt2top !*invsq getv(row,ii)));
  294. % II:=ISUB1 II;
  295. end;
  296. if swapflg
  297. then vecsort(swaps,list ans);
  298. return ans;
  299. failed:
  300. if !*tra then printc "Unable to force correct zeroes";
  301. return 'failed
  302. end;
  303. symbolic procedure desparse(matrx,rightside);
  304. begin
  305. scalar vect,changed,n,m,zero,failed;
  306. zero := nil ./ 1;
  307. n:=upbv matrx;
  308. m:=upbv getv(matrx,0);
  309. vect := mkvect m;
  310. % for i:=0:m do putv(vect,i,zero); %%% initialize - ach
  311. changed:=t;
  312. while changed and not failed do begin
  313. changed:=nil;
  314. for i:=0:n do
  315. if changed or failed
  316. then i:=n % and hence quit the loop.
  317. else begin
  318. scalar nzcount,row,pivot;
  319. row:=getv(matrx,i);
  320. if null row
  321. then return;
  322. nzcount:=0;
  323. for j:=0:m do
  324. if numr getv(row,j)
  325. then <<
  326. nzcount:=iadd1 nzcount;
  327. pivot:=j >>;
  328. if nzcount = 0
  329. then if null numr getv(rightside,i)
  330. then return putv(matrx,i,nil)
  331. else return (failed:='failed);
  332. if nzcount > 1
  333. then return nil;
  334. nzcount:=getv(rightside,i);
  335. if null numr nzcount
  336. then <<
  337. putv(vect,pivot,zero);
  338. go to was!-zero >>;
  339. nzcount:=!*multsq(nzcount,!*invsq getv(row,pivot));
  340. putv(vect,pivot,nzcount);
  341. nzcount:=negsq nzcount;
  342. for i:=0:n do
  343. if (row:=getv(matrx,i))
  344. then if numr (row:=getv(row,pivot))
  345. then putv(rightside,i,!*addsq(getv(rightside,i),
  346. !*multsq(row,nzcount)));
  347. was!-zero:
  348. for i:=0:n do
  349. if (row:=getv(matrx,i))
  350. then putv(row,pivot,zero);
  351. changed:=t;
  352. putv(matrx,i,nil);
  353. swap(matrx,i,n);
  354. swap(rightside,i,n);
  355. end;
  356. end;
  357. if failed
  358. then return 'failed;
  359. changed:=t;
  360. for i:=0:n do
  361. if getv(matrx,i)
  362. then changed:=nil;
  363. if changed
  364. then matrx:=nil;
  365. % We have completely solved the equations by these machinations.
  366. return matrx.(rightside . vect)
  367. end;
  368. symbolic procedure astore(a,i,j,val);
  369. putv(getv(a,i),j,val);
  370. endmodule;
  371. end;