codad1.red 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  1. module codad1; % Description of some procedures.
  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 CODAD1 contains the description of the procedures ;
  10. % IMPROVELAYOUT (part 1), TCHSCHEME (part 2) and CODFAC (part 3), ;
  11. % which are used in the procedure OPTIMIZELOOP (see the module CODCTL);
  12. % to complete the effect of an application of EXTBRSEA (see the module;
  13. % CODOPT). Application of each of these routines is completed by re- ;
  14. % turning a Boolean value, which is used to decide if further optimi- ;
  15. % zation is still profitable. ;
  16. % The Smacro's Find!+Var and Find!*Var form service facilities, needed;
  17. % at different places in this module. These Smacro's define an applic-;
  18. % ation of the procedure GetCind. ;
  19. % ------------------------------------------------------------------- ;
  20. % ------------------------------------------------------------------- ;
  21. % Global identifiers needed in this module are: ;
  22. % ------------------------------------------------------------------- ;
  23. global '(rowmin rowmax kvarlst codbexl!*);
  24. % ------------------------------------------------------------------- ;
  25. % The meaning of these globals is given in the module CODMAT. ;
  26. % ------------------------------------------------------------------- ;
  27. symbolic procedure getcind(var,varlst,op,fa,iv);
  28. % ------------------------------------------------------------------- ;
  29. % The purpose of the procedure GetCind is to create a column in CODMAT;
  30. % which will be associated with the variable Var if this variable does;
  31. % not yet belong to the set Varlst,i.e.does not yet play a role in the;
  32. % corresponding PLUS- or TIMES setting (known by the value of Op).Once;
  33. % the column exists (either created or already available), its Zstrt ;
  34. % is modified by inserting the Z-element (Fa,IV) in it. Finally the ;
  35. % corresponding Z-element for the father-row, i.e. (Y,IV) is returned.;
  36. % ------------------------------------------------------------------- ;
  37. begin scalar y,z;
  38. if null(y:=get(var,varlst))
  39. then
  40. <<y:=rowmin:=rowmin-1;
  41. put(var,varlst,y);
  42. setrow(y,op,var,nil,nil)
  43. >>;
  44. setzstrt(y,inszzzn(z:=mkzel(fa,iv),zstrt y));
  45. return mkzel(y,val z)
  46. end;
  47. symbolic smacro procedure find!+var(var,fa,iv);
  48. getcind(var,'varlst!+,'plus,fa,iv);
  49. symbolic smacro procedure find!*var(var,fa,iv);
  50. getcind(var,'varlst!*,'times,fa,iv);
  51. % ------------------------------------------------------------------- ;
  52. % PART 1 : LAYOUT IMPROVEMENT ;
  53. % ------------------------------------------------------------------- ;
  54. symbolic procedure improvelayout;
  55. % ------------------------------------------------------------------- ;
  56. % During optimization, and thus during common subexpression generation;
  57. % it might happen that a (sub)expression is reduced to a single varia-;
  58. % ble, leading to output containing the assignment statements : ;
  59. % b:=b-thing; ;
  60. % ...... ;
  61. % a:=b; ;
  62. % This redundancy can be removed by replacing all occurrences of b by ;
  63. % a, by replacing b:=b-thing by a:=b=thing and by removing a:=b. Here ;
  64. % we assume a,b to be only cse-names. ;
  65. % ------------------------------------------------------------------- ;
  66. begin scalar var,b;
  67. for x:=0:rowmax do
  68. if not (numberp(var:=farvar x)
  69. or
  70. pairp(var)
  71. or
  72. (member(x,codbexl!*)
  73. and
  74. (get(var,'nex) or
  75. not(flagp(var, 'newsym)) or
  76. get(var,'alias)
  77. % or not(get(var,'alias)) % JB 10/3/94
  78. % finds no cse in p.e. cos(e^s6),sin(e^s6)
  79. )))
  80. and testononeel(var,x) then b:=t;
  81. % ----------------------------------------------------------------- ;
  82. % If B=T redundancy was removed from CODMAT, but not necessarily ;
  83. % from Kvarlst, the list of pairs of kernels and names associated ;
  84. % with them. ImproveKvarlst is applied to achieve this. ;
  85. % ----------------------------------------------------------------- ;
  86. if b then improvekvarlst();
  87. return b
  88. end;
  89. symbolic procedure testononeel(var,x);
  90. % ------------------------------------------------------------------- ;
  91. % Row X,having Var as its assigned variable, and defining some expres-;
  92. % sion, through its Zstrt, Chrow and ExpCof, is analysed. ;
  93. % If this row defines a redundant assignment statement the above indi-;
  94. % cated actions are performed. ;
  95. % ------------------------------------------------------------------- ;
  96. begin
  97. scalar scol,srow,el,signiv,signec,zz,ordrx,negcof,trow,
  98. oldvar,b,el1,scof,bop!+,lhs;
  99. if (zz:=zstrt x) and null(cdr zz) and null(chrow x) and
  100. !:onep(dm!-abs(signiv:=ival(el:=car zz))) and
  101. !:onep(signec:=expcof(x))
  102. % !:onep(dm!-abs(signec:=expcof(x)))
  103. % This could mean a:=b^(-1), which is rather tricky to update
  104. % when b is used in other plusrows. JB. 7-5-93.
  105. then
  106. << % ------------------------------------------------------------- ;
  107. % Row(X) defines a Zstreet, consisting of one Z-element. The ;
  108. % variable-name, associated with this element is stored in the ;
  109. % FarVar-field of the column, whose index is in the Yind-part of;
  110. % this Z-element,i.e. Oldvar:=FarVar(SCol),the b mentioned above;
  111. % The IVal-value of this element, an exponent or a coefficient, ;
  112. % is 1 or -1 and the ExpCof-value, a coefficient or an exponent,;
  113. % is also 1 or -1. Realistic possibilities are of course only ;
  114. % 1*Oldvar^1 or -1*Oldvar^1 (i.e. 1*b^1 or -1*b^1). ;
  115. % ------------------------------------------------------------- ;
  116. scol:=yind el;
  117. oldvar:=farvar(scol);
  118. if srow:=get(oldvar,'rowindex)
  119. then b:=t
  120. else
  121. if assoc(oldvar,kvarlst) and
  122. !:onep(signiv) and !:onep(signec) and
  123. not member(oldvar,codbexl!*)
  124. then b:=t;
  125. % ------------------------------------------------------------- ;
  126. % So B=T if either Oldvar has its own defining row, whose index ;
  127. % is stored as value of the indicator Rowindex, i.e. if Oldvar ;
  128. % defines a cse, or if Oldvar is the name of a kernel, stored in;
  129. % Kvarlst, as cdr-part of the pair having Oldvar as its car-part;
  130. % ------------------------------------------------------------- ;
  131. if b
  132. then
  133. << % ------------------------------------------------------- ;
  134. % We start replacing all occurrences of Oldvar by Var, in ;
  135. % both the PLUS- and the TIMES-part of CODMAT, by applying;
  136. % the function TShrinkCol. In addition all eventually exis;
  137. % ting occurences of Oldvar in Kvarlst have to replaced as;
  138. % well by Var(,the a mentioned above). ;
  139. % ------------------------------------------------------- ;
  140. setzstrt(scol,delyzz(x,zstrt scol));
  141. tshrinkcol(oldvar,var,'varlst!+);
  142. tshrinkcol(oldvar,var,'varlst!*);
  143. if ((opval(x) eq 'plus) and !:onep(dm!-minus signiv))
  144. or
  145. ((opval(x) eq 'times) and !:onep(dm!-minus signec))
  146. then << var:=list('minus,var);
  147. kvarlst:=subst(var,oldvar,kvarlst);
  148. preprefixlist:=subst(var,oldvar,preprefixlist);
  149. var:=cadr var;
  150. negcof:=-1
  151. >>
  152. else << kvarlst:=subst(var,oldvar,kvarlst);
  153. preprefixlist:=subst(var,oldvar,preprefixlist);
  154. negcof:=1
  155. >>;
  156. if (lhs:=get(oldvar,'inlhs))
  157. then
  158. << put(lhs,'nex,subst(var,oldvar,get(lhs,'nex)));
  159. remprop(oldvar,'inlhs)>>;
  160. if (lhs:=get(oldvar,'inalias))
  161. then
  162. << updatealiases(oldvar,var);
  163. %put(lhs,'alias,subst(var,oldvar,get(lhs,'alias)));
  164. remprop(oldvar,'inalias)>>;
  165. if srow
  166. then
  167. << % --------------------------------------------------- ;
  168. % Oldvar is the name of a cse, defined through the row;
  169. % index Srow. So this cse-definition has to be assign-;
  170. % ed to Var as new value and the Srow itself has to be;
  171. % made redundant. The Ordr-field of Var has to be chan;
  172. % ged to be able to remain guaranteeing a correct out-;
  173. % put sequence. ;
  174. % --------------------------------------------------- ;
  175. ordrx:=ordr(x);
  176. bop!+:=opval(srow) eq 'plus;
  177. if bop!+ then scof:=expcof srow
  178. else scof:=dm!-times(negcof,expcof(srow));
  179. setrow(x,opval srow,var,list(chrow srow,scof),
  180. zstrt srow);
  181. setordr(x,append(ordr srow,remordr(srow,ordrx)));
  182. if !:onep(dm!-minus signiv)
  183. then
  184. <<foreach z in zstrt(scol) do
  185. setival(z,dm!-minus ival(z));
  186. foreach ch in chrow(x) do
  187. setexpcof(ch,dm!-minus expcof(ch));
  188. if trow:=get(var,'varlst!*) then
  189. foreach el in zstrt(trow) do
  190. setexpcof(xind el, dm!-minus expcof(xind el));
  191. >>;
  192. foreach ch in chrow(srow) do setfarvar(ch,x);
  193. clearrow(srow);
  194. setordr(srow,nil);
  195. codbexl!*:=subst(x,srow,codbexl!*);
  196. foreach z in zstrt(x) do
  197. <<if bop!+ then setival(z,dm!-times(signiv,ival(z)));
  198. setzstrt(yind z,inszzz(mkzel(x,val z),
  199. delyzz(srow,zstrt yind z)))
  200. >>;
  201. for sindex:=0:rowmax
  202. do setordr(sindex,subst(x,srow,ordr sindex));
  203. testononeel(var,x)
  204. >>
  205. else
  206. << % --------------------------------------------------- ;
  207. % Oldvar is the system-generated name of a kernel. ;
  208. % The internal administration is modified, as to pro- ;
  209. % vide Var with its new role. ;
  210. % As a side-effect the index X of the kernel defining ;
  211. % row is replaced in CodBexl!* by the name Var, if oc-;
  212. % curring of course, i.e. if this function definition ;
  213. % was given at toplevel on input. ;
  214. % This information is used in ImproveKvarlst. ;
  215. % --------------------------------------------------- ;
  216. codbexl!*:=subst(var,x,codbexl!*);
  217. ordrx:=remordr(oldvar,ordr x);
  218. clearrow(x);
  219. setordr(x,nil);
  220. for sindex:=0:rowmax do
  221. setordr(sindex,
  222. updordr(ordr sindex,var,oldvar,ordrx,x));
  223. improvekvarlst()
  224. >>;
  225. >>
  226. >>;
  227. return b;
  228. end$
  229. symbolic procedure remordr(x,olst);
  230. % ------------------------------------------------------------------- ;
  231. % Olst is the value of the Ordr-field of a row of CODMAT. Olst defines;
  232. % in which order the cse's, occurring in the (sub)expression, whose ;
  233. % description starts in this row, have to be printed ahead of this ;
  234. % (sub)expression. It is a list of kernelnames and/or indices of rows ;
  235. % where cse-descriptions start. ;
  236. % RemOrdr returns Olst after removal of X, if occcurring. ;
  237. % ------------------------------------------------------------------- ;
  238. if null(olst)
  239. then olst
  240. else
  241. if car(olst)=x
  242. then remordr(x,cdr olst)
  243. else car(olst).remordr(x,cdr olst);
  244. symbolic procedure updordr(olst,var,oldvar,ordrx,x);
  245. % ------------------------------------------------------------------- ;
  246. % Olst is described in RemOrdr. OrdrX is the Olst of row X after remo-;
  247. % val Oldvar from it. Row X defines Var:=Oldvar. Oldvar, a kernelname,;
  248. % is replaced by Var in Olst. If X is occurring in Olst OrdrX have to ;
  249. % be inserted in Olst. The thus modified version of Olst is returned. ;
  250. % ------------------------------------------------------------------- ;
  251. if null(olst)
  252. then olst
  253. else
  254. if car(olst) eq oldvar
  255. then var.updordr(cdr olst,var,oldvar,ordrx,x)
  256. else
  257. if car(olst)=x
  258. then append(var.ordrx,updordr(cdr olst,var,oldvar,ordrx,x))
  259. else car(olst).updordr(cdr olst,var,oldvar,ordrx,x);
  260. symbolic procedure improvekvarlst;
  261. % ------------------------------------------------------------------- ;
  262. % Kvarlst, a list of pairs (name . function definition) is improved,if;
  263. % necessary. This is only required if in the list CodBexl!* occuring ;
  264. % names are not yet used in Kvarlst. Hence adequate rewriting of ;
  265. % b:=sin(x) ;
  266. % ........ ;
  267. % a:=b ;
  268. % into ;
  269. % a:=sin(x) is needed,i.e. replacement of (b . sin(x)) by (a . sin(x));
  270. % in Kvarlst. ;
  271. % ------------------------------------------------------------------- ;
  272. begin scalar invkvl,newkvl,x,y,kv,lkvl,cd,cd1;
  273. newkvl:=kvarlst;
  274. repeat
  275. <<lkvl:=kvarlst:=newkvl;
  276. invkvl:=newkvl:=nil;
  277. while lkvl do
  278. <<kv:=car(lkvl);
  279. lkvl:=cdr(lkvl);
  280. cd1:=member(car kv,codbexl!*);
  281. x:=assoc(cdr kv,invkvl);
  282. if x
  283. then cd:=(cd1 and member(cdr x,codbexl!*));
  284. if x and not cd
  285. then
  286. <<kv:=car(kv);
  287. x:=cdr(x);
  288. if cd1
  289. then <<y:=x;
  290. x:=kv;
  291. kv:=y>>;
  292. tshrinkcol(kv,x,'varlst!+);
  293. tshrinkcol(kv,x,'varlst!*);
  294. for rindx:=0:rowmax do
  295. setordr(rindx,subst(x,kv,ordr rindx));
  296. newkvl:=subst(x,kv,newkvl);
  297. invkvl:=subst(x,kv,invkvl);
  298. lkvl:=subst(x,kv,lkvl)
  299. >>
  300. else
  301. <<invkvl:=(cdr(kv).car(kv)).invkvl;
  302. newkvl:=kv.newkvl
  303. >>
  304. >>
  305. >>
  306. until length(kvarlst)=length(newkvl);
  307. end;
  308. symbolic procedure tshrinkcol(oldvar,var,varlst);
  309. % ------------------------------------------------------------------- ;
  310. % All occurrences of Oldvar have to be replaced by Var. This is done ;
  311. % by replacing the PLUS and TIMES column-indices of Oldvar by the cor-;
  312. % responding indices of Var. Y1 and Y2 get the value of the Oldvar- ;
  313. % index and the Var-index, respectively. As a side-effect, all additi-;
  314. % onal information, stored in the property-list of Oldvar is removed. ;
  315. % ------------------------------------------------------------------- ;
  316. begin scalar y1,y2;
  317. if get(oldvar,'inalias)
  318. then updatealiases(oldvar, var);
  319. if y1:=get(oldvar,varlst)
  320. then
  321. <<if y2:=get(var,varlst)
  322. then
  323. <<foreach z in zstrt(y1) do
  324. <<setzstrt(y2,inszzzn(z,zstrt y2));
  325. setzstrt(xind z,inszzzr(mkzel(y2,val z),
  326. delyzz(y1,zstrt xind z)))
  327. >>;
  328. clearrow(y1)
  329. >>
  330. else
  331. <<setfarvar(y1,var);
  332. put(var,varlst,y1)
  333. >>;
  334. remprop(oldvar,varlst)
  335. >>;
  336. remprop(oldvar,'npcdvar);
  337. remprop(oldvar,'nvarlst);
  338. end;
  339. symbolic procedure updatealiases(old, new);
  340. % ----------------------------------------------------------------- ;
  341. % Variable old is going to be replaced by new.
  342. % We hav eto ensure that the alias-linking remains
  343. % consistent. This means that the following has to
  344. % be updated:
  345. % Occurrence-info of index-alias:
  346. % new.inalias <- old.inalias
  347. % The aliased vars have to be informed that the alias
  348. % is performed by a new variable:
  349. % alias <- new|old
  350. % original.finalalias <- new|old
  351. % where A|B means : replace B by A.
  352. % ----------------------------------------------------------------- ;
  353. begin scalar original;
  354. put(new,'inalias,get(old,'inalias));
  355. flag(list new,'aliasnewsym);
  356. foreach el in get(old,'inalias) do
  357. <<put(el,'alias,subst(new,old,(original:=get(el,'alias))));
  358. if atom original
  359. then put(original,'finalalias,
  360. subst(new, old, get(original,'finalalias)))
  361. else put(car original,'finalalias,
  362. subst(new,old,get(car original,'finalalias)))
  363. >>;
  364. end$
  365. % ------------------------------------------------------------------- ;
  366. % PART 2 : INFORMATION MIGRATION ;
  367. % ------------------------------------------------------------------- ;
  368. symbolic procedure tchscheme;
  369. % ------------------------------------------------------------------- ;
  370. % A product(sum) -reduced to a single element- can eventually be remo-;
  371. % ved from the TIMES(PLUS)-part of CODMAT. If certain conditions are ;
  372. % fulfilled (defined by the function TransferRow) it is transferred to;
  373. % the Zstreet of its father PLUS(TIMES)-row and its index is removed ;
  374. % from the ChRow of its father. ;
  375. % T is returned if atleast one such a migration event takes place. ;
  376. % NIL is returned otherwise. ;
  377. % ------------------------------------------------------------------- ;
  378. begin scalar zz,b;
  379. for x:=0:rowmax do
  380. if not(farvar(x)=-1)
  381. and (zz:=zstrt x) and null(cdr zz) and transferrow(x,ival car zz)
  382. then <<chscheme(x,car zz); b:=t>>;
  383. return b;
  384. end;
  385. symbolic procedure chscheme(x,z);
  386. % ------------------------------------------------------------------- ;
  387. % The Z-element Z, the only element the Zstreet of row(X) has, has to ;
  388. % be transferred from the PLUS(TIMES)-part to the TIMES(PLUS)-part of ;
  389. % CODMAT. ;
  390. % ------------------------------------------------------------------- ;
  391. begin scalar fa,opv,cof,exp;
  392. setzstrt(yind z,delyzz(x,zstrt yind z));
  393. setzstrt(x,nil);
  394. if opval(x) eq 'plus
  395. then <<exp:=1; cof:=ival z>>
  396. else <<exp:=ival z; cof:=1>>;
  397. l1: fa:=farvar(x);
  398. opv:=opval(x);
  399. if opv eq 'plus
  400. then
  401. <<cof:=dm!-expt(cof,expcof(x));
  402. exp:=dm!-times(expcof(x),exp);
  403. chdel(fa,x);
  404. clearrow(x);
  405. if null(zstrt fa) and transferrow(fa,exp)
  406. then <<x:=fa; goto l1>>
  407. >>
  408. else
  409. << if opv eq 'times
  410. then
  411. <<cof:=dm!-times(cof,expcof(x));
  412. chdel(fa,x);
  413. clearrow(x);
  414. if null(zstrt fa) and transferrow(fa,cof)
  415. then <<x:=fa; goto l1>>
  416. >>
  417. >>;
  418. updfa(fa,exp,cof,z)
  419. end;
  420. symbolic procedure updfa(fa,exp,cof,z);
  421. % ------------------------------------------------------------------- ;
  422. % FA is the index of the father-row of the Z-element Z,which has to ;
  423. % be incorporated in the Zstreet of this row. Its exponent is Exp and ;
  424. % its coefficient is Cof, both computed in its calling function ;
  425. % ChScheme. ;
  426. % ------------------------------------------------------------------- ;
  427. if opval(fa) eq 'plus
  428. then setzstrt(fa,inszzzr(find!+var(farvar yind z,fa,cof),zstrt fa))
  429. else
  430. <<setzstrt(fa,inszzzr(find!*var(farvar yind z,fa,exp),zstrt fa));
  431. setexpcof(fa,dm!-times(cof,expcof(fa)))
  432. >>;
  433. symbolic procedure transferrow(x,iv);
  434. % ------------------------------------------------------------------- ;
  435. % IV is the Ivalue of the Z-element, oreming the Zstreet of row X. ;
  436. % This element can possibly be transferred. ;
  437. % T is returned if this element can be transferred. NIL is returned ;
  438. % otherwise. ;
  439. % ------------------------------------------------------------------- ;
  440. if opval(x) eq 'plus
  441. then transferrow1(x) and opval(farvar x) eq 'times
  442. else transferrow1(x) and transferrow2(x,iv);
  443. symbolic procedure transferrow1(x);
  444. % ------------------------------------------------------------------- ;
  445. % T is returned if row(X) defines a primitive expression (no children);
  446. % which is part of a larger expression, i.e. row(X) defines a child- ;
  447. % expression. ;
  448. % ------------------------------------------------------------------- ;
  449. null(chrow x) and numberp(farvar x);
  450. symbolic procedure transferrow2(x,iv);
  451. % ------------------------------------------------------------------- ;
  452. % Row(X) defines a product of the form ExpCof(X)*(a variable) ^ IV, ;
  453. % which is part of a sum. ;
  454. % X is temporarily removed from the list of its fathers children when ;
  455. % computing B, the return-value. ;
  456. % B=T if the father-row defines a sum and if either the exponent IV=1 ;
  457. % or if the father-Zstreet is empty (no primitive terms) and the fa- ;
  458. % ther itself can be transferred, i.e. if ExpCof(X)*(a variable) ^ (IV;
  459. % *ExpCof(Fa)) can be incorporated in the Zstreet of the grandfather- ;
  460. % row (,which again defines a product). ;
  461. % ------------------------------------------------------------------- ;
  462. begin scalar fa,b;
  463. fa:=farvar(x);
  464. chdel(fa,x);
  465. b:=opval(fa) eq 'plus and (iv=1 or (null(zstrt fa) and
  466. transferrow(fa,iv*expcof(fa))));
  467. setchrow(fa,x.chrow(fa));
  468. return b;
  469. end;
  470. % ------------------------------------------------------------------- ;
  471. % PART 3 : APPLICATION OF THE DISTRIBUTIVE LAW. ;
  472. % ------------------------------------------------------------------- ;
  473. % An expression of the form a*b + a*c + d is distributed over 3 rows ;
  474. % of CODMAT : One to store the sum structure, i.e. to store the pp of ;
  475. % the sum, being d, in a Zstrt and 2 others to store the composite ;
  476. % terms a*b and a*c as monomials. The indices of the latter rows are ;
  477. % also stored in the list Chrow, associated with the sum-row. ;
  478. % In addition 4 columns are introduced. One to store the 2 occurrences;
  479. % of a and 3 others to store the information about b,c and d. The a,b ;
  480. % and c column belong to the set of TIMES-columns, i.e. a,b and c are ;
  481. % elements of the list Varlst!* (see the module CODMAT). Similarly the;
  482. % d belongs to Varlst!+. If this sum is remodelled to obtain a*(b + c);
  483. % + d changes have to be made in the CODMAT-structure: ;
  484. % Now 2 sum-rows are needed and only 1 product-row. Hence the Chrow- ;
  485. % information of the original sum-row has to be changed and the 2 pro-;
  486. % duct-rows have to be removed and replaced by one new row, defining ;
  487. % the Zstrt for a and the Chrow to find the description of b + c back.;
  488. % In addition the column-information for all 4 columns has to be reset;
  489. % This is a simple example. In general more complicated situations can;
  490. % be expected. An expression like a*b + a*sin(c) + d requires 4 rows, ;
  491. % for instance . A CODFAC-application always follows a ExtBrsea-execu-;
  492. % tion. This implies that potential common factors, defined through *-;
  493. % col's always have an exponent-value = 1. A common factor like a^3 is;
  494. % always replaced by a cse (via an appl. of Expand- and Shrinkprod), ;
  495. % before the procedure CODFAC is applied. Hence atmost 1 exponent in a;
  496. % column is not equal 1. ;
  497. % ------------------------------------------------------------------- ;
  498. symbolic procedure codfac;
  499. % ------------------------------------------------------------------- ;
  500. % An application of the procedure CodFac results in an exhaustive all-;
  501. % level application of the distributive law on the present structure ;
  502. % of the set of input-expressions, as reflected by the present version;
  503. % of CODMAT. ;
  504. % If any application of the distributive law proves to be possible the;
  505. % value T is returned.This is an indication for the calling routine ;
  506. % OptimizeLoop that an additional application of ExtBrsea might be ;
  507. % profitable. ;
  508. % If such an application is not possible the value Nil is returned. ;
  509. % ------------------------------------------------------------------- ;
  510. begin scalar b,lxx;
  511. for y:=rowmin:(-1) do
  512. % ---------------------------------------------------------------- ;
  513. % The Zstrts of all *-columns, which are usable (because their Far-;
  514. % Var-field contains a Var-name), are examined by applying the pro-;
  515. % cedure SameFar. If this application leads to a non empty list LXX;
  516. % with information, needed to be able to apply the distributive law;
  517. % the local variable B is set T, possibly the value to be returned.;
  518. % B gets the initial value Nil, by declaration. ;
  519. % ---------------------------------------------------------------- ;
  520. if not (farvar(y)=-1 or farvar(y)=-2) and
  521. opval(y) eq 'times and (lxx:=samefar y)
  522. then
  523. <<b:=t;
  524. foreach el in lxx do commonfac(y,el)
  525. >>;
  526. return b
  527. end;
  528. symbolic procedure samefar(y);
  529. % ------------------------------------------------------------------- ;
  530. % Y is the index of a TIMES-column. The procedure SameFar is designed ;
  531. % to allow to find and return a list Flst consisting of pairs, formed ;
  532. % by a father-index and a sub-Zstrt of the Zstrt(Y), consisting of Z's;
  533. % such that Farvar(Xind Z) = Car Flst, i.e. the Xind(Z)-rows define ;
  534. % (composite) productterms of the same sum, which contain the variable;
  535. % corresponding with column Y as factor in their primitive part. ;
  536. % ------------------------------------------------------------------- ;
  537. begin scalar flst,s,far;
  538. foreach z in zstrt(y) do
  539. if numberp(far:=farvar xind z) and opval(far) eq 'plus
  540. then
  541. if s:=assoc(far,flst)
  542. then rplacd(s,inszzz(z,cdr(s)))
  543. else flst:=(far.inszzz(z,s)).flst;
  544. return
  545. foreach el in flst conc
  546. if cddr(el)
  547. then list(el)
  548. else nil
  549. end;
  550. symbolic procedure commonfac(y,xx);
  551. % ------------------------------------------------------------------- ;
  552. % Y is the index of a TIMES-column and XX an element of LXX, made with;
  553. % SameFar(Y), i.e. a pair consisting of the index Far of a father-sum ;
  554. % row and a sub-Zstrt,consisting of Z-elements, defining factors in ;
  555. % productterms of this father-sum. ;
  556. % These factors are defined by Z-elements (Y.exponent). Atmost one of ;
  557. % these exponents is greater than 1. ;
  558. % The purpose of CommonFac is to factor out this element,i.e. to remo-;
  559. % ve a Z-element (Y.1) from the Zstrts of the children and also its ;
  560. % corresponding occurrences from ZZ3 = Zstrt(Y), to combine the remai-;
  561. % ning sum-information in a new PLUS-row, with index Nsum, and to cre-;
  562. % ate a TIMES-row, with index Nprod, defining the product of the sum, ;
  563. % given by the row Nsum, and the variable corresponding with column Y.;
  564. % ZZ2 and CH2 are used to (re)structure information, by allowing to ;
  565. % combine the remaining portions of the child-rows.The father (with ;
  566. % index Far) is defined by a Zstrt (its primitive part) and by CH1 = ;
  567. % Chrow (its composite part). ZZ4 and CH4 are used to identify the ;
  568. % Zstrts of the children after removal of a (Y.1)-element and the ;
  569. % Chrow's,respectively.If exponent>1 in (Y.exponent) the Zstrt has to ;
  570. % be modified to obtain ZZ4, instead of a simple removal of (Y.1) from;
  571. % from Zstrt X. ;
  572. % Alternatives for the structure of the such a child-row are : ;
  573. % -1- A combination of a non-empty Zstrt and a non-empty list Chrow ;
  574. % of children. ;
  575. % -2- An empty Zstrt, but a non-empty Chrow. ;
  576. % -3- A non-empty Zstrt, but an empty Chrow. ;
  577. % Special attention is required when in case -3- the Zstrt consists of;
  578. % only 1 Z-element besides the element shared with column Y. ;
  579. % In case -2- similar care have to be taken when Chrow consists of 1 ;
  580. % row index only. ;
  581. % Remark : Since the overall intention is optimization, i.e. reduction;
  582. % of the arithmetic complexity of a set of expressions, viewed as ru- ;
  583. % les to perform arithmetic operations, expression parts like a*b + a ;
  584. % are not changed into a*(b + 1). Hence a forth alternative, being an ;
  585. % empty Zstrt and an empty Chrow is irrelevant. ;
  586. % ------------------------------------------------------------------- ;
  587. begin scalar far,ch1,ch2,ch4,chindex,zel,zeli,zz2,zz3,zz4,
  588. nsum,nprod,opv,y1,cof,x,ivalx;
  589. far:=car(xx);
  590. ch1:=chrow(far);
  591. zz3:=zstrt(y);
  592. nprod:=rowmax+1;
  593. nsum:=rowmax:=rowmax+2;
  594. % ----------------------------------------------------------------- ;
  595. % After some initial settings all children,accessible via the Z-el.s;
  596. % collected in Cdr(XX) are examined using a FOREACH_loop. ;
  597. % ----------------------------------------------------------------- ;
  598. foreach item in cdr(xx) do
  599. <<x:=xind item;
  600. if (ivalx:=ival item)=1
  601. then zz4:=delyzz(y,zstrt x)
  602. else zz4:=inszzzr(zeli:=mkzel(y,ivalx-1),delyzz(y,zstrt x));
  603. ch4:=chrow(x);
  604. cof:=expcof(x);
  605. % --------------------------------------------------------------- ;
  606. % (Y.1) is removed from the child's Zstrt, defining a monomial, ;
  607. % without the coefficient, stored in Cof. ;
  608. % --------------------------------------------------------------- ;
  609. if null(zz4) and (null(cdr ch4) and car(ch4))
  610. then
  611. <<% ------------------------------------------------------------- ;
  612. % This is the special case of possibility -2-. ZZ4 is empty and ;
  613. % CH4 contains only 1 index. ;
  614. % ------------------------------------------------------------- ;
  615. if (opv:=opval(ch4:=car ch4)) eq 'plus and expcof(ch4)=1
  616. then
  617. <<% ----------------------------------------------------------- ;
  618. % The child with row-index CH4 has the form (..+..+..)^1 = ..+;
  619. % ..+.. . Its definition has to be moved to the row Nsum. ;
  620. % The different terms can be either primitive or composite and;
  621. % have all to be multiplied by Cof. Both Zstrt(CH4) - the pri-;
  622. % mitives - and Chrow(CH4) - the composites - have to be exa- ;
  623. % mined. ;
  624. % ----------------------------------------------------------- ;
  625. foreach z in zstrt(ch4) do
  626. <<% --------------------------------------------------------- ;
  627. % A new Zstrt ZZ2 is made with the primitive elements of the;
  628. % the different Zstrt(CH4)'s. InsZZZr guarantees summation ;
  629. % of the Ival's if the Xind's are equal (see module CODMAT).;
  630. % ZZ2 is build using the FOREACH X loop. The Zstrt's of the ;
  631. % columns, which share an element with ZZ2,are also updated:;
  632. % The CH4-indexed elements are removed and the Nsum-indexed ;
  633. % elements are inserted. ;
  634. % --------------------------------------------------------- ;
  635. zel:=mkzel(xind z,dm!-times(ival(z),cof));
  636. zz2:=inszzzr(zel,zz2);
  637. setzstrt(yind z,inszzz(mkzel(nsum,ival zel),
  638. delyzz(ch4,zstrt yind z)))
  639. >>;
  640. foreach ch in chrow(ch4) do
  641. <<% --------------------------------------------------------- ;
  642. % The row CH defines a child directly if Cof = 1. In all ;
  643. % other cases a multiplication with Cof has to be performed.;
  644. % Either by changing the ExpCof field if the child is a pro-;
  645. % duct or by introducing a new TIMES-row. ;
  646. % --------------------------------------------------------- ;
  647. chindex:=ch;
  648. if not(!:onep cof)
  649. then
  650. if opval(ch) eq 'times
  651. then
  652. << setexpcof(ch,dm!-times(cof,expcof(ch)));
  653. setfarvar(ch,nsum)
  654. >>
  655. else
  656. << chindex:=rowmax:=rowmax+1;
  657. setrow(chindex,'times,nsum,(ch).cof,nil)
  658. >>
  659. else setfarvar(ch,nsum);
  660. ch2:=chindex.ch2
  661. >>;
  662. % ----------------------------------------------------------- ;
  663. % The row CH4 is not longer needed in CODMAT, because its ;
  664. % content is distributed over other rows. ;
  665. % ----------------------------------------------------------- ;
  666. clearrow(ch4);
  667. >>
  668. else
  669. <<% ----------------------------------------------------------- ;
  670. % This is still the special case -2-. (CH4) contains 1 child ;
  671. % index. The leading operator of this child is not PLUS. So ;
  672. % CH4 is simply added to the list of children indices CH2 and ;
  673. % the father index of row CH4 is changed into Nsum. ;
  674. % ----------------------------------------------------------- ;
  675. setfarvar(ch4,nsum);
  676. ch2:=ch4.ch2
  677. >>;
  678. % ------------------------------------------------------------- ;
  679. % The row X is not longer needed in CODMAT, because its content ;
  680. % is distributed over other rows. ;
  681. % ------------------------------------------------------------- ;
  682. clearrow(x)
  683. >>
  684. else
  685. if null(ch4) and (null(cdr zz4) and car(zz4))
  686. then
  687. <<% ----------------------------------------------------------- ;
  688. % This is the special case of possibility -3-: A Zstrt ZZ4 ;
  689. % consisting of only one Z-element. ;
  690. % This Z-element defines just a variable if IVal(Car ZZ4) =1. ;
  691. % It is a power of a variable in case IVal-value > 1 holds. ;
  692. % In the latter situation Nsum ought to become the new father ;
  693. % index of the row with index Xind Car ZZ4.In the former case ;
  694. % the single variable is added to the Zstrt ZZ2, before row X ;
  695. % can be cleared. ;
  696. % ----------------------------------------------------------- ;
  697. if not(!:onep ival(car(zz4)))
  698. then
  699. << setfarvar(x,nsum);
  700. setzstrt(x,zz4);
  701. ch2:=x.ch2
  702. >>
  703. else
  704. << zz2:=inszzzr(find!+var(farvar(y1:=yind car zz4),nsum,
  705. cof),zz2);
  706. setzstrt(y1,delyzz(x,zstrt y1));
  707. clearrow(x)
  708. >>
  709. >>
  710. else
  711. <<% ----------------------------------------------------------- ;
  712. % Now the general form of one of the 3 alternatives holds. ;
  713. % Row index X is added to the list of children indices CH2 ;
  714. % and the new father index for row X becomes Nsum. The Zstrt ;
  715. % of X is also reset. It becomes ZZ4, i.e. the previous Zstrt ;
  716. % after removal of (Y.1). ;
  717. % ----------------------------------------------------------- ;
  718. ch2:=x.ch2;
  719. setfarvar(x,nsum);
  720. setzstrt(x,zz4)
  721. >>;
  722. % --------------------------------------------------------------- ;
  723. % The previous "life" of X is skipped by removing its impact from ;
  724. % the "history book" CODMAT. ;
  725. % --------------------------------------------------------------- ;
  726. ch1:=delete(x,ch1);
  727. zz3:=delyzz(x,zz3);
  728. if ivalx>2 then zz3:=inszzz(mkzel(x,val(zeli)),zz3)
  729. >>;
  730. % ----------------------------------------------------------------- ;
  731. % Some final bookkeeping is needed : ;
  732. % -1- (Y.1) was deleted from the ZZ4's. Its new role, factor in the ;
  733. % product,defined via the row Nprod, has still to be establish- ;
  734. % ed by inserting this information in Y's Zstrt. ;
  735. % ----------------------------------------------------------------- ;
  736. setzstrt(y,(zel:=mkzel(nprod,1)).zz3);
  737. % ----------------------------------------------------------------- ;
  738. % -2- The list of indices of children of the row with index Far ;
  739. % ought to be extended with Nprod. ;
  740. % ----------------------------------------------------------------- ;
  741. setchrow(far,nprod.ch1);
  742. % ----------------------------------------------------------------- ;
  743. % -3- Finally the new rows Nprod and Nsum have to be filled. How- ;
  744. % ever the :=: assignment-option might cause - otherwise non- ;
  745. % existing - problems, because simplification is skipped before ;
  746. % parsing input and storing the relevant information in CODMAT. ;
  747. % An input expression of the form x*(a + t) + x*(a - t) can thus be ;
  748. % transformed - by an application of CODFAC - into the form ;
  749. % x*(2*a + 0). Its Zstrt can contain an element (index . 0), like ;
  750. % the Zstrt associated with t. The latter is due to the coefficient ;
  751. % addition, implied by insert-operations, like InsZZZ or InsZZZr. ;
  752. % Hence a test is made to discover if a Z-element Zel exists, such ;
  753. % that IVal(Zel)=0. If so, its occurrence is removed from both ZZ2 ;
  754. % and the Zstrt of the t-column. ;
  755. % If now Null(CH2) and Null(Cdr ZZ2) holds the PLUS-row Nsum is ;
  756. % superfluous. Only 2*a*x has to be stored in Nprod. The row Nsum ;
  757. % is removed when it is easily detectable, because this index is ;
  758. % not used anymore and anywhere, when the above limitations are ;
  759. % valid. ;
  760. % ----------------------------------------------------------------- ;
  761. foreach z in zz2 do if zeropp(ival(z))
  762. then << zz2:=delyzz(y1:=xind z,zz2);
  763. setzstrt(y1,delyzz(nsum,zstrt y1))
  764. >>;
  765. % ----------------------------------------------------------------- ;
  766. % Expressions like x(a-w)+x(a+w) lead to printable, but not yet to ;
  767. % completely satisfactory prefixlist-representations. This problem ;
  768. % is solved in the module CODPRI in the function ConstrExp. ;
  769. % ----------------------------------------------------------------- ;
  770. setrow(nprod,'times,far,list list nsum,list mkzel(y,val zel));
  771. setrow(nsum,'plus,nprod,list ch2,zz2)
  772. end;
  773. endmodule;
  774. end;