poly.red 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665
  1. OFF ECHO,RAISE$
  2. LISP;
  3. % Simple POLY, RAT AND ALG system, based on POLY by Fitch and Marti.
  4. % Modifed by GRISS and GALWAY
  5. % September 1980.
  6. % Further modified by MORRISON
  7. % October 1980.
  8. % Parser modified by OTTENHEIMER
  9. % February 1981, to be left associative March 1981.
  10. % Current bug: print routines print as if right associative.
  11. % MORRISON again, March 1981.
  12. % Parses INFIX expressions to PREFIX, then SIMPlifies and PRINTs
  13. % Handles also PREFIX expressions
  14. % RUNNING: After loading POLY.RED, run function ALGG();
  15. % This accepts a sequence of expressions:
  16. % <exp> ; (Semicolon terminator)
  17. % <exp> ::= <term> [+ <exp> | - <exp>]
  18. % <term> ::= <primary> [* <term> | / <term>]
  19. % <primary> ::= <primary0> [^ <primary0> | ' <primary0> ]
  20. % ^ is exponentiation, ' is derivative
  21. % <primary0> ::= <number> | <variable> | ( <exp> )
  22. % PREFIX Format: <number> | <id> | (op arg1 arg2)
  23. % + -> PLUS2
  24. % - -> DIFFERENCE (or MINUS)
  25. % * -> TIMES2
  26. % / -> QUOTIENT
  27. % ^ -> EXPT
  28. % ' -> DIFF
  29. % Canonical Formats: Polynomial: integer | (term . polynomial)
  30. % term : (power . polynomial)
  31. % power : (variable . integer)
  32. % Rational : (polynomial . polynomial)
  33. %******************** Selectors and Constructors **********************
  34. SYMBOLIC SMACRO PROCEDURE RATNUM X; % parts of Rational
  35. CAR X;
  36. SYMBOLIC SMACRO PROCEDURE RATDEN X;
  37. CDR X;
  38. SYMBOLIC SMACRO PROCEDURE MKRAT(X,Y);
  39. CONS(X,Y);
  40. SYMBOLIC SMACRO PROCEDURE POLTRM X; % parts of Poly
  41. CAR X;
  42. SYMBOLIC SMACRO PROCEDURE POLRED X;
  43. CDR X;
  44. SYMBOLIC SMACRO PROCEDURE MKPOLY(X,Y);
  45. CONS(X,Y);
  46. SYMBOLIC SMACRO PROCEDURE TRMPWR X; % parts of TERM
  47. CAR X;
  48. SYMBOLIC SMACRO PROCEDURE TRMCOEF X;
  49. CDR X;
  50. SYMBOLIC SMACRO PROCEDURE MKTERM(X,Y);
  51. CONS(X,Y);
  52. SYMBOLIC SMACRO PROCEDURE PWRVAR X; % parts of Poly
  53. CAR X;
  54. SYMBOLIC SMACRO PROCEDURE PWREXPT X;
  55. CDR X;
  56. SYMBOLIC SMACRO PROCEDURE MKPWR(X,Y);
  57. CONS(X,Y);
  58. SYMBOLIC SMACRO PROCEDURE POLVAR X;
  59. PWRVAR TRMPWR POLTRM X;
  60. SYMBOLIC SMACRO PROCEDURE POLEXPT X;
  61. PWREXPT TRMPWR POLTRM X;
  62. SYMBOLIC SMACRO PROCEDURE POLCOEF X;
  63. TRMCOEF POLTRM X;
  64. %*********************** Utility Routines *****************************
  65. SYMBOLIC PROCEDURE VARP X;
  66. IDP X OR (PAIRP X AND IDP CAR X);
  67. %*********************** Entry Point **********************************
  68. GLOBAL '(!*RBACKTRACE !*RECHO REXPRESSION!* !*RMESSAGE);
  69. !*RECHO := !*RMESSAGE := T;
  70. SYMBOLIC PROCEDURE ALGG(); %. Main LOOP, end with QUIT OR Q
  71. BEGIN SCALAR VVV;
  72. ALGINIT();
  73. CLEARTOKEN(); % Initialize scanner
  74. LOOP: VVV := ERRORSET('(RPARSE),T,!*RBACKTRACE);
  75. IF ATOM VVV THEN % What about resetting the Scanner?
  76. <<PRINT LIST('ALGG, 'error, VVV); CLEARTOKEN();GO TO LOOP>>;
  77. REXPRESSION!* := CAR VVV;
  78. IF !*RECHO THEN PRINT REXPRESSION!*;
  79. IF REXPRESSION!* EQ 'QUIT THEN <<
  80. PRINT 'QUITTING;
  81. RETURN >>;
  82. ERRORSET('(PREPRINT (PRESIMP REXPRESSION!*)),T,!*RBACKTRACE);
  83. GO TO LOOP
  84. END ALGG;
  85. SYMBOLIC PROCEDURE ALGINIT(); %. Called to INIT tables
  86. BEGIN
  87. INITTOKEN();
  88. PUT('TIMES2,'RSIMP,'R!*); %. Simplifier Tables
  89. PUT('PLUS2,'RSIMP,'R!+);
  90. PUT('DIFFERENCE,'RSIMP,'R!-);
  91. PUT('QUOTIENT,'RSIMP,'R!/);
  92. PUT('EXPT,'RSIMP,'R!^);
  93. PUT('DIFF,'RSIMP,'R!');
  94. PUT('MINUS,'RSIMP,'R!.NEG);
  95. PUT('!+,'REXP,'PLUS2); % Use corresponding 'R!xx in EVAL mode
  96. PUT('!-,'REXP,'DIFFERENCE);
  97. PUT('!*,'RTERM,'TIMES2);;
  98. PUT('!/,'RTERM,'QUOTIENT);
  99. PUT('!^,'RPRIMARY,'EXPT);
  100. PUT('!','RPRIMARY,'DIFF);
  101. PUT('PLUS2,'PRINOP,'PLUSPRIN); %. Output funs
  102. PUT('DIFFERENCE,'PRINOP,'DIFFERENCEPRIN);
  103. PUT('TIMES2,'PRINOP,'TIMESPRIN);
  104. PUT('QUOTIENT,'PRINOP,'QUOTPRIN);
  105. PUT('EXPT,'PRINOP,'EXPPRIN);
  106. END;
  107. SYMBOLIC PROCEDURE RSIMP X; %. Simplify Prefix Form to Canonical
  108. IF ATOM X THEN RCREATE X
  109. ELSE BEGIN SCALAR Y,OP;
  110. OP:=CAR X;
  111. IF (Y:=GET(OP,'RSIMP)) THEN RETURN XAPPLY(Y,RSIMPL CDR X);
  112. Y:=PRESIMP X; % As "variable" ?
  113. IF ATOM Y OR NOT(X=Y) THEN RETURN RSIMP Y;
  114. RETURN RCREATE Y;
  115. END;
  116. SYMBOLIC PROCEDURE RSIMPL X; %. Simplify argument list
  117. IF NULL X THEN NIL ELSE RSIMP(CAR X) . RSIMPL CDR X;
  118. SYMBOLIC PROCEDURE PRESIMP X; %. Simplify Prefix Form to PREFIX
  119. IF ATOM X THEN X
  120. ELSE BEGIN SCALAR Y,OP;
  121. OP:=CAR X;
  122. IF (Y:=GET(OP,'RSIMP)) THEN RETURN RAT2PRE XAPPLY(Y,RSIMPL CDR X);
  123. X:=PRESIMPL CDR X;
  124. IF (Y:=GET(OP,'PRESIMP)) THEN RETURN XAPPLY(Y,X);
  125. RETURN (OP . X);
  126. END;
  127. SYMBOLIC PROCEDURE PRESIMPL X; %. Simplify argument list
  128. IF NULL X THEN NIL ELSE PRESIMP(CAR X) . PRESIMPL CDR X;
  129. %**************** Simplification Routines for Rationals ***************
  130. SYMBOLIC PROCEDURE R!+(A,B); %. RAT addition
  131. IF RATDEN A = RATNUM B THEN
  132. MAKERAT(P!+(RATNUM A,RATNUM B),CDR A)
  133. ELSE
  134. MAKERAT(P!+(P!*(RATNUM A,RATDEN B),
  135. P!*(RATDEN A,RATNUM B)),
  136. P!*(RATDEN A,RATDEN B));
  137. SYMBOLIC PROCEDURE R!-(A,B); %. RAT subtraction
  138. R!+(A,R!.NEG B);
  139. SYMBOLIC PROCEDURE R!.NEG A; %. RAT negation
  140. MKRAT(P!.NEG RATNUM A,RATDEN A);
  141. SYMBOLIC PROCEDURE R!*(A,B); %. RAT multiplication
  142. BEGIN SCALAR X,Y;
  143. X:=MAKERAT(RATNUM A,RATDEN B);
  144. Y:=MAKERAT(RATNUM B,RATDEN A);
  145. IF RATNUM X=0 OR RATNUM Y=0 THEN RETURN 0 . 1;
  146. RETURN MKRAT(P!*(RATNUM X,RATNUM Y),
  147. P!*(RATDEN X,RATDEN Y))
  148. END;
  149. SYMBOLIC PROCEDURE R!.RECIP A; %. RAT inverse
  150. IF RATNUM A=0 THEN ERROR(777,'(ZERO DIVISOR))
  151. ELSE MKRAT(RATDEN A,RATNUM A);
  152. SYMBOLIC PROCEDURE R!/(A,B); %. RAT division
  153. R!*(A,R!.RECIP B);
  154. SYMBOLIC PROCEDURE R!.LVAR A; %. Leading VARIABLE of RATIONAL
  155. BEGIN SCALAR P;
  156. P:=RATNUM A;
  157. IF NUMBERP P THEN RETURN ERROR(99,'(non structured polynomial));
  158. P:=POLVAR P;
  159. RETURN P;
  160. END;
  161. SYMBOLIC PROCEDURE R!'(A,X); %. RAT derivative
  162. <<X:=R!.LVAR X;
  163. IF RATDEN A=1 THEN MKRAT(PDIFF(RATNUM A,X),1)
  164. ELSE R!-(MAKERAT(PDIFF(RATNUM A,X),RATDEN A),
  165. MAKERAT(P!*(RATNUM A,PDIFF(RATDEN A,X)),
  166. P!*(RATDEN A,RATDEN A) ) ) >>;
  167. SYMBOLIC PROCEDURE RCREATE X; %. RAT create
  168. IF NUMBERP X THEN X . 1
  169. ELSE IF VARP X THEN (PCREATE X) . 1
  170. ELSE ERROR(100,LIST(X, '(non kernel)));
  171. SYMBOLIC PROCEDURE MAKERAT(A,B);
  172. IF A=B THEN MKRAT(1,1)
  173. ELSE IF A=0 THEN 0 . 1
  174. ELSE IF B=0 THEN ERROR(777,'(ZERO DIVISOR))
  175. ELSE IF NUMBERP A AND NUMBERP B THEN
  176. BEGIN SCALAR GG;
  177. GG:=NUMGCD(A,B);
  178. IF B<0 THEN <<B:=-B; A := -A>>;
  179. RETURN MKRAT(A/GG,B/GG)
  180. END
  181. ELSE BEGIN SCALAR GG,NN;
  182. GG:=PGCD(A,B);
  183. IF GG=1 THEN RETURN MKRAT(A,B);
  184. NN:=GG;
  185. LL: IF NUMBERP NN THEN NN:=GCDPT(GG,NN)
  186. ELSE << NN:=POLCOEF GG; GOTO LL >>;
  187. GG:=CAR PDIVIDE(GG,NN);
  188. RETURN MKRAT(DIVIDEOUT(A,GG),DIVIDEOUT(B,GG))
  189. END;
  190. SYMBOLIC PROCEDURE R!^(A,N); %. RAT Expt
  191. BEGIN SCALAR AA;
  192. N:=RATNUM N;
  193. IF NOT NUMBERP N THEN RETURN ERROR(777,'(Non numeric exponent))
  194. ELSE IF N=0 THEN RETURN RCREATE 1;
  195. IF N<0 THEN <<A:=R!.RECIP A; N:=-N>>;
  196. AA:=1 . 1;
  197. FOR I:=1:N DO AA:=R!*(AA,A);
  198. RETURN AA
  199. END;
  200. %**************** Simplification Routines for Polynomials *************
  201. SYMBOLIC PROCEDURE P1!+(A, B); % Fix for UCSD pascal to cut down proc size
  202. BEGIN SCALAR AA,BB;
  203. AA:=P!+(POLCOEF A,POLCOEF B);
  204. IF AA=0 THEN RETURN P!+(POLRED A,POLRED B);
  205. AA:=MKPOLY(TRMPWR POLTRM A,AA);
  206. AA:=ZCONS AA; BB:=P!+(POLRED A,POLRED B);
  207. RETURN P!+(AA,BB)
  208. END P1!+;
  209. SYMBOLIC PROCEDURE P!+(A,B); %. POL addition
  210. IF A=0 THEN B ELSE IF B=0 THEN A ELSE
  211. IF NUMBERP A AND NUMBERP B THEN PLUS2(A,B)
  212. ELSE IF NUMBERP A THEN MKPOLY(POLTRM B,P!+(A,POLRED B))
  213. ELSE IF NUMBERP B THEN MKPOLY(POLTRM A,P!+(B,POLRED A))
  214. ELSE BEGIN SCALAR ORD;
  215. ORD:=PORDERP(POLVAR A,POLVAR B);
  216. IF ORD=1 THEN RETURN MKPOLY(POLTRM A,P!+(POLRED A,B));
  217. IF ORD=-1 THEN RETURN MKPOLY(POLTRM B,P!+(POLRED B,A));
  218. IF POLEXPT A=POLEXPT B THEN RETURN P1!+(A, B);
  219. IF POLEXPT A>POLEXPT B THEN RETURN
  220. MKPOLY(POLTRM A,P!+(POLRED A,B));
  221. RETURN MKPOLY(POLTRM B,P!+(POLRED B,A))
  222. END;
  223. SYMBOLIC PROCEDURE PORDERP(A,B); %. POL variable ordering
  224. IF A EQ B THEN 0
  225. ELSE IF ORDERP(A,B) THEN 1 ELSE -1;
  226. SYMBOLIC PROCEDURE P!*(A,B); %. POL multiply
  227. IF NUMBERP A THEN
  228. IF A=0 THEN 0
  229. ELSE IF NUMBERP B THEN TIMES2(A,B)
  230. ELSE CONS(CONS(CAAR B,PNTIMES(CDAR B,A)),
  231. PNTIMES(CDR B,A))
  232. ELSE IF NUMBERP B THEN PNTIMES(A,B)
  233. ELSE P!+(PTTIMES(CAR A,B),P!*(CDR A,B));
  234. SYMBOLIC PROCEDURE PTTIMES(TT,A); %. POL term mult
  235. IF NUMBERP A THEN
  236. IF A=0 THEN 0 ELSE
  237. ZCONS CONS(CAR TT,PNTIMES(CDR TT,A))
  238. ELSE P!+(TTTIMES(TT,CAR A),PTTIMES(TT,CDR A));
  239. SYMBOLIC PROCEDURE PNTIMES(A,N); %. POL numeric coef mult
  240. IF N=0 THEN 0
  241. ELSE IF NUMBERP A THEN TIMES2(A,N)
  242. ELSE CONS(CONS(CAAR A,PNTIMES(CDAR A,N)),PNTIMES(CDR A,N));
  243. SYMBOLIC PROCEDURE TTTIMES(TA,TB); %. TERM Mult
  244. BEGIN SCALAR ORD;
  245. ORD:=PORDERP(CAAR TA,CAAR TB);
  246. RETURN IF ORD=0 THEN
  247. ZCONS(CONS(CONS(CAAR TA,PLUS2(CDAR TA,CDAR TB)),
  248. P!*(CDR TA,CDR TB)))
  249. ELSE IF ORD=1 THEN
  250. ZCONS(CONS(CAR TA,P!*(ZCONS TB,CDR TA)))
  251. ELSE ZCONS(CONS(CAR TB,P!*(ZCONS TA,CDR TB)))
  252. END;
  253. SYMBOLIC PROCEDURE ZCONS A; %. Make single term POL
  254. CONS(A,0);
  255. SYMBOLIC PROCEDURE PCREATE1(X); %. Create POLY from Variable/KERNEL
  256. ZCONS(CONS(CONS(X,1),1));
  257. SYMBOLIC PROCEDURE PCREATE X;
  258. IF IDP X THEN PCREATE1 X
  259. ELSE IF PAIRP X AND IDP CAR X THEN PCREATE1 MKKERNEL X
  260. ELSE ERROR(1000,LIST(X, '(bad kernel)));
  261. SYMBOLIC PROCEDURE PGCD(A,B); %. POL Gcd
  262. % A and B must be primitive.
  263. IF A=1 OR B=1 THEN 1 ELSE
  264. IF NUMBERP A AND NUMBERP B THEN NUMGCD(A,B)
  265. ELSE IF NUMBERP A THEN GCDPT(B,A)
  266. ELSE IF NUMBERP B THEN GCDPT(A,B)
  267. ELSE BEGIN SCALAR ORD;
  268. ORD:=PORDERP(CAAAR A,CAAAR B);
  269. IF ORD=0 THEN RETURN GCDPP(A,B);
  270. IF ORD>0 THEN RETURN GCDPT(A,B);
  271. RETURN GCDPT(B,A)
  272. END;
  273. SYMBOLIC PROCEDURE NUMGCD(A,B); %. Numeric GCD
  274. IF A=0 THEN ABS B
  275. ELSE NUMGCD(REMAINDER(B,A),A);
  276. SYMBOLIC PROCEDURE GCDPT(A,B); %. POL GCD, non-equal vars
  277. IF NUMBERP A THEN IF NUMBERP B THEN NUMGCD(A,B) ELSE
  278. GCDPT(B,A) ELSE
  279. BEGIN SCALAR ANS,ANS1;
  280. ANS:=PGCD(CDAR A,B);
  281. A:=CDR A;
  282. WHILE NOT NUMBERP A DO <<
  283. ANS1:=PGCD(CDAR A,B);
  284. ANS:=PGCD(ANS,ANS1);
  285. A:=CDR A;
  286. IF ANS=1 THEN RETURN ANS >>;
  287. RETURN IF A=0 THEN ANS ELSE GCDPT(ANS,A)
  288. END;
  289. SYMBOLIC PROCEDURE GCDPP(A,B); %. POL GCD, equal vars
  290. BEGIN SCALAR TT,PA,ALPHA,PREVALPHA;
  291. IF POLEXPT B>POLEXPT A THEN <<
  292. TT := A;
  293. A := B;
  294. B := TT >>;
  295. ALPHA := 1;
  296. LOOP: PREVALPHA := ALPHA;
  297. ALPHA := POLCOEF B;
  298. PA := POLEXPT A - POLEXPT B;
  299. IF PA<0 THEN <<
  300. PRINT A;
  301. PRINT B;
  302. PRINT PA;
  303. ERROR(999,'(WRONG)) >>;
  304. WHILE NOT (PA=0) DO <<
  305. PA := PA-1;
  306. ALPHA := P!*(POLCOEF B,ALPHA) >>;
  307. A := P!*(A,ALPHA); % to ensure no fractions;
  308. TT := CDR PDIVIDE(A,B); % quotient and remainder of polynomials;
  309. IF TT=0 THEN
  310. RETURN B; % which is the GCD;
  311. A := B;
  312. B := PDIVIDE(TT,PREVALPHA);
  313. IF NOT(CDR B=0) THEN
  314. ERROR(12,'(REDUCED PRS FAILS));
  315. B := CAR B;
  316. IF NUMBERP B OR NOT (POLVAR A EQ POLVAR B) THEN RETURN 1;
  317. % Lost leading VAR we started with. /MLG
  318. GO TO LOOP
  319. END;
  320. SYMBOLIC PROCEDURE DIVIDEOUT(A,B); %. POL exact division
  321. CAR PDIVIDE(A,B);
  322. SYMBOLIC PROCEDURE PDIVIDE(A,B); %. POL (quotient.remainder)
  323. IF NUMBERP A THEN
  324. IF NUMBERP B THEN DIVIDE(A,B)
  325. ELSE CONS(0,A)
  326. ELSE IF NUMBERP B THEN
  327. BEGIN SCALAR SS,TT;
  328. SS:=PDIVIDE(CDR A,B);
  329. TT:=PDIVIDE(CDAR A,B);
  330. RETURN CONS(
  331. P!+(P!*(ZCONS CONS(CAAR A,1),CAR TT),CAR SS),
  332. P!+(P!*(ZCONS CONS(CAAR A,1),CDR TT),CDR SS))
  333. END
  334. ELSE
  335. BEGIN SCALAR QQ,BB,CC,TT;
  336. IF NOT(POLVAR A EQ POLVAR B) OR POLEXPT A < POLEXPT B THEN
  337. RETURN CONS(0,A); % Not same var/MLG, degree check/DFM
  338. QQ:=PDIVIDE(POLCOEF A,POLCOEF B); % Look for leading term;
  339. IF NOT(CDR QQ=0) THEN RETURN CONS(0,A);
  340. QQ:=CAR QQ; %Get the quotient;
  341. BB:=P!*(B,QQ);
  342. IF CDAAR A > CDAAR B THEN
  343. << TT:=ZCONS CONS(CONS(CAAAR A,CDAAR A-CDAAR B),1);
  344. BB:=P!*(BB,TT);
  345. QQ:=P!*(QQ,TT)
  346. >>;
  347. CC:=P!-(A,BB); %Take it off;
  348. BB:=PDIVIDE(CC,B);
  349. RETURN CONS(P!+(QQ,CAR BB),CDR BB)
  350. END;
  351. SYMBOLIC PROCEDURE P!-(A,B); %. POL subtract
  352. P!+(A,P!.NEG B);
  353. SYMBOLIC PROCEDURE P!.NEG(A); %. POL Negate
  354. IF NUMBERP A THEN -A
  355. ELSE CONS(CONS(CAAR A,P!.NEG CDAR A),P!.NEG CDR A);
  356. SYMBOLIC PROCEDURE PDIFF(A,X); %. POL derivative (to variable)
  357. IF NUMBERP A THEN 0
  358. ELSE BEGIN SCALAR ORD;
  359. ORD:=PORDERP(POLVAR A,X);
  360. RETURN
  361. IF ORD=-1 THEN 0
  362. ELSE IF ORD=0 THEN
  363. IF CDAAR A=1 THEN
  364. CDAR A
  365. ELSE P!+(ZCONS CONS(CONS(X,CDAAR A-1),P!*(CDAAR A,CDAR A)),
  366. PDIFF(CDR A,X))
  367. ELSE P!+(P!*(ZCONS CONS(CAAR A,1),PDIFF(CDAR A,X)),PDIFF(CDR A,X))
  368. END;
  369. SYMBOLIC PROCEDURE MKKERNEL X;
  370. BEGIN SCALAR KERNELS,K,OP;
  371. K:=KERNELS:=GET(OP:=CAR X,'KERNELS);
  372. L: IF NULL K THEN RETURN<<PUT(OP,'KERNELS,X.KERNELS);X>>;
  373. IF X=CAR K THEN RETURN CAR K;
  374. K:=CDR K;
  375. GOTO L
  376. END;
  377. %***************************** Parser *********************************
  378. % Simple parser creates expressions to be evaluated by the
  379. % rational polynomial routines.
  380. % J. Marti, August 1980.
  381. % Modified and Extended by GRISS and GALWAY
  382. % Rewritten to be left associative by OTTENHEIMER, March 1981
  383. GLOBAL '(TOK!*);
  384. SYMBOLIC PROCEDURE RPARSE(); %. PARSE Infix to Prefix
  385. BEGIN SCALAR X;
  386. NTOKEN();
  387. IF TOK!* EQ '!; THEN RETURN NIL; % Fix for null exp RBO 9 Feb 81
  388. IF NULL(X := REXP()) THEN RETURN ERROR(105, '(Unparsable Expression));
  389. IF TOK!* NEQ '!; THEN RETURN ERROR(106, '(Missing !; at end of expression));
  390. RETURN X
  391. END RPARSE;
  392. SYMBOLIC PROCEDURE REXP(); %. Parse an EXP and rename OP
  393. BEGIN SCALAR LEFT, RIGHT,OP;
  394. IF NOT (LEFT := RTERM()) THEN RETURN NIL;
  395. WHILE (OP := GET(TOK!*,'REXP)) DO
  396. << NTOKEN();
  397. IF NOT(RIGHT := RTERM()) THEN RETURN ERROR(100, '(Missing Term in Exp));
  398. LEFT := LIST(OP, LEFT, RIGHT)
  399. >>;
  400. RETURN LEFT
  401. END REXP;
  402. SYMBOLIC PROCEDURE RTERM(); %. PARSE a TERM
  403. BEGIN SCALAR LEFT, RIGHT, OP;
  404. IF NOT (LEFT := RPRIMARY()) THEN RETURN NIL;
  405. WHILE (OP := GET(TOK!*,'RTERM)) DO
  406. << NTOKEN();
  407. IF NOT (RIGHT := RPRIMARY()) THEN
  408. RETURN ERROR (101, '(Missing Primary in Term));
  409. LEFT := LIST(OP, LEFT, RIGHT)
  410. >>;
  411. RETURN LEFT
  412. END RTERM;
  413. SYMBOLIC PROCEDURE RPRIMARY(); %. RPRIMARY, allows "^" and "'"
  414. BEGIN SCALAR LEFT, RIGHT, OP;
  415. IF TOK!* EQ '!+ THEN RETURN <<NTOKEN(); RPRIMARY0()>>;
  416. IF TOK!* EQ '!-
  417. THEN RETURN << NTOKEN();
  418. IF (LEFT := RPRIMARY0()) THEN LIST('MINUS, LEFT)
  419. ELSE RETURN ERROR(200,'(Missing Primary0 after MINUS))
  420. >>;
  421. IF NOT (LEFT := RPRIMARY0()) THEN RETURN NIL;
  422. WHILE (OP := GET(TOK!*,'RPRIMARY)) DO
  423. << NTOKEN();
  424. IF NOT (RIGHT := RPRIMARY0()) THEN
  425. RETURN ERROR(200, '(Missing Primary0 in Primary));
  426. LEFT := LIST(OP, LEFT, RIGHT)
  427. >>;
  428. RETURN LEFT;
  429. END RPRIMARY;
  430. SYMBOLIC PROCEDURE RPRIMARY0(); %. Variables, etc
  431. BEGIN SCALAR EXP, ARGS;
  432. IF TOK!* EQ '!( THEN
  433. << NTOKEN();
  434. IF NOT (EXP := REXP()) THEN RETURN ERROR(102, '(Missing Expression));
  435. IF TOK!* NEQ '!) THEN RETURN ERROR(103, '(Missing Right Parenthesis));
  436. NTOKEN();
  437. RETURN EXP
  438. >>;
  439. IF NUMBERP(EXP := TOK!*)
  440. THEN RETURN <<NTOKEN(); EXP>>;
  441. IF NOT IDP EXP THEN RETURN NIL;
  442. NTOKEN();
  443. IF ARGS := RARGS(EXP) THEN RETURN ARGS;
  444. RETURN EXP;
  445. END RPRIMARY0;
  446. SYMBOLIC PROCEDURE RARGS(X);
  447. BEGIN SCALAR ARGS,ARG;
  448. IF TOK!* NEQ '!( THEN RETURN NIL;
  449. NTOKEN();
  450. IF TOK!* EQ '!) THEN RETURN <<NTOKEN();X . NIL>>;
  451. L: IF NOT (ARG :=REXP()) THEN ERROR(104,'(Not expression in ARGLST));
  452. ARGS := ARG . ARGS;
  453. IF TOK!* EQ '!, THEN <<NTOKEN(); GOTO L>>;
  454. IF TOK!* EQ '!) THEN RETURN <<NTOKEN();X . REVERSE ARGS>>;
  455. ERROR(105,'(Missing !) or !, in ARGLST));
  456. END;
  457. SYMBOLIC PROCEDURE MKATOM X;
  458. % Use LIST('RCREATE, LIST('QUOTE,x)); if doing EVAL mode
  459. X;
  460. %******************* Printing Routines ********************************
  461. SYMBOLIC PROCEDURE PPRINT A;
  462. % Print internal canonical form in Infix notation.
  463. IF NUMBERP A THEN PRIN2 A ELSE
  464. BEGIN
  465. IF NUMBERP CDAR A THEN
  466. IF CDAR A = 0 THEN
  467. << PRIN2 '0; RETURN NIL >>
  468. ELSE IF CDAR A NEQ 1 THEN
  469. << PRIN2 CDAR A; PRIN2 '!* >>
  470. ELSE
  471. ELSE IF RPREC!* CDAR A THEN << PPRINT CDAR A; PRIN2 '!* >>
  472. ELSE <<PRIN2 '!(; PPRINT CDAR A; PRIN2 '!)!* >>;
  473. IF CDAAR A = 0 THEN PRIN2 1
  474. ELSE IF CDAAR A = 1 THEN PRIN2 CAAAR A
  475. ELSE << PRIN2 CAAAR A; PRIN2 '!^;
  476. IF RPREC!^ CDAAR A THEN PPRINT CDAAR A
  477. ELSE <<PRIN2 '!(; PPRINT CAAAR A; PRIN2 '!) >> >>;
  478. IF NUMBERP CDR A THEN
  479. IF CDR A> 0 THEN <<PRIN2 '!+ ; PRIN2 CDR A; RETURN NIL>>
  480. ELSE IF CDR A < 0 THEN <<PRIN2 '!-! ; PRIN2 (-CDR A);
  481. RETURN NIL>>
  482. ELSE RETURN NIL;
  483. IF ATOM CDR A THEN <<PRIN2 '!+ ; PRIN2 CDR A; RETURN NIL>>;
  484. PRIN2 '!+ ; PPRINT CDR A;
  485. END;
  486. SYMBOLIC PROCEDURE RPREC!* X; %. T if there is no significant addition in X.
  487. ATOM X OR (NUMBERP POLRED X AND POLRED X = 0);
  488. SYMBOLIC PROCEDURE RPREC!^ X; %. T if there is not significant addition or multiplication in X.
  489. RPREC!* X AND (ATOM X OR
  490. (ATOM CDAR X AND NUMBERP CDAR X));
  491. SYMBOLIC PROCEDURE SIMPLE X; %. POL that doest need ()
  492. ATOM X OR ((POLRED X=0) AND (POLEXPT X=1) AND (POLCOEF X =1));
  493. SYMBOLIC PROCEDURE RATPRINT A; %. Print a RAT
  494. BEGIN
  495. IF CDR A = 1 THEN PPRINT CAR A
  496. ELSE <<NPRINT CAR A;
  497. PRIN2 '!/;
  498. NPRINT CDR A>>;
  499. TERPRI()
  500. END;
  501. SYMBOLIC PROCEDURE NPRINT A; %. Add parens, if needed
  502. IF NOT SIMPLE A THEN <<PRIN2 '!( ; PPRINT A; PRIN2 '!) >>
  503. ELSE PPRINT A;
  504. %. Convert RCAN back to PREFIX form
  505. SYMBOLIC PROCEDURE RAT2PRE X; %. RATIONAL to Prefix
  506. IF RATDEN X = 1 THEN POL2PRE RATNUM X
  507. ELSE LIST('QUOTIENT,POL2PRE RATNUM X, POL2PRE RATDEN X);
  508. SYMBOLIC PROCEDURE POL2PRE X; %. Polynomial to Prefix
  509. BEGIN SCALAR TT,RR;
  510. IF NOT PAIRP X THEN RETURN X;
  511. TT:=TRM2PRE POLTRM X;
  512. RR:=POL2PRE POLRED X;
  513. IF RR = 0 THEN RETURN TT;
  514. IF NUMBERP RR AND RR <0 THEN RETURN LIST('DIFFERENCE,TT,-RR);
  515. RETURN LIST('PLUS2,TT,RR);
  516. END;
  517. SYMBOLIC PROCEDURE TRM2PRE X; %. Term to Prefix
  518. IF TRMCOEF X = 1 THEN PWR2PRE TRMPWR X
  519. ELSE IF TRMCOEF X = (-1) THEN LIST('MINUS,PWR2PRE TRMPWR X)
  520. ELSE LIST('TIMES2,POL2PRE TRMCOEF X,PWR2PRE TRMPWR X);
  521. SYMBOLIC PROCEDURE PWR2PRE X; %. Power to Prefix
  522. IF PWREXPT X = 1 THEN PWRVAR X
  523. ELSE LIST('EXPT,PWRVAR X,PWREXPT X);
  524. %. prefix Pretty print
  525. SYMBOLIC PROCEDURE PREPRIN(A,PARENS); %. Print PREFIX form in Infix notation.
  526. BEGIN SCALAR PRINOP;
  527. IF ATOM A THEN RETURN PRIN2 A;
  528. IF (PRINOP:=GET(CAR A,'PRINOP))
  529. THEN RETURN XAPPLY(PRINOP,LIST(A,PARENS));
  530. PRIN2(CAR A); PRINARGS CDR A;
  531. RETURN A;
  532. END;
  533. SYMBOLIC PROCEDURE PRINARGS A; %. Print ArgLIST
  534. IF NOT PAIRP A THEN PRIN2 '!(!)
  535. ELSE <<PRIN2 '!(; WHILE PAIRP A DO
  536. <<PREPRIN(CAR A,NIL);
  537. IF PAIRP (A:=CDR A) THEN PRIN2 '!,>>;
  538. PRIN2 '!)>>;
  539. SYMBOLIC PROCEDURE PREPRINT A;
  540. <<PREPRIN(A,NIL); TERPRI(); A>>;
  541. SYMBOLIC PROCEDURE NARYPRIN(OP,ARGS,PARENS);
  542. IF NOT PAIRP ARGS THEN NIL
  543. ELSE IF NOT PAIRP CDR ARGS THEN PREPRIN(CAR ARGS,PARENS)
  544. ELSE <<IF PARENS THEN PRIN2 '!(;
  545. WHILE PAIRP ARGS DO
  546. <<PREPRIN(CAR ARGS,T); % Need precedence here
  547. IF PAIRP(ARGS:=CDR ARGS) THEN PRIN2 OP>>;
  548. IF PARENS THEN PRIN2 '!)>>;
  549. SYMBOLIC PROCEDURE PLUSPRIN(A,PARENS);
  550. NARYPRIN('! !+! ,CDR A,PARENS);
  551. SYMBOLIC PROCEDURE DIFFERENCEPRIN(A,PARENS);
  552. NARYPRIN('! !-! ,CDR A,PARENS);
  553. SYMBOLIC PROCEDURE TIMESPRIN(A,PARENS);
  554. NARYPRIN('!*,CDR A,PARENS);
  555. SYMBOLIC PROCEDURE QUOTPRIN(A,PARENS);
  556. NARYPRIN('!/,CDR A,PARENS);
  557. SYMBOLIC PROCEDURE EXPPRIN(A,PARENS);
  558. NARYPRIN('!^,CDR A,PARENS);
  559. ON RAISE;
  560. END;