alg2.red 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341
  1. %*********************************************************************
  2. %*********************************************************************
  3. % REDUCE BASIC ALGEBRAIC PROCESSOR (PART 2)
  4. %*********************************************************************
  5. %********************************************************************;
  6. %Copyright (c) 1983 The Rand Corporation;
  7. SYMBOLIC;
  8. COMMENT The following free variables are referenced in this module;
  9. FLUID '(!*MCD);
  10. GLOBAL '(ASYMPLIS!* FRLIS!* KORD!* MCHFG!* MCOND!* POWLIS!* POWLIS1!*
  11. SPLIS!* SUBFG!* TYPL!* VARNAM!* WTL!* !*FLOAT !*FORT !*MATCH
  12. !*NAT !*PRI !*RESUBS !*SUB2);
  13. %*********************************************************************
  14. %*********************************************************************
  15. % FUNCTIONS WHICH APPLY MORE GENERAL PATTERN MATCHING RULES
  16. %*********************************************************************
  17. %********************************************************************;
  18. %*********************************************************************
  19. % FUNCTIONS FOR MATCHING POWERS
  20. %********************************************************************;
  21. COMMENT Fluid variable used in this section;
  22. FLUID '(!*STRUCTURE);
  23. !*STRUCTURE := NIL;
  24. COMMENT If STRUCTURE is ON, then expressions like (a**(b/2))**2 are not
  25. simplified, to allow some attempt at a structure theorem use, especially
  26. in the integrator;
  27. SYMBOLIC PROCEDURE SUBS2Q U; QUOTSQ(SUBS2F NUMR U,SUBS2F DENR U);
  28. SYMBOLIC PROCEDURE SUBS2F U;
  29. BEGIN SCALAR X;
  30. !*SUB2 := NIL;
  31. X := SUBS2F1 U;
  32. IF (!*SUB2 OR POWLIS1!*) AND !*RESUBS
  33. THEN IF NUMR X=U AND DENR X=1 THEN !*SUB2 := NIL
  34. ELSE X := SUBS2Q X; RETURN X;
  35. END;
  36. SYMBOLIC PROCEDURE SUBS2F1 U;
  37. IF DOMAINP U THEN !*D2Q U
  38. ELSE BEGIN SCALAR KERN,V,W,X,Y,Z;
  39. KERN := MVAR U;
  40. Z := NIL ./ 1;
  41. A: IF NULL U OR DEGR(U,KERN)=0 THEN GO TO A1;
  42. Y := LT U .+ Y;
  43. U := RED U;
  44. GO TO A;
  45. A1: X := POWLIS!*;
  46. A2: IF NULL X THEN GO TO B
  47. ELSE IF CAAAR Y = CAAR X
  48. THEN <<W := SUBS2P(CAAR Y,CADAR X,CADDDR CAR X); GO TO E1>>
  49. % ELSE IF EQCAR(KERN,'SQRT) AND CADR KERN = CAAR X
  50. % THEN <<W := RADDSQ(SUBS2P(CADR KERN . CDAAR Y,
  51. % CADAR X,CADDDR CAR X),2);% GO TO E1>>;
  52. ELSE IF EQCAR(KERN,'EXPT)
  53. AND CADR KERN = CAAR X
  54. AND EQCAR(CADDR KERN,'QUOTIENT)
  55. AND CADR CADDR KERN = 1
  56. AND NUMBERP CADDR CADDR KERN
  57. THEN <<V := DIVIDE(CDAAR Y,CADDR CADDR KERN);
  58. IF CAR V NEQ 0 THEN W := MKSQ(CADR KERN,CAR V)
  59. ELSE W := 1 ./ 1;
  60. IF CDR V NEQ 0
  61. THEN <<V := CANCEL(CDR V.CADDR CADDR KERN);
  62. W := MULTSQ(RADDSQ(SUBS2P(CADR KERN . CAR V,
  63. CADAR X,CADDDR CAR X),
  64. CDR V),W)>>;
  65. GO TO E1>>;
  66. X := CDR X;
  67. GO TO A2;
  68. B: X := POWLIS1!*;
  69. L2: IF NULL X THEN GO TO L3
  70. ELSE IF W:= MTCHP(CAAR Y,CAAR X,CADDAR X,CAADAR X,CDADAR X)
  71. THEN GO TO E1;
  72. X := CDR X;
  73. GO TO L2;
  74. L3: IF EQCAR(KERN,'EXPT) AND NOT !*STRUCTURE THEN GO TO L1;
  75. Z := ADDSQ(MULTPQ(CAAR Y,SUBS2F1 CDAR Y),Z);
  76. C: Y := CDR Y;
  77. IF Y THEN GO TO A1;
  78. D: RETURN ADDSQ(Z,SUBS2F1 U);
  79. E1: Z := ADDSQ(MULTSQ(W,SUBS2F1 CDAR Y),Z);
  80. GO TO C;
  81. L1: IF ONEP CDAAR Y THEN W := MKSQ(KERN,1)
  82. ELSE W := SIMPEXPT LIST(CADR KERN,
  83. LIST('TIMES,CADDR KERN,CDAAR Y));
  84. Z := ADDSQ(MULTSQ(W,SUBS2F1 CDAR Y),Z);
  85. Y := CDR Y;
  86. IF Y THEN GO TO L1 ELSE GO TO D;
  87. END;
  88. SYMBOLIC PROCEDURE SUBS2P(U,V,W);
  89. %U is a power, V an integer, and W an algebraic expression, such
  90. %that CAR U**V=W. Value is standard quotient for U with this
  91. %substitution;
  92. BEGIN
  93. V := DIVIDE(CDR U,V);
  94. IF CAR V=0 THEN RETURN !*P2Q U;
  95. W := EXPTSQ(SIMP W,CAR V);
  96. RETURN IF CDR V=0 THEN W ELSE MULTPQ(CAR U TO CDR V,W)
  97. END;
  98. SYMBOLIC PROCEDURE RADDSQ(U,N);
  99. %U is a standard quotient, N and integer. Value is sq for U**(1/N);
  100. SIMPEXPT LIST(MK!*SQ U,LIST('QUOTIENT,1,N));
  101. SYMBOLIC PROCEDURE MTCHP(U,V,W,FLG,BOOL);
  102. %U is a standard power, V a power to be matched against.
  103. %W is the replacement expression.
  104. %FLG is a flag which is T if an exact power match required.
  105. %BOOL is a boolean expression to be satisfied for substitution.
  106. %Value is the substitution standard quotient if a match found,
  107. %NIL otherwise;
  108. BEGIN SCALAR X;
  109. X := MTCHP1(U,V,FLG,BOOL);
  110. A: IF NULL X THEN RETURN NIL
  111. ELSE IF EVAL SUBLA(CAR X,BOOL) THEN GO TO B;
  112. X := CDR X;
  113. GO TO A;
  114. B: V := DIVIDE(CDR U,SUBLA(CAR X,CDR V));
  115. W := EXPTSQ(SIMP SUBLA(CAR X,W),CAR V);
  116. IF CDR V NEQ 0 THEN W := MULTPQ(CAR U TO CDR V,W);
  117. RETURN W
  118. END;
  119. SYMBOLIC PROCEDURE MTCHP1(U,V,FLG,BOOL);
  120. %U is a standard power, V a power to be matched against.
  121. %FLG is a flag which is T if an exact power match required.
  122. %BOOL is a boolean expression to be satisfied for substitution.
  123. %Value is a list of possible free variable pairings which
  124. %match conditions;
  125. BEGIN SCALAR X;
  126. IF U=V THEN RETURN LIST NIL
  127. ELSE IF NOT (X:= MCHK(CAR U,CAR V)) THEN RETURN NIL
  128. ELSE IF CDR V MEMQ FRLIS!*
  129. THEN RETURN MAPCONS(X,CDR V . CDR U)
  130. ELSE IF (FLG AND NOT CDR U=CDR V)
  131. OR (IF !*MCD THEN CDR U<CDR V
  132. ELSE (CDR U*CDR V)<0 OR
  133. %implements explicit sign matching;
  134. ABS CDR U<ABS CDR V)
  135. THEN RETURN NIL
  136. ELSE RETURN X
  137. END;
  138. %*********************************************************************
  139. % FUNCTIONS FOR MATCHING PRODUCTS
  140. %********************************************************************;
  141. SYMBOLIC PROCEDURE SUBS3Q U;
  142. %U is a standard quotient.
  143. %Value is a standard quotient with all product substitutions made;
  144. BEGIN SCALAR X;
  145. X := MCHFG!*; %save value in case we are in inner loop;
  146. MCHFG!* := NIL;
  147. U := QUOTSQ(SUBS3F NUMR U,SUBS3F DENR U);
  148. MCHFG!* := X;
  149. RETURN U
  150. END;
  151. SYMBOLIC PROCEDURE SUBS3F U;
  152. %U is a standard form.
  153. %Value is a standard quotient with all product substitutions made;
  154. SUBS3F1(U,!*MATCH,T);
  155. SYMBOLIC PROCEDURE SUBS3F1(U,L,BOOL);
  156. %U is a standard form.
  157. %L is a list of possible matches.
  158. %BOOL is a boolean variable which is true if we are at top level.
  159. %Value is a standard quotient with all product substitutions made;
  160. BEGIN SCALAR X,Z;
  161. Z := NIL ./ 1;
  162. A: IF NULL U THEN RETURN Z
  163. ELSE IF DOMAINP U THEN RETURN ADDSQ(Z,U ./ 1)
  164. ELSE IF BOOL AND DOMAINP LC U THEN GO TO C;
  165. X := SUBS3T(LT U,L);
  166. IF NOT BOOL %not top level;
  167. OR NOT MCHFG!* THEN GO TO B; %no replacement made;
  168. MCHFG!* := NIL;
  169. IF NULL !*RESUBS THEN GO TO B
  170. ELSE IF !*SUB2 OR POWLIS1!* THEN X := SUBS2Q X;
  171. %make another pass;
  172. X := SUBS3Q X;
  173. B: Z := ADDSQ(Z,X);
  174. U := CDR U;
  175. GO TO A;
  176. C: X := LIST LT U ./ 1;
  177. GO TO B
  178. END;
  179. SYMBOLIC PROCEDURE SUBS3T(U,V);
  180. %U is a standard term, V a list of matching templates.
  181. %Value is a standard quotient for the substituted term;
  182. BEGIN SCALAR X,Y,Z;
  183. X := MTCHK(CAR U,IF DOMAINP CDR U THEN SIZCHK(V,1) ELSE V);
  184. IF NULL X THEN GO TO A %lpow doesn't match;
  185. ELSE IF NULL CAAR X THEN GO TO B; %complete match found;
  186. Y := SUBS3F1(CDR U,X,NIL); %check tc for match;
  187. IF MCHFG!* THEN RETURN MULTPQ(CAR U,Y);
  188. A: RETURN LIST U . 1; %no match;
  189. B: X := CDDAR X; %list(<subst value>,<denoms>);
  190. Z := CAADR X; %leading denom;
  191. MCHFG!* := NIL; %initialize for tc check;
  192. Y := SUBS3F1(CDR U,!*MATCH,NIL);
  193. MCHFG!* := T;
  194. IF CAR Z NEQ CAAR U THEN GO TO E
  195. ELSE IF Z NEQ CAR U %powers don't match;
  196. THEN Y := MULTPQ(CAAR U TO (CDAR U-CDR Z),Y);
  197. B1: Y := MULTSQ(SIMPCAR X,Y);
  198. X := CDADR X;
  199. IF NULL X THEN RETURN Y;
  200. Z := 1; %unwind remaining denoms;
  201. C: IF NULL X THEN GO TO D;
  202. Z:=LIST(MKSP(CAAR X,
  203. %was IF ATOM CAAR X OR SFP CAAR X THEN CAAR X ELSE REVOP1 CAAR X;
  204. IF !*MCD THEN CDAR X ELSE -CDAR X) . Z);
  205. %kernel CAAR X is not unique here;
  206. X := CDR X;
  207. GO TO C;
  208. D: RETURN IF !*MCD THEN CAR Y . MULTF(Z,CDR Y)
  209. ELSE MULTF(Z,CAR Y) . CDR Y;
  210. E: IF SIMP CAR Z NEQ SIMP CAAR U THEN ERRACH LIST('SUBS3T,U,X,Z);
  211. %maybe arguments were in different order, otherwise it's fatal;
  212. IF CDR Z NEQ CDAR U
  213. THEN Y:= MULTPQ(CAAR U TO (CDAR U-CDR Z),Y);
  214. GO TO B1
  215. END;
  216. SYMBOLIC PROCEDURE SIZCHK(U,N);
  217. IF NULL U THEN NIL
  218. ELSE IF LENGTH CAAR U>N THEN SIZCHK(CDR U,N)
  219. ELSE CAR U . SIZCHK(CDR U,N);
  220. SYMBOLIC PROCEDURE MTCHK(U,V);
  221. %U is a standard power, V a list of matching templates.
  222. %If a match is made, value is of the form:
  223. %list list(NIL,<boolean form>,<subst value>,<denoms>),
  224. %otherwise value is an updated list of templates;
  225. BEGIN SCALAR FLG,V1,W,X,Y,Z;
  226. FLG := NONCOMP CAR U;
  227. A0: IF NULL V THEN RETURN Z;
  228. V1 := CAR V;
  229. W := CAR V1;
  230. A: IF NULL W THEN GO TO D;
  231. X := MTCHP1(U,CAR W,CAADR V1,CDADR V1);
  232. B: IF NULL X THEN GO TO C
  233. ELSE IF CAR (Y := SUBLA(CAR X,DELETE(CAR W,CAR V1))
  234. . LIST(SUBLA(CAR X,CADR V1),
  235. SUBLA(CAR X,CADDR V1),
  236. SUBLA(CAR X,CAR W)
  237. . CADDDR V1))
  238. THEN Z := Y . Z
  239. ELSE IF EVAL SUBLA(CAR X,CDADR V1) THEN RETURN LIST Y;
  240. X := CDR X;
  241. GO TO B;
  242. C: IF FLG THEN GO TO C1;
  243. W := CDR W;
  244. GO TO A;
  245. C1: IF CADDDR V1 AND NOT NOCP CADDDR V1 THEN GO TO E;
  246. D: Z := APPEND(Z,LIST V1);
  247. E: V := CDR V;
  248. GO TO A0
  249. END;
  250. SYMBOLIC PROCEDURE NOCP U;
  251. NULL U OR (NONCOMP CAAR U AND NOCP CDR U);
  252. %*********************************************************************
  253. % FUNCTIONS FOR MATCHING SUMS
  254. %********************************************************************;
  255. SYMBOLIC PROCEDURE SUBS4Q U;
  256. QUOTSQ(SUBS4F NUMR U,SUBS4F DENR U);
  257. SYMBOLIC PROCEDURE SUBS4F U;
  258. BEGIN SCALAR W,X,Y,Z;
  259. X := SPLIS!*;
  260. A: IF NULL X THEN RETURN U ./ 1;
  261. W := LQREMF!*(U,CAAR X);
  262. IF NULL CDR W THEN <<X := CDR X; GO TO A>>;
  263. X := SIMP CADDAR X;
  264. Y := 1 ./ 1;
  265. Z := NIL ./ 1;
  266. WHILE W DO
  267. <<IF CAR W THEN Z := ADDSQ(MULTSQ(CAR W ./ 1,Y),Z);
  268. Y := MULTSQ(X,Y);
  269. W := CDR W>>;
  270. RETURN IF DENR Z=1 AND NUMR Z=U THEN U ./ 1 ELSE SUBS4Q Z;
  271. %one could test on size here and only change if smaller;
  272. END;
  273. SYMBOLIC PROCEDURE LQREMF!*(U,V);
  274. IF DOMAINP U THEN LIST U ELSE LQREMF(U,REORDER V);
  275. %*********************************************************************
  276. %*********************************************************************
  277. % EXTENDED OUTPUT PACKAGE FOR EXPRESSIONS
  278. %*********************************************************************
  279. %********************************************************************;
  280. %Global variables used in this Section;
  281. GLOBAL '(DNL!* FACTORS!* ORDL!* UPL!* !*ALLFAC !*DIV !*RAT);
  282. DNL!* := NIL; %output control flag: puts powers in denom;
  283. FACTORS!* := NIL; %list of output factors;
  284. ORDL!* := NIL; %list of kernels introduced by ORDER statement;
  285. UPL!* := NIL; %output control flag: puts denom powers in
  286. %numerator;
  287. !*ALLFAC := T; %factoring option for this package;
  288. !*DIV := NIL; %division option in this package;
  289. !*RAT := NIL; %flag indicating rational mode for output;
  290. !*PRI := T; %to activate this package;
  291. SYMBOLIC PROCEDURE FACTOR U;
  292. FACTOR1(U,T,'FACTORS!*);
  293. SYMBOLIC PROCEDURE FACTOR1(U,V,W);
  294. BEGIN SCALAR X,Y;
  295. Y := EVAL W;
  296. FOR EACH J IN U DO
  297. <<X := !*A2K J;
  298. IF V THEN Y := ACONC(DELETE(X,Y),X)
  299. ELSE IF NOT X MEMBER Y
  300. THEN MSGPRI(NIL,J,"not found",NIL,NIL)
  301. ELSE Y := DELETE(X,Y)>>;
  302. SET(W,Y)
  303. END;
  304. SYMBOLIC PROCEDURE REMFAC U;
  305. FACTOR1(U,NIL,'FACTORS!*);
  306. RLISTAT '(FACTOR REMFAC);
  307. SYMBOLIC PROCEDURE ORDER U;
  308. IF U AND NULL CAR U AND NULL CDR U THEN (ORDL!* := NIL)
  309. ELSE FOR EACH X IN U DO
  310. <<IF (X := !*A2K X) MEMBER ORDL!* THEN ORDL!* := DELETE(X,ORDL!*);
  311. ORDL!* := ACONC(ORDL!*,X)>>;
  312. RLISTAT '(ORDER);
  313. SYMBOLIC PROCEDURE UP U;
  314. FACTOR1(U,T,'UPL!*);
  315. SYMBOLIC PROCEDURE DOWN U;
  316. FACTOR1(U,T,'DNL!*);
  317. RLISTAT '(UP DOWN);
  318. SYMBOLIC PROCEDURE FORMOP U;
  319. IF DOMAINP U THEN U
  320. ELSE RADDF(MULTOP(LPOW U,FORMOP LC U),FORMOP RED U);
  321. SYMBOLIC PROCEDURE MULTOP(U,V);
  322. IF NULL KORD!* THEN MULTPF(U,V)
  323. ELSE IF CAR U EQ 'K!* THEN V
  324. ELSE RMULTPF(U,V);
  325. SYMBOLIC SMACRO PROCEDURE LCX U;
  326. %returns leading coefficient of a form with zero reductum, or an
  327. %error otherwise;
  328. CDR CARX U;
  329. SYMBOLIC PROCEDURE QUOTOF(P,Q);
  330. %P is a standard form, Q a standard form which is either a domain
  331. %element or has zero reductum.
  332. %returns the quotient of P and Q for output purposes;
  333. IF NULL P THEN NIL
  334. ELSE IF P=Q THEN 1
  335. ELSE IF Q=1 THEN P
  336. ELSE IF DOMAINP Q THEN QUOTOFD(P,Q)
  337. ELSE IF DOMAINP P
  338. THEN MKSP(MVAR Q,-LDEG Q) .* QUOTOF(P,LCX Q) .+ NIL
  339. ELSE (LAMBDA (X,Y);
  340. IF CAR X EQ CAR Y
  341. THEN (LAMBDA (N,W,Z);
  342. IF N=0 THEN RADDF(W,Z)
  343. ELSE ((CAR Y TO N) .* W) .+ Z)
  344. (CDR X-CDR Y,QUOTOF(LC P,LCX Q),QUOTOF(RED P,Q))
  345. ELSE IF ORDOP(CAR X,CAR Y)
  346. THEN (X .* QUOTOF(LC P,Q)) .+ QUOTOF(RED P,Q)
  347. ELSE MKSP(CAR Y,- CDR Y) .* QUOTOF(P,LCX Q) .+ NIL)
  348. (LPOW P,LPOW Q);
  349. SYMBOLIC PROCEDURE QUOTOFD(P,Q);
  350. %P is a form, Q a domain element. Value is quotient of P and Q
  351. %for output purposes;
  352. IF NULL P THEN NIL
  353. ELSE IF DOMAINP P THEN QUOTODD(P,Q)
  354. ELSE (LPOW P .* QUOTOFD(LC P,Q)) .+ QUOTOFD(RED P,Q);
  355. SYMBOLIC PROCEDURE QUOTODD(P,Q);
  356. %P and Q are domain elements. Value is domain element for P/Q;
  357. IF ATOM P AND ATOM Q THEN MKRN(P,Q) ELSE LOWEST!-TERMS(P,Q);
  358. SYMBOLIC PROCEDURE LOWEST!-TERMS(U,V);
  359. %reduces compatible domain elements U and V to a ratio in lowest
  360. %terms. Value as a rational may contain domain arguments rather than
  361. %just integers;
  362. IF FLAGP(CAR V,'FIELD) OR FLAGP(CAR U,'FIELD)
  363. THEN MULTDM(U,!:EXPT(V,-1))
  364. ELSE BEGIN SCALAR X;
  365. X := DCOMBINE(U,V,'GCD);
  366. U := DCOMBINE(U,X,'QUOTIENT);
  367. V := DCOMBINE(V,X,'QUOTIENT);
  368. RETURN IF !:ONEP V THEN U ELSE '!:RN!: . (U . V)
  369. END;
  370. SYMBOLIC PROCEDURE CKRN U;
  371. BEGIN SCALAR X;
  372. IF DOMAINP U THEN RETURN U;
  373. A: X := GCK2(CKRN CDAR U,X);
  374. IF NULL CDR U
  375. THEN RETURN IF NONCOMP MVAR U THEN X ELSE LIST(CAAR U . X)
  376. ELSE IF DOMAINP CDR U OR NOT CAAAR U EQ CAAADR U
  377. THEN RETURN GCK2(CKRN CDR U,X);
  378. U := CDR U;
  379. GO TO A
  380. END;
  381. SYMBOLIC PROCEDURE GCK2(U,V);
  382. %U and V are domain elements or forms with a zero reductum.
  383. %Value is the gcd of U and V;
  384. IF NULL V THEN U
  385. ELSE IF U=V THEN U
  386. ELSE IF DOMAINP U THEN IF DOMAINP V THEN GCDDD(U,V)
  387. ELSE GCK2(U,CDARX V)
  388. ELSE IF DOMAINP V THEN GCK2(CDARX U,V)
  389. ELSE (LAMBDA (X,Y);
  390. IF CAR X EQ CAR Y
  391. THEN LIST((IF CDR X>CDR Y THEN Y ELSE X) .
  392. GCK2(CDARX U,CDARX V))
  393. ELSE IF ORDOP(CAR X,CAR Y) THEN GCK2(CDARX U,V)
  394. ELSE GCK2(U,CDARX V))
  395. (CAAR U,CAAR V);
  396. SYMBOLIC PROCEDURE CDARX U;
  397. CDR CARX U;
  398. SYMBOLIC PROCEDURE PREPSQ!* U;
  399. BEGIN SCALAR X;
  400. IF NULL NUMR U THEN RETURN 0;
  401. X := KORD!*;
  402. KORD!* := APPEND((FOR EACH J IN FACTORS!*
  403. CONC IF NOT IDP J THEN NIL
  404. ELSE FOR EACH K IN GET(J,'KLIST)
  405. COLLECT CAR K),
  406. APPEND(FACTORS!*,ORDL!*));
  407. IF KORD!* NEQ X OR WTL!*
  408. THEN U := FORMOP NUMR U . FORMOP DENR U;
  409. U := IF !*RAT OR (NOT !*FLOAT AND !*DIV) OR UPL!* OR DNL!*
  410. THEN REPLUS PREPSQ!*1(NUMR U,DENR U,NIL)
  411. ELSE SQFORM(U,FUNCTION(LAMBDA J;
  412. REPLUS PREPSQ!*1(J,1,NIL)));
  413. KORD!* := X;
  414. RETURN U
  415. END;
  416. SYMBOLIC PROCEDURE PREPSQ!*0(U,V);
  417. %U is a standard quotient, but not necessarily in lowest terms.
  418. %V a list of factored powers;
  419. %Value is equivalent list of prefix expressions (an implicit sum);
  420. BEGIN SCALAR X;
  421. RETURN IF NULL NUMR U THEN NIL
  422. ELSE IF (X := GCDF(NUMR U,DENR U)) NEQ 1
  423. THEN PREPSQ!*1(QUOTF(NUMR U,X),QUOTF(DENR U,X),V)
  424. ELSE PREPSQ!*1(NUMR U,DENR U,V)
  425. END;
  426. SYMBOLIC PROCEDURE PREPSQ!*1(U,V,W);
  427. %U and V are the numerator and denominator expression resp,
  428. %in lowest terms.
  429. %W is a list of powers to be factored from U;
  430. BEGIN SCALAR X,Y,Z;
  431. %look for "factors" in the numerator;
  432. IF NOT DOMAINP U AND (MVAR U MEMBER FACTORS!* OR (NOT
  433. ATOM MVAR U AND CAR MVAR U MEMBER FACTORS!*))
  434. THEN RETURN NCONC(IF V=1 THEN PREPSQ!*0(LC U ./ V,LPOW U . W)
  435. ELSE (BEGIN SCALAR N,V1,Z1;
  436. %see if the same "factor" appears in denominator;
  437. N := LDEG U;
  438. V1 := V;
  439. Z1 := !*K2F MVAR U;
  440. WHILE (Z := QUOTF(V1,Z1))
  441. DO <<V1 := Z; N := N-1>>;
  442. RETURN
  443. PREPSQ!*0(LC U ./ V1,
  444. IF N>0 THEN (MVAR U .** N) . W
  445. ELSE IF N<0
  446. THEN MKSP(LIST('EXPT,MVAR U,N),1) . W
  447. ELSE W)
  448. END),
  449. PREPSQ!*0(RED U ./ V,W));
  450. %now see if there are any remaining "factors" in denominator
  451. %(KORD!* contains all potential kernel factors);
  452. IF NOT DOMAINP V
  453. THEN FOR EACH J IN KORD!* DO
  454. BEGIN INTEGER N; SCALAR Z1;
  455. N := 0;
  456. Z1 := !*K2F J;
  457. WHILE Z := QUOTF(V,Z1) DO <<N := N-1; V := Z>>;
  458. IF N<0 THEN W := MKSP(LIST('EXPT,J,N),1) . W
  459. END;
  460. %now all "factors" have been removed;
  461. IF KERNLP U THEN <<U := MKKL(W,U); W := NIL>>;
  462. IF DNL!*
  463. THEN <<X := IF NULL !*ALLFAC THEN 1 ELSE CKRN U;
  464. Z := CKRN!*(X,DNL!*);
  465. X := QUOTOF(X,Z);
  466. U := QUOTOF(U,Z);
  467. V := QUOTOF(V,Z)>>;
  468. Y := CKRN V;
  469. IF UPL!*
  470. THEN <<Z := CKRN!*(Y,UPL!*);
  471. Y := QUOTOF(Y,Z);
  472. U := QUOTOF(U,Z);
  473. V := QUOTOF(V,Z)>>;
  474. IF NULL !*DIV AND NULL !*FLOAT THEN Y := 1;
  475. U := CANONSQ (U . QUOTOF(V,Y));
  476. % IF !*GCD THEN U := CANCEL U;
  477. U := QUOTOF(NUMR U,Y) ./ DENR U;
  478. IF NULL !*ALLFAC THEN X := 1 ELSE X := CKRN NUMR U;
  479. IF !*ALLFAC AND X NEQ CAR U THEN GO TO B
  480. ELSE IF W THEN <<W := EXCHK(W,NIL,NIL); GO TO C>>;
  481. D: U := PREPSQ U;
  482. RETURN IF EQCAR(U,'PLUS) THEN CDR U ELSE LIST U;
  483. B: IF ONEP X AND NULL W THEN GO TO D
  484. ELSE IF !*FLOAT THEN X := QUOTOF(X,KERNLP X);
  485. U := QUOTOF(NUMR U,X) . DENR U;
  486. W := PREPF MKKL(W,X);
  487. IF U = (1 ./ 1) THEN RETURN W
  488. ELSE IF EQCAR(W,'TIMES) THEN W := CDR W
  489. ELSE W := LIST W;
  490. C: RETURN LIST RETIMES ACONC(W,PREPSQ U)
  491. END;
  492. SYMBOLIC PROCEDURE MKKL(U,V);
  493. IF NULL U THEN V ELSE MKKL(CDR U,LIST (CAR U . V));
  494. SYMBOLIC PROCEDURE CKRN!*(U,V);
  495. IF NULL U THEN ERRACH 'CKRN!*
  496. ELSE IF DOMAINP U THEN 1
  497. ELSE IF CAAAR U MEMBER V
  498. THEN LIST (CAAR U . CKRN!*(CDR CARX U,V))
  499. ELSE CKRN!*(CDR CARX U,V);
  500. COMMENT Procedures for printing the structure of expressions;
  501. FLUID '(COUNTR VAR VARLIS);
  502. SYMBOLIC PROCEDURE STRUCTR U;
  503. BEGIN SCALAR COUNTR,FVAR,VAR,VARLIS;
  504. %VARLIS is a list of elements of form:
  505. %(<unreplaced expression> . <newvar> . <replaced exp>);
  506. COUNTR :=0;
  507. FVAR := VAR := VARNAM!*;
  508. IF CDR U THEN FVAR := CADR U;
  509. U := SIMPCAR U;
  510. U := STRUCTF NUMR U./ STRUCTF DENR U;
  511. IF NULL !*FORT THEN MATHPRINT MK!*SQ U;
  512. IF COUNTR=0 AND NULL !*FORT THEN RETURN NIL;
  513. IF NULL !*FORT THEN <<IF NULL !*NAT THEN TERPRI();
  514. PRIN2T " WHERE">>
  515. ELSE VARLIS := REVERSIP VARLIS;
  516. FOR EACH X IN VARLIS DO
  517. <<TERPRI!* T;
  518. IF NULL !*FORT THEN PRIN2!* " ";
  519. VARPRI(CDDR X,LIST MKQUOTE CADR X,T)>>;
  520. IF !*FORT THEN VARPRI(MK!*SQ U,LIST MKQUOTE FVAR,T)
  521. END;
  522. RLISTAT '(STRUCTR);
  523. SYMBOLIC PROCEDURE STRUCTF U;
  524. IF NULL U THEN NIL
  525. ELSE IF DOMAINP U THEN U
  526. ELSE BEGIN SCALAR X,Y;
  527. X := MVAR U;
  528. IF SFP X THEN IF Y := ASSOC(X,VARLIS) THEN X := CADR Y
  529. ELSE X := STRUCTK(PREPSQ!*(STRUCTF X ./ 1),GENVAR(),X)
  530. ELSE IF NOT ATOM X AND NOT ATOMLIS CDR X
  531. THEN IF Y := ASSOC(X,VARLIS) THEN X := CADR Y
  532. ELSE X := STRUCTK(X,GENVAR(),X);
  533. RETURN X .** LDEG U .* STRUCTF LC U .+ STRUCTF RED U
  534. END;
  535. SYMBOLIC PROCEDURE STRUCTK(U,ID,V);
  536. BEGIN SCALAR X;
  537. IF X := SUBCHK1(U,VARLIS,ID)
  538. THEN RPLACD(X,(V . ID . U) . CDR X)
  539. ELSE IF X := SUBCHK2(U,VARLIS)
  540. THEN VARLIS := (V . ID . X) . VARLIS
  541. ELSE VARLIS := (V . ID . U) . VARLIS;
  542. RETURN ID
  543. END;
  544. SYMBOLIC PROCEDURE SUBCHK1(U,V,ID);
  545. BEGIN SCALAR W;
  546. WHILE V DO
  547. <<SMEMBER(U,CDDAR V)
  548. AND <<W := V; RPLACD(CDAR V,SUBST(ID,U,CDDAR V))>>;
  549. V := CDR V>>;
  550. RETURN W
  551. END;
  552. SYMBOLIC PROCEDURE SUBCHK2(U,V);
  553. BEGIN SCALAR BOOL;
  554. FOR EACH X IN V DO
  555. SMEMBER(CDDR X,U)
  556. AND <<BOOL := T; U := SUBST(CADR X,CDDR X,U)>>;
  557. IF BOOL THEN RETURN U ELSE RETURN NIL
  558. END;
  559. UNFLUID '(COUNTR VAR VARLIS);
  560. %*********************************************************************
  561. %*********************************************************************
  562. % COEFF OPERATOR PACKAGE
  563. %*********************************************************************
  564. %********************************************************************;
  565. %*********************************************************************
  566. % REQUIRES EXTENDED OUTPUT PACKAGE
  567. %********************************************************************;
  568. FLAG ('(HIPOW!* LOWPOW!*),'SHARE);
  569. GLOBAL '(HIPOW!* LOWPOW!*);
  570. SYMBOLIC PROCEDURE COEFF(U,V,W);
  571. BEGIN SCALAR X,Y,Z;
  572. V := !*A2K V;
  573. IF ATOM W THEN (IF NOT ARRAYP W
  574. THEN (IF NUMBERP(W := REVAL W) THEN TYPERR(W,'ID)))
  575. ELSE IF NOT ARRAYP CAR W THEN TYPERR(CAR W,'array)
  576. ELSE W := CAR W . FOR EACH X IN CDR W
  577. COLLECT IF X EQ 'TIMES THEN X ELSE REVAL X;
  578. U := !*Q2F SIMP!* U;
  579. X := SETKORDER LIST V;
  580. Y := REORDER U;
  581. SETKORDER X;
  582. IF NULL Y THEN GO TO B0;
  583. WHILE NOT DOMAINP Y AND MVAR Y=V
  584. DO <<Z := (LDEG Y . MK!*SQ1 CANCEL (LC Y ./ 1)) . Z;
  585. Y := RED Y>>;
  586. B: IF NULL Y THEN GO TO B1;
  587. B0: Z := (0 . MK!*SQ1 CANCEL (Y ./ 1)) . Z;
  588. B1: LOWPOW!* := CAAR Z;
  589. IF (NOT ATOM W AND ATOM CAR W
  590. AND (Y := DIMENSION CAR W))
  591. OR ((Y := DIMENSION W) AND NULL CDR Y)
  592. THEN GO TO G;
  593. Y := EXPLODE W;
  594. W := NIL;
  595. C: W := INTERN COMPRESS APPEND(Y,EXPLODE CAAR Z) . W;
  596. SETK1(CAR W,CDAR Z,T);
  597. IF NULL CDR Z THEN GO TO D;
  598. Z := CDR Z;
  599. GO TO C;
  600. D: HIPOW!* := CAAR Z;
  601. LPRIM ACONC(W,"are non zero");
  602. E: RETURN HIPOW!*;
  603. G: Z := REVERSE Z;
  604. IF ATOM W
  605. THEN <<IF CAAR Z NEQ (CAR Y-1)
  606. THEN <<Y := LIST(CAAR Z+1);
  607. PUT(W,'ARRAY,MKARRAY Y);
  608. PUT(W,'DIMENSION,Y)>>;
  609. W := LIST(W,'TIMES)>>;
  610. HIPOW!* := CAAR Z;
  611. Y := PAIR(CDR W,Y);
  612. G0: WHILE NOT SMEMQ('TIMES,CAAR Y) DO Y := CDR Y;
  613. Y := CDAR Y-REVAL SUBST(0,'TIMES,CAAR Y)-1;
  614. %-1 needed since DIMENSION gives length, not highest index;
  615. IF CAAR Z>Y
  616. THEN REDERR LIST("Index",CAAR Z,"out of range");
  617. H: IF NULL Z OR Y NEQ CAAR Z
  618. THEN SETELV(SUBST(Y,'TIMES,W),0)
  619. ELSE <<SETELV(SUBST(Y,'TIMES,W),CDAR Z); Z := CDR Z>>;
  620. IF Y=0 THEN GO TO E;
  621. Y := Y-1;
  622. GO TO H
  623. END;
  624. SYMBOLIC PROCEDURE MK!*SQ1 U;
  625. IF WTL!* THEN PREPSQ U ELSE MK!*SQ U;
  626. FLAG ('(COEFF),'OPFN);
  627. FLAG ('(COEFF),'NOVAL);
  628. %*********************************************************************
  629. %*********************************************************************
  630. % ASYMPTOTIC COMMAND PACKAGE
  631. %********************************************************************;
  632. %********************************************************************;
  633. SYMBOLIC PROCEDURE WEIGHT U;
  634. BEGIN SCALAR Y,Z;
  635. RMSUBS();
  636. FOR EACH X IN U DO
  637. IF NOT EQEXPR X THEN ERRPRI2(X,'HOLD)
  638. ELSE <<Y := !*A2K CADR X;
  639. Z := REVAL CADDR X;
  640. IF NOT (NUMBERP Z AND FIXP Z AND Z>0)
  641. THEN TYPERR(Z,"weight");
  642. WTL!* := (Y . Z) . DELASC(Y,WTL!*)>>
  643. END;
  644. SYMBOLIC PROCEDURE WTLEVEL U;
  645. BEGIN INTEGER N; SCALAR X;
  646. N := REVAL CAR U;
  647. IF NOT(NUMBERP N AND FIXP N AND NOT N<0)
  648. THEN ERRPRI2(N,'HOLD);
  649. N := N+1;
  650. X := ATSOC('K!*,ASYMPLIS!*);
  651. IF N=CDR X THEN RETURN NIL ELSE IF N<=CDR X THEN RMSUBS2();
  652. RMSUBS1();
  653. RPLACD(X,N)
  654. END;
  655. RLISTAT '(WEIGHT WTLEVEL);
  656. ALGEBRAIC LET K!***2=0;
  657. %*********************************************************************
  658. %*********************************************************************
  659. % LINEAR OPERATOR PACKAGE
  660. %*********************************************************************
  661. %********************************************************************;
  662. %Global variables referenced in this Section;
  663. GLOBAL '(DEPL!*); %list of dependencies among kernels;
  664. %*********************************************************************
  665. % FUNCTIONS FOR DEFINING AND CHECKING EXPRESSION DEPENDENCY
  666. %********************************************************************;
  667. SYMBOLIC PROCEDURE DEPEND U;
  668. FOR EACH X IN CDR U DO DEPEND1(CAR U,X,T);
  669. SYMBOLIC PROCEDURE NODEPEND U;
  670. <<RMSUBS(); FOR EACH X IN CDR U DO DEPEND1(CAR U,X,NIL)>>;
  671. RLISTAT '(DEPEND NODEPEND);
  672. SYMBOLIC PROCEDURE DEPEND1(U,V,BOOL);
  673. BEGIN SCALAR Y,Z;
  674. U := !*A2K U;
  675. V := !*A2K V;
  676. IF U EQ V THEN RETURN NIL;
  677. Y := ASSOC(U,DEPL!*);
  678. IF Y THEN IF BOOL THEN RPLACD(Y,UNION(LIST V,CDR Y))
  679. ELSE IF (Z := DELETE(V,CDR Y)) THEN RPLACD(Y,Z)
  680. ELSE DEPL!* := DELETE(Y,DEPL!*)
  681. ELSE IF NULL BOOL
  682. THEN LPRIM LIST(U,"has no prior dependence on",V)
  683. ELSE DEPL!* := LIST(U,V) . DEPL!*
  684. END;
  685. SYMBOLIC PROCEDURE DEPENDS(U,V);
  686. IF NULL U OR NUMBERP U OR NUMBERP V THEN NIL
  687. ELSE IF U=V THEN U
  688. ELSE IF ATOM U AND U MEMQ FRLIS!* THEN T
  689. %to allow the most general pattern matching to occur;
  690. ELSE IF (LAMBDA X; X AND LDEPENDS(CDR X,V)) ASSOC(U,DEPL!*)
  691. THEN T
  692. ELSE IF NOT ATOM U
  693. AND (LDEPENDS(CDR U,V) OR DEPENDS(CAR U,V)) THEN T
  694. ELSE IF ATOM V THEN NIL
  695. ELSE DEPENDSL(U,CDR V);
  696. SYMBOLIC PROCEDURE LDEPENDS(U,V);
  697. U AND (DEPENDS(CAR U,V) OR LDEPENDS(CDR U,V));
  698. SYMBOLIC PROCEDURE DEPENDSL(U,V);
  699. V AND (DEPENDS(U,CAR V) OR DEPENDSL(U,CDR V));
  700. SYMBOLIC PROCEDURE FREEOF(U,V);
  701. NOT(SMEMBER(V,U) OR V MEMBER ASSOC(U,DEPL!*));
  702. FLAG('(FREEOF),'BOOLEAN);
  703. INFIX FREEOF;
  704. PRECEDENCE FREEOF,LESSP; %put it above all boolean operators;
  705. %*********************************************************************
  706. % FUNCTIONS FOR SIMPLIFYING LINEAR OPERATORS
  707. %********************************************************************;
  708. SYMBOLIC PROCEDURE LINEAR U;
  709. FOR EACH X IN U DO
  710. <<IF NOT IDP X THEN TYPERR(X,'operator); FLAG(LIST X,'LINEAR);
  711. MKOP X>>;
  712. RLISTAT '(LINEAR);
  713. PUT('LINEAR,'SIMPFG,'((RMSUBS)));
  714. SYMBOLIC PROCEDURE FORMLNR U;
  715. (LAMBDA (X,Y,Z);
  716. IF Y = 1 THEN U
  717. ELSE IF NOT DEPENDS(Y,CAR Z)
  718. THEN LIST('TIMES,Y,X . 1 . Z)
  719. ELSE IF ATOM Y THEN U
  720. ELSE IF CAR Y EQ 'PLUS
  721. THEN 'PLUS . FOR EACH J IN CDR Y COLLECT FORMLNR(X . J. Z)
  722. ELSE IF CAR Y EQ 'MINUS
  723. THEN LIST('MINUS,FORMLNR(X . CADR Y . Z))
  724. ELSE IF CAR Y EQ 'DIFFERENCE
  725. THEN LIST('DIFFERENCE,FORMLNR(X . CADR Y . Z),
  726. FORMLNR(X . CADDR Y . Z))
  727. ELSE IF CAR Y EQ 'TIMES THEN FORMLNTMS(X,CDR Y,Z,U)
  728. ELSE IF CAR Y EQ 'QUOTIENT THEN FORMLNQUOT(X,CDR Y,Z,U)
  729. ELSE IF CAR Y EQ 'RECIP AND NOT DEPENDS(CADR Y,CAR Z)
  730. THEN LIST('QUOTIENT,X . 1 . Z,CADR Y)
  731. ELSE (LAMBDA V; IF V THEN LIST('TIMES,CAR V,X . CDR V . Z) ELSE U)
  732. EXPT!-SEPARATE(Y,CAR Z))
  733. (CAR U,CADR U,!*A2K CADDR U . CDDDR U);
  734. SYMBOLIC PROCEDURE FORMSEPARATE(U,V);
  735. %separates U into two parts, and returns a dotted pair of them: those
  736. %which are not commutative and do not depend on V, and the remainder;
  737. BEGIN SCALAR W,X,Y;
  738. FOR EACH Z IN U DO
  739. IF NOT NONCOMP Z AND NOT DEPENDS(Z,V) THEN X := Z . X
  740. ELSE IF (W := EXPT!-SEPARATE(Z,V))
  741. THEN <<X := CAR W . X; Y := CDR W . Y>>
  742. ELSE Y := Z . Y;
  743. RETURN REVERSIP X . REVERSIP Y
  744. END;
  745. SYMBOLIC PROCEDURE EXPT!-SEPARATE(U,V);
  746. %determines if U is an expression in EXPT that can be separated into
  747. %two parts, one that does not depend on V and one that does,
  748. %except if there is no non-dependent part, NIL is returned;
  749. IF NOT EQCAR(U,'EXPT) OR DEPENDS(CADR U,V)
  750. OR NOT EQCAR(CADDR U,'PLUS)
  751. THEN NIL
  752. ELSE EXPT!-SEPARATE1(CDADDR U,CADR U,V);
  753. SYMBOLIC PROCEDURE EXPT!-SEPARATE1(U,V,W);
  754. BEGIN SCALAR X;
  755. X := FORMSEPARATE(U,W);
  756. RETURN IF NULL CAR X THEN NIL
  757. ELSE LIST('EXPT,V,REPLUS CAR X) .
  758. IF NULL CDR X THEN 1 ELSE LIST('EXPT,V,REPLUS CDR X)
  759. END;
  760. SYMBOLIC PROCEDURE FORMLNTMS(U,V,W,X);
  761. %U is a linear operator, V its first argument with TIMES removed,
  762. %W the rest of the arguments and X the whole expression.
  763. %Value is the transformed expression;
  764. BEGIN SCALAR Y;
  765. Y := FORMSEPARATE(V,CAR W);
  766. RETURN IF NULL CAR Y THEN X
  767. ELSE 'TIMES . ACONC(CAR Y,
  768. IF NULL CDDR Y THEN FORMLNR(U . CADR Y . W)
  769. ELSE U . ('TIMES . CDR Y) . W)
  770. END;
  771. SYMBOLIC PROCEDURE FORMLNQUOT(FN,QUOTARGS,REST,WHOLE);
  772. %FN is a linear operator, QUOTARGS its first argument with QUOTIENT
  773. %removed, REST the remaining arguments, WHOLE the whole expression.
  774. %Value is the transformed expression;
  775. BEGIN SCALAR X;
  776. RETURN IF NOT DEPENDS(CADR QUOTARGS,CAR REST)
  777. THEN LIST('QUOTIENT,FORMLNR(FN . CAR QUOTARGS . REST),
  778. CADR QUOTARGS)
  779. ELSE IF NOT DEPENDS(CAR QUOTARGS,CAR REST)
  780. AND CAR QUOTARGS NEQ 1
  781. THEN LIST('TIMES,CAR QUOTARGS,
  782. FORMLNR(FN . LIST('RECIP,CADR QUOTARGS) . REST))
  783. ELSE IF EQCAR(CAR QUOTARGS,'PLUS)
  784. THEN 'PLUS . FOR EACH J IN CDAR QUOTARGS
  785. COLLECT FORMLNR(FN . ('QUOTIENT . J . CDR QUOTARGS)
  786. . REST)
  787. ELSE IF EQCAR(CAR QUOTARGS,'MINUS)
  788. THEN LIST('MINUS,FORMLNR(FN .
  789. ('QUOTIENT . CADAR QUOTARGS . CDR QUOTARGS)
  790. . REST))
  791. ELSE IF EQCAR(CAR QUOTARGS,'TIMES)
  792. AND CAR(X := FORMSEPARATE(CDAR QUOTARGS,CAR REST))
  793. THEN 'TIMES . ACONC(CAR X,
  794. FORMLNR(FN . LIST('QUOTIENT,MKTIMES CDR X,
  795. CADR QUOTARGS) . REST))
  796. ELSE IF EQCAR(CADR QUOTARGS,'TIMES)
  797. AND CAR(X := FORMSEPARATE(CDADR QUOTARGS,CAR REST))
  798. THEN LIST('TIMES,LIST('RECIP,MKTIMES CAR X),
  799. FORMLNR(FN . LIST('QUOTIENT,CAR QUOTARGS,MKTIMES CDR X)
  800. . REST))
  801. ELSE IF X := EXPT!-SEPARATE(CAR QUOTARGS,CAR REST)
  802. THEN LIST('TIMES,CAR X,FORMLNR(FN . LIST('QUOTIENT,CDR X,CADR
  803. QUOTARGS) . REST))
  804. ELSE IF X := EXPT!-SEPARATE(CADR QUOTARGS,CAR REST)
  805. THEN LIST('TIMES,LIST('RECIP,CAR X),
  806. FORMLNR(FN . LIST('QUOTIENT,CAR QUOTARGS,CDR X)
  807. . REST))
  808. ELSE IF (X := REVAL!* CADR QUOTARGS) NEQ CADR QUOTARGS
  809. THEN FORMLNQUOT(FN,LIST(CAR QUOTARGS,X),REST,WHOLE)
  810. ELSE WHOLE
  811. END;
  812. SYMBOLIC PROCEDURE MKTIMES U;
  813. IF NULL CDR U THEN CAR U ELSE 'TIMES . U;
  814. SYMBOLIC PROCEDURE REVAL!* U;
  815. %like REVAL, except INTSTR is always ON;
  816. BEGIN SCALAR !*INTSTR;
  817. !*INTSTR := T;
  818. RETURN REVAL U
  819. END;
  820. %*********************************************************************
  821. % FUNCTIONS FOR ALGEBRAIC MODE OPERATIONS ON POLYNOMIALS
  822. %********************************************************************;
  823. SYMBOLIC PROCEDURE POLPART(EXPRN,KERN,FN);
  824. BEGIN SCALAR X,Y;
  825. EXPRN := !*A2F EXPRN;
  826. KERN := !*A2K KERN;
  827. IF DOMAINP EXPRN THEN RETURN NIL
  828. ELSE IF MVAR EXPRN EQ KERN
  829. THEN RETURN !*F2A APPLY(FN,LIST EXPRN);
  830. X := SETKORDER LIST KERN;
  831. EXPRN := REORDER EXPRN;
  832. IF NOT(MVAR EXPRN EQ KERN) THEN EXPRN := NIL
  833. ELSE EXPRN := APPLY(FN,LIST EXPRN);
  834. SETKORDER X;
  835. RETURN !*F2A EXPRN
  836. END;
  837. SYMBOLIC PROCEDURE DEG(U,KERN); POLPART(U,KERN,'CDAAR);
  838. SYMBOLIC PROCEDURE LCOF(U,KERN); POLPART(U,KERN,'CDAR);
  839. SYMBOLIC PROCEDURE LTERM(U,KERN); POLPART(U,KERN,'!*LTERM);
  840. SYMBOLIC PROCEDURE !*LTERM U; LT U .+ NIL;
  841. SYMBOLIC PROCEDURE MAINVAR U;
  842. IF DOMAINP(U := !*A2F U) THEN NIL
  843. ELSE IF SFP(U := MVAR U) THEN PREPF U
  844. ELSE U;
  845. SYMBOLIC PROCEDURE REDUCT(EXPRN,KERN);
  846. BEGIN SCALAR X,Y;
  847. EXPRN := !*A2F EXPRN;
  848. KERN := !*A2K KERN;
  849. IF DOMAINP EXPRN THEN RETURN EXPRN
  850. ELSE IF MVAR EXPRN EQ KERN THEN RETURN !*F2A CDR EXPRN;
  851. X := SETKORDER LIST KERN;
  852. EXPRN := REORDER EXPRN;
  853. IF MVAR EXPRN EQ KERN THEN EXPRN := CDR EXPRN;
  854. SETKORDER X;
  855. RETURN !*F2A EXPRN
  856. END;
  857. SYMBOLIC OPERATOR DEG,LCOF,LTERM,MAINVAR,REDUCT;
  858. %*********************************************************************
  859. % SIMPLIFICATION RULES FOR ELEMENTARY FUNCTIONS
  860. %********************************************************************;
  861. ALGEBRAIC;
  862. COMMENT RULE FOR I**2;
  863. REMFLAG('(I),'RESERVED);
  864. LET I**2= -1;
  865. FLAG('(E I NIL PI T),'RESERVED);
  866. COMMENT LOGARITHMS;
  867. OPERATOR LOG;
  868. LET LOG(E)= 1,
  869. LOG(1)= 0;
  870. FOR ALL X LET LOG(E**X)=X;
  871. FOR ALL X LET DF(LOG(X),X) = 1/X;
  872. COMMENT TRIGONOMETRICAL FUNCTIONS;
  873. SYMBOLIC PROCEDURE SIMPTRIG U;
  874. %This is a basic simplification function for trigonometrical
  875. %functions. The prefix expression U is of the form (<trig-function>
  876. % <argument>). It is assumed that the trig-function is either even
  877. %or odd, with even the default (and the odd case a flag "odd").
  878. %The value is a standard quotient for the simplified expression;
  879. BEGIN SCALAR BOOL,FN,X,Y,Z;
  880. FN := CAR U;
  881. U := CDR U;
  882. IF NULL U OR CDR U
  883. THEN REDERR LIST("Wrong number of arguments to",FN);
  884. U := SIMP!* CAR U;
  885. IF NULL NUMR U AND FLAGP(FN,'ODD) THEN RETURN NIL ./ 1;
  886. X := LIST(FN,PREPSQ!* U);
  887. IF SUBFG!* AND (Z := OPMTCH X) THEN RETURN SIMP Z
  888. ELSE IF Z := NUMVALCHK X THEN RETURN Z
  889. ELSE IF MINUSF NUMR U
  890. THEN <<IF FLAGP(FN,'ODD) THEN BOOL := T;
  891. X := LIST(FN,PREPSQ!*(NEGF NUMR U ./ DENR U));
  892. IF SUBFG!* AND (Z := OPMTCH X) THEN RETURN SIMP Z>>;
  893. X := MKSQ(X,1);
  894. RETURN IF BOOL THEN NEGSQ X ELSE X
  895. END;
  896. DEFLIST('((ACOS SIMPTRIG) (ASIN SIMPTRIG) (ATAN SIMPTRIG)
  897. (ACOSH SIMPTRIG) (ASINH SIMPTRIG) (ATANH SIMPTRIG)
  898. (COS SIMPTRIG) (SIN SIMPTRIG) (TAN SIMPTRIG)
  899. (COT SIMPTRIG)(ACOT SIMPTRIG)(COTH SIMPTRIG)(ACOTH SIMPTRIG)
  900. (COSH SIMPTRIG) (SINH SIMPTRIG) (TANH SIMPTRIG)
  901. ),'SIMPFN);
  902. %The following declaration causes the simplifier to pass the full
  903. %expression (including the function) to SIMPTRIG;
  904. FLAG ('(ACOS ASIN ATAN ACOSH ASINH ATANH COS SIN TAN COSH SINH TANH
  905. COT ACOT COTH ACOTH),
  906. 'FULL);
  907. FLAG('(ASIN ATAN ASINH ATANH SIN TAN SINH TANH COT ACOT COTH ACOTH),
  908. 'ODD);
  909. %In the following rules, it is not necessary to let f(0)=0, when f
  910. %is odd, since SIMPTRIG already does this;
  911. LET COS(0)= 1,
  912. COS(PI/2)= 0,
  913. SIN(PI/2)= 1,
  914. SIN(PI)= 0,
  915. COS(PI)=-1,
  916. COSH 0=1;
  917. FOR ALL X LET COS ACOS X=X, SIN ASIN X=X, TAN ATAN X=X,
  918. COSH ACOSH X=X, SINH ASINH X=X, TANH ATANH X=X,
  919. COT ACOT X=X, COTH ACOTH X=X;
  920. FOR ALL N SUCH THAT NUMBERP N AND FIXP N
  921. LET SIN(N*PI)=0, COS(N*PI) = (-1)**N;
  922. FOR ALL X LET DF(ACOS(X),X)= -SQRT(1-X**2)/(1-X**2),
  923. DF(ASIN(X),X)= SQRT(1-X**2)/(1-X**2),
  924. DF(ATAN(X),X)= 1/(1+X**2),
  925. DF(ACOSH(X),X)= SQRT(X**2-1)/(X**2-1),
  926. DF(ASINH(X),X)= SQRT(X**2+1)/(X**2+1),
  927. DF(ATANH(X),X)= 1/(1-X**2),
  928. DF(COS X,X)= -SIN(X),
  929. DF(SIN(X),X)= COS(X),
  930. DF(TAN X,X)=1+TAN X**2,
  931. DF(SINH X,X)=COSH X,
  932. DF(COSH X,X)=SINH X,
  933. DF(TANH X,X)=1-TANH X**2,
  934. DF(COT X,X)=-1-COT X**2,
  935. DF(COTH X,X)=1-COTH X**2;
  936. LET E**(I*PI/2) = I,
  937. E**(I*PI) = -1,
  938. E**(3*I*PI/2)=-I;
  939. %FOR ALL X LET E**LOG X=X; %requires every power to be checked;
  940. FOR ALL X,Y LET DF(X**Y,X)= Y*X**(Y-1),
  941. DF(X**Y,Y)= LOG X*X**Y;
  942. COMMENT SQUARE ROOTS;
  943. DEFLIST('((SQRT SIMPSQRT)),'SIMPFN);
  944. %FOR ALL X LET SQRT X**2=X;
  945. FLUID '(!*!*SQRT); %Used to indicate that SQRTs have been used;
  946. SYMBOLIC PROCEDURE MKSQRT U;
  947. <<IF NULL !*!*SQRT THEN <<!*!*SQRT := T;
  948. ALGEBRAIC FOR ALL X LET SQRT X**2=X>>;
  949. LIST('SQRT,U)>>;
  950. FOR ALL X LET DF(SQRT X,X)=SQRT X/(2*X);
  951. COMMENT ERF,EXP, EXPINT AND DILOG;
  952. OPERATOR ERF,EXP,EXPINT,DILOG;
  953. LET ERF 0=0;
  954. LET DILOG(0)=PI**2/6;
  955. FOR ALL X LET ERF(-X)=-ERF X;
  956. FOR ALL X LET DF(ERF X,X)=2*SQRT(PI)*E**(-X**2/2)/PI;
  957. FOR ALL X LET EXP(X)=E**X;
  958. FOR ALL X LET DF(EXPINT(X),X)=E**X/X;
  959. FOR ALL X LET DF(DILOG X,X)=-LOG X/(X-1);
  960. SYMBOLIC;
  961. %*********************************************************************
  962. %*********************************************************************
  963. % SIMPLIFICATION FUNCTIONS FOR NON-SCALAR QUANTITIES
  964. %*********************************************************************
  965. %********************************************************************;
  966. SYMBOLIC PROCEDURE NSSIMP(U,V);
  967. %U is a prefix expression involving non-commuting
  968. %quantities. Result is an expression of the form
  969. % SUM R(I)*PRODUCT M(I,J) where the R(I) are standard
  970. %quotients and the M(I,J) non-commuting expressions;
  971. %N. B: the products in M(I,J) are returned in reverse order
  972. %(to facilitate, e.g., matrix augmentation);
  973. BEGIN SCALAR W,X,Y,Z;
  974. U := DSIMP(U,V);
  975. A: IF NULL U THEN RETURN Z;
  976. W := CAR U;
  977. C: IF NULL W THEN GO TO D
  978. ELSE IF NUMBERP CAR W
  979. OR NOT(EQCAR(CAR W,'!*DIV) OR APPLY(V,LIST CAR W))
  980. THEN X := ACONC(X,CAR W)
  981. ELSE Y := ACONC(Y,CAR W);
  982. W := CDR W;
  983. GO TO C;
  984. D: IF NULL Y THEN GO TO ER;
  985. E: Z := ADDNS(((IF NULL X THEN 1 ./ 1 ELSE SIMPTIMES X) . Y),Z);
  986. U := CDR U;
  987. X := Y:= NIL;
  988. GO TO A;
  989. ER: Y := GET(V,'NAME);
  990. IF IDP CAR X
  991. THEN IF NOT FLAGP(CAR X,GET(Y,'FN)) THEN REDMSG(CAR X,Y)
  992. ELSE REDERR LIST(Y,X,"not set")
  993. ELSE IF Y EQ 'MATRIX THEN <<Y:= '((MAT (1))); GO TO E>>
  994. %to allow a scalar to be a 1 by 1 matrix;
  995. ELSE REDERR LIST("Missing",Y,X);
  996. PUT(CAR X,Y,Y);
  997. Y := LIST CAR X;
  998. X := CDR X;
  999. GO TO E
  1000. END;
  1001. SYMBOLIC PROCEDURE DSIMP(U,V);
  1002. %result is a list of lists representing a sum of products;
  1003. %N. B: symbols are in reverse order in product list;
  1004. IF NUMBERP U THEN LIST LIST U
  1005. ELSE IF ATOM U THEN (LAMBDA W; (LAMBDA X;
  1006. IF X AND NOT X EQ W AND SUBFG!* THEN DSIMP(X,V)
  1007. ELSE IF FLAGP(U,'SHARE) THEN DSIMP(EVAL U,V)
  1008. ELSE <<FLAG(LIST U,'USED!*); LIST LIST U>>)
  1009. GET(U,W))
  1010. GET(V,'NAME)
  1011. ELSE IF CAR U EQ 'PLUS
  1012. THEN FOR EACH J IN CDR U CONC DSIMP(J,V)
  1013. ELSE IF CAR U EQ 'DIFFERENCE
  1014. THEN NCONC(DSIMP(CADR U,V),
  1015. DSIMP('MINUS . CDDR U,V))
  1016. ELSE IF CAR U EQ 'MINUS
  1017. THEN DSIMPTIMES(LIST(-1,CARX CDR U),V)
  1018. ELSE IF CAR U EQ 'TIMES
  1019. THEN DSIMPTIMES(CDR U,V)
  1020. ELSE IF CAR U EQ 'QUOTIENT
  1021. THEN DSIMPTIMES(LIST(CADR U, LIST('RECIP,CARX CDDR U)),V)
  1022. ELSE IF NOT APPLY(V,LIST U) THEN LIST LIST U
  1023. ELSE IF CAR U EQ 'RECIP THEN LIST LIST LIST('!*DIV,CARX CDR U)
  1024. ELSE IF CAR U EQ 'EXPT THEN (LAMBDA Z;
  1025. IF NOT NUMBERP Z OR NOT FIXP Z THEN ERRPRI2(U,T)
  1026. ELSE IF Z<0
  1027. THEN LIST LIST LIST('!*DIV,'TIMES . NLIST(CADR U,-Z))
  1028. ELSE IF Z=0 THEN LIST LIST LIST('!*DIV,CADR U,1)
  1029. ELSE DSIMPTIMES(NLIST(CADR U,Z),V))
  1030. REVAL CADDR U
  1031. ELSE IF CAR U EQ 'MAT THEN LIST LIST U
  1032. ELSE IF ARRAYP CAR U
  1033. THEN DSIMP(GETELV U,V)
  1034. ELSE (LAMBDA X; IF X THEN DSIMP(X,V)
  1035. ELSE (LAMBDA Y; IF Y THEN DSIMP(Y,V)
  1036. ELSE LIST LIST U)
  1037. OPMTCH REVOP1 U)
  1038. OPMTCH U;
  1039. SYMBOLIC PROCEDURE DSIMPTIMES(U,V);
  1040. IF NULL U THEN ERRACH 'DSIMPTIMES
  1041. ELSE IF NULL CDR U THEN DSIMP(CAR U,V)
  1042. ELSE (LAMBDA J;
  1043. FOR EACH K IN DSIMPTIMES(CDR U,V) CONC MAPPEND(J,K))
  1044. DSIMP(CAR U,V);
  1045. SYMBOLIC PROCEDURE ADDNS(U,V);
  1046. IF NULL V THEN LIST U
  1047. ELSE IF CDR U=CDAR V
  1048. THEN (LAMBDA X; IF NULL CAR X THEN CDR V
  1049. ELSE (X . CDR U) . CDR V)
  1050. ADDSQ(CAR U,CAAR V)
  1051. ELSE IF ORDP(CDR U,CDAR V) THEN U . V
  1052. ELSE CAR V . ADDNS(U,CDR V);
  1053. SYMBOLIC PROCEDURE NSLET(U,V,W,B,FLG);
  1054. BEGIN
  1055. IF FLG THEN GO TO A
  1056. ELSE IF NOT ATOM U
  1057. THEN IF ARRAYP CAR U THEN GO TO A ELSE TYPERR(U,"array");
  1058. REDMSG(U,W);
  1059. PUT(U,W,W);
  1060. A: IF NULL B THEN GO TO C
  1061. ELSE IF NOT ATOM U OR FLAGP(U,'USED!*) THEN RMSUBS();
  1062. C: IF NOT ATOM U
  1063. THEN IF ARRAYP CAR U
  1064. THEN SETELV(U,IF B THEN V ELSE NIL)
  1065. ELSE PUT(CAR U,'OPMTCH,XADD!*(CDR U .
  1066. LIST(NIL . (IF MCOND!* THEN MCOND!* ELSE T),V,NIL),
  1067. GET(CAR U,'OPMTCH),U,B))
  1068. ELSE IF NULL B THEN REMPROP(U,W)
  1069. ELSE IF W EQ 'MATRIX AND NOT EQCAR(V,'MAT)
  1070. THEN PUT(U,W,IF MATP V THEN GET(V,'MATRIX)
  1071. ELSE LIST('MAT,LIST V)) %1 by 1 matrix case;
  1072. ELSE PUT(U,W,V)
  1073. END;
  1074. SYMBOLIC PROCEDURE NSP(U,V);
  1075. IF NUMBERP U THEN NIL
  1076. ELSE IF ATOM U THEN GET(U,V)
  1077. OR (FLAGP(U,'SHARE) AND NSP(EVAL U,V))
  1078. ELSE IF CAR U MEMQ '(TIMES QUOTIENT) THEN NSOR(CDR U,V)
  1079. ELSE IF CAR U MEMQ '(PLUS DIFFERENCE MINUS EXPT RECIP)
  1080. THEN NSP(CADR U,V)
  1081. ELSE IF ARRAYP CAR U THEN NSP(GETELX U,V)
  1082. ELSE FLAGP(CAR U,GET(V,'FN));
  1083. SYMBOLIC PROCEDURE GETELX U;
  1084. %to take care of free variables in LET statements;
  1085. IF SMEMQLP(FRLIS!*,CDR U) THEN NIL
  1086. ELSE IF NULL(U := GETELV U) THEN 0
  1087. ELSE REVAL U;
  1088. SYMBOLIC PROCEDURE NSOR(U,V);
  1089. U AND (NSP(CAR U,V) OR NSOR(CDR U,V));
  1090. %*********************************************************************
  1091. %*********************************************************************
  1092. % MATRIX PACKAGE
  1093. %*********************************************************************
  1094. %********************************************************************;
  1095. %*********************************************************************
  1096. % REQUIRES SIMPLIFICATION FUNCTIONS FOR NON-SCALAR QUANTITIES
  1097. %********************************************************************;
  1098. SYMBOLIC PROCEDURE MATRIX U;
  1099. %declares list U as matrices;
  1100. BEGIN SCALAR V,W; INTEGER N;
  1101. TYPL!* := UNION('(MATP),TYPL!*);
  1102. A: IF NULL U THEN RETURN NIL
  1103. ELSE IF ATOM CAR U AND NOT TYPECHK(CAR U,'MATRIX)
  1104. THEN PUT(CAR U,'MATRIX,'MATRIX)
  1105. ELSE IF NOT IDP CAAR U
  1106. OR LENGTH (V := REVLIS CDAR U) NEQ 2 OR NOT NUMLIS V
  1107. THEN GO TO ER
  1108. ELSE IF NOT TYPECHK(CAAR U,'MATRIX) THEN GO TO C;
  1109. B: U := CDR U;
  1110. GO TO A;
  1111. C: N := CAR V;
  1112. D: IF N=0 THEN GO TO E;
  1113. W := NZERO CADR V . W;
  1114. N := N-1;
  1115. GO TO D;
  1116. E: PUT(CAAR U,'MATRIX,'MAT . W);
  1117. W := NIL;
  1118. GO TO B;
  1119. ER: ERRPRI2(CAR U,'HOLD);
  1120. GO TO B
  1121. END;
  1122. RLISTAT '(MATRIX);
  1123. SYMBOLIC PROCEDURE NZERO N;
  1124. %returns a list of N zeros;
  1125. IF N=0 THEN NIL ELSE 0 . NZERO(N-1);
  1126. SYMBOLIC PROCEDURE FORMMAT(U,VARS,MODE);
  1127. 'LIST . MKQUOTE 'MAT
  1128. . FOR EACH X IN U COLLECT('LIST . FORMLIS(X,VARS,MODE));
  1129. PUT('MAT,'FORMFN,'FORMMAT);
  1130. SYMBOLIC PROCEDURE MATP U;
  1131. %predicate which tests for matrix expressions;
  1132. NSP(U,'MATRIX);
  1133. FLAG('(MAT TP),'MATFLG);
  1134. PUT('TP,'MSIMPFN,'TP);
  1135. PUT('MATP,'LETFN,'NSLET);
  1136. PUT('MATP,'NAME,'MATRIX);
  1137. PUT('MATRIX,'FN,'MATFLG);
  1138. PUT('MATP,'EVFN,'MATSM!*);
  1139. PUT('MATP,'PRIFN,'MATPRI!*);
  1140. END;