anum.red 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740
  1. module arnum; % Support for algebraic rationals.
  2. % Author: Eberhard Schruefer.
  3. global '(domainlist!* arbase!* arvars!* repowl!* curdefpol!*
  4. !*acounter!* !*extvar!* reexpressl!*);
  5. !*acounter!* := 0; %counter for number of extensions;
  6. !*extvar!* := 'a; %default print character for primitive element;
  7. fluid '(!*arnum dmode!* !*exp !*minimal !*reexpress !*arinv !*arquot
  8. !*arq alglist!*);
  9. global '(timer timef);
  10. switch arnum;
  11. timer:=timef:=0;
  12. domainlist!*:=union('(!:ar!:),domainlist!*);
  13. symbolic procedure defpoly u;
  14. begin
  15. if null(dmode!* eq '!:ar!:) then on 'arnum;
  16. for each j in u do
  17. (if eqexpr j then
  18. if cadr j=0 then mkextension caddr j else
  19. if caddr j=0 then mkextension cadr j else
  20. rederr list(cadr j,"=",caddr j,
  21. " is not a proper defining polynomial")
  22. else mkextension j)
  23. end;
  24. rlistat '(defpoly);
  25. symbolic procedure mkextension u;
  26. if null curdefpol!* then initalgnum u
  27. else begin scalar !*exp;
  28. !*exp := t;
  29. primitive!_elem !*a2f u
  30. end;
  31. symbolic procedure initalgnum u;
  32. begin scalar dmode!*,alglist!*,!*exp;
  33. !*exp := t;
  34. arbase!* := nil;
  35. u := numr simp0 u;
  36. if lc u neq 1 then u := monicize u;
  37. % rederr("defining polynomial must be monic");
  38. curdefpol!* := u;
  39. for j:=0:(ldeg u-1) do
  40. arbase!* := (if j=0 then 1
  41. else mksp(mvar u,j)) . arbase!*;
  42. arvars!* := mvar u . arvars!*;
  43. mk!-algebraic!-number!-vars list mvar u;
  44. repowl!* := lpow u . negf red u
  45. end;
  46. symbolic procedure put!-current!-representation(u,v);
  47. put(u,'currep,v);
  48. symbolic procedure get!-current!-representation u;
  49. get(u,'currep);
  50. symbolic procedure mkdar u;
  51. %puts any algebraic number domain element into its tagged form.
  52. %updated representations (through field extension) are accessed here;
  53. ((if x then x else '!:ar!: . !*k2f u) ./ 1)
  54. where x = get!-current!-representation u;
  55. symbolic procedure release u;
  56. %Undeclares elements of list u to be algebraic numbers;
  57. for each j in u do
  58. if atom j then remprop(j,'idvalfn)
  59. else remprop(car j,'opvalfn);
  60. symbolic procedure mk!-algebraic!-number!-vars u;
  61. %Declares elements of list u to be algebraic numbers;
  62. for each j in u do
  63. if atom j then put(j,'idvalfn,'mkdar)
  64. else put(car j,'opvalfn,'mkdar);
  65. symbolic procedure uncurrep u;
  66. for each j in u do remprop(j,'currep);
  67. symbolic procedure update!-extension u;
  68. %Updates representation of elements in list u;
  69. for each j in u do
  70. ((x and put(j,'currep,numr simp prepf cdr x))
  71. where x = get(j,'currep));
  72. symbolic procedure express!-in!-arvars u;
  73. %u is an untagged rational number. Result is equivalent algebraic
  74. %number expressed in input variables.
  75. rederr "switch reexpress not yet implemented";
  76. % begin scalar x;
  77. % for each j in reexpressl!* do
  78. % x := extmult(extadd(...,j),x);
  79. % return solve!-for!-arvars x
  80. % end;
  81. symbolic procedure mkreexpressl;
  82. %Sets up the homogenous part of the system to be solved for
  83. %expressing a primitive element expression in terms of the
  84. %input variables.
  85. reexpressl!* := nil;
  86. % begin scalar x;
  87. %
  88. put('reexpress,'simpfg,'((t (mkreexpressl))
  89. (nil (setq reexpressl!* nil))));
  90. %*** tables for algebraic rationals ***;
  91. flag('(!:ar!:),'field);
  92. put('arnum,'tag,'!:ar!:);
  93. put('!:ar!:,'dname,'arnum);
  94. put('!:ar!:,'i2d,'!*i2ar);
  95. %put('!:ar!:,'!:rn!:,'ar2rn);
  96. put('!:ar!:,'!:ft!:,'arconv);
  97. put('!:ar!;,'!:bf!:,'arconv);
  98. put('!:ar!:,'!:mod!:,'arconv);
  99. put('!:ar!:,'minusp,'arminusp!:);
  100. put('!:ar!:,'zerop,'arzerop!:);
  101. put('!:ar!:,'onep,'aronep!:);
  102. put('!:ar!:,'plus,'arplus!:);
  103. put('!:ar!:,'difference,'ardifference!:);
  104. put('!:ar!:,'times,'artimes!:);
  105. put('!:ar!:,'quotient,'arquotient!:);
  106. put('!:ar!:,'factorfn,'arfactor!:);
  107. put('!:ar!:,'rationalizefn,'arrationalize!:);
  108. put('!:ar!:,'prepfn,'arprep!:);
  109. put('!:ar!:,'intequivfn,'arintequiv!:);
  110. put('!:ar!:,'prifn,'arprn!:);
  111. put('!:rn!:,'!:ar!:,'rn2ar);
  112. flag('(!:ar!:),'ratmode);
  113. symbolic procedure rn2ar u;
  114. '!:ar!: . if cddr u=1 then cadr u else u;
  115. symbolic procedure ar2rn u;
  116. if cadr u eq '!:rn!: then cdr u
  117. else if numberp cdr u then '!:rn!: . (cdr u . 1)
  118. else rederr list "conversion to rational not possible";
  119. symbolic procedure !*i2ar u;
  120. '!:ar!: . u;
  121. symbolic procedure arconv u;
  122. rederr list("conversion between current extension and",
  123. get(car u,'dname),"not possible");
  124. symbolic procedure arminusp!: u;
  125. minusf cdr u;
  126. symbolic procedure arzerop!: u;
  127. null cdr u;
  128. symbolic procedure aronep!: u;
  129. cdr u=1;
  130. symbolic procedure arintequiv!: u;
  131. if numberp cdr u then cdr u
  132. else if (cadr u eq '!:rn!:) and (cdddr u=1) then caddr u
  133. else nil;
  134. smacro procedure mkar u;
  135. '!:ar!: . u;
  136. symbolic procedure arplus!:(u,v);
  137. begin scalar dmode!*,!*exp;
  138. !*exp := t;
  139. return mkar addf(cdr u,cdr v)
  140. end;
  141. symbolic procedure ardifference!:(u,v);
  142. begin scalar dmode!*,!*exp;
  143. !*exp := t;
  144. return mkar addf(cdr u,negf cdr v)
  145. end;
  146. symbolic procedure artimes!:(u,v);
  147. begin scalar dmode!*,!*exp;
  148. !*exp := t;
  149. return mkar reducepowers multf(cdr u,cdr v)
  150. end;
  151. symbolic procedure arquotient!:(u,v);
  152. begin scalar r,s,y,z,dmode!*,!*exp;
  153. !*exp := t;
  154. if domainp cdr v then
  155. return mkar multd(<<dmode!* := '!:rn!:;
  156. s := !:recip cdr v;
  157. dmode!* := nil;
  158. s>>,cdr u);
  159. if !*arinv then
  160. return mkar reducepowers multf(cdr u,arinv cdr v);
  161. if !*arquot then return mkar arquot(cdr v,cdr u);
  162. if !*arq then return mkar reducepowers multf(u,arquot1 v);
  163. r := ilnrsolve(mkqmatr cdr v,mkqcol cdr u);
  164. z := arbase!*;
  165. dmode!* := '!:rn!:;
  166. for each j in r do
  167. s := addf(multf(int!-equiv!-chk car j,
  168. <<y := if atom car z then 1 else !*p2f car z;
  169. z := cdr z; y>>),s);
  170. return mkar s
  171. end;
  172. symbolic procedure arfactor!: v;
  173. if domainp v then list v
  174. else if null curdefpol!* then factorf v
  175. else
  176. begin scalar w,x,y,z,aftrs,ifctr,ftrs,mva,mvu,
  177. dmode!*,!*exp;
  178. timer:=timef:=0;
  179. !*exp := t;
  180. mva := mvar curdefpol!*;
  181. mvu := mvar v;
  182. ifctr := factorft numr(v := fd2q v);
  183. dmode!* := '!:ar!:;
  184. w := if denr v neq 1 then mkrn(car ifctr,denr v)
  185. else car ifctr;
  186. for each f in cdr ifctr do
  187. begin scalar l;
  188. y := numr subf1(car f,nil);
  189. if domainp y then <<w := multd(y,w); return>>;
  190. y := sqfrnorm y;
  191. dmode!* := nil;
  192. ftrs := factorft car y;
  193. dmode!* := '!:ar!:;
  194. if cadr y neq 0 then
  195. l := list(mvu . prepf addf(!*k2f mvu,
  196. negf multd(cadr y,!*k2f mva)));
  197. y := cddr y;
  198. for each j in cdr ftrs do
  199. <<x := gcdf!*(car j,y);
  200. y := quotf!*(y,x);
  201. z := if l then numr subf1(x,l) else x;
  202. x := lnc ckrn z;
  203. z := quotf(z,x);
  204. w := multf(w,exptf(x,cdr f));
  205. aftrs := (z . cdr f) . aftrs>>
  206. end;
  207. %print timer; print timef;
  208. return w . aftrs
  209. end;
  210. symbolic procedure afactorize u;
  211. begin scalar ftrs,x,!*exp; integer n;
  212. !*exp := t;
  213. if cdr u then <<off 'arnum; defpoly cdr u>>;
  214. x := arfactor!: !*a2f car u;
  215. ftrs := (0 . mk!*sq(car x ./ 1)) . nil;
  216. for each j in cdr x do
  217. for k := 1:cdr j do
  218. ftrs := ((n := n+1) . mk!*sq(car j ./ 1)) . ftrs;
  219. return multiple!-result(ftrs,nil)
  220. end;
  221. put('algeb!_factorize,'psopfn,'afactorize);
  222. symbolic procedure arprep!: u; %u;
  223. prepf if !*reexpress then express!-in!-arvars cdr u
  224. else cdr u;
  225. %symbolic procedure simpar u;
  226. %('!:ar!: . !*a2f car u) ./ 1;
  227. %put('!:ar!:,'simpfn,'simpar);
  228. symbolic procedure arprn!: v;
  229. ( if atom u or (car u memq '(times expt)) then maprin u
  230. else <<prin2!* "(";
  231. maprin u;
  232. prin2!* ")" >>) where u = prepsq!*(cdr v ./ 1);
  233. %*** utility functions ***;
  234. symbolic procedure monicize u;
  235. %makes standard form u monic by the appropriate variable subst.;
  236. begin scalar a,mvu,x;
  237. integer n;
  238. x := lc u;
  239. mvu := mvar u;
  240. n := ldeg u;
  241. !*acounter!* := !*acounter!* + 1;
  242. a := intern compress append(explode !*extvar!*,
  243. explode !*acounter!*);
  244. u := multsq(subf(u,list(mvu . list('quotient,a,x))),
  245. x**(n-1) ./ 1);
  246. mk!-algebraic!-number!-vars list mvu;
  247. put!-current!-representation(mvu,
  248. mkar(a to 1 .* ('!:rn!: . 1 . x)
  249. .+ nil));
  250. terpri();
  251. prin2 "defining polynomial has been monicized";
  252. terpri();
  253. maprin prepsq u;
  254. terpri!* t;
  255. return !*q2f u
  256. end;
  257. symbolic procedure polynorm u;
  258. begin scalar dmode!*,x,y;
  259. integer n;
  260. n := ldeg curdefpol!*;
  261. x := fd2q u;
  262. y := resultantft(curdefpol!*,numr x,mvar curdefpol!*);
  263. dmode!* := '!:ar!:;
  264. return if denr x = 1 then y
  265. else !*q2f multsq(y ./ 1,1 ./ (denr x)**n)
  266. end;
  267. symbolic procedure resultantft(u,v,w);
  268. resultant(u,v,w);
  269. symbolic procedure factorft u;
  270. begin scalar dmode!*; return factorf u end;
  271. symbolic procedure fd2q u;
  272. %converts a s.f. over ar to a s.q. over the integers;
  273. if atom u then u ./ 1
  274. else if car u eq '!:ar!: then fd2q cdr u
  275. else if car u eq '!:rn!: then cdr u
  276. else addsq(multsq(!*p2q lpow u,fd2q lc u),fd2q red u);
  277. symbolic procedure sqfrnorm u;
  278. begin scalar l,norm,y; integer s;
  279. y := u;
  280. if algebnp u then go to b;
  281. a: s := s-1;
  282. l := list(mvar u . prepf
  283. addf(!*k2f mvar u,multd(s,!*k2f mvar curdefpol!*)));
  284. y := numr subf1(u,l);
  285. if null algebnp y then go to a;
  286. b: norm := polynorm y;
  287. if not ar!-sqfrp norm then go to a;
  288. return norm . (s . y)
  289. end;
  290. symbolic procedure algebnp u;
  291. if atom u then nil
  292. else if car u eq '!:ar!: then t
  293. else if domainp u then nil
  294. else algebnp lc u or algebnp red u;
  295. symbolic procedure ar!-sqfrp u;
  296. % This is same as sqfrp in gint module.
  297. domainp gcdf!*(u,diff(u,mvar u));
  298. symbolic procedure primitive!_elem u;
  299. begin scalar a,x,y,z,newu,newdefpoly,olddefpoly;
  300. if x := not!_in!_extension u then u := x
  301. else return;
  302. !*acounter!* := !*acounter!* + 1;
  303. a := intern compress append(explode !*extvar!*,
  304. explode !*acounter!*);
  305. x := sqfrnorm u;
  306. newdefpoly := !*q2f subf(car x,list(mvar car x . a));
  307. olddefpoly := curdefpol!*;
  308. newu := !*q2f subf(cddr x,list(mvar car x . a));
  309. rmsubs();
  310. release arvars!*;
  311. initalgnum prepf newdefpoly;
  312. y := gcdf!*(numr simp prepf newu,olddefpoly);
  313. arvars!* := mvar car x . arvars!*;
  314. mk!-algebraic!-number!-vars arvars!*;
  315. put!-current!-representation(mvar olddefpoly,
  316. z := quotf!*(negf red y,lc y));
  317. put!-current!-representation(mvar car x,
  318. addf(mkar !*k2f a,
  319. multf(!*n2f cadr x,z)));
  320. rmsubs();
  321. update!-extension arvars!*;
  322. terpri!* t;
  323. prin2!* "*** Defining polynomial for primitive element:";
  324. terpri!* t;
  325. maprin prepf curdefpol!*;
  326. terpri!* t
  327. end;
  328. symbolic procedure not!_in!_extension u;
  329. %We still need a criterion which branch to choose;
  330. %Isolating intervals would do;
  331. begin scalar ndp,x; integer cld;
  332. if null !*minimal then return u;
  333. cld := ldeg u;
  334. x := arfactor!: u;
  335. for each j in cdr x do
  336. if ldeg car j < cld then
  337. <<ndp := car j;
  338. cld := ldeg ndp>>;
  339. if cld=1 then <<mk!-algebraic!-number!-vars list mvar u;
  340. put!-current!-representation(mvar u,
  341. quotf!*(negf red ndp,lc ndp));
  342. return nil>>
  343. else return ndp
  344. end;
  345. symbolic procedure split!_field1(u,v);
  346. %determines the minimal splitting field for u;
  347. begin scalar a,ftrs,mvu,q,x,y,z,roots,bpoly,minpoly,newminpoly,
  348. polys,newfactors,dmode!*,!*exp;
  349. integer indx,k,n,new!_s;
  350. off 'arnum; %crude way to clear previous extensions;
  351. !*exp := t;
  352. u := !*q2f simp!* u;
  353. mvu := mvar u;
  354. indx := 1;
  355. polys := (1 . u) . polys;
  356. !*acounter!* := !*acounter!* + 1;
  357. a := intern compress append(explode !*extvar!*,
  358. explode !*acounter!*);
  359. minpoly := newminpoly := numr subf(u,list(mvu . a));
  360. dmode!* := '!:ar!:;
  361. mkextension prepf minpoly;
  362. roots := mkar !*k2f a . roots;
  363. b: polys := for each j in polys collect
  364. if indx=car j then
  365. car j . quotf!*(cdr j,
  366. addf(!*k2f mvu,negf car roots))
  367. else j;
  368. k := 1;
  369. indx := 0;
  370. for each j in polys do
  371. begin scalar l;
  372. x := sqfrnorm cdr j;
  373. if cadr x neq 0 then
  374. l := list(mvu . prepf addf(!*k2f mvu,
  375. negf multd(cadr x,!*k2f a)));
  376. z := cddr x;
  377. dmode!* := nil;
  378. ftrs := cdr factorf car x;
  379. dmode!* := '!:ar!:;
  380. for each qq in ftrs do
  381. <<y := gcdf!*(z,q:=car qq);
  382. if ldeg q > ldeg newminpoly then
  383. <<newminpoly := q;
  384. new!_s := cadr x;
  385. indx := k;
  386. bpoly := y>>;
  387. z := quotf!*(z,y);
  388. if l then y := numr subf(y,l);
  389. if ldeg y=1 then
  390. roots := quotf(negf red y,lc y) . roots
  391. else <<newfactors:=(k . y) . newfactors;
  392. k:=k+1>>>>
  393. end;
  394. if null newfactors then
  395. <<terpri();
  396. prin2t "*** Splitting field is generated by:";
  397. terpri();
  398. maprin prepf newminpoly;
  399. terpri!* t;
  400. n := length roots;
  401. return multiple!-result(
  402. for each j in roots collect
  403. (n := n-1) . mk!*sq(j ./ 1),v)>>;
  404. !*acounter!* := !*acounter!* + 1;
  405. a := intern compress append(explode !*extvar!*,
  406. explode !*acounter!*);
  407. newminpoly := numr subf(newminpoly,list(mvu . a));
  408. bpoly := numr subf(bpoly,list(mvu . a));
  409. rmsubs();
  410. release arvars!*;
  411. initalgnum prepf newminpoly;
  412. x := gcdf!*(minpoly,numr simp prepf bpoly);
  413. mk!-algebraic!-number!-vars arvars!*;
  414. put!-current!-representation(mvar minpoly,
  415. z := quotf!*(negf red x,lc x));
  416. rmsubs();
  417. roots := addf(mkar !*k2f a,multf(!*n2f new!_s,z)) .
  418. for each j in roots collect numr subf(cdr j,nil);
  419. polys := for each j in newfactors collect
  420. car j . numr simp prepf cdr j;
  421. newfactors := nil;
  422. minpoly := newminpoly;
  423. go to b
  424. end;
  425. symbolic procedure split!-field!-eval u;
  426. begin scalar x;
  427. if length u > 2
  428. then rederr "split!_field called with wrong number of arguments";
  429. x := split!_field1(car u,if cdr u then cadr u else nil);
  430. dmode!* := '!:ar!:;
  431. %The above is necessary for working with the results.
  432. return x
  433. end;
  434. put('split!_field,'psopfn,'split!-field!-eval);
  435. symbolic procedure arrationalize!: u;
  436. %We should actually factorize the denominator first to
  437. %make sure that the result is in lowest terms. ????
  438. begin scalar x,y,z,dmode!*;
  439. if domainp denr u then return quotf(numr u,denr u) ./ 1;
  440. if null algebnp denr u then return u;
  441. x := polynorm numr fd2q denr u;
  442. y := multsq(fd2q multf(numr u,quotf!*(x,denr u)),1 ./ x);
  443. dmode!* := '!:ar!:;
  444. x := numr subf(denr y,nil);
  445. y := numr subf(numr y,nil);
  446. z := lnc x;
  447. return quotf(y,z) ./ quotf(x,z)
  448. end;
  449. %put('rationalize,'simpfn,'rationalize); its now activated by a switch.
  450. put('polynorm,'polyfn,'polynorm);
  451. %*** support functions ***;
  452. comment the function ilnrsolve and others are identical to the
  453. %ones in matr except they work only on integers here;
  454. %there should be better algorithms;
  455. symbolic procedure reducepowers u;
  456. %reduces powers with the help of the defining polynomial;
  457. if domainp u or (ldeg u<pdeg car repowl!*) then u
  458. else if ldeg u=pdeg car repowl!* then
  459. addf(multf(cdr repowl!*,lc u),red u)
  460. else reducepowers
  461. addf(multf(multpf(mvar u .** (ldeg u-pdeg car repowl!*),lc u),
  462. cdr repowl!*),red u);
  463. symbolic procedure mkqmatr u;
  464. %u is an ar domainelement, result is a matrix form which
  465. %needs to be inverted for calculating the inverse of ar;
  466. begin scalar r,x,v,w;
  467. v := mkqcol u;
  468. for each k in cdr reverse arbase!* do
  469. <<w := reducepowers multpf(k,u);
  470. v := for each j in arbase!* collect
  471. <<r := ((if atom j then ratn w
  472. else if domainp w then 0 . 1
  473. else if j=lpow w then
  474. <<x:=ratn lc w; w:=cdr w; x>>
  475. else 0 . 1) . car v);
  476. v := cdr v;
  477. r>>>>;
  478. return v
  479. end;
  480. symbolic procedure mkqcol u;
  481. %u is an ar domainelement result is a matrix form
  482. %representing u as a coefficient matrix of the ar base;
  483. begin scalar x,v;
  484. v := for each j in arbase!* collect
  485. if atom j then list ratn u
  486. else if domainp u then list(0 . 1)
  487. else if j=lpow u then <<x:=list ratn lc u; u:=cdr u; x>>
  488. else list(0 . 1);
  489. return v
  490. end;
  491. symbolic procedure ratn u;
  492. if null u then 0 . 1
  493. else if atom u then u . 1
  494. else if car u eq '!:rn!: then cdr u
  495. else rederr "Illegal domain in :ar:";
  496. symbolic procedure inormmat u;
  497. begin integer y; scalar z;
  498. % x := 1;
  499. for each v in u do
  500. <<y := 1;
  501. for each w in v do y := ilcm(y,denr w);
  502. z := (for each w in v
  503. collect numr w*y/denr w) . z>>;
  504. return reverse z
  505. end;
  506. symbolic procedure ilcm(u,v);
  507. if u=0 or v=0 then 0
  508. else if u=1 then v
  509. else if v=1 then u
  510. else u*v/gcdn(u,v);
  511. symbolic procedure ilnrsolve(u,v);
  512. %u is a matrix standard form, v a compatible matrix form;
  513. %value is u**(-1)*v;
  514. begin integer n;
  515. n := length u;
  516. v := ibacksub(ibareiss inormmat ar!-augment(u,v),n);
  517. u := ar!-rhside(car v,n);
  518. v := cdr v;
  519. return for each j in u collect
  520. for each k in j collect mkrn(k,v)
  521. end;
  522. symbolic procedure ar!-augment(u,v);
  523. % Same as augment in bareiss module.
  524. if null u then nil
  525. else append(car u,car v) . ar!-augment(cdr u,cdr v);
  526. symbolic procedure ar!-rhside(u,m);
  527. % Same as rhside in bareiss module.
  528. if null u then nil else pnth(car u,m+1) . ar!-rhside(cdr u,m);
  529. symbolic procedure ibareiss u;
  530. %as in matr but only for integers;
  531. begin scalar ik1,ij,kk1,kj,k1j,k1k1,ui,u1,x;
  532. integer k,k1,aa,c0,ci1,ci2;
  533. aa:= 1;
  534. k:= 2;
  535. k1:=1;
  536. u1:=u;
  537. go to pivot;
  538. agn: u1 := cdr u1;
  539. if null cdr u1 or null cddr u1 then return u;
  540. aa:=nth(car u1,k); %aa := u(k,k);
  541. k:=k+2;
  542. k1:=k-1;
  543. u1:=cdr u1;
  544. pivot: %pivot algorithm;
  545. k1j:= k1k1 := pnth(car u1,k1);
  546. if car k1k1 neq 0 then go to l2;
  547. ui:= cdr u1; %i := k;
  548. l: if null ui then return nil
  549. else if car(ij := pnth(car ui,k1))=0
  550. then go to l1;
  551. l0: if null ij then go to l2;
  552. x:= car ij;
  553. rplaca(ij,-car k1j);
  554. rplaca(k1j,x);
  555. ij:= cdr ij;
  556. k1j:= cdr k1j;
  557. go to l0;
  558. l1: ui:= cdr ui;
  559. go to l;
  560. l2: ui:= cdr u1; %i:= k;
  561. l21: if null ui then return; %if i>m then return;
  562. ij:= pnth(car ui,k1);
  563. c0:= car k1k1*cadr ij-cadr k1k1*car ij;
  564. if c0 neq 0 then go to l3;
  565. ui:= cdr ui; %i:= i+1;
  566. go to l21;
  567. l3: c0:= c0/aa;
  568. kk1 := kj := pnth(cadr u1,k1); %kk1 := u(k,k-1);
  569. if cdr u1 and null cddr u1 then go to ev0
  570. else if ui eq cdr u1 then go to comp;
  571. l31: if null ij then go to comp; %if i>n then go to comp;
  572. x:= car ij;
  573. rplaca(ij,-car kj);
  574. rplaca(kj,x);
  575. ij:= cdr ij;
  576. kj:= cdr kj;
  577. go to l31;
  578. %pivoting complete;
  579. comp:
  580. if null cdr u1 then go to ev;
  581. ui:= cddr u1; %i:= k+1;
  582. comp1:
  583. if null ui then go to ev; %if i>m then go to ev;
  584. ik1:= pnth(car ui,k1);
  585. ci1:= (cadr k1k1*car ik1-car k1k1*cadr ik1)/aa;
  586. ci2:= (car kk1*cadr ik1-cadr kk1*car ik1)/aa;
  587. if null cddr k1k1 then go to comp3;%if j>n then go to comp3;
  588. ij:= cddr ik1; %j:= k+1;
  589. kj:= cddr kk1;
  590. k1j:= cddr k1k1;
  591. comp2:
  592. if null ij then go to comp3;
  593. rplaca(ij,(car ij*c0+car kj*ci1+car k1j*ci2)/aa);
  594. ij:= cdr ij;
  595. kj:= cdr kj;
  596. k1j:= cdr k1j;
  597. go to comp2;
  598. comp3:
  599. ui:= cdr ui;
  600. go to comp1;
  601. ev0:if c0=0 then return;
  602. ev: kj := cdr kk1;
  603. x := cddr k1k1; %x := u(k-1,k+1);
  604. rplaca(kj,c0);
  605. ev1:kj:= cdr kj;
  606. if null kj then go to agn;
  607. rplaca(kj,(car k1k1*car kj-car kk1*car x)/aa);
  608. x := cdr x;
  609. go to ev1
  610. end;
  611. symbolic procedure ibacksub(u,m);
  612. begin scalar ij,ijj,ri,uj,ur; integer i,jj,summ,detm,det1;
  613. %n in comments is number of columns in u;
  614. if null u then rederr "singular matrix";
  615. ur := reverse u;
  616. detm := car pnth(car ur,m); %detm := u(i,j);
  617. if detm=0 then rederr "singular matrix";
  618. i := m;
  619. rows:
  620. i := i-1;
  621. ur := cdr ur;
  622. if null ur then return u . detm;
  623. %if i=0 then return u . detm;
  624. ri := car ur;
  625. jj := m+1;
  626. ijj:=pnth(ri,jj);
  627. r2: if null ijj then go to rows; %if jj>n then go to rows;
  628. ij := pnth(ri,i); %j := i;
  629. det1 := car ij; %det1 := u(i,i);
  630. uj := pnth(u,i);
  631. summ := 0; %summ := 0;
  632. r3: uj := cdr uj; %j := j+1;
  633. if null uj then go to r4; %if j>m then go to r4;
  634. ij := cdr ij;
  635. summ := summ+car ij*nth(car uj,jj);
  636. %summ:=summ+u(i,j)*u(j,jj);
  637. go to r3;
  638. r4: rplaca(ijj,(detm*car ijj-summ)/det1);
  639. %u(i,j):=(detm*u(i,j)-summ)/det1;
  640. jj := jj+1;
  641. ijj := cdr ijj;
  642. go to r2
  643. end;
  644. initdmode 'arnum;
  645. put('arnum,'simpfg,
  646. '((t (setdmode (quote arnum) t))
  647. (nil (setdmode (quote arnum) nil) (release arvars!*)
  648. (uncurrep arvars!*) (setq curdefpol!* nil)
  649. (setq arvars!* nil))));
  650. endmodule;
  651. end;