codad2.red 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317
  1. module codad2; % Facilities applied after optimization.
  2. % ------------------------------------------------------------------- ;
  3. % Copyright : J.A. van Hulzen, Twente University, Dept. of Computer ;
  4. % Science, P.O.Box 217, 7500 AE Enschede, the Netherlands.;
  5. % Authors : J.A. van Hulzen, B.J.A. Hulshof, W.N. Borst. ;
  6. % ------------------------------------------------------------------- ;
  7. symbolic$
  8. % ------------------------------------------------------------------- ;
  9. % The module CODAD2 contains a number of facilities, to be applied ;
  10. % when the optimization process itself is finished and before produ- ;
  11. % cing output. This finishing touch, obtained by applying the function;
  12. % PrepFinalplst (see the module CODCTL), covers the following one-row ;
  13. % and/or one-column operations: ;
  14. % ;
  15. % PART 1 : Sum restructuring : s = (t1 + ... + tn) ^ exponent is re- ;
  16. % placed by name := t1 + ... + tn; s:= name ^ exponent. ;
  17. % Remark : This form allows application of an addition chain ;
  18. % algorithm on the exponent, as part of the print process, ;
  19. % and as defined in the module CODPRI. ;
  20. % ;
  21. % PART 2 : REMoval of REPeatedly occurring MULTiples of VARiables in ;
  22. % linear (sub)expressions, which could not be replaced by a ;
  23. % Breuer-search, since it requires one-column operations in ;
  24. % the PLUS-part of CodMat. If such a multiple occurs atleast ;
  25. % twice, it is replaced by a new name. The TIMES-part of ;
  26. % CodMat is consulted if such a multiple is found to allow ;
  27. % the replacement of such multiples in monomials as well. So ;
  28. % x = 3.a + b, y = 3.a + c, z = 3.a.b + c ;
  29. % is replaced by ;
  30. % s = 3.a ;
  31. % x = s + b, y = s + c, z = s.b + c. ;
  32. % ;
  33. % PART 3 : An UPDATE of MONOMIALS is performed. Constant multilpes of ;
  34. % identifiers are selected using the TIMES-part of CodMat. ;
  35. % Since the PLUS-part is already checked with REMREPMULTVARS ;
  36. % the search is limited to the TIMES-part. Replacement by a ;
  37. % new name is only effectuated if such a multiple literally ;
  38. % occurs twice. So ;
  39. % x = 3.a.b + 6.b.c, y = 3.a.c + 6.a.b ;
  40. % is replaced by ;
  41. % s1 = 3.a, s2 = 6.b ;
  42. % x = s1.b + s2.c, y = s1.c + s2.a. ;
  43. % ;
  44. % PART 4 : An all level factoring out of gcd's of constant coeff.'s in;
  45. % (composite) sums, using the function CODGCD. For example ;
  46. % sum = 9.a - 18.b + 6.sin(x) + 5.c -5.d ;
  47. % can be rewritten into ;
  48. % sum = 3.(3.a - 6.b + 2.sin(x)) + 5.(c - d). ;
  49. % But the arithmetic complexity of both representations of ;
  50. % sum is equal. We therefore produce ;
  51. % sum = 9.a - 18.b + 6.sin(x) + 5.(c - d). ;
  52. % Regrouping of (composite) products demands for an identical;
  53. % algorithm. For instance ;
  54. % 9 18 6 ;
  55. % prod = a b sin (x) ;
  56. % can be rewritten into ;
  57. % 3 ;
  58. % 3 6 2 ;
  59. % prod = {a b sin (x)} ;
  60. % thus reducing the required number of multiplications. ;
  61. % ;
  62. % PART 5 : A quotient-cse search. For example ;
  63. % kvarlst = ( (g1 quotient g2 g3) ;
  64. % (g4 quotient g5 dm) ) ;
  65. % matrix : g2 = nr * a ;
  66. % g3 = dm * b ;
  67. % g5 = nr * c ;
  68. % will be rewritten as ;
  69. % kvarlst = ( (g7 quotient nr dm) ;
  70. % (g1 quotient g2 b) ;
  71. % (g4 g5) ) ;
  72. % matrix : g2 = g7 * a ;
  73. % g5 = g7 * c ;
  74. % ------------------------------------------------------------------- ;
  75. % ------------------------------------------------------------------- ;
  76. % Global identifiers needed in this module are : ;
  77. % ------------------------------------------------------------------- ;
  78. global '(rowmin rowmax);
  79. % ------------------------------------------------------------------- ;
  80. % The meaning of these globals is given in the module CODMAT. ;
  81. % ------------------------------------------------------------------- ;
  82. symbolic smacro procedure find!+var(var,fa,iv);
  83. getcind(var,'varlst!+,'plus,fa,iv);
  84. symbolic smacro procedure find!*var(var,fa,iv);
  85. getcind(var,'varlst!*,'times,fa,iv);
  86. symbolic procedure getcind(var,varlst,op,fa,iv);
  87. % ------------------------------------------------------------------- ;
  88. % REMARK : GETCIND is also defined in the module CODAD1. This copy ;
  89. % allows seperate compilation. ;
  90. % ------------------------------------------------------------------- ;
  91. % The purpose of the procedure GetCind is to create a column in CODMAT;
  92. % which will be associated with the variable Var if this variable does;
  93. % not yet belong to the set Varlst,i.e.does not yet play a role in the;
  94. % corresponding PLUS- or TIMES setting (known by the value of Op).Once;
  95. % the column exists (either created or already available), its Zstrt ;
  96. % is modified by inserting the Z-element (Fa,IV) in it. Finally the ;
  97. % corresponding Z-element for the father-row, i.e. (Y,IV) is returned.;
  98. % ------------------------------------------------------------------- ;
  99. begin scalar y,z;
  100. if null(y:=get(var,varlst))
  101. then
  102. <<y:=rowmin:=rowmin-1;
  103. put(var,varlst,y);
  104. setrow(y,op,var,nil,nil)
  105. >>;
  106. setzstrt(y,inszzzn(z:=mkzel(fa,iv),zstrt y));
  107. return mkzel(y,val z)
  108. end;
  109. % ------------------------------------------------------------------- ;
  110. % PART 1 : SUM RESTRUCTURING ;
  111. % ------------------------------------------------------------------- ;
  112. symbolic procedure powerofsums;
  113. % ------------------------------------------------------------------- ;
  114. % The CODMAT PLUS-rows are investigated, who have an ExpCof-value > 1.;
  115. % Such rows define a sum raised to the exponent ExpCof(rowindex). ;
  116. % ------------------------------------------------------------------- ;
  117. begin scalar var,z,rmax;
  118. rmax:=rowmax;
  119. for x:=0:rmax do
  120. if opval(x) eq 'plus and expcof(x)>1 and not(farvar(x)=-1)
  121. then
  122. <<var:=fnewsym();
  123. setrow(rowmax:=rowmax+1,'plus,var,list chrow x,zstrt x);
  124. % -------------------------------------------------------------- ;
  125. % A new name Var is introduced and 2 new CODMAT-rows to store the;
  126. % information about the new expression,in connection with the al-;
  127. % raedy available information. Furthermore some bookkeeping is ;
  128. % required. ;
  129. % The new row above contains all the information about the sum, ;
  130. % except its exponent.Below the second row is used to store Var ^;
  131. % ExpCof in the form of a Z-element in a TIMES-row. ;
  132. % This row becomes the only child of the old sum-defining row. ;
  133. % -------------------------------------------------------------- ;
  134. put(var,'rowindex,rowmax);
  135. foreach z in zstrt(x) do
  136. setzstrt(yind z,mkzel(rowmax,val z).delyzz(x,zstrt yind z));
  137. foreach ch in chrow(x) do setfarvar(ch,rowmax);
  138. setprev(x,rowmax); % Preserve ordening;
  139. setrow(rowmax:=rowmax+1,'times,x,list nil,
  140. list(z:=mkzel(rowmin:=rowmin-1,expcof x)));
  141. % -------------------------------------------------------------- ;
  142. % The new row for the power of the sum is based on indirection to;
  143. % guarantee a correct functioning of the function Tchscheme. ;
  144. % -------------------------------------------------------------- ;
  145. setrow(rowmin,'times,var,nil,list mkzel(rowmax,val z));
  146. % -------------------------------------------------------------- ;
  147. % A new column is generated, associated with the new name genera-;
  148. % ted for the sum. ;
  149. % -------------------------------------------------------------- ;
  150. setchrow(x,list rowmax);
  151. put(var,'varlst!*,rowmin);
  152. setzstrt(x,nil);
  153. setexpcof(x,1)
  154. >>;
  155. end;
  156. % ------------------------------------------------------------------- ;
  157. % PART 2 : REMoval of REPeatedly Occurring Constant MULTiples of PLUS ;
  158. % VARiableS. ;
  159. % ------------------------------------------------------------------- ;
  160. symbolic procedure remrepmultvars;
  161. % ------------------------------------------------------------------- ;
  162. % All PLUS-columns of CODMAT are investigated. Let Var be the variable;
  163. % associated with thw column Y. A list P(lus)col(umn)inf(ormation) is ;
  164. % made out of the Zstreet of column Y. Pcolinf consists of pairs of ;
  165. % the form constant(k). list of pairs (rowindex.sign(constant(k))), ;
  166. % such that 0<constant(i)<constant(j) if i<j and also such that coef- ;
  167. % ficient of Var in Zstreet(rowindex) is sign(k)*constant(k). ;
  168. % Then for each element of this list Pcolinf a corresponding list with;
  169. % T(imes)col(umn)inf(ormation) is made. This is a list consisting of ;
  170. % pairs of the form (rowindex . Z-element with the same index as value;
  171. % of its index-part and taken from the Zstreet of the column with the ;
  172. % index Prod(uct)col(umn)i(ndex), whose Expcof-value is a multiple of ;
  173. % the car of the element of Pcolinf, which is under consideration). ;
  174. % So assuming some multiples 3*A occur in some sums, which are easily ;
  175. % retrievable using the corresponding element of Pcolinf, we also re- ;
  176. % place parts of monomials of the same form. Hence 6*A^2*B is replaced;
  177. % by 2*A*B*(cse-name for 3*A).This does not increase the multiplicati-;
  178. % ve complexity. It can even decrease if some monomials of the form ;
  179. % 3*A*(something else) occur in the set of expressions currently being;
  180. % investigated. ;
  181. % ------------------------------------------------------------------- ;
  182. begin
  183. scalar
  184. rmin,var,prodcoli,pcolinf,mmult,srows,tcolinf,rindx,nvar,z,zz,zz1;
  185. rmin:=rowmin;
  186. for y:=rmin:(-1) do
  187. % ----------------------------------------------------------------- ;
  188. % Analysis of Zstreets of the PLUS-columns, which are associated ;
  189. % with variables Var. ;
  190. % ----------------------------------------------------------------- ;
  191. if (not numberp(var:=farvar y)) and (var neq '!+one) and
  192. (opval(y) eq 'plus)
  193. then
  194. <<prodcoli:=get(var,'varlst!*);
  195. pcolinf:=nil;
  196. foreach z in zstrt(y) do
  197. if not(!:onep dm!-abs(ival z))
  198. then pcolinf:=inspcvv(xind(z).(if !:minusp(ival(z)) then -1 else 1),
  199. dm!-abs(ival z),pcolinf);
  200. % --------------------------------------------------------------- ;
  201. % The function InsPCvv, defined in the module CODOPT, is used to ;
  202. % produce the list Pcolinf. The NIL-initialisation is necessary ;
  203. % since a fresh start is required for each column under investiga-;
  204. % tion. The different elements of Pcolinf are used for a closer ;
  205. % look. ;
  206. % --------------------------------------------------------------- ;
  207. foreach cseinfo in pcolinf do
  208. <<mmult:=car(cseinfo);
  209. srows:=cdr(cseinfo);
  210. tcolinf:=nil;
  211. if prodcoli
  212. then
  213. foreach z in zstrt(prodcoli) do
  214. <<rindx:=xind(z);
  215. if dm!-eq(dm!-abs expcof rindx,mmult)
  216. then tcolinf:=(rindx.z).tcolinf
  217. >>;
  218. % ------------------------------------------------------------- ;
  219. % The list Tcolinf is now ready.If the number of elem.s of Srows;
  220. % and Tcolinf together is atleast 2 the multiplicative complexi-;
  221. % ty is not increasing if say 3*A is replaced by cse-name. ;
  222. % ------------------------------------------------------------- ;
  223. if length(srows)+length(tcolinf)>1
  224. then
  225. << % --------------------------------------------------------- ;
  226. % A new expression is made and all required bookkeeping ac- ;
  227. % tions are performed. So all occurrences of say 3*A are re-;
  228. % moved from the Zstreet of the corresponding PLUS-column, a;
  229. % new column to store the placeholder for this 3*A is crea- ;
  230. % ted and all required modifications in the affected Zstrts ;
  231. % are carries out. ;
  232. % --------------------------------------------------------- ;
  233. z:=mkzel(y,mmult);
  234. nvar:=fnewsym();
  235. rowmax:=rowmax+1;
  236. setrow(rowmax,'plus,nvar,list nil,list z);
  237. put(nvar,'rowindex,rowmax);
  238. rowmin:=rowmin-1;
  239. zz:=nil;
  240. foreach rowinf in srows do
  241. <<rindx:=car(rowinf);
  242. zz:=mkzel(rindx,cdr rowinf).zz;
  243. setzstrt(rindx,mkzel(rowmin,val car zz).
  244. delyzz(y,zstrt rindx));
  245. setprev(rindx,rowmax)
  246. >>;
  247. setzstrt(y,mkzel(rowmax,val z).remzzzz(zz,zstrt y));
  248. setrow(rowmin,'plus,nvar,nil,zz);
  249. put(nvar,'varlst!+,rowmin);
  250. if tcolinf
  251. then
  252. << % --------------------------------------------------- ;
  253. % Since Tcolinf is not empty some monomials have to be;
  254. % modified as well. ;
  255. % --------------------------------------------------- ;
  256. rowmin:=rowmin-1;
  257. zz1:=zz:=nil;
  258. foreach rowinf in tcolinf do
  259. <<rindx:=car(rowinf);
  260. z:=cdr(rowinf);
  261. zz:=mkzel(rindx,1).zz;
  262. if ival(z)>1
  263. then setival(z,ival(z)-1)
  264. else
  265. <<zz1:=car(zz).zz1;
  266. setzstrt(rindx,delyzz(prodcoli,zstrt rindx))
  267. >>;
  268. setzstrt(rindx,mkzel(rowmin,val car zz).
  269. zstrt(rindx));
  270. setprev(rindx,rowmax);
  271. setexpcof(rindx,dm!-quotient(expcof(rindx),mmult))
  272. >>;
  273. setzstrt(prodcoli,remzzzz(zz1,zstrt prodcoli));
  274. setrow(rowmin,'times,nvar,nil,zz);
  275. put(nvar,'varlst!*,rowmin)
  276. >>
  277. >>
  278. >>
  279. >>
  280. end;
  281. % ------------------------------------------------------------------- ;
  282. % PART 3 : An UPDATE of MONOMIALS via a TIMES-columns search. ;
  283. % ------------------------------------------------------------------- ;
  284. symbolic procedure updatemonomials;
  285. % ------------------------------------------------------------------- ;
  286. % For each column, which is associated with an identifier, a Gclst is ;
  287. % produced. The syntax of such a list is given in PART 4. Each element;
  288. % of such a list, is itself a list, consisting of a constant and ;
  289. % structural information about the occurrences of this constant. These;
  290. % sublists are used to deside if constant multiples can be replaced by;
  291. % new names. The decision are made by applying the function REMGCMON. ;
  292. % ------------------------------------------------------------------- ;
  293. for y:=rowmin:(-1) do
  294. if not numberp(farvar y) and opval(y) eq 'times
  295. then foreach gcel in mkgclstmon(y) do remgcmon(gcel,y);
  296. symbolic procedure mkgclstmon(y);
  297. % ------------------------------------------------------------------- ;
  298. % All monomial coefficients of the TIMES-rows sharing an element with ;
  299. % the current TIMES-column are grouped in a Gclst if their absolute ;
  300. % value is atleast 2. ;
  301. % ------------------------------------------------------------------- ;
  302. begin scalar gclst,cof,indxsgn;
  303. foreach z in zstrt(y) do
  304. if not !:onep dm!-abs(cof:=expcof xind z)
  305. then
  306. << indxsgn:=cons(xind(z), if !:minusp cof then -1 else 1);
  307. gclst:=insgclst(cof,indxsgn,gclst,1)
  308. >>;
  309. return gclst
  310. end;
  311. symbolic procedure remgcmon(gcel,y);
  312. % ------------------------------------------------------------------- ;
  313. % RemGcMon is recursively applied on Gcel. Its purpose is finding re- ;
  314. % peatedly occurring multiples of idntifiers in monomials. However 6.a;
  315. % is not considered when 3.a proves to be a cse, simply because it ;
  316. % does not reduce the multiplicative complexity of the set of expres- ;
  317. % sions being optimized. ;
  318. % The srategy employed is very similar to the techniques used in PART ;
  319. % 4. ;
  320. % ------------------------------------------------------------------- ;
  321. begin scalar x,nvar,gc,zel,zzy,zzgc,ivalz;
  322. if length(cadr gcel)>1
  323. then
  324. << gc:=car gcel;
  325. rowmin:=rowmin-1; rowmax:=rowmax+1;
  326. nvar:=fnewsym();
  327. zel:=mkzel(y,1);
  328. setrow(rowmax,'times,nvar,list(nil,gc),list(zel));
  329. put(nvar,'rowindex,rowmax);
  330. zzy:=mkzel(rowmax,val(zel)).zstrt(y);
  331. zzgc:=nil;
  332. foreach z in cadr(gcel) do
  333. << x:=car(z);
  334. setexpcof(x,1);
  335. setprev(x,rowmax);
  336. zel:=car(pnthxzz(x,zzy));
  337. if ival(zel)>1
  338. then
  339. << zzy:=inszzz(mkzel(x,ivalz:=dm!-difference(ival(zel),1)),
  340. delyzz(x,zzy));
  341. setzstrt(x,inszzzr(mkzel(y,ivalz),delyzz(y,zstrt x)))
  342. >>
  343. else
  344. << zzy:=delyzz(x,zzy);
  345. setzstrt(x,delyzz(y,zstrt x))
  346. >>;
  347. zzgc:=inszzz(zel:=mkzel(x,1),zzgc);
  348. setzstrt(x,mkzel(rowmin,val zel).zstrt(x))
  349. >>;
  350. setzstrt(y,zzy);
  351. setrow(rowmin,'times,nvar,nil,zzgc);
  352. put(nvar,'varlst!*,rowmin)
  353. >>;
  354. if cddr(gcel) then foreach item in cddr(gcel) do remgcmon(item,y)
  355. end;
  356. % ------------------------------------------------------------------- ;
  357. % PART 4 : Gcd-based expression rewriting ;
  358. % ------------------------------------------------------------------- ;
  359. % We employ a two stage strategy. We start producing a Gclst, consis- ;
  360. % ting of row-information. If relevant, Gclst is used to rewrite the ;
  361. % expression (part), defined by the current row of CodMat. The Gclst- ;
  362. % syntax is : ;
  363. % ;
  364. % Gclst ::= (Gcdlst Gcdlst ... Gcdlst ) , n >= 1 . ;
  365. % 1 2 n ;
  366. % Gcdlst ::= (G Glocations glst ... glst ) , m >= 0 . ;
  367. % 1 m ;
  368. % G ::= positive integer ;
  369. % Glocations ::= (location ... location ) , k >= 0 . ;
  370. % 1 k ;
  371. % location ::= (index . coeffsign) ;
  372. % coeffsign ::= +1 | -1 ;
  373. % index ::= columnindex | rowindex ;
  374. % columnindex ::= negative integer (relative value, see CodMat def.) ;
  375. % rowindex ::= non-negative integer (relative value, see Codmat def.) ;
  376. % glst ::= (g Glocations) ;
  377. % g ::= positive integer ;
  378. % ;
  379. % Semantics : We assume G = gcd(g1,...,gm) > 1. When other domains are;
  380. % introduced, the presumed domain is not longer Z, implying that Gcd2,;
  381. % * and / have to be made generic, when producing Gclst and rewriting ;
  382. % the expression using the function RemGc. ;
  383. % When m = 0, i.e. no glst's occur, the absolute value of all coeffi- ;
  384. % cients is equal to G. ;
  385. % Glocations can be an empty list,as shown in the following example : ;
  386. % ;
  387. % ((3 NIL (9 ((a.1))) (18 ((b.-1))) (6 ((sin(x).1)))) ;
  388. % (5 ((c.1) (d.-1)))) ;
  389. % ;
  390. % is the Gclst, associated with ;
  391. % sum = 9.a - 18.b + 6.sin(x) + 5.c - 5.d, ;
  392. % when replacing the negative, relative column-indices by a,b,c and d,;
  393. % and the positive relative child row-index by sin(x). ;
  394. % This list is used for the remodelling. The Glocations list is NIL, ;
  395. % because sum has no coefficients equal to either 3 or -3. ;
  396. % ------------------------------------------------------------------- ;
  397. symbolic procedure codgcd();
  398. begin scalar presentrowmax;
  399. % ------------------------------------------------------------------- ;
  400. % For all relevant rows of CodMat we compute the Gclst, by applying ;
  401. % the function MkGclst. Then each item in this list, a Gcdlst, is used;
  402. % for a reconstruction of the expression( part) defined by row X. ;
  403. % ------------------------------------------------------------------- ;
  404. presentrowmax:=rowmax;
  405. for x:=0:presentrowmax do
  406. if not(farvar(x)=-1)then foreach gcel in mkgclst(x) do remgc(gcel,x)
  407. end;
  408. symbolic procedure mkgclst(x);
  409. % ------------------------------------------------------------------- ;
  410. % The Gclst of row X is produced and returned. ;
  411. % ------------------------------------------------------------------- ;
  412. begin scalar gclst,iv,opv;
  413. foreach z in zstrt(x) do
  414. if not !:onep(dm!-abs(iv:=ival z))
  415. then
  416. % -------------------------------------------------------------- ;
  417. % The location (Yind(Z).coeffsign) is added to the glst with g = ;
  418. % abs(IV). ;
  419. % -------------------------------------------------------------- ;
  420. if !:minusp(iv)
  421. then gclst:=insgclst(dm!-minus(iv),yind(z).(-1),gclst,1)
  422. else gclst:=insgclst(iv,yind(z) . 1,gclst,1);
  423. opv:=opval(x);
  424. foreach ch in chrow(x) do
  425. if not(opval(ch)=opv) and not(!:onep dm!-abs(iv:=expcof ch))
  426. % --------------------------------------------------------------- ;
  427. % Only non *(+)-children of *(+)-parents are considered. ;
  428. % --------------------------------------------------------------- ;
  429. then
  430. % ------------------------------------------------------------- ;
  431. % The location (CH(=rowindex of child).coeffsign) is added to ;
  432. % the glst with g = abs(IV). ;
  433. % ------------------------------------------------------------- ;
  434. if !:minusp(iv)
  435. then gclst:=insgclst(dm!-minus iv,ch.(-1),gclst,1)
  436. else gclst:=insgclst(iv,ch . 1,gclst,1);
  437. return gclst;
  438. end;
  439. symbolic procedure insgclst(iv,y,gclst,gc0);
  440. % ------------------------------------------------------------------- ;
  441. % The most recent version of Gclst is returned after being updated by ;
  442. % adding the location Y to the glst with g = abs(IV) in Gclst, assu- ;
  443. % ming that G = Gc0. ;
  444. % ------------------------------------------------------------------- ;
  445. begin scalar gc,cgcl;
  446. return
  447. if null(gclst)
  448. then
  449. % ------------------------------------------------------------- ;
  450. % Start making such a list : If Y = (-1 . 1) and IV = 4 then we ;
  451. % get ((4 ((-1 . 1)))). ;
  452. % ------------------------------------------------------------- ;
  453. list(iv.(list(y).nil))
  454. else
  455. % ------------------------------------------------------------- ;
  456. % Extend the Gclst. ;
  457. % ------------------------------------------------------------- ;
  458. if dm!-eq(caar(gclst),iv)
  459. % ------------------------------------------------------------ ;
  460. % Add floats only to Gcdlst's of type (G Glocations). ;
  461. % Then IV = G (of Gcdlst ) and Y is added to Glocations as new;
  462. % 1 1 ;
  463. % location (since Cadar(Gclst) = Glocations of Gcdlst , Cddar ;
  464. % 1 ;
  465. % (Gclst) = (glst ... glst ) and Cdr(Gclst) = (Gcdlst ... ;
  466. % 1 m 2 ;
  467. % Gcdlst )). ;
  468. % n ;
  469. % If now IV = 4 and Y =(-2 . 1) then Gclst = ((4 ((-1 . 1)))) ;
  470. % is extended to ((4 ((-2 . 1) (-1 . 1)))). ;
  471. % ------------------------------------------------------------ ;
  472. then (iv.((y.cadar(gclst)).cddar(gclst))).(cdr gclst)
  473. else
  474. if floatprop(iv) or floatprop(caar gclst) or
  475. (gc:=gcd2(iv,caar gclst)) <= gc0
  476. then
  477. % ---------------------------------------------------------- ;
  478. % IV and G are relative prime. The elements Gcdlst , i > 1, ;
  479. % i ;
  480. % are further investigated, if existing. ;
  481. % So if IV = 5 and Y = (-2 . 1) then Gclst = ((4 (-1 . 1)))) ;
  482. % is extended to ((4 ((-1 . 1))) (5 ((-2 . 1))))). ;
  483. % ---------------------------------------------------------- ;
  484. car(gclst).insgclst(iv,y,cdr gclst,gc0)
  485. else
  486. % ----------------------------------------------------------- ;
  487. % Gc = gcd(IV,G ) > Gc0 (=1, initially). ;
  488. % 1 ;
  489. % ----------------------------------------------------------- ;
  490. if gc=caar(gclst)
  491. % -------------------------------------------------------- ;
  492. % IV > Gc = G , implying that the (IV,Y)-info has to be ;
  493. % 1 ;
  494. % stored in one of the Gcdlst lists, i > 1. ;
  495. % i ;
  496. % So if IV=8 and Y=(-2 . 1) then Gclst = ((4 ((-1 . 1)))) ;
  497. % is extended to ((4 ((-1 . 1)) (8 ((-2 . 1)))). ;
  498. % -------------------------------------------------------- ;
  499. then (append
  500. (list(gc,cadar gclst),insdiff(iv,y,cddar gclst))).
  501. (cdr gclst)
  502. else
  503. if gc=iv
  504. % ------------------------------------------------------- ;
  505. % Gc = IV < G demands for remodelling of Gcdlst , such ;
  506. % 1 1 ;
  507. % that now Gcdlst = (Gc Etc).So if IV = 2 and Y =(-2 . 1);
  508. % 1 ;
  509. % then Gclst = ((4 ((-1 . 1)))) is extended to the list ;
  510. % ((2 ((-2 . 1)) (4 ((-1 . 1))))). ;
  511. % ------------------------------------------------------- ;
  512. then << if null(cadar gclst)
  513. then list(append(list(gc,list(y)),cddar gclst))
  514. else if cddar(gclst) and caddar(gclst)
  515. % ------------------------------------------------------- ;
  516. % ^ Neccesary test for R35. ;
  517. % Can't take car of cddar if cddar is NIL (a.o.t. R34) ;
  518. %----------------------------------------------JB 1994----;
  519. then (append(list(gc,list(y),list(caar gclst,
  520. cadar gclst)),cddar gclst)).(cdr gclst)
  521. else (gc.(list(y).list(car gclst))).(cdr gclst)
  522. >>
  523. else
  524. % ------------------------------------------------------ ;
  525. % Gc < IV and Gc < G , i.e. Glocations := NIL. So if IV =;
  526. % 1 1 ;
  527. % 6 and Y = (-2 . 1) then Gclst = ((4 (-1 . 1)))0 is ex- ;
  528. % tended to ((2 NIL (6 ((-2 . 1))) (4 ((-1 . 1))))). ;
  529. % ------------------------------------------------------ ;
  530. (gc.(nil.append(list(iv.(list(y).nil)),
  531. if cddar gclst
  532. then append(list(list(caar gclst,cadar gclst)),
  533. cddar gclst)
  534. else list(list(caar gclst,cadar gclst)))))
  535. .(cdr gclst)
  536. end;
  537. symbolic procedure insdiff(iv,y,glsts);
  538. % ------------------------------------------------------------------- ;
  539. % glstst is a list of glst 's, i >= 0. If IV = g , k<= i, then Y is ;
  540. % i k ;
  541. % inserted in glocations and else list(IV.(list(Y).NIL)) is added to ;
  542. % k ;
  543. % glsts. ;
  544. % ------------------------------------------------------------------- ;
  545. begin scalar b,rlst;
  546. while glsts and (not b) do
  547. << if caar(glsts)=iv
  548. then <<rlst:=list(iv,append(list(y),cadar glsts)).rlst;
  549. b:=t >>
  550. else rlst:=car(glsts).rlst;
  551. glsts:=cdr(glsts)
  552. >>;
  553. return if b
  554. then append(reverse(rlst),glsts)
  555. else append(list(iv.(list(y).nil)),reverse(rlst))
  556. end;
  557. symbolic procedure remgc(gcel,x);
  558. % ------------------------------------------------------------------- ;
  559. % RemGc allows a recursive investigation of Gcel, a Gcdlst being an ;
  560. % element of the Gclst of row X. Therefore it returns a list of loca- ;
  561. % tions, which can be empty as well. These locations are remodelled ;
  562. % into Zstrt-elements, subject to some profitability criteria, which ;
  563. % will be explained in the body of this function. ;
  564. % Once the list of remodelled locations is ready, it is used to re- ;
  565. % arrange the corresponding CodMat-elements into the desired form. ;
  566. % ------------------------------------------------------------------- ;
  567. begin scalar zzch,zzchl,zzr,chr,zz,ch,nsum,nprod,ns,np,opv,gc,cof,
  568. cofloc,iv,var1,var2;
  569. % ----------------------------------------------------------------- ;
  570. % Gcel is a Gcdlst, i.e. it has the structure (G Glocations glst's).;
  571. % So Cddr(Gcel) = (glsts's) =(glst ... glst ), m>= 0. A glst itself;
  572. % 1 m ;
  573. % has the structure (g Glocations), i.e. Cddr(glst) = NIL. ;
  574. % Hence Gcel is either a Gcdlst or a glst. For both alternatives ;
  575. % holds : Car(Gcel) = a positive integer (G or g) and Cadr(Gcel) = ;
  576. % a Glocations-list, i.e. each element of Cadr(Gcel) ia a pair ;
  577. % (index.coeffsign), where Car(Gcel) is the absolute value of the ;
  578. % coefficient (exponent) to be associated with row X and a column- ;
  579. % index or the row-index of a child, respectively. ;
  580. % If Gcel defines the structure of a monomial the description is im-;
  581. % proved if atleast 2 exponents are G or if the exponents have a gcd;
  582. % 6 6 6 9 2 3 3 ;
  583. % > 1. So both a b and a b are restructured into (a b ) and ;
  584. % 6 ;
  585. % (ab) , respectively. ;
  586. % If Gcel defines the structure of a sum coefficients are factored ;
  587. % out (recursively), i.e. 6.a + 9.b remains unchanged and 6.a + 6.b ;
  588. % is restructured into 6.(a + b). The Gcel is (3 NIL (6 ((a.1))) ;
  589. % (9 ((b.1)))) and (6 ((a.1) (b.1))), respectively. ;
  590. % Restructuring requires a new TIMES(PLUS)-row to store the EXPCOF ;
  591. % value GC (6) and a new PLUS(TIMES)-row to store its base ab or ;
  592. % factor a + b, respectively. ;
  593. % ----------------------------------------------------------------- ;
  594. if ((opv:=opval(x)) eq 'times and
  595. (length(cadr gcel)>1 or cddr(gcel))) or
  596. ((opv eq 'plus) and (length(cadr gcel)>1))
  597. then
  598. <<if opv eq 'times
  599. then
  600. << nsum:=rowmax:=rowmax+1;
  601. var1:=fnewsym();
  602. put(var1,'rowindex,nsum);
  603. setprev(x,nsum);
  604. setrow(rowmin:=rowmin-1,'times,var1,nil,
  605. list(iv:=mkzel(x,gc:=car gcel)));
  606. setzstrt(x,inszzzr(mkzel(rowmin,val iv),zstrt x));
  607. put(var1,'varlst!*,rowmin);
  608. setrow(nsum,'times,var1,list nil,nil)
  609. >>
  610. else
  611. << nprod:=rowmax+1; nsum:=rowmax:=rowmax+2;
  612. setchrow(x,nprod.chrow(x));
  613. setrow(nprod,if opv eq 'plus then 'times else 'plus,x,
  614. list(list(nsum),gc:=car gcel),nil);
  615. setrow(nsum,opv,nprod,list nil,nil)
  616. >>;
  617. zzch:=updaterowinf(x,nsum,1,cadr gcel,zzr,chr);
  618. foreach y in cddr gcel do
  619. <<cof:=dm!-quotient(car(y),gc); cofloc:=cadr y;
  620. if cdr cofloc
  621. then
  622. << if opv eq 'plus
  623. then
  624. << np:=rowmax+1; ns:=rowmax:=rowmax+2;
  625. setrow(np,if opv eq 'plus then 'times else 'plus,
  626. nsum,list(list(ns),cof),nil);
  627. setrow(ns,opv,np,list nil,nil);
  628. setchrow(nsum,np.chrow(nsum))
  629. >>
  630. else
  631. << ns:=rowmax:=rowmax+1;
  632. var2:=fnewsym();
  633. put(var2,'rowindex,ns);
  634. setprev(get(var1,'rowindex),ns);
  635. setrow(rowmin:=rowmin-1,'times,var2,nil,
  636. list(iv:=mkzel(nsum,cof)));
  637. setzstrt(nsum,inszzzr(mkzel(rowmin,val iv),
  638. zstrt nsum));
  639. put(var2,'varlst!*,rowmin);
  640. setrow(ns,'times,var2,list nil,nil)
  641. >>;
  642. zz:=ch:=nil;
  643. zzchl:=updaterowinf(x,ns,1,cofloc,zz,ch);
  644. setzstrt(ns,car zzchl);
  645. setchrow(ns,cdr zzchl)
  646. >>
  647. else
  648. zzch:=updaterowinf(x,nsum,cof,cofloc,car zzch,cdr zzch)
  649. >>;
  650. foreach zel in car(zzch) do setzstrt(nsum,inszzzr(zel,zstrt nsum));
  651. setchrow(nsum,if chrow(nsum) then append(chrow(nsum),cdr zzch)
  652. else cdr zzch)
  653. >>
  654. else
  655. foreach item in cddr gcel do remgc(item,x)
  656. end;
  657. symbolic procedure updaterowinf(x,nrow,cof,infolst,zz,ch);
  658. % ------------------------------------------------------------------- ;
  659. % UpdateRowInf is used in the function RemGc to construct the Zstrt ;
  660. % ZZ and the list of children CH of row Nrow and using the Infol(i)st.;
  661. % Infolst is a glst. ;
  662. % ------------------------------------------------------------------- ;
  663. begin scalar indx,iv,mz,dyz;
  664. foreach item in infolst do
  665. << indx:=car(item);
  666. if indx < 0
  667. then
  668. << zz:=inszzzr(iv:=mkzel(indx,dm!-times(cof,cdr(item))),zz);
  669. setzstrt(indx,inszzz(mkzel(nrow,val(iv)),
  670. delyzz(x,zstrt indx)));
  671. setzstrt(x,delyzz(indx,zstrt x))
  672. >>
  673. else
  674. << ch:=indx.ch;
  675. chdel(x,indx);
  676. setfarvar(indx,nrow);
  677. setexpcof(indx,dm!-times(cof,cdr(item)))
  678. >>
  679. >>;
  680. return zz.ch
  681. end;
  682. % ------------------------------------------------------------------- ;
  683. % PART 5 : QUOTIENT-CSE SEARCH ;
  684. % ------------------------------------------------------------------- ;
  685. global '(kvarlst qlhs qrhs qlkvl);
  686. symbolic procedure tchscheme2;
  687. % ---
  688. % Moves every plus-row having just one z-element to the times-scheme.
  689. % Also copies every single child(i.e. it's the only child of its father)
  690. % of a plus-row to its father-row.
  691. % ---
  692. begin
  693. for x:=0:rowmax do
  694. << removechild x;
  695. to!*scheme x
  696. >>;
  697. end;
  698. symbolic procedure to!*scheme x;
  699. % ---
  700. % Moves plus-row x, which has just one z-element, to the times-scheme.
  701. % ---
  702. begin scalar z,yi,exp;
  703. if not(numberp farvar(x)) and opval(x) eq 'plus and
  704. length(zstrt x)=1 and null(chrow x) then
  705. << z:=car zstrt(x);
  706. yi:=yind z;
  707. exp:=expcof x;
  708. setexpcof(x,dm!-expt(ival z,exp));
  709. z:=find!*var(farvar yi,x,exp.bval(z));
  710. setzstrt(yi,delyzz(x,zstrt yi));
  711. setzstrt(x,list z);
  712. setopval(x,'times);
  713. >>
  714. end;
  715. symbolic procedure removechild x;
  716. % ---
  717. % Copies the only child of plus-row x to row x.
  718. % ---
  719. begin scalar ch,exp,iv;
  720. if not(numberp farvar(x)) and opval(x) eq 'plus and
  721. null(zstrt x) and length(chrow x)=1 then
  722. << ch:=car chrow x;
  723. exp:=expcof x;
  724. foreach z in zstrt ch do
  725. << setzstrt(yind z,delyzz(ch,zstrt yind z));
  726. iv:=dm!-times(ival(z),exp);
  727. setzstrt(yind z,inszzz(mkzel(x,iv),zstrt yind z));
  728. setzstrt(x,inszzzr(mkzel(yind z,iv),zstrt x))
  729. >>;
  730. foreach chld in chrow(ch) do setfarvar(chld,x);
  731. setopval(x,'times);
  732. setexpcof(x,dm!-times(expcof ch,exp));
  733. setchrow(x,chrow ch);
  734. clearrow ch;
  735. >>
  736. end;
  737. symbolic procedure searchcsequotients;
  738. begin
  739. scalar res,continuesearch;
  740. tchscheme2();
  741. res := continuesearch := searchcsequotients2();
  742. while continuesearch do
  743. continuesearch := searchcsequotients2();
  744. return res;
  745. end;
  746. symbolic procedure searchcsequotients2;
  747. % -------------------------------------------------------------------- ;
  748. % Quotient-structured cse's can exist in the prefixlist, defining the
  749. % result of an extended Breuer-search, since this search is performed
  750. % on a set of polynomial-like (sub)-expressions, which may contain
  751. % numerators and denominators as seperate expressions.
  752. % So we know after optimization that neither the subset of numerators
  753. % nor the subset of denominators have a cse in common.
  754. % This implies that possibly occurring cse's always have the form
  755. % (quotient numer denom), where both numer and denom are either numbers
  756. % or identifiers.
  757. % An example:
  758. % The set {x:=(ab)/(cd),y:=(ae)/(cf),z:=(bg)/(dh)} contains the cse's
  759. % s1:=a/c and s2:=b/d,
  760. % which can lead to the new set
  761. % {s1:=a/c,s2:=b/d, x:=s1.s2, y:=(s1.e)/f,z:=(s2.g)/h},
  762. % thus saving 3 *'s but adding 1 /.
  763. % This function serves to produce such revisions when ever possible,
  764. % and assuming that one / is equivalent to at most two *'s.
  765. % -------------------------------------------------------------------- ;
  766. begin
  767. scalar j,quotients,dmlst,dm,numerinfol,nrlst,selecteddms,
  768. selectednrs,quotlst,b,quots,profit,qcse,cselst,var,s;
  769. qlkvl:=length(kvarlst);
  770. qlhs:=mkvect(qlkvl); qrhs:=mkvect(qlkvl);
  771. j:=0;
  772. quotients:=nil;
  773. foreach item in kvarlst do
  774. << putv(qlhs,j:=j+1,car item);
  775. putv(qrhs,j,cdr item);
  776. if relquottest(getv(qrhs,j))
  777. then quotients:=cons(j,quotients);
  778. >>;
  779. % ---
  780. % quotients contains indices of relevant quotients in lhs-rhs (kvarlst)
  781. % ---
  782. if quotients then
  783. <<
  784. foreach indx in quotients do
  785. dmlst:=insertin(dmlst,caddr getv(qrhs,indx),indx);
  786. dmlst:=addmatnords(dmlst);
  787. % ---
  788. % dmlst = ( (item.(indices to quotients containing item in denominator))
  789. % ... )
  790. % ---
  791. selecteddms:=selectmostfreqnord(dmlst);
  792. if selecteddms and length(cdr selecteddms)>1
  793. then % at least 2 ../dm's.
  794. << % selecteddms = item which appears the most in
  795. % denominators.
  796. dm:=car selecteddms; numerinfol:=cdr selecteddms;
  797. nrlst:=nil;
  798. foreach indx in numerinfol do
  799. nrlst:=insertin(nrlst,cadr getv(qrhs,indx),indx);
  800. nrlst:=addmatnords(nrlst);
  801. % ---
  802. % nrlst = ((item.(indices of quotients containing item
  803. % in numerator and the selected denominator
  804. % in the denominator) ... )
  805. % ---
  806. if (selectednrs:=selectmostfreqnord(nrlst))
  807. then if length(cdr selectednrs)>1
  808. then % cse is car(selectednrs)/dm.
  809. quotlst:=((car(selectednrs).dm).cdr(selectednrs))
  810. . quotlst
  811. >>;
  812. % dmlst:=delete(selecteddms,dmlst);
  813. % ---
  814. % quotlst = (((numerator . denominator) .
  815. % st of indices to quotients containing quotient)) ...)
  816. % i.e. list of quotients containing the cse-quotient
  817. % ---
  818. if quotlst then
  819. << quots:=mkvect(qlkvl);
  820. foreach item in quotlst do
  821. << profit:=qprofit(item);
  822. % ----------------------------------------------------------- ;
  823. % qprofit delivers the pair *-savings./-savings. The assoc. ;
  824. % quotient, defined as pair numerator.denominator and stored ;
  825. % as car of the item, will be considered as cse if profit=t. ;
  826. % ----------------------------------------------------------- ;
  827. if ((cdr profit) geq 0) or ((car(profit)+2*cdr(profit)) geq 0)
  828. then % cse-quotient is profitable
  829. << b:=t;
  830. qcse:=list('quotient,caar item,cdar item);
  831. if (var:=assoc(qcse,s:=get(car qcse,'kvarlst))) then
  832. qcse:=cdr(var).qcse
  833. else
  834. << var:=fnewsym();
  835. put(car qcse,'kvarlst,(qcse.var).s);
  836. qcse:=var.qcse;
  837. cselst:=qcse.cselst
  838. >>;
  839. foreach indx in cdr(item) do
  840. if car(qcse) neq getv(qlhs,indx)
  841. then substqcse(qcse,indx)
  842. >>
  843. >>;
  844. kvarlst:=nil;
  845. for j:=1:qlkvl do
  846. if getv(qlhs,j)
  847. then % remove cleared quotients
  848. kvarlst:=append(kvarlst,list(getv(qlhs,j).getv(qrhs,j)));
  849. % add new quotients
  850. kvarlst:=append(kvarlst,cselst);
  851. >>
  852. >>;
  853. qlkvl:=qlhs:=qrhs:=nil;
  854. return(b)
  855. end$
  856. symbolic procedure relquottest(item);
  857. % -------------------------------------------------------------------- ;
  858. % returns t if item is a quotient with a numerator (cadr item) and a
  859. % denominator (caddr item), which are a product, a constant or an . ;
  860. % identifier i.e. , which have a relv(evant) str(ucture). ;
  861. % -------------------------------------------------------------------- ;
  862. eqcar(item,'quotient) and relvstr(cadr item) and relvstr(caddr item);
  863. symbolic procedure relvstr(item);
  864. % -------------------------------------------------------------------- ;
  865. % Only those numerators or denominators are relevant which can possibly;
  866. % contribute to cse-quotients, i.e. constants, identifiers or products ;
  867. % -------------------------------------------------------------------- ;
  868. begin scalar rowindx;
  869. return
  870. constp(item) or idp(item) %or
  871. % ((rowindx:=get(item,'rowindex)) and opval(rowindx) eq 'times)
  872. end;
  873. symbolic procedure addmatnords(nordlst);
  874. % ---
  875. % The numerators and denominators are concidered at two levels:
  876. % 1) nords in the kvarlst and
  877. % 2) nords in rows which are used in the kvarlst. Nordlst contains
  878. % relevant nords from level 1.
  879. % A row from level 1 is opened, i.e. replaced by relevant nords from
  880. % level 2 (its z-elements) when:
  881. % o The row occurs only once in the union of both levels.
  882. % o The row is only used for this nord and is used nowhere else in
  883. % codmat or kvarlst.
  884. % Otherwise the nord is unchanged.
  885. % ---
  886. begin scalar matnords,templst,rowindx;
  887. % First: find all the nords at level 2 (matnords)
  888. foreach nord in nordlst do
  889. foreach indx in cdr nord do
  890. if (rowindx:=get(car nord,'rowindex)) and
  891. opval(rowindx) eq 'times then
  892. << foreach z in zstrt rowindx do
  893. matnords:=insertin(matnords,farvar yind z,indx);
  894. if abs(expcof rowindx) neq 1 then
  895. matnords:=insertin(matnords,expcof rowindx,indx)
  896. >>;
  897. % Second: open the appropriate 1st level rows
  898. foreach nord in nordlst do
  899. << if length(cdr nord)>1 then
  900. foreach indx in cdr nord do
  901. templst:=insertin(templst,car nord,indx)
  902. else
  903. if assoc(car nord,matnords) then
  904. templst:=insertin(templst,car nord,cadr nord)
  905. else
  906. if (rowindx:=get(car nord,'rowindex)) and
  907. opval(rowindx) eq 'times and nofnordocc(car nord)=1 then
  908. << foreach z in zstrt rowindx do
  909. templst:=insertin(templst,farvar yind z,cadr nord);
  910. templst:=insertin(templst,expcof rowindx,cadr nord)
  911. >>
  912. >>;
  913. return templst
  914. end;
  915. symbolic procedure nofnordocc(nord);
  916. % ---
  917. % Finds out howmany times nord occurs in the kvarlst and the schemes.
  918. % ---
  919. begin scalar nofocc;
  920. nofocc:=nofmatnords nord;
  921. for i:=1:qlkvl do
  922. nofocc:=nofocc+numberofocc(nord,getv(qrhs,i));
  923. return nofocc
  924. end;
  925. symbolic procedure numberofocc(var,expression);
  926. % -------------------------------------------------------------------- ;
  927. % The number of occurrences of Var in Expression is computed and ;
  928. % returned. ;
  929. % -------------------------------------------------------------------- ;
  930. if constp(expression) or idp(expression)
  931. then
  932. if var=expression then 1 else 0
  933. else
  934. (if cdr expression
  935. then numberofocc(var,cdr expression)
  936. else 0)
  937. +
  938. (if var=car expression
  939. then 1
  940. else
  941. if not atom car expression
  942. then numberofocc(var,car expression)
  943. else 0);
  944. symbolic procedure nofmatnords nord;
  945. begin scalar nofocc,colindx;
  946. nofocc:=0;
  947. if (colindx:=get(nord,'varlst!*)) then
  948. nofocc:=length zstrt colindx;
  949. if (colindx:=get(nord,'varlst!+)) then
  950. nofocc:=nofocc+length zstrt colindx;
  951. return nofocc
  952. end;
  953. symbolic procedure insertin(nordlst,item,indx);
  954. % -------------------------------------------------------------------- ;
  955. % Once it is known that item is a constant or an identifier it can be ;
  956. % stored in the nordlst list.If item is a negative number the -indx is ;
  957. % attached to the cdr of nordlst and -item is used as recognizer. ;
  958. % -------------------------------------------------------------------- ;
  959. begin scalar pr;
  960. return(if !:onep(dm!-abs item) then nordlst
  961. else
  962. if (pr:=assoc(item,nordlst))
  963. then foreach el in nordlst collect
  964. if car(el)=item then item.append(cdr pr,list(indx)) else el
  965. else append(list(item.list(indx)),nordlst))
  966. end;
  967. symbolic procedure selectmostfreqnord(nordlst);
  968. % -------------------------------------------------------------------- ;
  969. % The nordlst consists of pairs, formed by a constant or identifier as ;
  970. % car and a list of indices of rhs's, denoting the quotients containing;
  971. % this car. ;
  972. % The pair with the longest indxlst is selected and returned. ;
  973. % -------------------------------------------------------------------- ;
  974. begin scalar templst,temp,selectedpr,lmax;
  975. if nordlst
  976. then
  977. << selectedpr:=car nordlst;
  978. lmax:=length(cdr selectedpr);
  979. templst:=cdr nordlst;
  980. foreach pr in templst do
  981. << if lmax < (temp:=length(cdar templst))
  982. then << lmax:=temp; selectedpr:=car templst >>;
  983. templst:=cdr templst
  984. >>
  985. >>;
  986. return(selectedpr)
  987. end;
  988. symbolic procedure qprofit(item);
  989. % -------------------------------------------------------------------- ;
  990. % indxlist consists of signed indices of the vectors lhs and rhs. The ;
  991. % structure of the rhs's, being quotients is used to determine the ;
  992. % number of multiplications and divisions saved by considering the ;
  993. % corresponding quotient as a cse. ;
  994. % The rules we apply are straightforward. Assume the cse-candidate ;
  995. % is defined by s:=nr/dm. Then we can distinguish between the 4 fol- ;
  996. % lowing situations: ;
  997. % -1- quotient=s, i.e. 1 /-operation can be saved. ;
  998. % -2- quotient=s/a, i.e. 1 *-operation can be saved. ;
  999. % -3- quotient=s*a, i.e. 1 /-operation can be saved. ;
  1000. % -4- quotient=(s*a)/b, i.e. 1 *-operation can de saved, but no ;
  1001. % /-operation is saved. ;
  1002. % We simply test if dm is a constant or an identifier (1 /-saving) or a;
  1003. % product (1 *-saving). ;
  1004. % But if nr is a product we still need the /-operation ;
  1005. % s will function as cse if nbof!/>=0 or when nbof!*+2*nbof!/>=0, ;
  1006. % assuming that a division is atmost as costly as 2 multiplications. ;
  1007. % We neglect for the moment the extra assignments, i.e. stores. ;
  1008. % -------------------------------------------------------------------- ;
  1009. begin scalar nbof!*,nbof!/,tempquot,h,f,tf,il;
  1010. il:=cdr(item);
  1011. while il do
  1012. << h:= car(il); il:=cdr(il); f:=h.f;
  1013. foreach indx in il do << if indx neq h then tf:=indx.tf >>;
  1014. if not null(tf)
  1015. then << il:=reverse tf, tf:=nil >>
  1016. else il:=nil
  1017. >>;
  1018. if length(il:=reverse f)=1
  1019. then
  1020. << nbof!*:=0; nbof!/:=-1 >>
  1021. else
  1022. << nbof!*:=0; nbof!/:=-1;
  1023. % nbof!* is atmost 0. nbof!/ may be negative.
  1024. foreach sgnindx in il do
  1025. << tempquot:=getv(qrhs,sgnindx);
  1026. % The rhs-struct. is '(quotient nr dm).
  1027. if cdar(item)=caddr(tempquot) then nbof!/:=1+nbof!/
  1028. else nbof!*:=1+nbof!*;
  1029. >>
  1030. >>;
  1031. return(cons(nbof!*,nbof!/))
  1032. end;
  1033. symbolic procedure substqcse(csepair,indx);
  1034. % -------------------------------------------------------------------- ;
  1035. % csepair is a pair consisting of a system generated cse name and the ;
  1036. % struct. of a quotient-cse. If sgnindx<0 the cse parent has a minus as;
  1037. % leading operator. If minsgn the cse has also a minus as leading ope- ;
  1038. % rator. Based on this information the rhs(abs(sgnindx)) is rewritten, ;
  1039. % i.e. the cse-value is removed and replaced by the cse-name. ;
  1040. % -------------------------------------------------------------------- ;
  1041. begin scalar var,val,dm,nr,pnr,pdm,ninrow,dinrow,expo;
  1042. var:=car(csepair);
  1043. val:=cdr(csepair);
  1044. nr:=cadr val;
  1045. dm:=caddr val;
  1046. pnr:=cadr(getv(qrhs,indx));
  1047. pdm:=caddr(getv(qrhs,indx));
  1048. ninrow:=if (nr neq pnr) then get(pnr,'rowindex) else nil;
  1049. dinrow:=if (dm neq pdm) then get(pdm,'rowindex) else nil;
  1050. expo:=min(nordexpo(nr,pnr),nordexpo(dm,pdm));
  1051. pnr:=remnord(nr,expo,pnr,indx);
  1052. pnr:=insnord(var,expo,pnr,indx);
  1053. pdm:=remnord(dm,expo,pdm,indx);
  1054. pnr:=checknord(pnr,ninrow,indx);
  1055. pdm:=checknord(pdm,dinrow,indx);
  1056. % If we want to remove qlhs[indx] this should not be a protected
  1057. % variable of some sort...
  1058. if !:onep(pdm) and unprotected(getv(qlhs,indx))
  1059. then << remquotient(pnr,indx); putv(qlhs,indx,nil) >>
  1060. else putv(qrhs,indx,if !:onep(pdm)
  1061. then pnr else list('quotient,pnr,pdm))
  1062. end;
  1063. symbolic procedure unprotected var;
  1064. % States wether var is free to be removed or not.
  1065. flagp(var,'newsym) and not get(var,'alias);
  1066. symbolic procedure nordexpo(x,y);
  1067. % ---
  1068. % Calculates the power of x in product y.
  1069. % Assumption : y contains x.
  1070. % ---
  1071. if constp x then
  1072. 1
  1073. else if idp x then
  1074. if x=y then
  1075. 1
  1076. else
  1077. begin scalar res;
  1078. if (res:=assoc(get(x,'varlst!*),zstrt get(y,'rowindex)))
  1079. then res := ival res
  1080. else res := 0;
  1081. return res
  1082. end;
  1083. symbolic procedure remnord(item,expo,dest,indx);
  1084. % ---
  1085. % Divides item^expo out of dest. Dest is a constant, a variable or a
  1086. % variable determining a row in CODMAT.
  1087. % Item is a constant or a variable.
  1088. % Assumption : dest contains item^n, n >= expo.
  1089. % ---
  1090. begin scalar rowindx,colindx,z;
  1091. return
  1092. if constp dest then
  1093. dm!-quotient(dest,dm!-expt(item,expo))
  1094. else
  1095. if item=dest then
  1096. << remquotordr(indx,item);
  1097. if (rowindx:=get(item,'rowindex)) then
  1098. remquotordr(indx,rowindx);
  1099. 1
  1100. >>
  1101. else
  1102. << rowindx:=get(dest,'rowindex);
  1103. if constp(item) then
  1104. << if opval(rowindx)='times then
  1105. setexpcof(rowindx,dm!-quotient(expcof rowindx,
  1106. dm!-expt(item,expo)))
  1107. else <<setzstrt(rowindx,foreach z in zstrt(rowindx)
  1108. collect mkzel(xind z,
  1109. dm!-quotient(ival z,dm!-expt(item,expo))
  1110. . bval(z)));
  1111. foreach z in zstrt(rowindx) do
  1112. setzstrt(yind z,inszzz(mkzel(rowindx,val z),
  1113. zstrt(yind z)))
  1114. >>;
  1115. dest
  1116. >>
  1117. else
  1118. << colindx:=get(item,'varlst!*);
  1119. z:=assoc(colindx,zstrt rowindx);
  1120. setzstrt(colindx,delyzz(rowindx,zstrt colindx));
  1121. setzstrt(rowindx,delete(z,zstrt rowindx));
  1122. if ival(z)=expo then
  1123. << remprev(rowindx,item);
  1124. if get(item,'rowindex) then
  1125. remprev(rowindx,get(item,'rowindex))
  1126. >>
  1127. else
  1128. << setzstrt(colindx,
  1129. inszzz(mkzel(rowindx,(ival(z)-expo).bval(z)),
  1130. zstrt colindx));
  1131. setzstrt(rowindx,
  1132. inszzzr(mkzel(colindx,(ival(z)-expo).bval(z)),
  1133. zstrt rowindx))
  1134. >>;
  1135. dest
  1136. >>
  1137. >>
  1138. end;
  1139. symbolic procedure insnord(item,expo,dest,indx);
  1140. % ---
  1141. % Multiplies item^expo into dest. Dest is a constant, a variable or a
  1142. % variable determining a row in CODMAT.
  1143. % Item is a constant or a variable.
  1144. % ---
  1145. begin scalar rowindx;
  1146. return
  1147. if constp dest then
  1148. if constp item then
  1149. dm!-times(dest,dm!-expt(item,expo))
  1150. else
  1151. << %if (rowindx:=get(item,'rowindex)) then
  1152. % insquotordr(indx,rowindx)
  1153. %else
  1154. % insquotordr(indx,item);
  1155. item % dest = 1
  1156. >>
  1157. else
  1158. << rowindx:=get(dest,'rowindex);
  1159. if constp item then
  1160. <<setexpcof(rowindx,
  1161. dm!-times(expcof rowindx,dm!-expt(item,expo)));
  1162. dest
  1163. >>
  1164. else
  1165. << setzstrt(rowindx,inszzzr(mkzel(car find!*var(item,
  1166. rowindx,expo),
  1167. expo),zstrt rowindx));
  1168. if get(item,'rowindex) then
  1169. setprev(rowindx,get(item,'rowindex))
  1170. else
  1171. setprev(rowindx,item);
  1172. dest
  1173. >>
  1174. >>
  1175. end;
  1176. symbolic procedure insquotordr(indx,ord);
  1177. % ---
  1178. % This procedure inserts ord in all order-lists of rows containing the
  1179. % quotient indiced by indx.
  1180. % ---
  1181. begin scalar col;
  1182. if (col:=get(getv(qlhs,indx),'varlst!+)) then
  1183. foreach z in zstrt(col) do
  1184. setprev(xind z,ord);
  1185. if (col:=get(getv(qlhs,indx),'varlst!*)) then
  1186. foreach z in zstrt(col) do
  1187. setprev(xind z,ord)
  1188. end;
  1189. symbolic procedure remquotordr(indx,ord);
  1190. % ---
  1191. % This procedure removes ord from all order-lists of rows containing
  1192. % the quotient indiced by indx.
  1193. % ---
  1194. begin scalar col;
  1195. if (col:=get(getv(qlhs,indx),'varlst!+)) then
  1196. foreach z in zstrt(col) do
  1197. remprev(xind z,ord);
  1198. if (col:=get(getv(qlhs,indx),'varlst!*)) then
  1199. foreach z in zstrt(col) do
  1200. remprev(xind z,ord)
  1201. end;
  1202. symbolic procedure remprev(x,y);
  1203. % ---
  1204. % See setprev.
  1205. % ---
  1206. if numberp(farvar x) then
  1207. remprev(farvar x,y)
  1208. else
  1209. setordr(x,remordr(y,ordr x));
  1210. symbolic procedure checknord(nord,inrow,indx);
  1211. begin
  1212. if inrow then
  1213. << if null(zstrt inrow) and null(chrow inrow) then
  1214. << nord:=expcof inrow;
  1215. remquotordr(indx,inrow);
  1216. remquotordr(indx,farvar inrow);
  1217. clearrow(inrow)
  1218. >>
  1219. else insquotordr(indx,get(nord,'rowindex))
  1220. % In inrow obviously something usefull is defined, so
  1221. % this cse should be defined for its use.
  1222. % This means update ordr-fields. JB. 7-5-93.
  1223. %else
  1224. % if (zz:=zstrt(inrow)) and null(cdr zz) and
  1225. % null(chrow inrow) and
  1226. % !:onep(expcof inrow) and !:onep(ival car zz) then ...
  1227. % handled by IMPROVELAYOUT
  1228. >>;
  1229. return nord
  1230. end;
  1231. symbolic procedure remquotient(pnr,indx);
  1232. % pnr is a variable (row)
  1233. begin scalar var,col,rowindx;
  1234. var:=getv(qlhs,indx);
  1235. if (col:=get(var,'varlst!+)) then
  1236. foreach z in zstrt col do
  1237. remprev(xind z,var);
  1238. if (col:=get(var,'varlst!*)) then
  1239. foreach z in zstrt col do
  1240. remprev(xind z,var);
  1241. tshrinkcol(getv(qlhs,indx),pnr,'varlst!+);
  1242. tshrinkcol(getv(qlhs,indx),pnr,'varlst!*);
  1243. for i:=1:(qlkvl) do
  1244. putv(qrhs,i,subst(pnr,getv(qlhs,indx),getv(qrhs,i)));
  1245. if (rowindx:=get(pnr,'rowindex)) then
  1246. pnr:=rowindx;
  1247. if (col:=get(pnr,'varlst!+)) then
  1248. foreach z in zstrt col do
  1249. setprev(xind z,pnr);
  1250. if (col:=get(pnr,'varlst!*)) then
  1251. foreach z in zstrt col do
  1252. setprev(xind z,pnr)
  1253. end;
  1254. endmodule;
  1255. end;