forall.red 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916
  1. module forall; % FOR ALL and LET-related commands.
  2. % Author: Anthony C. Hearn.
  3. % Modifications by: Herbert Melenk.
  4. % Copyright (c) 1993 RAND. All rights reserved.
  5. fluid '(!*resimp !*sub2 alglist!* arbl!* asymplis!* frasc!* wtl!*);
  6. fluid '(!*!*noremove!*!* frlis!* newrule!* oldrules!* props!* subfg!*);
  7. fluid '(!*reduce4 !*sqrtrulep powlis!* powlis1!*);
  8. global '(!*match cursym!* erfg!* letl!* mcond!*);
  9. letl!* := '(let match clear saveas such); % Special delimiters.
  10. % Contains two RPLAC references commented out.
  11. remprop('forall,'stat);
  12. remprop('forall,'formfn);
  13. symbolic procedure forallstat;
  14. begin scalar arbl,conds;
  15. if cursym!* memq letl!* then symerr('forall,t);
  16. flag(letl!*,'delim);
  17. arbl := remcomma xread nil;
  18. if cursym!* eq 'such then
  19. <<if not(scan() eq 'that) then symerr('let,t);
  20. conds := xread nil>>;
  21. remflag(letl!*,'delim);
  22. if not(cursym!* memq letl!*) then symerr('let,t)
  23. else return list('forall,arbl,conds,xread1 t)
  24. end;
  25. symbolic procedure forall u;
  26. begin scalar x,y;
  27. x := for each j in car u collect newvar j;
  28. y := pair(car u,x);
  29. mcond!* := subla(y,cadr u);
  30. % mcond!* := formbool(subla(y,eval cadr u),nil,'algebraic);
  31. frasc!* := y;
  32. frlis!* := union(x,frlis!*);
  33. return lispeval caddr u
  34. end;
  35. symbolic procedure arbstat;
  36. <<lpriw("*****","ARB no longer supported");
  37. symerr('if,t)>>;
  38. put('arb,'stat,'arbstat);
  39. symbolic procedure newvar u;
  40. if not idp u then typerr(u,"free variable")
  41. % else if flagp(u,'reserved)
  42. % then typerr(list("Reserved variable",u),"free variable")
  43. else intern compress append(explode '!=,explode u);
  44. symbolic procedure formforall(u,vars,mode);
  45. begin scalar arbl!*,x,y;
  46. u := cdr u;
  47. % vars := append(car u,vars); % Semantics are different.
  48. if null cadr u then x := t else x := formbool(cadr u,vars,mode);
  49. % if null cadr u then x := t else x := form1(cadr u,vars,mode);
  50. y := form1(caddr u,vars,mode);
  51. % Allow for a LET or MATCH call during a similar evaluation.
  52. % This might occur in autoloading.
  53. if eqcar(y,'let) then y := 'let00 . cdr y
  54. else if eqcar(y,'match) then y := 'match00 . cdr y;
  55. return list('forall,list('list,mkquote union(arbl!*,car u),
  56. mkquote x,mkquote y))
  57. end;
  58. symbolic procedure def u;
  59. % Defines a list of operators.
  60. <<lprim "Please do not use the DEF operator; it is no longer supported";
  61. for each x in u do
  62. if not eqexpr x or not idlistp cadr x then errpri2(x,t)
  63. else <<mkop caadr x;
  64. forall list(cdadr x,t,list('let,mkarg(list x,nil)))>>>>;
  65. put('def,'stat,'rlis);
  66. deflist('((forall formforall)),'formfn);
  67. deflist('((forall forallstat)),'stat);
  68. flag ('(clear let match),'quote);
  69. symbolic procedure formlet1(u,vars,mode);
  70. requote ('list . for each x in u collect
  71. if eqexpr x
  72. then list('list,mkquote car x,form1(cadr x,vars,mode),
  73. !*s2arg(form1(caddr x,vars,mode),vars))
  74. else form1(x,vars,mode));
  75. symbolic procedure requote u;
  76. if atom u or not(car u eq 'list) then u
  77. else (if x then mkquote x else u) where x=requote1 cdr u;
  78. symbolic procedure requote1 u;
  79. begin scalar x,y;
  80. a: if null u then return reversip x
  81. else if numberp car u or car u memq '(nil t)
  82. then x := car u . x
  83. else if atom car u then return nil
  84. else if caar u eq 'quote then x := cadar u . x
  85. else if caar u eq 'list and (y := requote1 cdar u)
  86. then x := y . x
  87. else return nil;
  88. u := cdr u;
  89. go to a
  90. end;
  91. symbolic procedure !*s2arg(u,vars);
  92. %makes all NOCHANGE operators into their listed form;
  93. if atom u or eq(car u,'quote) then u
  94. else if not idp car u or not flagp(car u,'nochange)
  95. then for each j in u collect !*s2arg(j,vars)
  96. else mkarg(u,vars);
  97. put('let,'formfn,'formlet);
  98. put('clear,'formfn,'formclear);
  99. put('match,'formfn,'formmatch);
  100. symbolic procedure formclear(u,vars,mode);
  101. list('clear,formclear1(cdr u,vars,mode));
  102. symbolic procedure formclear1(u,vars,mode);
  103. 'list . for each x in u collect
  104. if flagp(x,'share) then mkquote x else form1(x,vars,mode);
  105. symbolic procedure formlet(u,vars,mode);
  106. list('let,formlet1(cdr u,vars,mode));
  107. symbolic procedure formmatch(u,vars,mode);
  108. list('match,formlet1(cdr u,vars,mode));
  109. symbolic procedure let u; let0 u; % to distinguish between operator
  110. % and function.
  111. symbolic procedure let0 u;
  112. let00 u where frasc!* = nil;
  113. symbolic procedure let00 u;
  114. begin
  115. u := errorset!*(list('let1,mkquote u),t);
  116. frasc!* := mcond!* := nil;
  117. if errorp u then error1() else return car u
  118. end;
  119. symbolic procedure let1 u;
  120. begin scalar x,y;
  121. u := reverse u; % So that rules are added in order given.
  122. while u do
  123. <<if idp u then typerr(u,"rule list")
  124. else if eqcar(y := listeval0(x := car u),'list)
  125. then rule!-list(reverse cdr y,t)
  126. else if idp x then revalruletst x
  127. else if car x eq 'replaceby
  128. then if frasc!*
  129. then rerror(alg,100,
  130. "=> invalid in FOR ALL statement")
  131. else rule!-list(list x,t)
  132. else if car x eq 'equal
  133. then if smemq('!~,x)
  134. then if frasc!* then typerr(x,"rule")
  135. else rule!-list(list x,t)
  136. else let2(cadr x,caddr x,nil,t)
  137. else revalruletst x;
  138. u := cdr u>>
  139. end;
  140. symbolic procedure revalruletst u;
  141. (if u neq v then let1 list v else typerr(u,"rule list"))
  142. where v = reval u;
  143. symbolic procedure let2(u,v,w,b);
  144. begin scalar flgg,x,y,z;
  145. % FLGG is set true if free variables are found.
  146. if (y := getrtype u) and (z := get(y,'typeletfn))
  147. and flagp(z,'direct)
  148. then return lispapply(z,list(u,v,y,b,getrtype v))
  149. else if (y := getrtype v) and (z := get(y,'typeletfn))
  150. and flagp(z,'direct)
  151. then return lispapply(z,list(u,v,nil,b,y));
  152. x := subla(frasc!*,u);
  153. if x neq u
  154. then if atom x then return errpri1 u
  155. else <<flgg := t; u := x>>;
  156. x := subla(frasc!*,v);
  157. if x neq v
  158. then <<v := x;
  159. if eqcar(v,'!*sq!*) then v := prepsq!* cadr v>>;
  160. % to ensure no kernels are replaced by uneq copies
  161. % during pattern matching process.
  162. % Check for unmatched free variables.
  163. x := smemql(frlis!*,mcond!*);
  164. y := smemql(frlis!*,u);
  165. if (z := setdiff(x,y))
  166. or (z := setdiff(setdiff(smemql(frlis!*,v),x),
  167. setdiff(y,x)))
  168. then <<lprie ("Unmatched free variable(s)" . z);
  169. erfg!* := 'hold;
  170. return nil>>
  171. else if atom u then nil
  172. else if car u eq 'getel then u := lispeval cadr u
  173. else if flagp(car u,'immediate) then u := reval u;
  174. return let3(u,v,w,b,flgg)
  175. end;
  176. symbolic procedure let3(u,v,w,b,flgg);
  177. % U is left-hand-side of a rule, v the right-hand-side.
  178. % W is true if a match, NIL otherwise.
  179. % B is true if the rule is being added, NIL if being removed.
  180. % Flgg is true if there are free variables in the rule.
  181. begin scalar x,y1,y2,z;
  182. x := u;
  183. if null x then <<u := 0; return errpri1 u>>
  184. else if numberp x then return errpri1 u;
  185. % Allow redefinition of id's, regardless of type.
  186. % The next line allows type of LHS to be redefined.
  187. y2 := getrtype v;
  188. if b and idp x then <<remprop(x,'rtype); remprop(x,'avalue)>>;
  189. % else if idp x and flagp(x,'reserved)
  190. % then rederr list(x,"is a reserved identifier");
  191. if (y1 := getrtype x)
  192. then return if z := get(y1,'typeletfn)
  193. then lispapply(z,list(x,v,y1,b,getrtype v))
  194. else typelet(x,v,y1,b,getrtype v)
  195. else if y2 and not(y2 eq 'yetunknowntype)
  196. then return if z := get(y2,'typeletfn)
  197. then lispapply(z,list(x,v,nil,b,y2))
  198. else typelet(x,v,nil,b,y2)
  199. else letscalar(u,v,w,x,b,flgg)
  200. end;
  201. symbolic procedure letscalar(u,v,w,x,b,flgg);
  202. begin
  203. if not atom x
  204. then if not idp car x then return errpri2(u,'hold)
  205. else if car x eq 'df
  206. then if null letdf(u,v,w,x,b) then nil
  207. else return nil
  208. else if getrtype car x
  209. then return let2(reval x,v,w,b)
  210. else if not get(car x,'simpfn)
  211. then <<redmsg(car x,"operator");
  212. mkop car x;
  213. return let3(u,v,w,b,flgg)>>
  214. else nil
  215. else if null b and null w
  216. then <<remprop(x,'avalue);
  217. remprop(x,'rtype); % just in case
  218. remflag(list x,'antisymmetric);
  219. remprop(x,'infix);
  220. % remprop(x,'klist);
  221. % commented out: the relevant objects may still exist.
  222. remprop(x,'kvalue);
  223. remflag(list x,'linear);
  224. remflag(list x,'noncom);
  225. remprop(x,'op);
  226. remprop(x,'opmtch);
  227. remprop(x,'simpfn);
  228. remflag(list x,'symmetric);
  229. wtl!* := delasc(x,wtl!*);
  230. if flagp(x,'opfn)
  231. then <<remflag(list x,'opfn); remd x>>;
  232. rmsubs(); % since all kernel lists are gone.
  233. return nil>>;
  234. if eqcar(x,'expt) and caddr x memq frlis!*
  235. then letexprn(u,v,w,!*k2q x,b,flgg)
  236. % Special case of a non-integer exponent match.
  237. else if eqcar(x,'sqrt)
  238. then <<!*sqrtrulep := t;
  239. let2({'expt,cadr x,'(quotient 1 2)},v,w,b)>>;
  240. % Since SQRTs can be converted into EXPTs.
  241. x := simp0 x where !*precise = t; % We don't want to break
  242. % up exponents.
  243. return if not domainp numr x then letexprn(u,v,w,x,b,flgg)
  244. else errpri1 u
  245. end;
  246. symbolic procedure letexprn(u,v,w,x,b,flgg);
  247. % Replacement of scalar expressions.
  248. begin scalar y,z;
  249. if denr x neq 1
  250. then return let2(let!-prepf numr x,
  251. list('times,let!-prepf denr x,v),w,b)
  252. else if red(x := numr x)
  253. then return let2(let!-prepf !*t2f lt x,
  254. list('difference,v,let!-prepf red x),w,b)
  255. else if null (y := kernlp x)
  256. then <<y := term!-split x;
  257. return let2(let!-prepf car y,
  258. list('difference,v,let!-prepf cdr y),w,b)>>
  259. else if y neq 1
  260. then return let2(let!-prepf quotf!*(x,y),
  261. list('quotient,v,let!-prepf y),w,b);
  262. x := klistt x;
  263. y := list(w . (if mcond!* then mcond!* else t),v,nil);
  264. if cdr x
  265. then return <<rmsubs(); !*match:= xadd!*(x . y,!*match,b)>>
  266. else if null w and cdar x=1 % ONEP
  267. then <<x := caar x;
  268. if null flgg and (null mcond!* or mcond!* eq 't
  269. or not smember(x,mcond!*))
  270. then <<if atom x
  271. then if flagp(x,'used!*) then rmsubs()
  272. else nil
  273. else if 'used!* memq cddr fkern x
  274. then rmsubs();
  275. setk1(x,v,b)>>
  276. else if atom x then return errpri1 u
  277. else <<rmsubs(); % if get(car x,'klist) then rmsubs();
  278. % the "get" is always true currently.
  279. put(car x,
  280. 'opmtch,
  281. xadd!*(cdr x . y,get(car x,'opmtch),b))>>>>
  282. else <<rmsubs();
  283. if v=0 and null w and not flgg
  284. then <<asymplis!* := xadd(car x,asymplis!*,b);
  285. powlis!*
  286. := xadd(caar x . cdar x . y,powlis!*,'replace)>>
  287. else if w or not(cdar y eq t) or frasc!*
  288. then powlis1!* := xadd(car x . y,powlis1!*,b)
  289. else if null b and (z := assoc(caar x,asymplis!*))
  290. and z=car x
  291. then asymplis!* := delasc(caar x,asymplis!*)
  292. else <<powlis!* := xadd(caar x . cdar x . y,powlis!*,b);
  293. if b then asymplis!* := delasc(caar x,asymplis!*)>>>>
  294. end;
  295. rlistat '(clear let match);
  296. % Further support for rule lists and local rule applications.
  297. symbolic procedure clearrules u;
  298. rule!-list(u,nil) where !*sqrtrulep=nil;
  299. % symbolic procedure letrules u; rule!-list(u,t);
  300. rlistat '(clearrules); % letrules.
  301. symbolic procedure rule!-list(u,type);
  302. % Type is true if the rule is being added, NIL if being removed.
  303. begin scalar v,x,y,z;
  304. a: frasc!* := nil; % Since free variables must be declared in each
  305. % rule.
  306. if null u or u = {{}} then return (mcond!* := nil);
  307. mcond!* := t;
  308. v := car u;
  309. if idp v
  310. then if (x := get(v,'avalue)) and car x eq 'list
  311. then <<u := append(reverse cdadr x,cdr u); go to a>>
  312. else typerr(v,"rule list")
  313. else if car v eq 'list
  314. then <<u := append(cdr v,cdr u); go to a>>
  315. else if car v eq 'equal
  316. then lprim "Please use => instead of = in rules"
  317. else if not(car v eq 'replaceby) then typerr(v,"rule");
  318. y := remove!-free!-vars cadr v;
  319. if eqcar(caddr v,'when)
  320. then <<mcond!* := formbool(remove!-free!-vars!* caddr caddr v,
  321. nil,'algebraic);
  322. z := remove!-free!-vars!* cadr caddr v>>
  323. else z := remove!-free!-vars!* caddr v;
  324. rule!*(y,z,frasc!*,mcond!*,type);
  325. u := cdr u;
  326. go to a
  327. end;
  328. symbolic procedure rule!*(u,v,frasc,mcond,type);
  329. % Type is T if a rule is being added, OLD if an old rule is being
  330. % reinstalled, or NIL if a rule is being removed.
  331. begin scalar x;
  332. frasc!* := frasc;
  333. mcond!* := mcond eq t or subla(frasc,mcond);
  334. if type and type neq 'old
  335. then <<newrule!* := list(u,v,frasc,mcond);
  336. % prin2t list("newrule:",newrule!*);
  337. if idp u
  338. then <<if x := get(u,'rtype)
  339. then <<props!*:= (u . ('rtype . x)) . props!*;
  340. remprop(u,'rtype)>>;
  341. if x := get(u,'avalue)
  342. then <<updoldrules(x,nil);
  343. remprop(u,'avalue)>>>>;
  344. % Asymptotic case.
  345. if v=0 and eqcar(u,'expt) and idp cadr u
  346. and numberp caddr u
  347. and (x := assoc(cadr u,asymplis!*))
  348. then updoldrules(x,nil)>>;
  349. return rule(u,v,frasc,if type eq 'old then t else type)
  350. end;
  351. symbolic procedure rule(u,v,frasc,type);
  352. begin scalar flg,frlis,x,y,z;
  353. % FLGG is set true if free variables are found.
  354. %
  355. x := subla(frasc,u);
  356. if x neq u
  357. then if atom x then return errpri1 u
  358. else <<flg := t; u := x>>;
  359. x := subla(frasc,v);
  360. if x neq v
  361. then <<v := x;
  362. if eqcar(v,'!*sq!*) then v := prepsq!* cadr v>>;
  363. % to ensure no kernels are replaced by uneq copies
  364. % during pattern matching process.
  365. % Check for unmatched free variables.
  366. frlis := for each j in frasc collect cdr j;
  367. x := smemql(frlis,mcond!*);
  368. y := smemql(frlis,u);
  369. if (z := setdiff(x,y))
  370. or (z := setdiff(setdiff(smemql(frlis,v),x),
  371. setdiff(y,x)))
  372. then <<lprie ("Unmatched free variable(s)" . z);
  373. erfg!* := 'hold;
  374. return nil>>
  375. else if eqcar(u,'getel) then u := lispeval cadr u;
  376. return let3(u,v,nil,type,flg)
  377. end;
  378. mkop '!~; % Declare as algebraic operator.
  379. put('!~,'prifn,'tildepri);
  380. symbolic procedure tildepri u; <<prin2!* "~"; prin2!* cadr u>>;
  381. newtok '((!= !>) replaceby);
  382. infix =>;
  383. precedence =>,to;
  384. symbolic procedure equalreplaceby u;
  385. 'replaceby . u;
  386. put('replaceby,'psopfn,'equalreplaceby);
  387. flag('(replaceby),'equalopr); % Make LHS, RHS etc work.
  388. flag('(replaceby),'spaced); % Make it print with spaces.
  389. symbolic procedure formreplaceby(u,vars,mode);
  390. list('list,mkquote car u,form1(cadr u,vars,mode),
  391. !*s2arg(form1(caddr u,vars,mode),vars));
  392. put('replaceby,'formfn,'formreplaceby);
  393. infix when;
  394. precedence when,=>;
  395. symbolic procedure formwhen(u,vars,mode);
  396. list('list,algid('when,vars),form1(cadr u,vars,mode),
  397. % We exclude formbool in following so that rules print prettily.
  398. % mkarg(formbool(caddr u,vars,mode),vars));
  399. mkarg(caddr u,vars));
  400. put('when,'formfn,'formwhen);
  401. flag('(whereexp),'listargp); % letsub.
  402. % put('letsub,'simpfn,'simpletsub);
  403. put('whereexp,'psopfn,'evalwhereexp);
  404. % symbolic procedure simpletsub u; simp evalletsub1(u,t);
  405. symbolic procedure evalwhereexp u;
  406. % We assume that the arguments of this function are well-formed, as
  407. % they would be if produced from a "where" parse.
  408. % It looks like there is a spurious simplification, but it's needed
  409. % in x:= (e^(12i*pi/5) - e^(8i*pi/5) + 4e^(6i*pi/5) - e^(4i*pi/5)
  410. % - 2e^(2i*pi/5) - 1)/(16e^(6i*pi/5)); y:= {e^(~a*i*pi/~(~ b))
  411. % => e^((a - b)/b*i*pi) when numberp a and numberp b and a>b};
  412. % x where y;
  413. evalletsub({cdar u,{'aeval,mkquote{'aeval,carx(cdr u,'where)}}},nil);
  414. flag('(aeval),'opfn); % To make the previous procedure work.
  415. % symbolic procedure evalletsub1(u,v);
  416. % begin scalar x;
  417. % x := car u;
  418. % u := carx(cdr u,'simpletsub);
  419. % if eqcar(x,'list) then x := cdr x else errach 'simpletsub;
  420. % return evalletsub2({x,{'aeval,mkquote u}},v)
  421. % end;
  422. symbolic procedure evalletsub(u,v);
  423. if errorp(u := evalletsub2(u,v))
  424. then rerror(alg,24,"Invalid simplification")
  425. else car u;
  426. symbolic procedure evalletsub2(u,v);
  427. % car u is an untagged list of rules or ruleset names,
  428. % cadr u is an expression to be evaluated by errorset* with the
  429. % rules activated locally,
  430. % v should be nil unless the rules contain equations.
  431. % Returns the expression value corresponding to the
  432. % errorset protocol.
  433. begin scalar newrule!*,oldrules!*,props!*,w;
  434. w := set_rules(car u,v);
  435. % We need resimp on since u may contain (*SQ ... T).
  436. u := errorset!*(cadr u,nil); % where !*resimp = t;
  437. % Restore previous environment, if changed.
  438. restore_rules w;
  439. return u
  440. end;
  441. symbolic procedure set_rules(u,v);
  442. begin scalar !*resimp,x,y,z;
  443. for each j in u do
  444. % The "v" check in next line causes "a where a=>4" to fail.
  445. if eqcar(j,'replaceby) then y := j . y
  446. else if null v and eqcar(j,'equal)
  447. then <<lprim "Please use => instead of = in rules";
  448. y := ('replaceby . cdr j) . y>>
  449. else if (x := validrule j)
  450. or idp j and (x := validrule reval j)
  451. then (x := reverse car x) and <<rule!-list(x,t); z := x . z>>
  452. else typerr(j,"rule list");
  453. rule!-list(y,t);
  454. return y . z
  455. end;
  456. symbolic procedure restore_rules u;
  457. <<for each j in u do rule!-list(j,nil);
  458. for each j in oldrules!*
  459. do if atom cdar j
  460. then if idp cdar j
  461. then if cdar j eq 'scalar
  462. then let3(caar j,cadr j,nil,t,nil)
  463. else typelet(caar j,cadr j,nil,t,cdar j)
  464. else nil
  465. else rule!*(car j,cadr j,caddr j,cadddr j,'old);
  466. restore_props()>>
  467. where !*resimp := nil;
  468. symbolic procedure restore_props;
  469. % At present, the only thing props!* can contain is an RTYPE
  470. % property. However, it is in this form to handle any other cases
  471. % that arise.
  472. for each j in props!* do
  473. if pairp cdr j then put(car j,cadr j,cddr j)
  474. else flag({car j},cdr j);
  475. symbolic procedure resimpcar u; resimp car u;
  476. symbolic procedure validrule u;
  477. (if null x then nil else list x) where x=validrule1 u;
  478. symbolic procedure validrule1 u;
  479. if atom u then nil
  480. else if car u eq 'list
  481. then if null cdr u then {{}}
  482. else for each j in cdr u collect validrule1 j
  483. else if car u eq 'replaceby then u
  484. else if car u eq 'equal then 'replaceby . cdr u
  485. else nil;
  486. symbolic procedure remove!-free!-vars!* u;
  487. remove!-free!-vars u where !*!*noremove!*!* := t;
  488. symbolic procedure remove!-free!-vars u;
  489. begin scalar x,w;
  490. return if atom u then u
  491. else if car u eq '!~
  492. then if !*!*noremove!*!*
  493. then if (x := atsoc(cadr u,frasc!*))
  494. or eqcar(cadr u,'!~)
  495. and (x := atsoc(cadadr u,frasc!*))
  496. then cdr x else u
  497. else if atom cdr u then typerr(u,"free variable")
  498. % Allow for the substitution of a free variable.
  499. else if numberp(w := cadr u) then u
  500. else if idp w or eqcar(w,'!~) and (w:=cadr w)
  501. then <<frlis!* := union(list get!-free!-form cadr u,
  502. frlis!*);
  503. w>>
  504. else if idp caadr u % Free operator.
  505. then <<frlis!* := union(list get!-free!-form caadr u,
  506. frlis!*);
  507. caadr u . remove!-free!-vars!-l cdadr u>>
  508. else typerr(u,"free variable")
  509. else remove!-free!-vars!-l u
  510. end;
  511. symbolic procedure remove!-free!-vars!-l u;
  512. if atom u then u
  513. else if car u eq '!*sq then remove!-free!-vars!-l prepsq!* cadr u
  514. else (if x=u then u else x)
  515. where x=remove!-free!-vars car u . remove!-free!-vars!-l cdr u;
  516. symbolic procedure get!-free!-form u;
  517. begin scalar x,opt;
  518. if x := atsoc(u,frasc!*) then return cdr x;
  519. if eqcar(u,'!~) then <<u:= cadr u; x := '(!! !~ !! !~); opt := t>>
  520. else x := '(!! !~);
  521. x := intern compress append(x,explode u);
  522. frasc!* := (u . x) . frasc!*;
  523. if opt then flag({x},'optional);
  524. return x
  525. end;
  526. symbolic procedure term!-split u;
  527. % U is a standard form which is not a kernel list (i.e., kernlp
  528. % is false). Result is the dotted pair of the leading part of the
  529. % expression for which kernlp is true, and the remainder;
  530. begin scalar x;
  531. while null red u do <<x := lpow u . x; u := lc u>>;
  532. return tpowadd(x,!*t2f lt u) . tpowadd(x,red u)
  533. end;
  534. symbolic procedure tpowadd(u,v);
  535. <<for each j in u do v := !*t2f(j .* v); v>>;
  536. symbolic procedure frvarsof(u,l);
  537. % Extract the free variables in u in their left-to-right order.
  538. if memq(u,frlis!*) then if memq(u,l) then l else append(l,{u})
  539. else if atom u then l
  540. else frvarsof(cdr u,frvarsof(car u,l));
  541. symbolic procedure simp0 u;
  542. begin scalar !*factor,x,y,z;
  543. if eqcar(u,'!*sq) then return simp0 prepsq!* cadr u;
  544. y := setkorder frvarsof(u,nil);
  545. x := subfg!* . !*sub2;
  546. alglist!* := nil . nil; % Since assignments will change.
  547. subfg!* := nil;
  548. if atom u
  549. or idp car u
  550. and (flagp(car u,'simp0fn) or get(car u,'rtype))
  551. then z := simp u
  552. else z := simpiden u;
  553. rplaca(alglist!*,delasc(u,car alglist!*));
  554. % Since we don't want to keep this value.
  555. subfg!* := car x;
  556. !*sub2 := cdr x;
  557. setkorder y;
  558. return z
  559. end;
  560. flag('(cons difference eps expt minus plus quotient times),'simp0fn);
  561. symbolic procedure let!-prepf u;
  562. subla(for each x in frasc!* collect (cdr x . car x),prepf u);
  563. symbolic procedure match u;
  564. match00 u where frasc!* = nil;
  565. symbolic procedure match00 u;
  566. <<for each x in u do let2(cadr x,caddr x,t,t);
  567. frasc!* := mcond!* := nil>>;
  568. symbolic procedure clear u;
  569. begin
  570. rmsubs();
  571. u := errorset!*(list('clear1,mkquote u),t);
  572. mcond!* := frasc!* := nil;
  573. if errorp u then error1() else return car u
  574. end;
  575. symbolic procedure clear1 u;
  576. begin scalar x,y;
  577. while u do
  578. <<if flagp(x := car u,'share)
  579. then if not flagp(x,'reserved) then set(x,x) else rsverr x
  580. % if argument is an explicit list, clear each element.
  581. else if eqcar(x,'list)
  582. then u := nil . append(cdr x,cdr u)
  583. % The following two cases allow for rules or the lhs of
  584. % rules as arguments to CLEAR.
  585. else if eqcar(x,'replaceby) then rule!-list(list x,nil)
  586. else if smemq('!~,x)
  587. then if eqcar(x,'equal) then rule!-list(list x,nil)
  588. else rule!-list(list list('replaceby,x,nil),nil)
  589. % Hook for a generalized "clear" facility.
  590. else if (y := get(if atom x then x else car x,'clearfn))
  591. then apply1(y,x)
  592. else <<let2(x,nil,nil,nil); let2(x,nil,t,nil)>>;
  593. u := cdr u>>
  594. end;
  595. symbolic procedure typelet(u,v,ltype,b,rtype);
  596. % General function for setting up rules for typed expressions.
  597. % LTYPE is the type of the left hand side U, RTYPE, that of RHS V.
  598. % B is a flag that is true if this is an update, nil for a removal.
  599. begin scalar ls;
  600. if null rtype then rtype := 'scalar;
  601. if ltype eq rtype then go to a
  602. else if null b then go to c
  603. else if ltype
  604. then if ltype eq 'list and rtype eq 'scalar
  605. then <<ls := t; go to l>>
  606. else typerr(list(ltype,u),rtype)
  607. else if not atom u
  608. then if arrayp car u then go to a else typerr(u,rtype);
  609. redmsg(u,rtype);
  610. l: put(u,'rtype,rtype);
  611. ltype := rtype;
  612. a: if b and (not atom u or flagp(u,'used!*)) then rmsubs();
  613. c: if not atom u
  614. then if arrayp car u
  615. then setelv(u,if b then v else nil)
  616. else put(car u,'opmtch,xadd!*(cdr u .
  617. list(nil . (if mcond!* then mcond!* else t),v,nil),
  618. get(car u,'opmtch),b))
  619. else if null b
  620. then <<remprop(u,'avalue);
  621. remprop(u,'rtype);
  622. if ltype eq 'array then remprop(u,'dimension)>>
  623. else if ls
  624. then <<remprop(u,'rtype); put!-avalue(u,rtype,v)>>
  625. else <<if (b := get(u,'avalue))
  626. then if not(rtype eq car b)
  627. and (not(car b memq(ls := '(scalar list)))
  628. or not(rtype memq ls))
  629. then typerr(list(car b,u),rtype);
  630. put!-avalue(u,rtype,v)>>
  631. end;
  632. symbolic procedure setk(u,v);
  633. if not atom u
  634. then (if x then setk0(car u . apply1(x,cdr u),v)
  635. else if get(car u,'rtype) eq 'matrix then setk0(u,v)
  636. else setk0(car u . revlis cdr u,v))
  637. where x=get(car u,'evalargfn)
  638. else setk0(u,v);
  639. symbolic procedure setk0(u,v);
  640. % Clear frasc!* to allow for autoloading within LET constructs.
  641. begin scalar x,frasc!*;
  642. % We need to reset alglist!* for structures on the left or right
  643. % hand side.
  644. if (x := getrtype v) and get(x,'setelemfn)
  645. then <<alglist!* := nil . nil; let2(u,v,nil,t)>>
  646. else if not atom u
  647. and idp car u
  648. % Excalc currently needs getrtype to check for free indices.
  649. % Getrtype *must* be called as first argument in OR below.
  650. and ((x := getrtype u or get(car u,'rtype))
  651. and (x := get(x,'setelemfn))
  652. or (x := get(car u,'setkfn)))
  653. % We must update alglist!* when an element is defined.
  654. then <<alglist!* := nil . nil; apply2(x,u,v)>>
  655. % alglist!* is updated here in simp0.
  656. else let2(u,v,nil,t);
  657. return v
  658. end;
  659. symbolic procedure setk1(u,v,b);
  660. begin scalar x,y,z,!*uncached;
  661. !*uncached := t;
  662. if atom u
  663. then <<if null b
  664. then <<if not get(u,'avalue)
  665. then msgpri(nil,u,"not found",nil,nil)
  666. else remprop(u,'avalue);
  667. return nil>>
  668. else if (x:= get(u,'avalue)) then put!-avalue(u,car x,v)
  669. else put!-avalue(u,'scalar,v);
  670. return v>>
  671. else if not atom car u
  672. then rerror(alg,25,"Invalid syntax: improper assignment");
  673. u := car u . revlis cdr u;
  674. if null b
  675. then <<z:=assoc(u,wtl!*);
  676. if not(y := get(car u,'kvalue))
  677. or not (x := assoc(u,y))
  678. then <<if null z and null !*sqrtrulep then
  679. msgpri(nil,u,"not found",nil,nil)>>
  680. else put(car u,'kvalue,delete(x,y));
  681. if z then wtl!*:=delasc(u,wtl!*);
  682. return nil>>
  683. else if not (y := get(car u,'kvalue))
  684. then put!-kvalue(car u,nil,u,v)
  685. else <<if x := assoc(u,y)
  686. then <<updoldrules(u,v); y := delasc(car x,y)>>;
  687. put!-kvalue(car u,y,u,v)>>;
  688. return v
  689. end;
  690. % symbolic procedure put!-avalue(u,v,w);
  691. % if smember(u,w) then recursiveerror u
  692. % else put(u,'avalue,{v,w});
  693. symbolic procedure put!-avalue(u,v,w);
  694. % This definition allows for an assignment such as a := a 4.
  695. if v eq 'scalar
  696. then if eqcar(w,'!*sq) and sq_member(u,cadr w)
  697. then recursiveerror u
  698. else if !*reduce4 then putobject(u,w,'generic)
  699. else put(u,'avalue,{v,w})
  700. else if smember(u,w) then recursiveerror u
  701. else put(u,'avalue,{v,w});
  702. symbolic procedure sq_member(u,v);
  703. sf_member(u,numr v) or sf_member(u,denr v);
  704. symbolic procedure sf_member(u,v);
  705. null domainp v and
  706. (mvar_member(u,mvar v) or sf_member(u,lc v) or sf_member(u,red v));
  707. symbolic procedure mvar_member(u,v);
  708. % This and arglist member have to cater for the funny forms we
  709. % find in packages like TAYLOR.
  710. u = v or (null atom v and arglist_member(u,cdr v));
  711. symbolic procedure arglist_member(u,v);
  712. null atom v and (mvar_member(u,car v) or arglist_member(u,cdr v));
  713. % symbolic procedure put!-kvalue(u,v,w,x);
  714. % if smember(w,x) then recursiveerror w
  715. % else put(u,'kvalue,aconc(v,{w,x}));
  716. symbolic procedure put!-kvalue(u,v,w,x);
  717. % This definition is needed to allow p(2) := sqrt(1-p^2).
  718. if (if eqcar(x,'!*sq) then sq_member(w,cadr x) else smember(w,x))
  719. then recursiveerror w
  720. else put(u,'kvalue,aconc(v,{w,x}));
  721. symbolic procedure klistt u;
  722. if atom u then nil else caar u . klistt cdr carx(u,'list);
  723. symbolic procedure kernlp u;
  724. % Returns leading domain coefficient if U is a monomial product
  725. % of kernels, NIL otherwise.
  726. if domainp u then u else if null red u then kernlp lc u else nil;
  727. symbolic procedure xadd(u,v,b);
  728. % Adds replacement U to table V, with new rule at head.
  729. % Note that format of u and v depends on whether a free variable
  730. % occurs in the expression or asymplis* is being updated!!.
  731. begin scalar x;
  732. x := assoc(car u,v);
  733. if null x
  734. then if b and not(b eq 'replace) then v := u . v else nil
  735. else if b
  736. then <<v := delete(x,v);
  737. if not atom cdr x and length x=5
  738. then x := cdr x; % No free variable.
  739. if not atom cdr x % atom is asymplis update.
  740. then updoldrules(caddr x,cdadr x);
  741. if not(b eq 'replace) then v := u . v>>
  742. % else if cadr x=cadr u then v := delete(x,v);
  743. else if atom cdr x and cdr x=cdr u
  744. or not atom cdr x and cadr x=cadr u
  745. then v := delete(x,v);
  746. return v
  747. end;
  748. symbolic procedure updoldrules(v,w);
  749. (if null u then nil
  750. else oldrules!* := append(
  751. (if not atom v and numberp cdr v % asymptotic case.
  752. then list list(list('expt,car v,cdr v),0,nil,t)
  753. else if atom car u
  754. then list list(car u . car v,cadr v,nil,t)
  755. else (if car u neq y
  756. then list list(car u,y,x,rsubla(x,w))
  757. else nil) where y=rsubla(x,v)),
  758. oldrules!*)
  759. where x=caddr u)
  760. where u=newrule!*;
  761. symbolic procedure xadd!*(u,v,b);
  762. % Adds replacement U to table V, with new rule at head.
  763. % Also checks boolean part for equality.
  764. % Note, in an earlier version, we removed all rules in the CLEAR mode
  765. % regardless of whether they came from a LET or a MATCH, or had
  766. % boolean constraints. However, this made the fps tests not work.
  767. begin scalar x,y;
  768. x := v;
  769. % while x and not(car u=caar x and (cadr u=cadar x or null b))
  770. while x and not(car u=caar x and cadr u=cadar x)
  771. do x := cdr x;
  772. if x then <<v := delete(car x,v); x := car x;
  773. % If this section is entered, then car x and car
  774. % newrule!* should be the same. If not, a rule of the
  775. % form a+b => c might have occurred, in which case we
  776. % need to adjust the form of the replaced value.
  777. if b and newrule!*
  778. then if car x neq (y := car newrule!*)
  779. and powlisp car x
  780. then updoldrules(prepsq simp {'plus,y,
  781. {'difference,caddr x,'times .
  782. for each j in car x collect {'expt,car j,cdr j}}},
  783. cdadr x)
  784. else updoldrules(caddr x,cdadr x)>>;
  785. if b then v := u . v;
  786. return v
  787. end;
  788. symbolic procedure powlisp u;
  789. null u or not atom car u and numberp cdar u and powlisp cdr u;
  790. symbolic procedure rsubla(u,v);
  791. begin scalar x;
  792. if null u or null v then return v
  793. else if atom v
  794. then return if x:= rassoc(v,u) then car x else v
  795. else return(rsubla(u,car v) . rsubla(u,cdr v))
  796. end;
  797. endmodule;
  798. end;