codstr.red 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. module gstructr; % Generalized structure routines.
  2. % ------------------------------------------------------------------- ;
  3. % Copyright : J.A. van Hulzen, Twente University, Dept. of Computer ;
  4. % Science, P.O.Box 217, 7500 AE Enschede, the Netherlands.;
  5. % Author : M.C. van Heerwaarden, J.A. van Hulzen ;
  6. % ------------------------------------------------------------------- ;
  7. symbolic$
  8. % ------------------------------------------------------------------- ;
  9. % This module contains an extended version of the structr facility of ;
  10. % REDUCE. ;
  11. % ;
  12. % Author of structr-routines: Anthony C. Hearn. ;
  13. % ;
  14. % Copyright (c) 1987 The RAND Corporation. All rights reserved. ;
  15. % ;
  16. % ------------------------------------------------------------------- ;
  17. % ------------------------------------------------------------------- ;
  18. % This is a generalization of the STRUCTR-command. Instead of one ;
  19. % expression, GSTRUCTR takes as input a list of assignment statements.;
  20. % SYNTAX: ;
  21. % <gstructr-command> ::= GSTRUCTR <ass-list> NAME <id> ;
  22. % <ass-list> ::= {<assignments> | <matrix>} ;
  23. % <id> ::= <name for CSE> ;
  24. % As a result, all assignments are printed with substitutions for the ;
  25. % CSE's. Then WHERE is printed, followed by the list of CSE's. These ;
  26. % CSE's are printed in reversed order. Matrices are treated as if ;
  27. % assignments were made for all matrix elements. ;
  28. % When the switch FORT is ON, the statements will be in FORTRAN execu;
  29. % table order. Be sure PERIOD is OFF when using a matrix,since FORTRAN;
  30. % expects integer subscripts, and REDUCE generates a floating point ;
  31. % representation for these subscripts when PERIOD is ON. ;
  32. % The switch ALGPRI can be turned OFF when the list of assignments is ;
  33. % needed in prefix-form. ;
  34. % ------------------------------------------------------------------- ;
  35. fluid '(countr svar !*varlis);
  36. global '(!*algpri );
  37. %global '(!*fort );
  38. %global '(!*nat );
  39. %global '(!*savestructr);
  40. global'(varnam!*);
  41. switch savestructr, algpri;
  42. % loadtime(on algpri);
  43. % ***** two essential uses of RPLACD occur in this module.
  44. put('gstructr, 'stat, 'gstructrstat);
  45. symbolic procedure gstructrstat;
  46. begin
  47. scalar x,y;
  48. flag('(name), 'delim);
  49. if eqcar(x := xread t, 'progn)
  50. then x := cdr x
  51. else x := list x;
  52. if cursym!* = 'name
  53. then y := xread t;
  54. remflag('(name), 'delim);
  55. return list('gstructr, x, y)
  56. end;
  57. put('gstructr, 'formfn, 'formgstructr);
  58. symbolic procedure formgstructr(u, vars, mode);
  59. list('gstructr, mkquote cadr u, mkquote caddr u);
  60. symbolic procedure gstructr(assset, name);
  61. begin
  62. !*varlis := nil;
  63. countr := 0;
  64. for each ass in assset
  65. do if not pairp ass
  66. then if get(ass, 'rtype) = 'matrix
  67. then prepstructr(cadr get(ass,'avalue),name,ass)
  68. else rederr {ass, "is not a matrix"}
  69. else prepstructr(caddr ass, name, cadr ass);
  70. if !*algpri
  71. then print!*varlis()
  72. else return remredundancy(for each x in reversip!* !*varlis
  73. collect list('setq, cadr x, cddr x))
  74. end;
  75. symbolic procedure prepstructr(u, name, fvar);
  76. begin scalar i, j;
  77. %!*VARLIS is a list of elements of form:
  78. %(<unreplaced expression> . <newvar> . <replaced exp>);
  79. if name
  80. then svar := name
  81. else svar := varnam!*;
  82. u := aeval u;
  83. if flagpcar(u, 'struct)
  84. then << i := 0;
  85. u:= car u .
  86. (for each row in cdr u collect
  87. << i := i + 1;
  88. j := 0;
  89. for each column in row collect
  90. << j := j + 1;
  91. !*varlis := (nil .
  92. list(fvar,i,j) .
  93. prepsq prepstruct!*sq column) .
  94. !*varlis
  95. >> >>
  96. )
  97. >>
  98. else if getrtype u
  99. then typerr(u,"STRUCTR argument")
  100. else !*varlis:=(nil.fvar.prepsq prepstruct!*sq u).!*varlis
  101. end;
  102. symbolic procedure print!*varlis;
  103. begin
  104. if !*fort
  105. then !*varlis := reversip!* !*varlis;
  106. if not !*fort
  107. then << for each x in reverse !*varlis
  108. do if null car x
  109. then << assgnpri(cddr x,list cadr x,t);
  110. if not flagpcar(cddr x,'struct) then terpri();
  111. if null !*nat then terpri()
  112. >>;
  113. if countr=0 then return nil;
  114. prin2t " where"
  115. >>;
  116. for each x in !*varlis
  117. do if !*fort or car x
  118. then <<terpri!* t;
  119. if null !*fort then prin2!* " ";
  120. assgnpri(cddr x,list cadr x,t)
  121. >>;
  122. if !*savestructr
  123. then <<if arrayp svar
  124. then <<put(svar,'array,
  125. % mkarray(list(countr+1),'algebraic));
  126. mkarray1(list(countr+1),'algebraic));
  127. put(svar,'dimension,list(countr+1))>>;
  128. for each x in !*varlis do
  129. if car x then setk2(cadr x,mk!*sq !*k2q car x)>>
  130. end;
  131. symbolic procedure prepstruct!*sq u;
  132. if eqcar(u,'!*sq)
  133. then prepstructf numr cadr u ./ prepstructf denr cadr u
  134. else u;
  135. symbolic procedure prepstructf u;
  136. if null u
  137. then nil
  138. else if domainp u
  139. then u
  140. else begin
  141. scalar x,y;
  142. x := mvar u;
  143. if sfp x
  144. then if y := assoc(x,!*varlis)
  145. then x:=cadr y
  146. else x:=prepstructk(prepsq!*(prepstructf x ./ 1),
  147. prepstructvar(),x)
  148. else if not atom x and not atomlis cdr x
  149. then if y := assoc(x,!*varlis)
  150. then x := cadr y
  151. else x := prepstructk(x,prepstructvar(),x);
  152. return x .** ldeg u .* prepstructf lc u .+ prepstructf red u
  153. end;
  154. symbolic procedure prepstructk(u,id,v);
  155. begin
  156. scalar x;
  157. if x := prepsubchk1(u,!*varlis,id)
  158. then rplacd(x,(v . id . u) . cdr x)
  159. else if x := prepsubchk2(u,!*varlis)
  160. then !*varlis := (v . id . x) . !*varlis
  161. else !*varlis := (v . id . u) . !*varlis;
  162. return id
  163. end;
  164. symbolic procedure prepsubchk1(u,v,id);
  165. begin scalar w;
  166. while v do
  167. <<smember(u,cddar v)
  168. and <<w := v; rplacd(cdar v,subst(id,u,cddar v))>>;
  169. v := cdr v>>;
  170. return w
  171. end;
  172. symbolic procedure prepsubchk2(u,v);
  173. begin scalar bool;
  174. for each x in v do
  175. smember(cddr x,u)
  176. and <<bool := t; u := subst(cadr x,cddr x,u)>>;
  177. if bool then return u else return nil
  178. end;
  179. symbolic procedure prepstructvar;
  180. begin
  181. countr := countr + 1;
  182. return if arrayp svar then list(svar,countr)
  183. else compress append(explode svar,explode countr)
  184. end;
  185. symbolic procedure remredundancy setqlist;
  186. % -------------------------------------------------------------------- ;
  187. % This function is used for backsubstitution of values of identifiers ;
  188. % in rhs's if the corresponding identifier occurs only once in the set ;
  189. % of rhs's. SetqList is thus made shorter if possible. ;
  190. % An element of Setqlist has the form (SETQ assname value), where ;
  191. % assname can be redundant if ;
  192. % Atom(assname) and Letterpart(assname) = svar ;
  193. % -------------------------------------------------------------------- ;
  194. begin scalar lsl,lhs,rhs,relevant,j,var,freq,k,firstocc,templist;
  195. lsl:=length(setqlist);
  196. lhs:=mkvect(lsl); rhs:=mkvect(lsl); relevant:=mkvect(lsl);
  197. j:=0; var:=explode(svar);
  198. foreach item in setqlist do
  199. <<putv(lhs,j:=j+1,cadr item); putv(rhs,j,caddr item);
  200. if atom(cadr item ) and letterparts(cadr item) = var
  201. then putv(relevant,j,t)
  202. >>;
  203. for j:=1:lsl do
  204. if getv(relevant,j)
  205. then
  206. << var:=getv(lhs,j); freq:=0; k:=j; firstocc:=0;
  207. while freq=0 and k<lsl do
  208. << if (freq:=numberofoccs(var,getv(rhs,k:=k+1)))=1 and firstocc=0
  209. then <<firstocc:=k; freq:=0>>;
  210. if firstocc>0 and freq>0 then firstocc:=0
  211. >>;
  212. if firstocc=0
  213. then templist:=list('setq,getv(lhs,j),getv(rhs,j)) . templist
  214. else putv(rhs,firstocc,
  215. subst(getv(rhs,j),var,getv(rhs,firstocc)))
  216. >>
  217. else templist:=list('setq,getv(lhs,j),getv(rhs,j)) . templist;
  218. return reverse(templist);
  219. end;
  220. symbolic procedure letterparts(name);
  221. % ----------------------------------------------------------------- ;
  222. % Eff: The exploded form of the Letterpart of Name returned, i.e. ;
  223. % (!a !a) if Name=aa55. ;
  224. % ----------------------------------------------------------------- ;
  225. begin scalar letters;
  226. letters:=reversip explode name;
  227. while digit car letters do letters:=cdr letters;
  228. return reversip letters
  229. end;
  230. symbolic procedure numberofoccs(var,expression);
  231. % -------------------------------------------------------------------- ;
  232. % The number of occurrences of Var in Expression is computed and ;
  233. % returned. ;
  234. % -------------------------------------------------------------------- ;
  235. if atom(expression)
  236. then
  237. if var=expression then 1 else 0
  238. else
  239. (if cdr expression
  240. then numberofoccs(var,cdr expression)
  241. else 0)
  242. +
  243. (if var=car expression
  244. then 1
  245. else
  246. if not atom car expression
  247. then numberofoccs(var,car expression)
  248. else 0);
  249. %-----------------------------------------------------------------------
  250. % Algebraic mode psop-function definition.
  251. %-----------------------------------------------------------------------
  252. symbolic procedure algstructreval u;
  253. % -------------------------------------------------------------------- ;
  254. % Variant of gstructr-command. Accepts list of equations and optionally
  255. % an initial part of a subpart recognizer name.
  256. % -------------------------------------------------------------------- ;
  257. begin scalar algpri,name,period,res; integer nargs;
  258. nargs:=length u;
  259. name:= (if nargs=1 and getd('newsym) then fnewsym()
  260. else if nargs=2 then cadr u
  261. else '!*!*error!*!*);
  262. if eq(name,'!*!*error!*!*)
  263. then rederr("WRONG NUMBER OF ARGUMENTS ALGSTRUCTR")
  264. else << algpri:=!*algpri; period:=!*period; !*algpri:=!*period:=nil;
  265. res:=apply('gstructr,list(cdar u,name));
  266. !*period:=period;
  267. if (!*algpri:=algpri)
  268. then return
  269. algresults1(foreach el in res
  270. collect cons(cadr el,caddr el))
  271. else return res
  272. >>
  273. end;
  274. put('algstructr,'psopfn,'algstructreval)$
  275. endmodule;
  276. end;