alg1.red 116 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946
  1. %*********************************************************************
  2. %*********************************************************************
  3. % REDUCE BASIC ALGEBRAIC PROCESSOR (PART 1)
  4. %*********************************************************************
  5. %********************************************************************;
  6. %Copyright (c) 1983 The Rand Corporation;
  7. SYMBOLIC;
  8. %*********************************************************************
  9. % NON-LOCAL VARIABLES REFERENCED IN THIS SECTION
  10. %********************************************************************;
  11. FLUID '(ALGLIST!* ARBL!* !*EXP !*GCD !*INTSTR !*LCM !*MCD !*MODE);
  12. GLOBAL '(ASYMPLIS!* CURSYM!* DMODE!* DOMAINLIST!* EXLIST!* EXPTL!*
  13. EXPTP!* FRASC!* FRLIS!* INITL!* KORD!* KPROPS!* LETL!* MCHFG!*
  14. MCOND!* MOD!* MUL!* NAT!*!* NCMP!* OFL!* POSN!* POWLIS!*
  15. POWLIS1!* SPLIS!* SUBFG!* TSTACK!* TYPL!* WS WTL!* !*EZGCD
  16. !*FLOAT !*FORT !*GROUP !*INT !*MATCH !*MSG !*NAT !*NERO
  17. !*NOSUBS !*NUMVAL !*OUTP !*PERIOD !*PRI !*RESUBS !*SQVAR!*
  18. !*SUB2 !*VAL !*XDN);
  19. GLOBAL '(DSUBL!* SUBL!*); %not used at moment;
  20. ALGLIST!* := NIL; %association list for previously simplified
  21. %expressions;
  22. ARBL!* := NIL; %used for storage of arbitrary vars in LET
  23. %statements;
  24. ASYMPLIS!* := NIL; %association list of asymptotic replacements;
  25. % CURSYM!* current symbol (i. e. identifier, parenthesis,
  26. % delimiter, e.t.c,) in input line;
  27. DMODE!* := NIL; %name of current polynomial domain mode if not
  28. %integer;
  29. DOMAINLIST!* := NIL; %list of currently supported poly domain modes;
  30. %DSUBL!* := NIL; %list of previously calculated derivatives of
  31. % expressions;
  32. EXLIST!* := '((!*)); %property list for standard forms used as
  33. % kernels;
  34. EXPTL!* := NIL; %list of exprs with non-integer exponents;
  35. EXPTP!* := NIL; %flag telling EXPTs appear in LET statements;
  36. FRASC!* := NIL; %association list for free variables in
  37. %substitution rules;
  38. FRLIS!* := NIL; %list of renamed free variables to be found in
  39. %substitutions;
  40. INITL!* := APPEND('(FRASC!* MCOND!* SUBFG!* !*SUB2 TSTACK!*),INITL!*);
  41. KORD!* := NIL; %kernel order in standard forms;
  42. KPROPS!* := NIL; %list of active non-atomic kernel plists;
  43. LETL!* := '(LET MATCH CLEAR SAVEAS SUCH); %special delimiters;
  44. MCHFG!* := NIL; %indicates that a pattern match occurred during
  45. %a cycle of the matching routines;
  46. MCOND!* := NIL; %used for temporary storage of a conditional
  47. %expression in a substitution;
  48. MOD!* := NIL; %modular base, NIL for integer arithmetic;
  49. MUL!* := NIL; %list of additional evaluations needed in a
  50. %given multiplication;
  51. NAT!*!* := NIL; %temporary variable used in algebraic mode;
  52. NCMP!* := NIL; %flag indicating non-commutative multiplication
  53. %mode;
  54. OFL!* := NIL; %current output file name;
  55. POSN!* := NIL; %used to store output character position in
  56. %printing functions;
  57. POWLIS!* := NIL; %association list of replacements for powers;
  58. POWLIS1!* := NIL; %association list of conditional replacements
  59. %for powers;
  60. SPLIS!* := NIL; %substitution list for sums and products;
  61. SUBFG!* := T; %flag to indicate whether substitution
  62. %is required during evaluation;
  63. %SUBL!* := NIL; %list of previously evaluated expressions;
  64. TSTACK!* := 0; %stack counter in SIMPTIMES;
  65. % TYPL!*;
  66. WTL!* := NIL; %tells that a WEIGHT assignment has been made;
  67. !*EXP := T; %expansion control flag;
  68. !*EZGCD := NIL; %ezgcd calculation flag;
  69. !*FLOAT := NIL; %floating arithmetic mode flag;
  70. !*FORT := NIL; %specifies FORTRAN output;
  71. !*GCD := NIL; %greatest common divisor mode flag;
  72. !*GROUP := NIL; %causes expressions to be grouped when EXP off;
  73. !*INTSTR := NIL; %makes expression arguments structured;
  74. %!*INT indicates interactive system use;
  75. !*LCM := T; %least common multiple computation flag;
  76. !*MATCH := NIL; %list of pattern matching rules;
  77. !*MCD := T; %common denominator control flag;
  78. !*MODE := 'SYMBOLIC; %current evaluation mode;
  79. !*MSG := T; %flag controlling message printing;
  80. !*NAT := T; %specifies natural printing mode;
  81. !*NERO := NIL; %flag to suppress printing of zeros;
  82. !*NOSUBS := NIL; %internal flag controlling substitution;
  83. !*NUMVAL := NIL; %used to indicate that numerical expressions
  84. %should be converted to a real value;
  85. !*OUTP := NIL; %holds prefix output form for extended output
  86. %package;
  87. !*PERIOD := T; %prints a period after a fixed coefficient
  88. %when FORT is on;
  89. !*PRI := NIL; %indicates that fancy output is required;
  90. !*RESUBS := T; %external flag controlling resubstitution;
  91. !*SQVAR!*:='(T); %variable used by *SQ expressions to control
  92. %resimplification;
  93. !*SUB2 := NIL; %indicates need for call of RESIMP;
  94. !*VAL := T; %controls operator argument evaluation;
  95. !*XDN := T; %flag indicating that denominators should be
  96. %expanded;
  97. %initial values of some global variables in BEGIN1 loops;
  98. PUT('TSTACK!*,'INITL,0);
  99. PUT('SUBFG!*,'INITL,T);
  100. %Old name for the expression workspace;
  101. %PUT('!*ANS,'NEWNAM,'WS);
  102. %*********************************************************************
  103. % GENERAL FUNCTIONS
  104. %********************************************************************;
  105. SYMBOLIC PROCEDURE ATOMLIS U;
  106. NULL U OR (ATOM CAR U AND ATOMLIS CDR U);
  107. SYMBOLIC PROCEDURE CARX(U,V);
  108. IF NULL CDR U THEN CAR U
  109. ELSE REDERR LIST("Wrong number of arguments to",V);
  110. SYMBOLIC PROCEDURE DELASC(U,V);
  111. IF NULL V THEN NIL
  112. ELSE IF ATOM CAR V OR U NEQ CAAR V THEN CAR V . DELASC(U,CDR V)
  113. ELSE CDR V;
  114. SYMBOLIC PROCEDURE LENGTHC U;
  115. %gives character length of U excluding string and escape chars;
  116. BEGIN INTEGER N; SCALAR X;
  117. N := 0;
  118. X := EXPLODE U;
  119. IF CAR X EQ '!" THEN RETURN LENGTH X-2;
  120. WHILE X DO
  121. <<IF CAR X EQ '!! THEN X := CDR X;
  122. N := N+1;
  123. X := CDR X>>;
  124. RETURN N
  125. END;
  126. SYMBOLIC PROCEDURE GET!*(U,V);
  127. IF NUMBERP U THEN NIL ELSE GET(U,V);
  128. SYMBOLIC PROCEDURE MAPCONS(U,V);
  129. FOR EACH J IN U COLLECT V . J;
  130. SYMBOLIC PROCEDURE MAPPEND(U,V);
  131. FOR EACH J IN U COLLECT APPEND(V,J);
  132. SYMBOLIC PROCEDURE NLIST(U,N);
  133. IF N=0 THEN NIL ELSE U . NLIST(U,N-1);
  134. SYMBOLIC PROCEDURE NTH(U,N);
  135. CAR PNTH(U,N);
  136. SYMBOLIC PROCEDURE PNTH(U,N);
  137. IF NULL U THEN REDERR "Index out of range"
  138. ELSE IF N=1 THEN U
  139. ELSE PNTH(CDR U,N-1);
  140. SYMBOLIC PROCEDURE PERMP(U,V);
  141. IF NULL U THEN T
  142. ELSE IF CAR U EQ CAR V THEN PERMP(CDR U,CDR V)
  143. ELSE NOT PERMP(CDR U,SUBST(CAR V,CAR U,CDR V));
  144. SYMBOLIC PROCEDURE REMOVE(X,N);
  145. %Returns X with Nth element removed;
  146. IF NULL X THEN NIL
  147. ELSE IF N=1 THEN CDR X
  148. ELSE CAR X . REMOVE(CDR X,N-1);
  149. SYMBOLIC PROCEDURE REVPR U;
  150. CDR U . CAR U;
  151. SYMBOLIC PROCEDURE REPEATS X;
  152. IF NULL X THEN NIL
  153. ELSE IF CAR X MEMBER CDR X THEN CAR X . REPEATS CDR X
  154. ELSE REPEATS CDR X;
  155. SYMBOLIC PROCEDURE SMEMBER(U,V);
  156. %determines if S-expression U is a member of V at any level;
  157. IF U=V THEN T
  158. ELSE IF ATOM V THEN NIL
  159. ELSE SMEMBER(U,CAR V) OR SMEMBER(U,CDR V);
  160. SYMBOLIC PROCEDURE SMEMQ(U,V);
  161. %true if id U is a member of V at any level (excluding
  162. %quoted expressions);
  163. IF ATOM V THEN U EQ V
  164. ELSE IF CAR V EQ 'QUOTE THEN NIL
  165. ELSE SMEMQ(U,CAR V) OR SMEMQ(U,CDR V);
  166. SYMBOLIC PROCEDURE SMEMQL(U,V);
  167. %Returns those members of id list U contained in V at any
  168. %level (excluding quoted expressions);
  169. IF NULL U THEN NIL
  170. ELSE IF SMEMQ(CAR U,V) THEN CAR U . SMEMQL(CDR U,V)
  171. ELSE SMEMQL(CDR U,V);
  172. SYMBOLIC PROCEDURE SMEMQLP(U,V);
  173. %True if any member of id list U is contained at any level
  174. %in V (exclusive of quoted expressions);
  175. IF NULL V THEN NIL
  176. ELSE IF ATOM V THEN V MEMQ U
  177. ELSE IF CAR V EQ 'QUOTE THEN NIL
  178. ELSE SMEMQLP(U,CAR V) OR SMEMQLP(U,CDR V);
  179. SYMBOLIC PROCEDURE SPACES N; FOR I:= 1:N DO PRIN2 " ";
  180. SYMBOLIC PROCEDURE SUBLA(U,V);
  181. BEGIN SCALAR X;
  182. IF NULL U OR NULL V THEN RETURN V
  183. ELSE IF ATOM V
  184. THEN RETURN IF X:= ATSOC(V,U) THEN CDR X ELSE V
  185. ELSE RETURN(SUBLA(U,CAR V) . SUBLA(U,CDR V))
  186. END;
  187. SYMBOLIC PROCEDURE XNP(U,V);
  188. %returns true if the atom lists U and V have at least one common
  189. %element;
  190. U AND (CAR U MEMQ V OR XNP(CDR U,V));
  191. %*********************************************************************
  192. % FUNCTIONS FOR PRINTING DIAGNOSTIC AND ERROR MESSAGES
  193. %********************************************************************;
  194. SYMBOLIC PROCEDURE MSGPRI(U,V,W,X,Y);
  195. BEGIN SCALAR NAT1,Z;
  196. IF NULL Y AND NULL !*MSG THEN RETURN;
  197. NAT1 := !*NAT;
  198. !*NAT := NIL;
  199. IF OFL!* AND (!*FORT OR NOT NAT1) THEN GO TO C;
  200. A: TERPRI();
  201. LPRI ((IF NULL Y THEN "***" ELSE "*****")
  202. . IF U AND ATOM U THEN LIST U ELSE U);
  203. POSN!* := POSN();
  204. MAPRIN V;
  205. PRIN2 " ";
  206. LPRI IF W AND ATOM W THEN LIST W ELSE W;
  207. POSN!* := POSN();
  208. MAPRIN X;
  209. IF NOT Y OR Y EQ 'HOLD THEN TERPRI();
  210. IF NULL Z THEN GO TO B;
  211. WRS CDR Z;
  212. GO TO D;
  213. B: IF NULL OFL!* THEN GO TO D;
  214. C: Z := OFL!*;
  215. WRS NIL;
  216. GO TO A;
  217. D: !*NAT := NAT1;
  218. IF Y THEN IF Y EQ 'HOLD THEN ERFG!* := Y ELSE ERROR1()
  219. END;
  220. SYMBOLIC PROCEDURE ERRACH U;
  221. BEGIN
  222. TERPRI!* T;
  223. LPRIE "CATASTROPHIC ERROR *****";
  224. PRINTTY U;
  225. LPRIW(" ",NIL);
  226. REDERR "Please send output and input listing to A. C. Hearn"
  227. END;
  228. SYMBOLIC PROCEDURE ERRPRI1 U;
  229. MSGPRI("Substitution for",U,"not allowed",NIL,'HOLD);
  230. SYMBOLIC PROCEDURE ERRPRI2(U,V);
  231. MSGPRI("Syntax error:",U,"invalid",NIL,V);
  232. SYMBOLIC PROCEDURE REDMSG(U,V);
  233. IF NULL !*MSG THEN NIL
  234. ELSE IF TERMINALP() THEN YESP LIST("Declare",U,V,"?") OR ERROR1()
  235. ELSE LPRIM LIST(U,"declared",V);
  236. SYMBOLIC PROCEDURE TYPERR(U,V);
  237. <<TERPRI!* T;
  238. PRIN2!* "***** ";
  239. IF NOT ATOM U AND ATOM CAR U AND ATOM CADR U AND NULL CDDR U
  240. THEN <<PRIN2!* CAR U; PRIN2!* " "; PRIN2!* CADR U>>
  241. ELSE MAPRIN U;
  242. PRIN2!* " invalid as "; PRIN2!* V;
  243. TERPRI!* NIL; ERFG!* := T; ERROR1()>>;
  244. %*********************************************************************
  245. % ALGEBRAIC MODE FUNCTIONS AND DECLARATIONS REFERENCED IN SECTION 1
  246. %********************************************************************;
  247. %SYMBOLIC PROCEDURE APROC(U,V);
  248. % IF NULL U THEN NIL
  249. % ELSE IF ATOM U
  250. % THEN IF NUMBERP U AND FIXP U THEN U ELSE LIST(V,MKARG U)
  251. % ELSE IF FLAGP(CAR U,'NOCHANGE) OR GET(CAR U,'STAT) THEN U
  252. % ELSE IF FLAGP(CAR U,'BOOLEAN)
  253. % THEN CAR U . FOR EACH J IN CDR U COLLECT APROC(J,'REVAL)
  254. % ELSE IF CDR U AND EQCAR(CADR U,'QUOTE) THEN U
  255. % ELSE LIST(V,MKARG U);
  256. SYMBOLIC PROCEDURE FORMINPUT(U,VARS,MODE);
  257. BEGIN SCALAR X;
  258. IF X := ASSOC(CAR U,INPUTBUFLIS!*) THEN RETURN CDR X
  259. ELSE REDERR LIST("Entry",CAR U,"not found")
  260. END;
  261. PUT('INPUT,'FORMFN,'FORMINPUT);
  262. SYMBOLIC PROCEDURE FORMWS(U,VARS,MODE);
  263. BEGIN SCALAR X;
  264. IF X := ASSOC(CAR U,RESULTBUFLIS!*) THEN RETURN MKQUOTE CDR X
  265. ELSE REDERR LIST("Entry",CAR U,"not found")
  266. END;
  267. PUT('WS,'FORMFN,'FORMWS);
  268. FLAG ('(AEVAL ARRAYFN COND FLAG GETEL GO PROG PROGN PROG2 RETURN
  269. SETQ SETK SETEL VARPRI),'NOCHANGE);
  270. %NB: FLAG IS NEEDED IN ALGEBRAIC PROC/OPERATOR DEFINITION;
  271. FLAG ('(OR AND NOT MEMBER MEMQ EQUAL NEQ EQ GEQ GREATERP LEQ
  272. FIXP LESSP NUMBERP ORDP),'BOOLEAN);
  273. FLAG ('(OR AND NOT),'BOOLARGS);
  274. DEFLIST ('((SUM (ADDSQ . (NIL . 1))) (PRODUCT (MULTSQ . (1 . 1)))),
  275. 'BIN);
  276. FLAG ('(SUM PRODUCT),'DELIM);
  277. FLAG ('(SUM PRODUCT),'NODEL);
  278. DEFLIST ('((EXP ((NIL (RMSUBS1)) (T (RMSUBS))))
  279. (FACTOR ((NIL (SETQ !*EXP T))
  280. (T (SETQ !*EXP NIL) (RMSUBS))))
  281. (FORT ((NIL (SETQ !*NAT NAT!*!*)) (T (SETQ !*NAT NIL))))
  282. (GCD ((T (RMSUBS))))
  283. (MCD ((NIL (RMSUBS)) (T (RMSUBS))))
  284. (NAT ((NIL (SETQ NAT!*!* NIL)) (T (SETQ NAT!*!* T))))
  285. (NUMVAL ((T (RMSUBS)) (NIL (SETDMODE NIL))))
  286. (VAL ((T (RMSUBS))))
  287. (FLOAT ((T (RMSUBS))))),'SIMPFG);
  288. %*********************************************************************
  289. % SELECTORS AND CONSTRUCTORS USED IN ALGEBRAIC CALCULATIONS
  290. %********************************************************************;
  291. NEWTOK '((!. !+) ADD);
  292. NEWTOK '((!. !*) MULT);
  293. NEWTOK '((!. !* !*) TO);
  294. NEWTOK '((!. !/) OVER);
  295. INFIX TO,.*,.+,./;
  296. SMACRO PROCEDURE U.+V; %standard (polynomial) addition constructor;
  297. U . V;
  298. SMACRO PROCEDURE LC U; %leading coefficient of standard form;
  299. CDAR U;
  300. SMACRO PROCEDURE LDEG U; %leading degree of standard form;
  301. CDAAR U;
  302. SMACRO PROCEDURE LT U; %leading term of standard form;
  303. CAR U;
  304. SMACRO PROCEDURE U.*V; %standard form multiplication constructor;
  305. U . V;
  306. SMACRO PROCEDURE MVAR U; %main variable of standard form;
  307. CAAAR U;
  308. SMACRO PROCEDURE LPOW U; %leading power of standard form;
  309. CAAR U;
  310. SMACRO PROCEDURE PDEG U;
  311. %returns the degree of the power U;
  312. CDR U;
  313. SMACRO PROCEDURE RED U; %reductum of standard form;
  314. CDR U;
  315. SMACRO PROCEDURE TC U; %coefficient of standard term;
  316. CDR U;
  317. SMACRO PROCEDURE TDEG U; %degree of standard term;
  318. CDAR U;
  319. SMACRO PROCEDURE TPOW U; %power of standard term;
  320. CAR U;
  321. SMACRO PROCEDURE TVAR U; %main variable of a standard term;
  322. CAAR U;
  323. SMACRO PROCEDURE NUMR U; %numerator of standard quotient;
  324. CAR U;
  325. SMACRO PROCEDURE DENR U; %denominator of standard quotient;
  326. CDR U;
  327. SMACRO PROCEDURE U ./ V; %constructor for standard quotient;
  328. U . V;
  329. %*********************************************************************
  330. % MACROS AND PROCEDURES FOR CONVERTING BETWEEN VARIOUS FORMS
  331. %********************************************************************;
  332. SYMBOLIC PROCEDURE !*A2F U;
  333. %U is an algebraic expression. Value is the equivalent form
  334. %or an error if conversion is not possible;
  335. !*Q2F SIMP!* U;
  336. SYMBOLIC PROCEDURE !*A2K U;
  337. %U is an algebraic expression. Value is the equivalent kernel
  338. %or an error if conversion is not possible.
  339. %earlier versions used SIMP0;
  340. BEGIN SCALAR X;
  341. IF KERNP(X := SIMP!* U) THEN RETURN MVAR NUMR X
  342. ELSE TYPERR(U,'kernel)
  343. END;
  344. SMACRO PROCEDURE !*F2A U; PREPF U;
  345. SMACRO PROCEDURE !*F2Q U;
  346. %U is a standard form, value is a standard quotient;
  347. U . 1;
  348. SMACRO PROCEDURE !*K2F U;
  349. %U is a kernel, value is a standard form;
  350. LIST (TO(U,1) . 1);
  351. SMACRO PROCEDURE !*K2Q U;
  352. %U is a kernel, value is a standard quotient;
  353. LIST(TO(U,1) . 1) . 1;
  354. SYMBOLIC PROCEDURE !*N2F U;
  355. %U is a number. Value is a standard form;
  356. IF ZEROP U THEN NIL ELSE U;
  357. SMACRO PROCEDURE !*P2F U;
  358. %U is a standard power, value is a standard form;
  359. LIST (U . 1);
  360. SMACRO PROCEDURE !*P2Q U;
  361. %U is a standard power, value is a standard quotient;
  362. LIST(U . 1) . 1;
  363. SYMBOLIC PROCEDURE !*Q2F U;
  364. %U is a standard quotient, value is a standard form;
  365. IF DENR U=1 THEN NUMR U ELSE TYPERR(PREPSQ U,'polynomial);
  366. SYMBOLIC PROCEDURE !*Q2K U;
  367. %U is a standard quotient, value is a kernel or an error if
  368. %conversion not possible;
  369. IF KERNP U THEN MVAR NUMR U
  370. ELSE TYPERR(PREPSQ U,'kernel);
  371. SMACRO PROCEDURE !*T2F U;
  372. %U is a standard term, value is a standard form;
  373. LIST U;
  374. SMACRO PROCEDURE !*T2Q U;
  375. %U is a standard term, value is a standard quotient;
  376. LIST U . 1;
  377. %*********************************************************************
  378. % FUNCTIONS FOR ALGEBRAIC EVALUATION OF PREFIX FORMS
  379. %********************************************************************;
  380. SYMBOLIC PROCEDURE REVAL U;
  381. REVAL1(U,T);
  382. SYMBOLIC PROCEDURE AEVAL U;
  383. REVAL1(U,NIL);
  384. SYMBOLIC PROCEDURE REVAL1(U,V);
  385. BEGIN SCALAR ALGLIST!*,X,Y;
  386. LOOP:
  387. IF STRINGP U THEN RETURN U
  388. ELSE IF NUMBERP U AND FIXP U
  389. THEN IF MOD!* THEN GO TO B ELSE RETURN U
  390. ELSE IF ATOM U THEN NIL
  391. ELSE IF CAR U EQ '!*COMMA!* THEN ERRPRI2(U,T)
  392. ELSE IF CAR U EQ '!*SQ THEN GO TO B
  393. ELSE IF ARRAYP CAR U
  394. THEN <<U := GETELV U; GO TO LOOP>>;
  395. X := LIST U;
  396. Y := TYPL!*;
  397. A: IF NULL Y THEN GO TO B
  398. ELSE IF APPLY(CAR Y,X)
  399. THEN RETURN APPLY(GET(CAR Y,'EVFN),X);
  400. Y := CDR Y;
  401. GO TO A;
  402. B: U := SIMP!* U;
  403. IF NULL V THEN RETURN MK!*SQ U;
  404. U := PREPSQX U;
  405. RETURN IF EQCAR(U,'MINUS) AND NUMBERP CADR U THEN -CADR U
  406. ELSE U
  407. END;
  408. SYMBOLIC PROCEDURE PREPSQX U;
  409. IF !*INTSTR THEN PREPSQ!* U ELSE PREPSQ U;
  410. SYMBOLIC PROCEDURE IEVAL U;
  411. %returns algebraic value of U if U is an integer or an error;
  412. BEGIN
  413. IF NUMBERP U
  414. THEN IF FIXP U THEN RETURN U ELSE TYPERR(U,"integer")
  415. ELSE IF NOT ATOM U AND ARRAYP CAR U THEN U := GETELV U;
  416. U := SIMP!* U;
  417. IF DENR U NEQ 1 OR NOT ATOM NUMR U
  418. THEN TYPERR(PREPSQ U,"integer");
  419. U := NUMR U;
  420. IF NULL U THEN U := 0;
  421. RETURN U
  422. END;
  423. SYMBOLIC PROCEDURE GETELV U;
  424. %returns the value of the array element U;
  425. GETEL(CAR U . FOR EACH X IN CDR U COLLECT IEVAL X);
  426. SYMBOLIC PROCEDURE SETELV(U,V);
  427. SETEL(CAR U . FOR EACH X IN CDR U COLLECT IEVAL X,V);
  428. SYMBOLIC PROCEDURE REVLIS U; FOR EACH J IN U COLLECT REVAL J;
  429. SYMBOLIC PROCEDURE REVOP1 U;
  430. IF !*VAL THEN CAR U . REVLIS CDR U ELSE U;
  431. SYMBOLIC PROCEDURE MK!*SQ U;
  432. IF NULL NUMR U THEN 0
  433. ELSE IF ATOM NUMR U AND DENR U=1 THEN NUMR U
  434. ELSE '!*SQ . EXPCHK U . IF !*RESUBS THEN !*SQVAR!* ELSE LIST NIL;
  435. SYMBOLIC PROCEDURE EXPCHK U;
  436. IF !*EXP THEN U ELSE CANPROD(MKPROD!* NUMR U,MKPROD!* DENR U);
  437. %*********************************************************************
  438. % EVALUATION FUNCTIONS FOR BOOLEAN OPERATORS
  439. %********************************************************************;
  440. SYMBOLIC PROCEDURE EVALEQUAL(U,V);
  441. (LAMBDA X; NUMBERP X AND ZEROP X) REVAL LIST('DIFFERENCE,U,V);
  442. PUT('EQUAL,'BOOLFN,'EVALEQUAL);
  443. SYMBOLIC PROCEDURE EVALGREATERP(U,V);
  444. (LAMBDA X;
  445. ATOM DENR X AND DOMAINP NUMR X AND NUMR X AND !:MINUSP NUMR X)
  446. SIMP!* LIST('DIFFERENCE,V,U);
  447. PUT('GREATERP,'BOOLFN,'EVALGREATERP);
  448. SYMBOLIC PROCEDURE EVALGEQ(U,V); NOT EVALLESSP(U,V);
  449. PUT('GEQ,'BOOLFN,'EVALGEQ);
  450. SYMBOLIC PROCEDURE EVALLESSP(U,V);
  451. (LAMBDA X;
  452. ATOM DENR X AND DOMAINP NUMR X AND NUMR X AND !:MINUSP NUMR X)
  453. SIMP!* LIST('DIFFERENCE,U,V);
  454. PUT('LESSP,'BOOLFN,'EVALLESSP);
  455. SYMBOLIC PROCEDURE EVALLEQ(U,V); NOT EVALGREATERP(U,V);
  456. PUT('LEQ,'BOOLFN,'EVALLEQ);
  457. SYMBOLIC PROCEDURE EVALNEQ(U,V); NOT EVALEQUAL(U,V);
  458. PUT('NEQ,'BOOLFN,'EVALNEQ);
  459. SYMBOLIC PROCEDURE EVALNUMBERP U;
  460. (LAMBDA X; ATOM DENR X AND DOMAINP NUMR X) SIMP!* U;
  461. PUT('NUMBERP,'BOOLFN,'EVALNUMBERP);
  462. %*********************************************************************
  463. % FUNCTIONS FOR CONVERTING PREFIX FORMS INTO CANONICAL FORM
  464. %********************************************************************;
  465. SYMBOLIC PROCEDURE SIMP!* U;
  466. BEGIN SCALAR X;
  467. IF EQCAR(U,'!*SQ) AND CADDR U THEN RETURN CADR U;
  468. X := MUL!* . !*SUB2; %save current environment;
  469. MUL!* := NIL;
  470. U:= SIMP U;
  471. A: IF NULL MUL!* THEN GO TO B;
  472. U:= APPLY(CAR MUL!*,LIST U);
  473. MUL!*:= CDR MUL!*;
  474. GO TO A;
  475. B: MUL!* := CAR X;
  476. U := SUBS2 U;
  477. !*SUB2 := CDR X;
  478. RETURN U
  479. END;
  480. SYMBOLIC PROCEDURE SUBS2 U;
  481. BEGIN SCALAR XEXP;
  482. IF NULL SUBFG!* THEN RETURN U
  483. ELSE IF !*SUB2 OR POWLIS1!* THEN U := SUBS2Q U;
  484. IF NULL !*MATCH AND NULL SPLIS!* THEN RETURN U
  485. ELSE IF NULL !*EXP
  486. THEN <<XEXP:= T; !*EXP := T; U := RESIMP U>>;
  487. IF !*MATCH THEN U := SUBS3Q U;
  488. IF SPLIS!* THEN U := SUBS4Q U;
  489. IF XEXP THEN !*EXP := NIL;
  490. RETURN U
  491. END;
  492. SYMBOLIC PROCEDURE SIMP U;
  493. BEGIN SCALAR X;
  494. IF ATOM U THEN RETURN SIMPATOM U
  495. ELSE IF CAR U EQ '!*SQ AND CADDR U THEN RETURN CADR U
  496. ELSE IF X := ASSOC(U,ALGLIST!*) THEN RETURN CDR X
  497. ELSE IF NOT IDP CAR U THEN GO TO E
  498. ELSE IF FLAGP(CAR U,'OPFN)
  499. THEN RETURN !*SSAVE(SIMP EVAL(CAR U . FOR EACH J IN
  500. (IF FLAGP(CAR U,'NOVAL) THEN CDR U
  501. ELSE REVLIS CDR U) COLLECT MKQUOTE J),U)
  502. ELSE IF X := GET(CAR U,'POLYFN)
  503. THEN RETURN !*SSAVE(!*F2Q APPLY(X,
  504. FOR EACH J IN CDR U COLLECT !*Q2F SIMP!* J),
  505. U)
  506. ELSE IF GET(CAR U,'OPMTCH)
  507. AND NOT(GET(CAR U,'SIMPFN) EQ 'SIMPIDEN)
  508. AND (X := OPMTCH REVOP1 U)
  509. THEN RETURN SIMP X
  510. ELSE IF X := GET(CAR U,'SIMPFN)
  511. THEN RETURN !*SSAVE(IF FLAGP(CAR U,'FULL) OR X EQ 'SIMPIDEN
  512. THEN APPLY(X,LIST U)
  513. ELSE APPLY(X,LIST CDR U),U)
  514. ELSE IF ARRAYP CAR U
  515. THEN RETURN !*SSAVE(SIMP GETELV U,U)
  516. ELSE IF (X := GET(CAR U,'MATRIX)) THEN GO TO M
  517. ELSE IF FLAGP(CAR U,'BOOLEAN)
  518. THEN TYPERR(GETINFIX CAR U,"algebraic operator")
  519. ELSE IF GET(CAR U,'INFIX) THEN GO TO E
  520. ELSE IF FLAGP(CAR U,'NOCHANGE)
  521. THEN RETURN !*SSAVE(SIMP EVAL U,U)
  522. ELSE <<REDMSG(CAR U,"operator"); MKOP CAR U; RETURN SIMP U>>;
  523. M: IF NOT EQCAR(X,'MAT) THEN REDERR LIST("Matrix",CAR U,"not set")
  524. ELSE IF NOT NUMLIS (U := REVLIS CDR U) OR LENGTH U NEQ 2
  525. THEN GO TO E;
  526. RETURN !*SSAVE(SIMP NTH(NTH(CDR X,CAR U),CADR U),U);
  527. E: IF EQCAR(CAR U,'MAT) THEN <<X := CAR U; GO TO M>>
  528. ELSE ERRPRI2(GETINFIX U,T)
  529. END;
  530. SYMBOLIC PROCEDURE GETINFIX U;
  531. %finds infix symbol for U if it exists;
  532. BEGIN SCALAR X;
  533. RETURN IF X := GET(U,'PRTCH) THEN CAR X ELSE U
  534. END;
  535. SYMBOLIC PROCEDURE !*SSAVE(U,V);
  536. BEGIN
  537. ALGLIST!* := (V . U) . ALGLIST!*;
  538. RETURN U
  539. END;
  540. SYMBOLIC PROCEDURE NUMLIS U;
  541. NULL U OR (NUMBERP CAR U AND NUMLIS CDR U);
  542. SYMBOLIC PROCEDURE SIMPATOM U;
  543. IF NULL U THEN NIL ./ 1
  544. ELSE IF NUMBERP U
  545. THEN IF ZEROP U THEN NIL ./ 1
  546. ELSE IF NOT FIXP U
  547. THEN !*D2Q IF NULL DMODE!* THEN !*FT2RN MKFLOAT U
  548. ELSE IF DMODE!* EQ '!:FT!: THEN MKFLOAT U
  549. ELSE APPLY(GET('!:FT!:,DMODE!*),LIST MKFLOAT U)
  550. ELSE IF DMODE!* AND FLAGP(DMODE!*,'CONVERT)
  551. THEN !*D2Q APPLY(GET(DMODE!*,'I2D),LIST U)
  552. ELSE U ./ 1
  553. ELSE IF FLAGP(U,'SHARE) THEN SIMP EVAL U
  554. ELSE BEGIN SCALAR Z;
  555. IF !*NUMVAL AND (Z := GET(U,'DOMAINFN))
  556. THEN <<SETDMODE GET(U,'TARGETMODE);
  557. RETURN !*D2Q APPLY(Z,NIL)>>;
  558. FOR EACH X IN TYPL!* DO IF APPLY(X,LIST U) THEN TYPERR(U,'scalar);
  559. RETURN MKSQ(U,1)
  560. END;
  561. SYMBOLIC PROCEDURE MKOP U;
  562. BEGIN SCALAR X;
  563. IF NULL U THEN TYPERR("Local variable","operator")
  564. ELSE IF (X := GETTYPE U) EQ 'OPERATOR
  565. THEN LPRIM LIST(U,"already defined as operator")
  566. ELSE IF X AND NOT X EQ 'PROCEDURE THEN TYPERR(U,'operator)
  567. ELSE IF U MEMQ FRLIS!* THEN TYPERR(U,"free variable")
  568. ELSE PUT(U,'SIMPFN,'SIMPIDEN)
  569. END;
  570. SYMBOLIC PROCEDURE SIMPCAR U;
  571. SIMP CAR U;
  572. PUT('QUOTE,'SIMPFN,'SIMPCAR);
  573. FLAGOP SHARE;
  574. FLAG('(WS !*MODE),'SHARE);
  575. %*********************************************************************
  576. % SIMPLIFICATION FUNCTIONS FOR EXPLICIT OPERATORS
  577. %********************************************************************;
  578. SYMBOLIC PROCEDURE SIMPABS U;
  579. (LAMBDA X; ABSF NUMR X ./ DENR X) SIMPCAR U;
  580. PUT('ABS,'SIMPFN,'SIMPABS);
  581. SYMBOLIC PROCEDURE SIMPEXPT U;
  582. BEGIN SCALAR FLG,M,N,X;
  583. IF DMODE!* EQ '!:MOD!: THEN <<X := T; DMODE!* := NIL>>;
  584. %exponents must not use modular arithmetic;
  585. N := SIMP!* CARX(CDR U,'EXPT);
  586. IF X THEN DMODE!* := '!:MOD!:;
  587. U := CAR U;
  588. A: M := NUMR N;
  589. IF NOT ATOM M OR DENR N NEQ 1 THEN GO TO NONUMEXP
  590. ELSE IF NULL M
  591. THEN RETURN IF NUMBERP U AND ZEROP U
  592. THEN REDERR " 0**0 formed"
  593. ELSE 1 ./ 1
  594. ELSE IF ONEP U THEN RETURN 1 ./ 1;
  595. X := SIMP U;
  596. %we could use simp!* here, except that it messes up the
  597. %handling of gamma matrix expressions;
  598. IF !*NUMVAL AND DOMAINP NUMR X AND DOMAINP DENR X
  599. AND NOT (ATOM NUMR X AND ATOM DENR X)
  600. THEN RETURN NUMEXPT(MK!*SQ X,M,1)
  601. ELSE IF NOT M<0 THEN RETURN EXPTSQ(X,M)
  602. ELSE IF !*MCD THEN RETURN INVSQ EXPTSQ(X,-M)
  603. ELSE RETURN EXPSQ(X,M); %using OFF EXP code here;
  604. %there may be a pattern matching problem though;
  605. NONUMEXP:
  606. IF ONEP U THEN RETURN 1 ./ 1
  607. ELSE IF ATOM U THEN GO TO A2
  608. ELSE IF CAR U EQ 'TIMES
  609. THEN <<N := PREPSQ N;
  610. X := 1 ./ 1;
  611. FOR EACH Z IN CDR U DO
  612. X := MULTSQ(SIMPEXPT LIST(Z,N),X);
  613. RETURN X>>
  614. ELSE IF CAR U EQ 'QUOTIENT
  615. THEN <<IF NOT FLG AND !*MCD THEN GO TO A2;
  616. N := PREPSQ N;
  617. RETURN MULTSQ(SIMPEXPT LIST(CADR U,N),
  618. SIMPEXPT LIST(CADDR U,LIST('MINUS,N)))>>
  619. ELSE IF CAR U EQ 'EXPT
  620. THEN <<N := MULTSQ(SIMP CADDR U,N);
  621. U := CADR U;
  622. X := NIL;
  623. GO TO A>>
  624. ELSE IF CAR U EQ 'MINUS AND NUMBERP M AND DENR N=1
  625. THEN RETURN MULTSQ(SIMPEXPT LIST(-1,M),
  626. SIMPEXPT LIST(CADR U,M));
  627. A2: IF NULL FLG
  628. THEN <<FLG := T;
  629. U := PREPSQ IF NULL X THEN (X := SIMP!* U) ELSE X;
  630. GO TO NONUMEXP>>
  631. ELSE IF NUMBERP U AND ZEROP U THEN RETURN NIL ./ 1
  632. ELSE IF NOT NUMBERP M THEN M := PREPF M;
  633. IF M MEMQ FRLIS!* THEN RETURN LIST ((U . M) . 1) . 1;
  634. %"power" is not unique here;
  635. N := PREPF CDR N;
  636. IF !*MCD OR CDR X NEQ 1 OR NOT NUMBERP M OR N NEQ 1
  637. OR ATOM U THEN GO TO C
  638. % ELSE IF MINUSF CAR X THEN RETURN MULTSQ(SIMPEXPT LIST(-1,M),
  639. % SIMPEXPT LIST(PREPF NEGF CAR X,M));
  640. ELSE IF CAR U EQ 'PLUS OR NOT !*MCD AND N=1
  641. THEN RETURN MKSQ(U,M); %to make pattern matching work;
  642. C: IF !*NUMVAL AND NUMTYPEP U AND NUMTYPEP M AND NUMTYPEP N
  643. THEN RETURN NUMEXPT(U,M,N)
  644. ELSE RETURN SIMPX1(U,M,N)
  645. END;
  646. SYMBOLIC PROCEDURE NUMEXPT(U,M,N);
  647. %U,M and N are all numbers. Result is standard quotient for U**(M/N);
  648. BEGIN SCALAR X;
  649. RETURN IF X := TARGETCONV(LIST(U,M,N),'BIGFLOAT)
  650. THEN !*D2Q IF N=1 AND ATOM M AND FIXP M THEN TEXPT!:(CAR X,M)
  651. ELSE TEXPT!:ANY(CAR X,
  652. IF N=1 THEN CADR X
  653. ELSE BFQUOTIENT!:(CADR X,CADDR X))
  654. ELSE SIMPX1(U,M,N)
  655. END;
  656. SYMBOLIC PROCEDURE IEXPT(U,N);
  657. IF NULL MOD!* THEN U**N
  658. ELSE IF N<0 THEN CEXPT(CRECIP U,-N)
  659. ELSE CEXPT(U,N);
  660. PUT('EXPT,'SIMPFN,'SIMPEXPT);
  661. SYMBOLIC PROCEDURE SIMPX1(U,M,N);
  662. %U,M and N are prefix expressions;
  663. %Value is the standard quotient expression for U**(M/N);
  664. BEGIN SCALAR FLG,X,Z;
  665. IF NUMBERP M AND NUMBERP N
  666. OR NULL SMEMQLP(FRLIS!*,M) OR NULL SMEMQLP(FRLIS!*,N)
  667. THEN GO TO A;
  668. EXPTP!* := T;
  669. RETURN !*K2Q LIST('EXPT,U,IF N=1 THEN M
  670. ELSE LIST('QUOTIENT,M,N));
  671. A: IF NUMBERP M THEN IF MINUSP M THEN <<M := -M; GO TO MNS>>
  672. ELSE IF FIXP M THEN GO TO E
  673. ELSE GO TO B
  674. ELSE IF ATOM M THEN GO TO B
  675. ELSE IF CAR M EQ 'MINUS THEN <<M := CADR M; GO TO MNS>>
  676. ELSE IF CAR M EQ 'PLUS THEN GO TO PLS
  677. ELSE IF CAR M EQ 'TIMES AND NUMBERP CADR M AND FIXP CADR M
  678. AND NUMBERP N
  679. THEN GO TO TMS;
  680. B: Z := 1;
  681. C: IF IDP U AND NOT FLAGP(U,'USED!*) THEN FLAG(LIST U,'USED!*);
  682. U := LIST('EXPT,U,IF N=1 THEN M ELSE LIST('QUOTIENT,M,N));
  683. IF NOT U MEMBER EXPTL!* THEN EXPTL!* := U . EXPTL!*;
  684. D: RETURN MKSQ(U,IF FLG THEN -Z ELSE Z); %U is already in lowest
  685. %terms;
  686. E: IF NUMBERP N AND FIXP N THEN GO TO INT;
  687. Z := M;
  688. M := 1;
  689. GO TO C;
  690. MNS: IF !*MCD THEN RETURN INVSQ SIMPX1(U,M,N);
  691. FLG := NOT FLG;
  692. GO TO A;
  693. PLS: Z := 1 ./ 1;
  694. PL1: M := CDR M;
  695. IF NULL M THEN RETURN Z;
  696. Z := MULTSQ(SIMPEXPT LIST(U,
  697. LIST('QUOTIENT,IF FLG THEN LIST('MINUS,CAR M)
  698. ELSE CAR M,N)),
  699. Z);
  700. GO TO PL1;
  701. TMS: Z := GCDN(N,CADR M);
  702. N := N/Z;
  703. Z := CADR M/Z;
  704. M := RETIMES CDDR M;
  705. GO TO C;
  706. INT:Z := DIVIDE(M,N);
  707. IF CDR Z<0 THEN Z:= (CAR Z - 1) . (CDR Z+N);
  708. X := SIMPEXPT LIST(U,CAR Z);
  709. IF CDR Z=0 THEN RETURN X
  710. ELSE IF N=2 THEN RETURN MULTSQ(X,SIMPSQRT LIST U)
  711. ELSE RETURN MULTSQ(X,EXPTSQ(SIMPRAD(SIMP!* U,N),CDR Z))
  712. END;
  713. SYMBOLIC PROCEDURE EXPSQ(U,N);
  714. %RAISES STANDARD QUOTIENT U TO NEGATIVE POWER N WITH EXP OFF;
  715. MULTF(EXPF(NUMR U,N),MKSFPF(DENR U,-N)) ./ 1;
  716. SYMBOLIC PROCEDURE EXPF(U,N);
  717. %U is a standard form. Value is standard form of U raised to
  718. %negative integer power N. MCD is assumed off;
  719. %what if U is invertable?;
  720. IF NULL U THEN NIL
  721. ELSE IF ATOM U THEN MKRN(1,U**(-N))
  722. ELSE IF DOMAINP U THEN !:EXPT(U,N)
  723. ELSE IF RED U THEN MKSP!*(U,N)
  724. ELSE (LAMBDA X; IF X>0 AND SFP MVAR U
  725. THEN MULTF(EXPTF(MVAR U,X),EXPF(LC U,N))
  726. ELSE MVAR U TO X .* EXPF(LC U,N) .+ NIL)
  727. (LDEG U*N);
  728. SYMBOLIC PROCEDURE SIMPRAD(U,N);
  729. %simplifies radical expressions;
  730. BEGIN SCALAR X,Y,Z;
  731. X := RADF(NUMR U,N);
  732. Y := RADF(DENR U,N);
  733. Z := MULTSQ(CAR X ./ 1,1 ./ CAR Y);
  734. Z := MULTSQ(MULTSQ(MKROOTLF(CDR X,N) ./ 1,
  735. 1 ./ MKROOTLF(CDR Y,N)),
  736. Z);
  737. RETURN Z
  738. END;
  739. SYMBOLIC PROCEDURE MKROOTLF(U,N);
  740. %U is a list of prefix expressions, N an integer.
  741. %Value is standard form for U**(1/N);
  742. IF NULL U THEN 1 ELSE MULTF(MKROOTF(CAR U,N),MKROOTLF(CDR U,N));
  743. SYMBOLIC PROCEDURE MKROOTF(U,N);
  744. %U is a prefix expression, N an integer.
  745. %Value is a standard form for U**(1/N);
  746. !*P2F IF EQCAR(U,'EXPT) AND FIXP CADDR U
  747. THEN MKSP(IF N=2 THEN MKSQRT CADR U
  748. ELSE LIST('EXPT,CADR U,LIST('QUOTIENT,1,N)),CADDR U)
  749. ELSE MKSP(IF N=2 THEN MKSQRT U
  750. ELSE LIST('EXPT,U,LIST('QUOTIENT,1,N)),1);
  751. COMMENT The following three procedures return a partitioned root
  752. expression, which is a dotted pair of integral part (a standard
  753. form) and radical part (a list of prefix expressions). The whole
  754. structure represents U**(1/N);
  755. SYMBOLIC PROCEDURE RADF(U,N);
  756. %U is a standard form, N a positive integer. Value is a partitioned
  757. %root expression for U**(1/N);
  758. BEGIN SCALAR IPART,RPART,X,Y,!*GCD;
  759. IF NULL U THEN RETURN LIST U;
  760. !*GCD := T;
  761. IPART := 1;
  762. WHILE NOT DOMAINP U DO
  763. <<Y := COMFAC U;
  764. IF CAR Y
  765. THEN <<X := DIVIDE(PDEG CAR Y,N);
  766. IF CAR X NEQ 0
  767. THEN IPART:=MULTF(!*P2F(MVAR U TO CAR X),IPART);
  768. IF CDR X NEQ 0
  769. THEN RPART :=
  770. MKEXPT(IF SFP MVAR U THEN PREPF MVAR U
  771. ELSE MVAR U,CDR X) . RPART>>;
  772. X := QUOTF1(U,COMFAC!-TO!-POLY Y);
  773. U := CDR Y;
  774. IF MINUSF X THEN <<X := NEGF X; U := NEGF U>>;
  775. IF X NEQ 1
  776. THEN <<X := RADF1(SQFRF X,N);
  777. IPART := MULTF(CAR X,IPART);
  778. RPART := APPEND(RPART,CDR X)>>>>;
  779. IF U NEQ 1
  780. THEN <<X := RADD(U,N);
  781. IPART := MULTF(CAR X,IPART);
  782. RPART := APPEND(CDR X,RPART)>>;
  783. RETURN IPART . RPART
  784. END;
  785. SYMBOLIC PROCEDURE RADF1(U,N);
  786. %U is a form_power list, N a positive integer. Value is a
  787. %partitioned root expression for U**(1/N);
  788. BEGIN SCALAR IPART,RPART,X;
  789. IPART := 1;
  790. FOR EACH Z IN U DO
  791. <<X := DIVIDE(CDR Z,N);
  792. IF NOT(CAR X=0)
  793. THEN IPART := MULTF(EXPTF(CAR Z,CAR X),IPART);
  794. IF NOT(CDR X=0)
  795. THEN RPART := MKEXPT(PREPSQ!*(CAR Z ./ 1),CDR X)
  796. . RPART>>;
  797. RETURN IPART . RPART
  798. END;
  799. SYMBOLIC PROCEDURE RADD(U,N);
  800. %U is a domain element, N an integer.
  801. %Value is a partitioned root expression for U**(1/N);
  802. BEGIN SCALAR IPART,X;
  803. IPART := 1;
  804. IF NOT ATOM U THEN RETURN LIST(1,U)
  805. ELSE IF U<0
  806. THEN IF N=2 THEN <<IPART := !*K2F 'I; U := -U>>
  807. ELSE IF REMAINDER(N,2)=1 THEN <<IPART := -1; U := -U>>
  808. ELSE RETURN LIST(1,U);
  809. X := NROOTN(U,N);
  810. RETURN IF CDR X=1 THEN LIST MULTD(CAR X,IPART)
  811. ELSE LIST(MULTD(CAR X,IPART),CDR X)
  812. END;
  813. SYMBOLIC PROCEDURE IROOT(M,N);
  814. %M and N are positive integers.
  815. %If M**(1/N) is an integer, this value is returned, otherwise NIL;
  816. BEGIN SCALAR X,X1,BK;
  817. IF M=0 THEN RETURN M;
  818. X := 10**CEILING(LENGTHC M,N); %first guess;
  819. A: X1 := X**(N-1);
  820. BK := X-M/X1;
  821. IF BK<0 THEN RETURN NIL
  822. ELSE IF BK=0 THEN RETURN IF X1*X=M THEN X ELSE NIL;
  823. X := X-CEILING(BK,N);
  824. GO TO A
  825. END;
  826. SYMBOLIC PROCEDURE CEILING(M,N);
  827. %M and N are positive integers. Value is ceiling of (M/N) (i.e.,
  828. %least integer greater or equal to M/N);
  829. (LAMBDA X; IF CDR X=0 THEN CAR X ELSE CAR X+1) DIVIDE(M,N);
  830. SYMBOLIC PROCEDURE MKEXPT(U,N);
  831. IF N=1 THEN U ELSE LIST('EXPT,U,N);
  832. SYMBOLIC PROCEDURE NROOTN(N,X);
  833. %N is an integer, X a positive integer. Value is a pair
  834. %of integers I,J such that I*J**(1/X)=N**(1/X);
  835. BEGIN SCALAR I,J,R,SIGNN;
  836. R := 1;
  837. IF N<0
  838. THEN <<N := -N;
  839. IF REMAINDER(X,2)=0 THEN SIGNN := T ELSE R := -1>>;
  840. J := 2**X;
  841. WHILE REMAINDER(N,J)=0 DO <<N := N/J; R := R*2>>;
  842. I := 3;
  843. J := 3**X;
  844. WHILE J<=N DO
  845. <<WHILE REMAINDER(N,J)=0 DO <<N := N/J; R := R*I>>;
  846. IF REMAINDER(I,3)=1 THEN I := I+4 ELSE I := I+2;
  847. J := I**X>>;
  848. IF SIGNN THEN N := -N;
  849. RETURN R . N
  850. END;
  851. SYMBOLIC PROCEDURE SIMPIDEN U;
  852. BEGIN SCALAR Y,Z;
  853. U:= REVOP1 U;
  854. IF FLAGP(CAR U,'NONCOM) THEN NCMP!* := T;
  855. IF NULL SUBFG!* THEN GO TO C
  856. ELSE IF FLAGP(CAR U,'LINEAR) AND (Z := FORMLNR U) NEQ U
  857. THEN RETURN SIMP Z
  858. ELSE IF Z := OPMTCH U THEN RETURN SIMP Z
  859. ELSE IF Z := NUMVALCHK U THEN RETURN Z;
  860. C: IF FLAGP(CAR U,'SYMMETRIC) THEN U := CAR U . ORDN CDR U
  861. ELSE IF FLAGP(CAR U,'ANTISYMMETRIC)
  862. THEN <<IF REPEATS CDR U THEN RETURN (NIL ./ 1)
  863. ELSE IF NOT PERMP(Z:= ORDN CDR U,CDR U) THEN Y := T;
  864. U := CAR U . Z>>;
  865. U := MKSQ(U,1);
  866. RETURN IF Y THEN NEGSQ U ELSE U
  867. END;
  868. SYMBOLIC PROCEDURE NUMVALCHK U;
  869. BEGIN SCALAR Y,Z;
  870. IF NULL !*NUMVAL THEN RETURN NIL
  871. ELSE IF ATOM U THEN RETURN NIL
  872. ELSE IF (Z := GET(CAR U,'DOMAINFN))
  873. AND DOMAINLISP CDR U
  874. AND (Y := TARGETCONV(CDR U,GET(CAR U,'TARGETMODE)))
  875. THEN <<SETDMODE GET(CAR U,'TARGETMODE);
  876. RETURN !*D2Q APPLY(Z,Y)>>
  877. ELSE RETURN NIL
  878. END;
  879. SYMBOLIC PROCEDURE NUMTYPEP U;
  880. %returns true if U is a possible number, NIL otherwise;
  881. IF ATOM U THEN NUMBERP U
  882. ELSE IF GET(CAR U,'DNAME) THEN U
  883. ELSE IF CAR U EQ 'MINUS THEN NUMTYPEP CADR U
  884. ELSE IF CAR U EQ 'QUOTIENT THEN NUMTYPEP CADR U AND NUMTYPEP CADDR U
  885. ELSE NIL;
  886. SYMBOLIC PROCEDURE DOMAINLISP U;
  887. %true if U is a list of domain element numbers, NIL otherwise;
  888. IF NULL U THEN T ELSE NUMTYPEP CAR U AND DOMAINLISP CDR U;
  889. SYMBOLIC PROCEDURE TARGETCONV(U,V);
  890. %U is a list of domain elements, V a domain mode;
  891. %if all elements of U can be converted to mode V, a list of the
  892. %converted elements is returned, otherwise NIL is returned;
  893. BEGIN SCALAR X,Y,Z;
  894. V := GET(V,'TAG);
  895. A: IF NULL U THEN RETURN REVERSIP X
  896. ELSE IF ATOM (Z := NUMR SIMPCAR U)
  897. THEN X := APPLY(GET(V,'I2D),LIST IF NULL Z THEN 0 ELSE Z) . X
  898. ELSE IF CAR Z EQ V THEN X := Z . X
  899. ELSE IF Y := GET(CAR Z,V)
  900. THEN X := APPLY(Y,LIST Z) . X
  901. ELSE RETURN NIL;
  902. U := CDR U;
  903. GO TO A
  904. END;
  905. SYMBOLIC PROCEDURE SIMPDIFF U;
  906. ADDSQ(SIMPCAR U,SIMPMINUS CDR U);
  907. PUT('DIFFERENCE,'SIMPFN,'SIMPDIFF);
  908. SYMBOLIC PROCEDURE SIMPMINUS U;
  909. NEGSQ SIMP CARX(U,'MINUS);
  910. PUT('MINUS,'SIMPFN,'SIMPMINUS);
  911. SYMBOLIC PROCEDURE SIMPPLUS U;
  912. BEGIN SCALAR Z;
  913. Z := NIL ./ 1;
  914. A: IF NULL U THEN RETURN Z;
  915. Z := ADDSQ(SIMPCAR U,Z);
  916. U := CDR U;
  917. GO TO A
  918. END;
  919. PUT('PLUS,'SIMPFN,'SIMPPLUS);
  920. SYMBOLIC PROCEDURE SIMPQUOT U;
  921. MULTSQ(SIMPCAR U,SIMPRECIP CDR U);
  922. PUT('QUOTIENT,'SIMPFN,'SIMPQUOT);
  923. SYMBOLIC PROCEDURE SIMPRECIP U;
  924. IF NULL !*MCD THEN SIMPEXPT LIST(CARX(U,'RECIP),-1)
  925. ELSE INVSQ SIMP CARX( U,'RECIP);
  926. PUT('RECIP,'SIMPFN,'SIMPRECIP);
  927. SYMBOLIC PROCEDURE SIMPSQRT U;
  928. BEGIN SCALAR X,Y;
  929. X := XSIMP CAR U;
  930. RETURN IF !*NUMVAL AND (Y := NUMVALCHK MKSQRT PREPSQ!* X)
  931. THEN Y
  932. ELSE SIMPRAD(X,2)
  933. END;
  934. SYMBOLIC PROCEDURE XSIMP U; EXPCHK SIMP!* U;
  935. SYMBOLIC PROCEDURE SIMPTIMES U;
  936. BEGIN SCALAR X,Y;
  937. IF TSTACK!* NEQ 0 OR NULL MUL!* THEN GO TO A0;
  938. Y := MUL!*;
  939. MUL!* := NIL;
  940. A0: TSTACK!* := TSTACK!*+1;
  941. X := SIMPCAR U;
  942. A: U := CDR U;
  943. IF NULL NUMR X THEN GO TO C
  944. ELSE IF NULL U THEN GO TO B;
  945. X := MULTSQ(X,SIMPCAR U);
  946. GO TO A;
  947. B: IF NULL MUL!* OR TSTACK!*>1 THEN GO TO C;
  948. X:= APPLY(CAR MUL!*,LIST X);
  949. MUL!*:= CDR MUL!*;
  950. GO TO B;
  951. C: TSTACK!* := TSTACK!*-1;
  952. IF TSTACK!* = 0 THEN MUL!* := Y;
  953. RETURN X;
  954. END;
  955. PUT('TIMES,'SIMPFN,'SIMPTIMES);
  956. SYMBOLIC PROCEDURE SIMPSUB U;
  957. BEGIN SCALAR X,Z,Z1;
  958. A: IF NULL CDR U THEN GO TO D
  959. ELSE IF NOT EQEXPR CAR U THEN ERRPRI2(CAR U,T);
  960. X := CADAR U;
  961. Z1 := TYPL!*;
  962. B: IF NULL Z1 THEN GO TO B1
  963. ELSE IF APPLY(CAR Z1,LIST X) THEN GO TO C;
  964. Z1 := CDR Z1;
  965. GO TO B;
  966. B1: X := !*A2K X;
  967. C: Z := (X . CADDAR U) . Z;
  968. U := CDR U;
  969. GO TO A;
  970. D: U := SIMP!* CAR U;
  971. RETURN QUOTSQ(SUBF(NUMR U,Z),SUBF(DENR U,Z))
  972. END;
  973. SYMBOLIC PROCEDURE RESIMP U;
  974. %U is a standard quotient.
  975. %Value is the resimplified standard quotient;
  976. QUOTSQ(SUBF1(NUMR U,NIL),SUBF1(DENR U,NIL));
  977. PUT('SUB,'SIMPFN,'SIMPSUB);
  978. SYMBOLIC PROCEDURE EQEXPR U;
  979. NOT ATOM U
  980. AND CAR U MEMQ '(EQ EQUAL) AND CDDR U AND NULL CDDDR U;
  981. SYMBOLIC PROCEDURE SIMP!*SQ U;
  982. IF NULL CADR U THEN RESIMP CAR U ELSE CAR U;
  983. PUT('!*SQ,'SIMPFN,'SIMP!*SQ);
  984. %*********************************************************************
  985. % FUNCTIONS FOR DEFINING AND MANIPULATING POLYNOMIAL DOMAIN MODES
  986. %********************************************************************;
  987. GLOBAL '(DMODE!* DOMAINLIST!*);
  988. SYMBOLIC PROCEDURE INITDMODE U;
  989. %checks that U is a valid domain mode, and sets up appropriate
  990. %interfaces to the system;
  991. BEGIN
  992. DMODECHK U;
  993. PUT(U,'SIMPFG,LIST(LIST(T,LIST('SETDMODE,MKQUOTE U)),
  994. '(NIL (SETDMODE NIL))))
  995. END;
  996. SYMBOLIC PROCEDURE SETDMODE U;
  997. %Sets polynomial domain mode to U. If U is NIL, integers are used;
  998. BEGIN SCALAR X;
  999. IF NULL U THEN RETURN <<RMSUBS(); DMODE!* := NIL>>
  1000. ELSE IF NULL(X := GET(U,'TAG))
  1001. THEN REDERR LIST("Domain mode error:",U,"is not a domain mode")
  1002. ELSE IF DMODE!* EQ X THEN RETURN NIL;
  1003. RMSUBS();
  1004. IF DMODE!*
  1005. THEN LPRIM LIST("Domain mode",
  1006. GET(DMODE!*,'DNAME),"changed to",U);
  1007. IF U := GET(U,'MODULE!-NAME) THEN LOAD!-MODULE U;
  1008. DMODE!* := X
  1009. END;
  1010. SYMBOLIC PROCEDURE DMODECHK U;
  1011. %checks to see if U has complete specification for a domain mode;
  1012. BEGIN SCALAR Z;
  1013. IF NOT(Z := GET(U,'TAG))
  1014. THEN REDERR LIST("Domain mode error:","No tag for",Z)
  1015. ELSE IF NOT(GET(Z,'DNAME) EQ U)
  1016. THEN REDERR LIST("Domain mode error:",
  1017. "Inconsistent or missing DNAME for",Z)
  1018. ELSE IF NOT Z MEMQ DOMAINLIST!*
  1019. THEN REDERR LIST("Domain mode error:",
  1020. Z,"not on domain list");
  1021. U := Z;
  1022. FOR EACH X IN DOMAINLIST!*
  1023. DO IF U=X THEN NIL
  1024. ELSE IF NOT(GET(U,X) OR GET(X,U))
  1025. THEN REDERR LIST("Domain mode error:",
  1026. "No conversion defined between",U,"and",X);
  1027. Z := '(DIFFERENCE I2D MINUSP PLUS PREPFN QUOTIENT SPECPRN TIMES
  1028. ZEROP);
  1029. IF NOT FLAGP(U,'FIELD) THEN Z := 'DIVIDE . 'GCD . Z;
  1030. FOR EACH X IN Z DO IF NOT GET(U,X)
  1031. THEN REDERR LIST("Domain mode error:",
  1032. X,"is not defined for",U)
  1033. END;
  1034. COMMENT *** General Support Functions ***;
  1035. SYMBOLIC PROCEDURE !*D2Q U;
  1036. %converts domain element U into a standard quotient;
  1037. IF EQCAR(U,'!:RN!:) AND !*MCD THEN CDR U ELSE U ./ 1;
  1038. SYMBOLIC PROCEDURE FIELDP U;
  1039. %U is a domain element. Value is T if U is invertable, NIL
  1040. %otherwise;
  1041. NOT ATOM U AND FLAGP(CAR U,'FIELD);
  1042. SYMBOLIC PROCEDURE !:EXPT(U,N);
  1043. %raises domain element U to power N. Value is a domain element;
  1044. IF NULL U THEN IF N=0 THEN REDERR "0/0 formed" ELSE NIL
  1045. ELSE IF N=0 THEN 1
  1046. ELSE IF N<0
  1047. THEN !:RECIP !:EXPT(IF NOT FIELDP U THEN MKRATNUM U ELSE U,-N)
  1048. ELSE IF ATOM U THEN U**N
  1049. ELSE BEGIN SCALAR V,W,X;
  1050. V := APPLY(GET(CAR U,'I2D),LIST 1); %unit element;
  1051. X := GET(CAR U,'TIMES);
  1052. A: W := DIVIDE(N,2);
  1053. IF CDR W=1 THEN V := APPLY(X,LIST(U,V));
  1054. IF CAR W=0 THEN RETURN V;
  1055. U := APPLY(X,LIST(U,U));
  1056. N := CAR W;
  1057. GO TO A
  1058. END;
  1059. SYMBOLIC PROCEDURE !:MINUS U;
  1060. %U is a domain element. Value is -U;
  1061. IF ATOM U THEN -U ELSE DCOMBINE(U,-1,'TIMES);
  1062. SYMBOLIC PROCEDURE !:MINUSP U;
  1063. IF ATOM U THEN MINUSP U ELSE APPLY(GET(CAR U,'MINUSP),LIST U);
  1064. GLOBAL '(!:PREC!:);
  1065. SYMBOLIC PROCEDURE !:ONEP U;
  1066. %Allow for round-up of two in the last place in bigfloats;
  1067. IF ATOM U THEN U=1
  1068. ELSE IF !:ZEROP DCOMBINE(U,1,'DIFFERENCE) THEN T
  1069. ELSE CAR U EQ '!:BF!:
  1070. AND !:ZEROP DCOMBINE(BFPLUS!:(U,'!:BF!: . 2 . -!:PREC!:),
  1071. 1,'DIFFERENCE);
  1072. SYMBOLIC PROCEDURE !:RECIP U;
  1073. %U is an invertable domain element. Value is 1/U;
  1074. IF NUMBERP U AND ABS U=1 THEN U ELSE DCOMBINE(1,U,'QUOTIENT);
  1075. SYMBOLIC PROCEDURE !:ZEROP U;
  1076. %returns T if domain element U is 0, NIL otherwise;
  1077. IF ATOM U THEN U=0 ELSE APPLY(GET(CAR U,'ZEROP),LIST U);
  1078. SYMBOLIC PROCEDURE DCOMBINE(U,V,FN);
  1079. %U and V are domain elements, but not both atoms (integers).
  1080. %FN is a binary function on domain elements;
  1081. %Value is the domain element representing FN(U,V);
  1082. IF ATOM U
  1083. THEN APPLY(GET(CAR V,FN),LIST(APPLY(GET(CAR V,'I2D),LIST U),V))
  1084. ELSE IF ATOM V
  1085. THEN APPLY(GET(CAR U,FN),LIST(U,APPLY(GET(CAR U,'I2D),LIST V)))
  1086. ELSE IF CAR U EQ CAR V THEN APPLY(GET(CAR U,FN),LIST(U,V))
  1087. ELSE BEGIN SCALAR X;
  1088. IF NOT(X := GET(CAR U,CAR V))
  1089. THEN <<V := APPLY(GET(CAR V,CAR U),LIST V);
  1090. X := GET(CAR U,FN)>>
  1091. ELSE <<U := APPLY(X,LIST U); X := GET(CAR V,FN)>>;
  1092. RETURN APPLY(X,LIST(U,V))
  1093. END;
  1094. COMMENT *** Tables for Various domain arithmetics ***:
  1095. Syntactically, such elements have the following form:
  1096. <domain element> := integer|(<domain identifier> . <domain structure>).
  1097. To introduce a new domain, we need to define:
  1098. 1) A conversion function from integer to the given mode.
  1099. 2) A conversion function from new mode to or from every other mode.
  1100. 3) Particular instance of the binary operations +,- and * for this mode.
  1101. 4) Particular instance of ZEROP, MINUSP for this mode.
  1102. 5) If domain is a field, a quotient must be defined.
  1103. If domain is a ring, a gcd and divide must be defined, and
  1104. also a quotient function which returns NIL if the division fails.
  1105. 6) A printing function for this mode.
  1106. 7) A function to convert structure to an appropriate prefix form.
  1107. 8) A reading function for this mode.
  1108. 9) A DNAME property for the tag, and a TAG property for the DNAME
  1109. To facilitate this, all such modes should be listed in the global
  1110. variable DOMAINLIST!*;
  1111. COMMENT *** Tables for rational numbers ***;
  1112. FLUID '(!*RATIONAL);
  1113. DOMAINLIST!* := UNION('(!:RN!:),DOMAINLIST!*);
  1114. PUT('RATIONAL,'TAG,'!:RN!:);
  1115. PUT('!:RN!:,'DNAME,'RATIONAL);
  1116. FLAG('(!:RN!:),'FIELD);
  1117. PUT('!:RN!:,'I2D,'!*I2RN);
  1118. PUT('!:RN!:,'MINUSP,'RNMINUSP!:);
  1119. PUT('!:RN!:,'PLUS,'RNPLUS!:);
  1120. PUT('!:RN!:,'TIMES,'RNTIMES!:);
  1121. PUT('!:RN!:,'DIFFERENCE,'RNDIFFERENCE!:);
  1122. PUT('!:RN!:,'QUOTIENT,'RNQUOTIENT!:);
  1123. PUT('!:RN!:,'ZEROP,'RNZEROP!:);
  1124. PUT('!:RN!:,'PREPFN,'RNPREP!:);
  1125. PUT('!:RN!:,'SPECPRN,'RNPRIN);
  1126. SYMBOLIC PROCEDURE MKRATNUM U;
  1127. %U is a domain element. Value is equivalent rational number;
  1128. IF ATOM U THEN !*I2RN U ELSE APPLY(GET(CAR U,'!:RN!:),LIST U);
  1129. SYMBOLIC PROCEDURE MKRN(U,V);
  1130. %converts two integers U and V into a rational number, an integer
  1131. %or NIL;
  1132. IF U=0 THEN NIL
  1133. ELSE IF V<0 THEN MKRN(-U,-V)
  1134. ELSE (LAMBDA M;
  1135. (LAMBDA (N1,N2); IF N2=1 THEN N1 ELSE '!:RN!: . (N1 . N2))
  1136. (U/M,V/M))
  1137. GCDN(U,V);
  1138. SYMBOLIC PROCEDURE !*I2RN U;
  1139. %converts integer U to rational number;
  1140. '!:RN!: . (U . 1);
  1141. SYMBOLIC PROCEDURE RNMINUSP!: U; CADR U<0;
  1142. SYMBOLIC PROCEDURE RNPLUS!:(U,V);
  1143. MKRN(CADR U*CDDR V+CDDR U*CADR V,CDDR U*CDDR V);
  1144. SYMBOLIC PROCEDURE RNTIMES!:(U,V);
  1145. MKRN(CADR U*CADR V,CDDR U*CDDR V);
  1146. SYMBOLIC PROCEDURE RNDIFFERENCE!:(U,V);
  1147. MKRN(CADR U*CDDR V-CDDR U*CADR V,CDDR U*CDDR V);
  1148. SYMBOLIC PROCEDURE RNQUOTIENT!:(U,V);
  1149. MKRN(CADR U*CDDR V,CDDR U*CADR V);
  1150. SYMBOLIC PROCEDURE RNZEROP!: U; CADR U=0;
  1151. SYMBOLIC PROCEDURE RNPREP!: U;
  1152. IF CDDR U=1 THEN CADR U ELSE LIST('QUOTIENT,CADR U,CDDR U);
  1153. SYMBOLIC PROCEDURE RNPRIN U; MAPRIN RNPREP!: U;
  1154. INITDMODE 'RATIONAL;
  1155. COMMENT *** Tables for floats ***;
  1156. DOMAINLIST!* := UNION('(!:FT!:),DOMAINLIST!*);
  1157. PUT('FLOAT,'TAG,'!:FT!:);
  1158. PUT('!:FT!:,'DNAME,'FLOAT);
  1159. FLAG('(!:FT!:),'FIELD);
  1160. PUT('!:FT!:,'I2D,'!*I2FT);
  1161. PUT('!:FT!:,'!:RN!:,'!*FT2RN);
  1162. PUT('!:FT!:,'MINUSP,'FTMINUSP!:);
  1163. PUT('!:FT!:,'PLUS,'FTPLUS!:);
  1164. PUT('!:FT!:,'TIMES,'FTTIMES!:);
  1165. PUT('!:FT!:,'DIFFERENCE,'FTDIFFERENCE!:);
  1166. PUT('!:FT!:,'QUOTIENT,'FTQUOTIENT!:);
  1167. PUT('!:FT!:,'ZEROP,'FTZEROP!:);
  1168. PUT('!:FT!:,'PREPFN,'FTPREP!:);
  1169. PUT('!:FT!:,'SPECPRN,'PRIN2!*);
  1170. SYMBOLIC PROCEDURE MKFLOAT U;
  1171. '!:FT!: . U;
  1172. SYMBOLIC PROCEDURE !*I2FT U;
  1173. %converts integer U to floating point form or NIL;
  1174. IF U=0 THEN NIL ELSE '!:FT!: . FLOAT U;
  1175. SYMBOLIC PROCEDURE !*FT2RN U;
  1176. BEGIN INTEGER M; SCALAR X;
  1177. U := CDR U; %pick up actual number;
  1178. M := FIX(1000000*U);
  1179. X := GCDN(1000000,M);
  1180. X := (M/X) . (1000000/X);
  1181. MSGPRI(NIL,U,"represented by",LIST('QUOTIENT,CAR X,CDR X),NIL);
  1182. RETURN '!:RN!: . X
  1183. END;
  1184. SYMBOLIC PROCEDURE FTMINUSP!: U; CDR U<0;
  1185. SYMBOLIC PROCEDURE FTPLUS!:(U,V);
  1186. (LAMBDA X; IF ABS(X/CDR U)<0.000001 AND ABS(X/CDR V)<0.000001 THEN 0
  1187. ELSE '!:FT!: . X)
  1188. (CDR U+CDR V);
  1189. SYMBOLIC PROCEDURE FTTIMES!:(U,V); CAR U . (CDR U*CDR V);
  1190. SYMBOLIC PROCEDURE FTDIFFERENCE!:(U,V); CAR U .(CDR U-CDR V);
  1191. SYMBOLIC PROCEDURE FTQUOTIENT!:(U,V); CAR U . (CDR U/CDR V);
  1192. SYMBOLIC PROCEDURE FTZEROP!: U; CDR U=0.0;
  1193. SYMBOLIC PROCEDURE FTPREP!: U; CDR U;
  1194. INITDMODE 'FLOAT;
  1195. COMMENT *** Entry points for the bigfloat package ***;
  1196. FLUID '(!*BIGFLOAT);
  1197. PUT('BIGFLOAT,'SIMPFG,'((T (RMSUBS) (SETDMODE (QUOTE BIGFLOAT)))
  1198. (NIL (SETDMODE NIL))));
  1199. PUT('NUMVAL,'SIMPFG,'((T (RMSUBS) (SETDMODE (QUOTE BIGFLOAT)))));
  1200. PUT('BIGFLOAT,'TAG,'!:BF!:);
  1201. COMMENT *** Tables for modular integers ***;
  1202. FLUID '(!*MODULAR);
  1203. DOMAINLIST!* := UNION('(!:MOD!:),DOMAINLIST!*);
  1204. PUT('MODULAR,'TAG,'!:MOD!:);
  1205. PUT('!:MOD!:,'DNAME,'MODULAR);
  1206. FLAG('(!:MOD!:),'FIELD);
  1207. FLAG('(!:MOD!:),'CONVERT);
  1208. PUT('!:MOD!:,'I2D,'!*I2MOD);
  1209. PUT('!:MOD!:,'!:BF!:,'MODCNV);
  1210. PUT('!:MOD!:,'!:FT!:,'MODCNV);
  1211. PUT('!:MOD!:,'!:RN!:,'MODCNV);
  1212. PUT('!:MOD!:,'MINUSP,'MODMINUSP!:);
  1213. PUT('!:MOD!:,'PLUS,'MODPLUS!:);
  1214. PUT('!:MOD!:,'TIMES,'MODTIMES!:);
  1215. PUT('!:MOD!:,'DIFFERENCE,'MODDIFFERENCE!:);
  1216. PUT('!:MOD!:,'QUOTIENT,'MODQUOTIENT!:);
  1217. PUT('!:MOD!:,'ZEROP,'MODZEROP!:);
  1218. PUT('!:MOD!:,'PREPFN,'MODPREP!:);
  1219. PUT('!:MOD!:,'SPECPRN,'MODPRIN);
  1220. SYMBOLIC PROCEDURE !*I2MOD U;
  1221. %converts integer U to modular form;
  1222. IF (U := CMOD U)=0 THEN NIL ELSE '!:MOD!: . U;
  1223. SYMBOLIC PROCEDURE MODCNV U;
  1224. REDERR LIST("Conversion between modular integers and",
  1225. GET(CAR U,'DNAME),"not defined");
  1226. SYMBOLIC PROCEDURE MODMINUSP!: U; NIL; %what else can one do?;
  1227. SYMBOLIC PROCEDURE MODPLUS!:(U,V);
  1228. (LAMBDA X; IF X=0 THEN NIL ELSE IF X=1 THEN 1 ELSE CAR U . X)
  1229. CPLUS(CDR U,CDR V);
  1230. SYMBOLIC PROCEDURE MODTIMES!:(U,V);
  1231. (LAMBDA X; IF X=1 THEN 1 ELSE CAR U . X) CTIMES(CDR U,CDR V);
  1232. SYMBOLIC PROCEDURE MODDIFFERENCE!:(U,V);
  1233. CAR U . CPLUS(CDR U,MOD!*-CDR V);
  1234. SYMBOLIC PROCEDURE MODQUOTIENT!:(U,V);
  1235. CAR U . CTIMES(CDR U,CRECIP CDR V);
  1236. SYMBOLIC PROCEDURE MODZEROP!: U; CDR U=0;
  1237. SYMBOLIC PROCEDURE MODPREP!: U; CDR U;
  1238. SYMBOLIC PROCEDURE MODPRIN U; PRIN2!* CDR U;
  1239. INITDMODE 'MODULAR;
  1240. %*********************************************************************
  1241. % FUNCTIONS FOR MODULAR ARITHMETIC
  1242. %********************************************************************;
  1243. COMMENT This section defines routines for modular integer arithmetic.
  1244. It assumes that such numbers are normalized in the range 0<=n<p,
  1245. where p is the modular base;
  1246. COMMENT The actual modulus is stored in MOD!*;
  1247. SYMBOLIC PROCEDURE CEXPT(M,N);
  1248. %returns the normalized value of M**N;
  1249. BEGIN INTEGER P;
  1250. P := 1;
  1251. WHILE N>0 DO
  1252. <<IF REMAINDER(N,2)=1 THEN P := CTIMES(P,M);
  1253. N := N/2;
  1254. IF N>0 THEN M := CTIMES(M,M)>>;
  1255. RETURN P
  1256. END;
  1257. SYMBOLIC PROCEDURE CPLUS(M,N);
  1258. %returns the normalized sum of U and V;
  1259. (LAMBDA L; IF L>=MOD!* THEN L-MOD!* ELSE L) (M+N);
  1260. SYMBOLIC PROCEDURE CMINUS(M);
  1261. %returns the negative of M;
  1262. IF M=0 THEN M ELSE MOD!*-M;
  1263. SYMBOLIC PROCEDURE CDIF(M,N);
  1264. %returns the normalized difference of M and N;
  1265. (LAMBDA L; IF L<0 THEN L+MOD!* ELSE L) (M-N);
  1266. SYMBOLIC PROCEDURE CRECIP M;
  1267. %returns the normalized reciprocal of M modulo MOD!*
  1268. %provided M is non-zero mod MOD!*, and M and MOD!* are co-prime.
  1269. %If not, an error results;
  1270. CRECIP1(MOD!*,M,0,1);
  1271. SYMBOLIC PROCEDURE CRECIP1(A,B,X,Y);
  1272. %This is essentially the same as RECIPROCAL-BY-GCD in the Norman/
  1273. %Moore factorizer;
  1274. IF B=0 THEN REDERR "Invalid modular division"
  1275. ELSE IF B=1 THEN IF Y<0 THEN Y+MOD!* ELSE Y
  1276. ELSE BEGIN SCALAR W;
  1277. W := A/B; %truncated integer division;
  1278. RETURN CRECIP1(B,A-B*W,Y,X-Y*W)
  1279. END;
  1280. SYMBOLIC PROCEDURE CTIMES(M,N);
  1281. %returns the normalized product of M and N;
  1282. REMAINDER(M*N,MOD!*);
  1283. SYMBOLIC PROCEDURE SETMOD U;
  1284. %always returns value of MOD!* on entry.
  1285. %if U=0, no other action, otherwise MOD!* is set to U;
  1286. IF U=0 THEN MOD!* ELSE (LAMBDA N; <<MOD!* := U; N>>) MOD!*;
  1287. FLAG('(SETMOD),'OPFN); %to make it a symbolic operator;
  1288. SYMBOLIC PROCEDURE CMOD M;
  1289. %returns normalized M;
  1290. (LAMBDA N; IF N<0 THEN N+MOD!* ELSE N) REMAINDER(M,MOD!*);
  1291. %A more general definition;
  1292. %SYMBOLIC PROCEDURE CMOD M;
  1293. %returns normalized M;
  1294. % (LAMBDA N; %IF N<0 THEN N+MOD!* ELSE N)
  1295. % IF ATOM M THEN REMAINDER(M,MOD!*)
  1296. % ELSE BEGIN SCALAR X;
  1297. % X := DCOMBINE(M,MOD!*,'DIVIDE);
  1298. % RETURN CDR X
  1299. % END;
  1300. %*********************************************************************
  1301. % FUNCTIONS FOR ADDING AND MULTIPLYING STANDARD QUOTIENTS
  1302. %********************************************************************;
  1303. SYMBOLIC PROCEDURE ADDSQ(U,V);
  1304. %U and V are standard quotients.
  1305. %Value is canonical sum of U and V;
  1306. IF NULL NUMR U THEN V
  1307. ELSE IF NULL NUMR V THEN U
  1308. ELSE IF DENR U=1 AND DENR V=1 THEN ADDF(NUMR U,NUMR V) ./ 1
  1309. ELSE BEGIN SCALAR X,Y,Z;
  1310. IF NULL !*EXP THEN <<U := NUMR U ./ MKPROD!* DENR U;
  1311. V := NUMR V ./ MKPROD!* DENR V>>;
  1312. IF !*LCM THEN X := GCDF!*(DENR U,DENR V)
  1313. ELSE X := GCDF(DENR U,DENR V);
  1314. Z := CANSQ1(QUOTF(DENR U,X) ./ QUOTF(DENR V,X));
  1315. Y := ADDF(MULTF(NUMR U,DENR Z),MULTF(NUMR V,NUMR Z));
  1316. IF NULL Y THEN RETURN NIL ./ 1;
  1317. Z := MULTF(DENR U,DENR Z);
  1318. IF ONEP X THEN RETURN Y ./ Z;
  1319. X := GCDF(Y,X);
  1320. RETURN IF X=1 THEN Y ./ Z
  1321. ELSE CANSQ1(QUOTF(Y,X) ./ QUOTF(Z,X))
  1322. END;
  1323. SYMBOLIC PROCEDURE MULTSQ(U,V);
  1324. %U and V are standard quotients.
  1325. %Value is canonical product of U and V;
  1326. IF NULL NUMR U OR NULL NUMR V THEN NIL ./ 1
  1327. ELSE IF DENR U=1 AND DENR V=1 THEN MULTF(NUMR U,NUMR V) ./ 1
  1328. ELSE BEGIN SCALAR X,Y;
  1329. X := GCDF(NUMR U,DENR V);
  1330. Y := GCDF(NUMR V,DENR U);
  1331. RETURN CANSQ1(MULTF(QUOTF(NUMR U,X),QUOTF(NUMR V,Y))
  1332. ./ MULTF(QUOTF(DENR U,Y),QUOTF(DENR V,X)))
  1333. END;
  1334. SYMBOLIC PROCEDURE NEGSQ U;
  1335. NEGF NUMR U ./ DENR U;
  1336. SMACRO PROCEDURE MULTPQ(U,V);
  1337. MULTSQ(!*P2Q U,V);
  1338. SYMBOLIC PROCEDURE CANCEL U;
  1339. %returns canonical form of non-canonical standard form U;
  1340. IF !*MCD OR DENR U=1 THEN CANONSQ MULTSQ(NUMR U ./ 1,1 ./ DENR U)
  1341. ELSE MULTSQ(NUMR U ./ 1,SIMPEXPT LIST(MK!*SQ(DENR U ./ 1),-1));
  1342. %*********************************************************************
  1343. % FUNCTIONS FOR ADDING AND MULTIPLYING STANDARD FORMS
  1344. %********************************************************************;
  1345. SYMBOLIC SMACRO PROCEDURE PEQ(U,V);
  1346. %tests for equality of powers U and V;
  1347. U = V;
  1348. SYMBOLIC PROCEDURE ADDF(U,V);
  1349. %U and V are standard forms. Value is standard form for U+V;
  1350. IF NULL U THEN V
  1351. ELSE IF NULL V THEN U
  1352. ELSE IF DOMAINP U THEN ADDD(U,V)
  1353. ELSE IF DOMAINP V THEN ADDD(V,U)
  1354. ELSE IF PEQ(LPOW U,LPOW V)
  1355. THEN (LAMBDA (X,Y); IF NULL X THEN Y ELSE LPOW U .* X .+ Y)
  1356. (ADDF(LC U,LC V),ADDF(RED U,RED V))
  1357. ELSE IF ORDPP(LPOW U,LPOW V) THEN LT U .+ ADDF(RED U,V)
  1358. ELSE LT V .+ ADDF(U,RED V);
  1359. SYMBOLIC PROCEDURE ADDD(U,V);
  1360. %U is a domain element, V a standard form.
  1361. %Value is a standard form for U+V;
  1362. IF NULL V THEN U
  1363. ELSE IF DOMAINP V THEN ADDDM(U,V)
  1364. ELSE LT V .+ ADDD(U,RED V);
  1365. SYMBOLIC PROCEDURE ADDDM(U,V);
  1366. %U and V are both domain elements.
  1367. %Value is standard form for U+V;
  1368. IF ATOM U AND ATOM V THEN !*N2F PLUS2(U,V)
  1369. ELSE BEGIN SCALAR X;
  1370. RETURN IF !:ZEROP(X := DCOMBINE(U,V,'PLUS)) THEN NIL ELSE X
  1371. END;
  1372. SYMBOLIC PROCEDURE DOMAINP U;
  1373. ATOM U OR ATOM CAR U;
  1374. SYMBOLIC PROCEDURE NONCOMP U;
  1375. NOT ATOM U AND FLAGP!*!*(CAR U,'NONCOM);
  1376. SYMBOLIC PROCEDURE MULTF(U,V);
  1377. %U and V are standard forms.
  1378. %Value is standard form for U*V;
  1379. BEGIN SCALAR X,Y;
  1380. A: IF NULL U OR NULL V THEN RETURN NIL
  1381. ELSE IF ONEP U THEN RETURN V
  1382. ELSE IF ONEP V THEN RETURN U
  1383. ELSE IF DOMAINP U THEN RETURN MULTD(U,V)
  1384. ELSE IF DOMAINP V THEN RETURN MULTD(V,U)
  1385. ELSE IF NOT(!*EXP OR NCMP!* OR WTL!* OR X)
  1386. THEN <<U := MKPROD U; V := MKPROD V; X := T; GO TO A>>;
  1387. X := MVAR U;
  1388. Y := MVAR V;
  1389. IF NONCOMP X AND NONCOMP Y THEN RETURN MULTFNC(U,V)
  1390. ELSE IF X EQ Y
  1391. THEN <<X := MKSPM(X,LDEG U+LDEG V);
  1392. Y := ADDF(MULTF(!*T2F LT U,RED V),MULTF(RED U,V));
  1393. RETURN IF NULL X OR NULL(U := MULTF(LC U,LC V)) THEN Y
  1394. ELSE IF NULL !*MCD
  1395. THEN ADDF(IF X=1 THEN U ELSE !*T2F(X .* U),Y)
  1396. ELSE X .* U .+ Y>>
  1397. ELSE IF ORDOP(X,Y)
  1398. THEN <<X := MULTF(LC U,V);
  1399. Y := MULTF(RED U,V);
  1400. RETURN IF NULL X THEN Y ELSE LPOW U .* X .+ Y>>;
  1401. X := MULTF(U,LC V);
  1402. Y := MULTF(U,RED V);
  1403. RETURN IF NULL X THEN Y ELSE LPOW V .* X .+ Y
  1404. END;
  1405. SYMBOLIC PROCEDURE MULTFNC(U,V);
  1406. %returns canonical product of U and V, with both main vars non-
  1407. %commutative;
  1408. BEGIN SCALAR X,Y;
  1409. X := MULTF(LC U,!*T2F LT V);
  1410. RETURN ADDF((IF NOT DOMAINP X AND MVAR X EQ MVAR U
  1411. THEN ADDF(!*T2F(MKSPM(MVAR U,LDEG U+LDEG V)
  1412. .* LC X),
  1413. MULTF(!*P2F LPOW U,RED X))
  1414. ELSE !*T2F(LPOW U .* X)),
  1415. ADDF(MULTF(RED U,V),MULTF(!*T2F LT U,RED V)))
  1416. END;
  1417. SYMBOLIC PROCEDURE MULTD(U,V);
  1418. %U is a domain element, V a standard form.
  1419. %Value is standard form for U*V;
  1420. IF NULL V THEN NIL
  1421. ELSE IF DOMAINP V THEN MULTDM(U,V)
  1422. ELSE LPOW V .* MULTD(U,LC V) .+ MULTD(U,RED V);
  1423. SYMBOLIC PROCEDURE MULTDM(U,V);
  1424. %U and V are both domain elements. Value is standard form for U*V;
  1425. IF ATOM U AND ATOM V THEN TIMES2(U,V)
  1426. ELSE BEGIN SCALAR X;
  1427. RETURN IF !:ONEP(X := DCOMBINE(U,V,'TIMES)) THEN 1 ELSE X
  1428. END;
  1429. SMACRO PROCEDURE MULTPF(U,V);
  1430. MULTF(!*P2F U,V);
  1431. GLOBAL '(!*FACTOR); %used to call a factorizing routine if it exists;
  1432. SYMBOLIC PROCEDURE MKPROD U;
  1433. BEGIN SCALAR W,X,Y,Z,!*EXP;
  1434. IF NULL U OR KERNLP U THEN RETURN U;
  1435. %first make sure there are no further simplifications;
  1436. IF DENR(X := SUBS2(U ./ 1)) = 1 AND NUMR X NEQ U
  1437. THEN <<U := NUMR X; IF NULL U OR KERNLP U THEN RETURN U>>;
  1438. !*EXP := T;
  1439. W := CKRN U;
  1440. U := QUOTF(U,W);
  1441. X := EXPND U;
  1442. IF NULL X OR KERNLP X THEN RETURN MULTF(W,X);
  1443. %after this point, U is not KERNLP;
  1444. IF !*FACTOR OR !*GCD THEN Y := FCTRF X
  1445. ELSE <<Y := CKRN X;
  1446. X := QUOTF(X,Y);
  1447. Y := LIST(Y,X . 1)>>;
  1448. IF CDADR Y>1 OR CDDR Y
  1449. THEN <<Z := CAR Y;
  1450. FOR EACH J IN CDR Y DO
  1451. Z := MULTF(MKSP!*(CAR J,CDR J),Z)>>
  1452. ELSE IF NOT !*GROUP AND TMSF U>TMSF CAADR Y
  1453. THEN Z := MULTF(MKSP!*(CAADR Y,CDADR Y),CAR Y)
  1454. ELSE Z := MKSP!*(U,1);
  1455. RETURN MULTF(W,Z)
  1456. END;
  1457. SYMBOLIC PROCEDURE MKSP!*(U,N);
  1458. %Returns a standard form for U**N, in which U is first made
  1459. %positive and then converted into a kernel;
  1460. BEGIN SCALAR B;
  1461. IF MINUSF U THEN <<B := T; U := NEGF U>>;
  1462. U := !*P2F MKSP(U,N);
  1463. RETURN IF B AND NOT ZEROP REMAINDER(N,2) THEN NEGF U ELSE U
  1464. END;
  1465. SYMBOLIC PROCEDURE TMSF U;
  1466. %U is a standard form.
  1467. %Value is number of terms in U (including kernel structure);
  1468. BEGIN INTEGER N; SCALAR X;
  1469. N := 0;
  1470. A: IF NULL U THEN RETURN N ELSE IF DOMAINP U THEN RETURN N+1;
  1471. N := N+(IF SFP(X := MVAR U) THEN TMSF X ELSE 1)+TMSF!* LC U;
  1472. IF LDEG U NEQ 1 THEN N := N+2;
  1473. U := RED U;
  1474. IF U THEN N := N+1;
  1475. GO TO A
  1476. END;
  1477. SYMBOLIC PROCEDURE TMSF!* U;
  1478. IF NUMBERP U AND ABS FIX U=1 THEN 0 ELSE TMSF U+1;
  1479. SYMBOLIC PROCEDURE TMS U;
  1480. TMSF NUMR SIMP!* U;
  1481. FLAG('(TMS),'OPFN);
  1482. FLAG('(TMS),'NOVAL);
  1483. SYMBOLIC PROCEDURE EXPND U;
  1484. IF DOMAINP U THEN U
  1485. ELSE ADDF(IF NOT SFP MVAR U OR LDEG U<0
  1486. THEN MULTPF(LPOW U,EXPND LC U)
  1487. ELSE MULTF(EXPTF(EXPND MVAR U,LDEG U),EXPND LC U),
  1488. EXPND RED U);
  1489. SYMBOLIC PROCEDURE MKPROD!* U;
  1490. IF DOMAINP U THEN U ELSE MKPROD U;
  1491. SYMBOLIC PROCEDURE CANPROD(P,Q);
  1492. %P and Q are kernel product standard forms, value is P/Q;
  1493. BEGIN SCALAR V,W,X,Y,Z;
  1494. IF DOMAINP Q THEN RETURN CANCEL(P ./ Q);
  1495. WHILE NOT DOMAINP P OR NOT DOMAINP Q DO
  1496. IF SFPF P THEN
  1497. <<Z := CPROD1(MVAR P,LDEG P,V,W);
  1498. V := CAR Z; W := CDR Z; P := LC P>>
  1499. ELSE IF SFPF Q THEN <<Z := CPROD1(MVAR Q,LDEG Q,W,V);
  1500. W := CAR Z; V := CDR Z; Q := LC Q>>
  1501. ELSE IF DOMAINP P THEN <<Y := LPOW Q . Y; Q := LC Q>>
  1502. ELSE IF DOMAINP Q THEN <<X := LPOW P . X; P := LC P>>
  1503. ELSE <<X := LPOW P . X; Y := LPOW Q . Y;
  1504. P := LC P; Q := LC Q>>;
  1505. V := REPROD(V,REPROD(X,P));
  1506. W := REPROD(W,REPROD(Y,Q));
  1507. IF MINUSF W THEN <<V := NEGF V; W := NEGF W>>;
  1508. W := CANCEL(V ./ W);
  1509. V := NUMR W;
  1510. IF NOT DOMAINP V AND NULL RED V AND ONEP LC V
  1511. AND LDEG V=1 AND SFP(X := MVAR V)
  1512. THEN V := X;
  1513. RETURN CANSQ1(V ./ DENR W)
  1514. END;
  1515. SYMBOLIC PROCEDURE SFPF U;
  1516. NOT DOMAINP U AND SFP MVAR U;
  1517. SYMBOLIC PROCEDURE SFP U;
  1518. %determines if mvar U is a standard form;
  1519. NOT ATOM U AND NOT ATOM CAR U;
  1520. SYMBOLIC PROCEDURE REPROD(U,V);
  1521. %U is a list of powers,V a standard form;
  1522. %value is product of terms in U with V;
  1523. <<WHILE U DO <<V := MULTPF(CAR U,V); U := CDR U>>; V>>;
  1524. SYMBOLIC PROCEDURE CPROD1(P,M,V,W);
  1525. %U is a standard form, which occurs in a kernel raised to power M.
  1526. %V is a list of powers multiplying P**M, W a list dividing it.
  1527. %Value is a dotted pair of lists of powers after all possible kernels
  1528. %have been cancelled;
  1529. BEGIN SCALAR Z;
  1530. Z := CPROD2(P,M,W,NIL);
  1531. W := CADR Z;
  1532. V := APPEND(CDDR Z,V);
  1533. Z := CPROD2(CAR Z,M,V,T);
  1534. V := CADR Z;
  1535. W := APPEND(CDDR Z,W);
  1536. IF CAR Z NEQ 1 THEN V := MKSP(CAR Z,M) . V;
  1537. RETURN V . W
  1538. END;
  1539. SYMBOLIC PROCEDURE CPROD2(P,M,U,B);
  1540. %P and M are as in CPROD1. U is a list of powers. B is true if P**M
  1541. %multiplies U, false if it divides.
  1542. %Value has three parts: the first is the part of P which does not
  1543. %have any common factors with U, the second a list of powers (plus
  1544. %U) which multiply U, and the third a list of powers which divide U;
  1545. %it is implicit here that the kernel standard forms are positive;
  1546. BEGIN SCALAR N,V,W,Y,Z;
  1547. WHILE U AND P NEQ 1 DO
  1548. <<IF (Z := GCDF(P,CAAR U)) NEQ 1
  1549. THEN
  1550. <<P := QUOTF(P,Z);
  1551. Y := QUOTF(CAAR U,Z);
  1552. IF Y NEQ 1 THEN V := MKSP(Y,CDAR U) . V;
  1553. IF B THEN V := MKSP(Z,M+CDAR U) . V
  1554. ELSE IF (N := M-CDAR U)>0 THEN W := MKSP(Z,N) . W
  1555. ELSE IF N<0 THEN V := MKSP(Z,-N) . V>>
  1556. ELSE V := CAR U . V;
  1557. U := CDR U>>;
  1558. RETURN (P . NCONC(U,V) . W)
  1559. END;
  1560. SYMBOLIC PROCEDURE MKSPM(U,P);
  1561. %U is a unique kernel, P an integer;
  1562. %value is 1 if P=0 and not the weight variable K!*,
  1563. %NIL if U**P is 0 or standard power of U**P otherwise;
  1564. IF P=0 AND NOT(U EQ 'K!*) THEN 1
  1565. ELSE BEGIN SCALAR X;
  1566. IF SUBFG!* AND (X:= ATSOC(U,ASYMPLIS!*)) AND CDR X<=P
  1567. THEN RETURN NIL;
  1568. SUB2CHK U;
  1569. RETURN U TO P
  1570. END;
  1571. SYMBOLIC PROCEDURE SUB2CHK U;
  1572. %determines if kernel U is such that a power substitution i
  1573. %necessary;
  1574. IF SUBFG!* AND(ATSOC(U,POWLIS!*)
  1575. OR NOT ATOM U AND CAR U MEMQ '(EXPT SQRT)
  1576. AND ASSOC(CADR U,POWLIS!*))
  1577. THEN !*SUB2 := T;
  1578. SYMBOLIC PROCEDURE NEGF U;
  1579. MULTD(-1,U);
  1580. %*********************************************************************
  1581. % FUNCTIONS FOR DIVIDING STANDARD FORMS
  1582. %********************************************************************;
  1583. SYMBOLIC PROCEDURE QUOTSQ(U,V);
  1584. MULTSQ(U,INVSQ V);
  1585. SYMBOLIC PROCEDURE QUOTF!*(U,V);
  1586. IF NULL U THEN NIL
  1587. ELSE (LAMBDA X; IF NULL X THEN ERRACH LIST("DIVISION FAILED",U,V)
  1588. ELSE X)
  1589. QUOTF(U,V);
  1590. SYMBOLIC PROCEDURE QUOTF(U,V);
  1591. BEGIN SCALAR XEXP;
  1592. XEXP := !*EXP;
  1593. !*EXP := T;
  1594. U := QUOTF1(U,V);
  1595. !*EXP := XEXP;
  1596. RETURN U
  1597. END;
  1598. SYMBOLIC PROCEDURE QUOTF1(P,Q);
  1599. %P and Q are standard forms
  1600. %Value is the quotient of P and Q if it exists or NIL;
  1601. IF NULL P THEN NIL
  1602. ELSE IF P=Q THEN 1
  1603. ELSE IF Q=1 THEN P
  1604. ELSE IF DOMAINP Q THEN QUOTFD(P,Q)
  1605. ELSE IF DOMAINP P THEN NIL
  1606. ELSE IF MVAR P EQ MVAR Q
  1607. THEN BEGIN SCALAR U,V,W,X,Y,Z,Z1; INTEGER N;
  1608. A:IF IDP(U := RANK P) OR IDP(V := RANK Q) OR U<V THEN RETURN NIL;
  1609. %the above IDP test is because of the possibility of a free
  1610. %variable in the degree position from LET statements;
  1611. U := LT!* P;
  1612. V := LT!* Q;
  1613. W := MVAR Q;
  1614. X := QUOTF1(TC U,TC V);
  1615. IF NULL X THEN RETURN NIL;
  1616. N := TDEG U-TDEG V;
  1617. IF N NEQ 0 THEN Y := W TO N;
  1618. P := ADDF(P,MULTF(IF N=0 THEN Q
  1619. ELSE MULTPF(Y,Q),NEGF X));
  1620. %leading terms of P and Q do not cancel if MCD is off;
  1621. %however, there may be a problem with off exp;
  1622. IF P AND (DOMAINP P OR MVAR P NEQ W) THEN RETURN NIL
  1623. ELSE IF N=0 THEN GO TO B;
  1624. Z := ACONC(Z,Y .* X);
  1625. %provided we have a non-zero power of X, terms
  1626. %come out in right order;
  1627. IF NULL P THEN RETURN IF Z1 THEN NCONC(Z,Z1) ELSE Z;
  1628. GO TO A;
  1629. B: IF NULL P THEN RETURN NCONC(Z,X)
  1630. ELSE IF !*MCD THEN RETURN NIL
  1631. ELSE Z1 := X;
  1632. GO TO A
  1633. END
  1634. ELSE IF ORDOP(MVAR P,MVAR Q) THEN QUOTK(P,Q)
  1635. ELSE NIL;
  1636. SYMBOLIC PROCEDURE QUOTFD(P,Q);
  1637. %P is a standard form, Q a domain element;
  1638. %Value is P/Q if division is exact or NIL otherwise;
  1639. IF FIELDP Q THEN MULTD(!:RECIP Q,P)
  1640. ELSE IF DOMAINP P THEN QUOTDD(P,Q)
  1641. ELSE QUOTK(P,Q);
  1642. SYMBOLIC PROCEDURE QUOTDD(U,V);
  1643. %U and V are domain elements, value is U/V if division is exact,
  1644. %NIL otherwise;
  1645. IF ATOM U THEN IF ATOM V
  1646. THEN IF REMAINDER(U,V)=0 THEN U/V ELSE NIL
  1647. ELSE QUOTDD(APPLY(GET(CAR V,'I2D),LIST U),V)
  1648. ELSE IF ATOM V THEN QUOTDD(U,APPLY(GET(CAR U,'I2D),LIST V))
  1649. ELSE DCOMBINE(U,V,'QUOTIENT);
  1650. SYMBOLIC PROCEDURE QUOTK(P,Q);
  1651. (LAMBDA W;
  1652. IF W THEN IF NULL RED P THEN LIST (LPOW P .* W)
  1653. ELSE (LAMBDA Y;IF Y THEN LPOW P .* W .+ Y ELSE NIL)
  1654. QUOTF1(RED P,Q)
  1655. ELSE NIL)
  1656. QUOTF1(LC P,Q);
  1657. SYMBOLIC PROCEDURE RANK P;
  1658. %P is a standard form
  1659. %Value is the rank of P;
  1660. IF !*MCD THEN LDEG P
  1661. ELSE BEGIN INTEGER M,N; SCALAR Y;
  1662. N := LDEG P;
  1663. Y := MVAR P;
  1664. A: M := LDEG P;
  1665. IF NULL RED P THEN RETURN N-M;
  1666. P := RED P;
  1667. IF DEGR(P,Y)=0 THEN RETURN IF M<0 THEN IF N<0 THEN -M
  1668. ELSE N-M ELSE N;
  1669. GO TO A
  1670. END;
  1671. SYMBOLIC PROCEDURE LT!* P;
  1672. %Returns true leading term of polynomial P;
  1673. IF !*MCD OR LDEG P>0 THEN CAR P
  1674. ELSE BEGIN SCALAR X,Y;
  1675. X := LT P;
  1676. Y := MVAR P;
  1677. A: P := RED P;
  1678. IF NULL P THEN RETURN X
  1679. ELSE IF DEGR(P,Y)=0 THEN RETURN (Y . 0) .* P;
  1680. GO TO A
  1681. END;
  1682. SYMBOLIC PROCEDURE REMF(U,V);
  1683. %returns the remainder of U divided by V;
  1684. CDR QREMF(U,V);
  1685. PUT('REMAINDER,'POLYFN,'REMF);
  1686. SYMBOLIC PROCEDURE QREMF(U,V);
  1687. %returns the quotient and remainder of U divided by V;
  1688. BEGIN INTEGER N; SCALAR X,Y,Z;
  1689. IF DOMAINP V THEN RETURN QREMD(U,V);
  1690. Z := LIST NIL; %final value;
  1691. A: IF DOMAINP U THEN RETURN PRADDF(Z,NIL . U)
  1692. ELSE IF MVAR U EQ MVAR V
  1693. THEN IF (N := LDEG U-LDEG V)<0 THEN RETURN PRADDF(Z,NIL . U)
  1694. ELSE <<X := QREMF(LC U,LC V);
  1695. Y := MULTPF(LPOW U,CDR X);
  1696. Z := PRADDF(Z,(IF N=0 THEN CAR X
  1697. ELSE MULTPF(MVAR U TO N,CAR X))
  1698. . Y);
  1699. U := IF NULL CAR X THEN RED U
  1700. ELSE ADDF(ADDF(U,MULTF(IF N=0 THEN V
  1701. ELSE MULTPF(MVAR U TO N,V),
  1702. NEGF CAR X)), NEGF Y);
  1703. GO TO A>>
  1704. ELSE IF NOT ORDOP(MVAR U,MVAR V)
  1705. THEN RETURN PRADDF(Z,NIL . U);
  1706. X := QREMF(LC U,V);
  1707. Z := PRADDF(Z,MULTPF(LPOW U,CAR X) . MULTPF(LPOW U,CDR X));
  1708. U := RED U;
  1709. GO TO A
  1710. END;
  1711. SYMBOLIC PROCEDURE PRADDF(U,V);
  1712. %U and V are dotted pairs of standard forms;
  1713. ADDF(CAR U,CAR V) . ADDF(CDR U,CDR V);
  1714. SYMBOLIC PROCEDURE QREMD(U,V);
  1715. %Returns a dotted pair of quotient and remainder of form U
  1716. %divided by domain element V;
  1717. IF NULL U THEN U . U
  1718. ELSE IF V=1 THEN LIST U
  1719. ELSE IF NOT ATOM V AND FLAGP(CAR V,'FIELD)
  1720. THEN LIST MULTDM(!:RECIP V,U)
  1721. ELSE IF DOMAINP U THEN QREMDD(U,V)
  1722. ELSE BEGIN SCALAR X;
  1723. X := QREMF(LC U,V);
  1724. RETURN PRADDF(MULTPF(LPOW U,CAR X) . MULTPF(LPOW U,CDR X),
  1725. QREMD(RED U,V))
  1726. END;
  1727. SYMBOLIC PROCEDURE QREMDD(U,V);
  1728. %returns a dotted pair of quotient and remainder of non-invertable
  1729. %domain element U divided by non-invertable domain element V;
  1730. IF ATOM U AND ATOM V THEN DIVIDEF(U,V) ELSE DCOMBINE(U,V,'DIVIDE);
  1731. SYMBOLIC PROCEDURE DIVIDEF(M,N);
  1732. (LAMBDA X; (IF CAR X=0 THEN NIL ELSE CAR X).
  1733. IF CDR X=0 THEN NIL ELSE CDR X)
  1734. DIVIDE(M,N);
  1735. SYMBOLIC PROCEDURE LQREMF(U,V);
  1736. %returns a list of coeffs of powers of V in U, constant term first;
  1737. BEGIN SCALAR X,Y;
  1738. Y := LIST U;
  1739. WHILE CAR(X := QREMF(CAR Y,V)) DO Y := CAR X . CDR X . CDR Y;
  1740. RETURN REVERSIP Y
  1741. END;
  1742. %*********************************************************************
  1743. % GREATEST COMMON DIVISOR ROUTINES
  1744. %********************************************************************;
  1745. SYMBOLIC PROCEDURE GCDN(P,Q);
  1746. %P and Q are integers. Value is absolute value of gcd of P and Q;
  1747. IF Q = 0 THEN ABS P ELSE GCDN(Q,REMAINDER(P,Q));
  1748. SYMBOLIC PROCEDURE COMFAC P;
  1749. %P is a non-atomic standard form
  1750. %CAR of result is lowest common power of leading kernel in
  1751. %every term in P (or NIL). CDR is gcd of all coefficients of
  1752. %powers of leading kernel;
  1753. BEGIN SCALAR X,Y;
  1754. IF NULL RED P THEN RETURN LT P;
  1755. X := LC P;
  1756. Y := MVAR P; %leading kernel;
  1757. A: P := RED P;
  1758. IF DEGR(P,Y)=0 THEN RETURN NIL . GCDF1(X,P)
  1759. ELSE IF NULL RED P THEN RETURN LPOW P . GCDF1(X,LC P)
  1760. ELSE X := GCDF1(LC P,X);
  1761. GO TO A
  1762. END;
  1763. SYMBOLIC PROCEDURE DEGR(U,VAR);
  1764. IF DOMAINP U OR NOT MVAR U EQ VAR THEN 0 ELSE LDEG U;
  1765. PUT('GCD,'POLYFN,'GCDF!*);
  1766. SYMBOLIC PROCEDURE GCDF!*(U,V);
  1767. BEGIN SCALAR !*GCD; !*GCD := T; RETURN GCDF(U,V) END;
  1768. SYMBOLIC PROCEDURE GCDF(U,V);
  1769. %U and V are standard forms.
  1770. %Value is the gcd of U and V, complete only if *GCD is true;
  1771. BEGIN SCALAR !*EXP,Y,Z;
  1772. !*EXP := T;
  1773. IF NULL U THEN RETURN ABSF V
  1774. ELSE IF NULL V THEN RETURN ABSF U
  1775. ELSE IF U=1 OR V=1 THEN RETURN 1
  1776. ELSE IF !*GCD AND !*EZGCD THEN RETURN EZGCDF(U,V);
  1777. IF QUOTF1(U,V) THEN Z := V
  1778. ELSE IF QUOTF1(V,U) THEN Z := U
  1779. ELSE <<IF !*GCD THEN <<Y := SETKORDER KERNORD(U,V);
  1780. U := REORDER U; V := REORDER V>>;
  1781. Z := GCDF1(U,V);
  1782. IF !*GCD
  1783. THEN <<IF U AND V
  1784. AND (NULL QUOTF1(U,Z) OR NULL QUOTF1(V,Z))
  1785. THEN ERRACH LIST("GCDF FAILED",PREPSQ U,PREPSQ V);
  1786. %this probably implies that integer overflow occurred;
  1787. SETKORDER Y;
  1788. Z := REORDER Z>>>>;
  1789. RETURN ABSF Z
  1790. END;
  1791. SYMBOLIC PROCEDURE GCDF1(U,V);
  1792. IF NULL U THEN V
  1793. ELSE IF NULL V THEN U
  1794. ELSE IF ONEP U OR ONEP V THEN 1
  1795. ELSE IF DOMAINP U THEN GCDFD(U,V)
  1796. ELSE IF DOMAINP V THEN GCDFD(V,U)
  1797. ELSE IF QUOTF1(U,V) THEN V
  1798. ELSE IF QUOTF1(V,U) THEN U
  1799. ELSE IF MVAR U EQ MVAR V
  1800. THEN BEGIN SCALAR X,Y,Z;
  1801. X := COMFAC U;
  1802. Y := COMFAC V;
  1803. Z := GCDF1(CDR X,CDR Y);
  1804. IF !*GCD
  1805. THEN Z := MULTF(GCDK(QUOTF1(U,COMFAC!-TO!-POLY X),
  1806. QUOTF1(V,COMFAC!-TO!-POLY Y)),
  1807. Z);
  1808. IF CAR X AND CAR Y
  1809. THEN IF PDEG CAR X>PDEG CAR Y
  1810. THEN Z := MULTPF(CAR Y,Z)
  1811. ELSE Z := MULTPF(CAR X,Z);
  1812. RETURN Z
  1813. END
  1814. ELSE IF ORDOP(MVAR U,MVAR V) THEN GCDF1(CDR COMFAC U,V)
  1815. ELSE GCDF1(CDR COMFAC V,U);
  1816. SYMBOLIC PROCEDURE GCDFD(U,V);
  1817. %U is a domain element, V a form;
  1818. %Value is gcd of U and V;
  1819. IF NOT ATOM U AND FLAGP(CAR U,'FIELD) THEN 1 ELSE GCDFD1(U,V);
  1820. SYMBOLIC PROCEDURE GCDFD1(U,V);
  1821. IF NULL V THEN U
  1822. ELSE IF DOMAINP V THEN GCDDD(U,V)
  1823. ELSE GCDFD1(GCDFD1(U,LC V),RED V);
  1824. SYMBOLIC PROCEDURE GCDDD(U,V);
  1825. %U and V are domain elements. If they are invertable, value is 1
  1826. %otherwise the gcd of U and V as a domain element;
  1827. IF U=1 OR V=1 THEN 1
  1828. ELSE IF ATOM U THEN IF NOT FIELDP V THEN GCDDD1(U,V) ELSE 1
  1829. ELSE IF ATOM V
  1830. THEN IF NOT FLAGP(CAR U,'FIELD) THEN GCDDD1(U,V) ELSE 1
  1831. ELSE IF FLAGP(CAR U,'FIELD) OR FLAGP(CAR V,'FIELD) THEN 1
  1832. ELSE GCDDD1(U,V);
  1833. SYMBOLIC PROCEDURE GCDDD1(U,V);
  1834. %U and V are non-invertable domain elements. Value is gcd of U and V;
  1835. IF ATOM U AND ATOM V THEN GCDN(U,V) ELSE DCOMBINE(U,V,'GCD);
  1836. SYMBOLIC PROCEDURE GCDK(U,V);
  1837. %U and V are primitive polynomials in the main variable VAR;
  1838. %result is gcd of U and V;
  1839. BEGIN SCALAR LCLST,VAR,W,X;
  1840. IF U=V THEN RETURN U
  1841. ELSE IF DOMAINP U OR DEGR(V,(VAR := MVAR U))=0 THEN RETURN 1
  1842. ELSE IF LDEG U<LDEG V THEN <<W := U; U := V; V := W>>;
  1843. IF QUOTF1(U,V) THEN RETURN V ELSE IF LDEG V=1 THEN RETURN 1;
  1844. A: W := REMK(U,V);
  1845. IF NULL W THEN RETURN V
  1846. ELSE IF DEGR(W,VAR)=0 THEN RETURN 1;
  1847. LCLST := ADDLC(V,LCLST);
  1848. IF X := QUOTF1(W,LC W) THEN W := X
  1849. ELSE FOR EACH Y IN LCLST DO WHILE (X := QUOTF1(W,Y)) DO W := X;
  1850. U := V; V := PP W;
  1851. IF DEGR(V,VAR)=0 THEN RETURN 1 ELSE GO TO A
  1852. END;
  1853. SYMBOLIC PROCEDURE ADDLC(U,V);
  1854. IF U=1 THEN V
  1855. ELSE (LAMBDA X;
  1856. IF X=1 OR X=-1 OR NOT ATOM X AND FLAGP(CAR X,'FIELD) THEN V
  1857. ELSE X . V)
  1858. LC U;
  1859. SYMBOLIC PROCEDURE DELALL(U,V);
  1860. IF NULL V THEN NIL
  1861. ELSE IF U EQ CAAR V THEN DELALL(U,CDR V)
  1862. ELSE CAR V . DELALL(U,CDR V);
  1863. SYMBOLIC PROCEDURE KERNORD(U,V);
  1864. BEGIN SCALAR X,Y,Z;
  1865. X := APPEND(POWERS(U,NIL),POWERS(V,NIL));
  1866. WHILE X DO
  1867. <<Y := MAXDEG(CDR X,CAR X);
  1868. X := DELALL(CAR Y,X);
  1869. Z := CAR Y . Z>>;
  1870. RETURN Z
  1871. END;
  1872. SYMBOLIC PROCEDURE MAXDEG(U,V);
  1873. IF NULL U THEN V
  1874. ELSE IF CDAR U>CDR V THEN MAXDEG(CDR U,CAR U)
  1875. ELSE MAXDEG(CDR U,V);
  1876. SYMBOLIC PROCEDURE POWERS(FORM,POWLST);
  1877. IF NULL FORM OR DOMAINP FORM THEN POWLST
  1878. ELSE BEGIN SCALAR X;
  1879. IF (X := ATSOC(MVAR FORM,POWLST))
  1880. THEN LDEG FORM>CDR X AND RPLACD(X,LDEG FORM)
  1881. ELSE POWLST := (MVAR FORM . LDEG FORM) . POWLST;
  1882. RETURN POWERS(RED FORM,POWERS(LC FORM,POWLST))
  1883. END;
  1884. SYMBOLIC PROCEDURE LCM(U,V);
  1885. %U and V are standard forms. Value is lcm of U and V;
  1886. IF NULL U OR NULL V THEN NIL
  1887. ELSE IF ONEP U THEN V
  1888. ELSE IF ONEP V THEN U
  1889. ELSE MULTF(U,QUOTF(V,GCDF(U,V)));
  1890. SYMBOLIC PROCEDURE REMK(U,V);
  1891. %modified pseudo-remainder algorithm
  1892. %U and V are polynomials, value is modified prem of U and V;
  1893. BEGIN SCALAR F1,VAR,X; INTEGER K,N;
  1894. F1 := LC V;
  1895. VAR := MVAR V;
  1896. N := LDEG V;
  1897. WHILE (K := DEGR(U,VAR)-N)>=0 DO
  1898. <<X := NEGF MULTF(LC U,RED V);
  1899. IF K>0 THEN X := MULTPF(VAR TO K,X);
  1900. U := ADDF(MULTF(F1,RED U),X)>>;
  1901. RETURN U
  1902. END;
  1903. SYMBOLIC PROCEDURE PP U;
  1904. %returns the primitive part of the polynomial U wrt leading var;
  1905. QUOTF1(U,COMFAC!-TO!-POLY COMFAC U);
  1906. SYMBOLIC PROCEDURE COMFAC!-TO!-POLY U;
  1907. IF NULL CAR U THEN CDR U ELSE LIST U;
  1908. SYMBOLIC PROCEDURE LNC U;
  1909. %U is a standard form.
  1910. %Value is the leading numerical coefficient;
  1911. IF NULL U THEN 0
  1912. ELSE IF DOMAINP U THEN U
  1913. ELSE LNC LC U;
  1914. COMMENT In this sub-section, we consider the manipulation of factored
  1915. forms. These have the structure
  1916. <monomial> . <form-power-list>
  1917. where the monomial is itself a standard form (satisfying the
  1918. KERNLP test) and a form-power is a dotted pair whose car is a
  1919. standard form and cdr an integer>0. We have thus represented the
  1920. form as a product of a monomial and powers of non-monomial
  1921. factors;
  1922. SYMBOLIC PROCEDURE FCTRF U;
  1923. %U is a standard form. Value is a standard factored form;
  1924. %The function FACTORF is an assumed entry point to a factorization
  1925. %module which itself returns a form power list;
  1926. BEGIN SCALAR X,Y,!*GCD;
  1927. !*GCD := T;
  1928. IF DOMAINP U THEN RETURN LIST U
  1929. ELSE IF !*FACTOR THEN RETURN FACTORF U;
  1930. X := COMFAC U;
  1931. U := QUOTF(U,COMFAC!-TO!-POLY X);
  1932. Y := FCTRF CDR X;
  1933. IF CAR X THEN Y := MULTPF(CAR X,CAR Y) . CDR Y;
  1934. IF DOMAINP U THEN RETURN MULTF(U,CAR Y) . CDR Y
  1935. ELSE IF MINUSF U
  1936. THEN <<U := NEGF U; Y := NEGF CAR Y . CDR Y>>;
  1937. RETURN CAR Y . FACMERGE(SQFRF U,CDR Y)
  1938. END;
  1939. SYMBOLIC PROCEDURE FACMERGE(U,V);
  1940. %Returns the merge of the form_power_lists U and V;
  1941. APPEND(U,V);
  1942. SYMBOLIC PROCEDURE SQFRF U;
  1943. %U is a non-trivial form which is primitive in its main variable
  1944. %and has a positive leading numerical coefficient.
  1945. %SQFRF performs square free factorization on U and returns a
  1946. %form power list;
  1947. BEGIN INTEGER K,N; SCALAR V,W,X,Z,!*GCD;
  1948. N := 1;
  1949. X := MVAR U;
  1950. !*GCD := T;
  1951. A: V := GCDF(U,DIFF(U,X));
  1952. K := DEGR(V,X);
  1953. IF K>0 THEN U := QUOTF(U,V);
  1954. IF W
  1955. THEN <<IF U NEQ W
  1956. THEN Z := FACMERGE(LIST(QUOTF(W,U) . N),Z);
  1957. N := N+1>>;
  1958. IF K=0 THEN RETURN FACMERGE(LIST(U . N),Z);
  1959. W := U;
  1960. U := V;
  1961. GO TO A
  1962. END;
  1963. SYMBOLIC PROCEDURE DIFF(U,V);
  1964. %a polynomial differentation routine which does not check
  1965. %indeterminate dependences;
  1966. IF DOMAINP U THEN NIL
  1967. ELSE ADDF(ADDF(MULTPF(LPOW U,DIFF(LC U,V)),
  1968. MULTF(LC U,DIFFP1(LPOW U,V))),
  1969. DIFF(RED U,V));
  1970. SYMBOLIC PROCEDURE DIFFP1(U,V);
  1971. IF NOT CAR U EQ V THEN NIL
  1972. ELSE IF CDR U=1 THEN 1
  1973. ELSE MULTD(CDR U,!*P2F(CAR U TO (CDR U-1)));
  1974. SYMBOLIC PROCEDURE MINUSF U;
  1975. %U is a non-zero standard form.
  1976. %Value is T if U has a negative leading numerical coeff,
  1977. %NIL otherwise;
  1978. IF NULL U THEN NIL
  1979. ELSE IF DOMAINP U
  1980. THEN IF ATOM U THEN U<0 ELSE APPLY(GET(CAR U,'MINUSP),LIST U)
  1981. ELSE MINUSF LC U;
  1982. SYMBOLIC PROCEDURE ABSF U;
  1983. %U is a standard form
  1984. %value is a standard form in which the leading power has a
  1985. %positive coefficient;
  1986. IF MINUSF U THEN NEGF U ELSE U;
  1987. SYMBOLIC PROCEDURE CANONSQ U;
  1988. %U is a standard quotient
  1989. %value is a standard quotient in which the leading power
  1990. %of the denominator has a positive numerical coefficient.
  1991. %If FLOAT is true, then denom is given LNC of 1;
  1992. BEGIN
  1993. IF NULL NUMR U THEN RETURN NIL ./ 1
  1994. ELSE IF MINUSF DENR U THEN U:= NEGF NUMR U ./ NEGF DENR U;
  1995. RETURN CANSQ1 U
  1996. END;
  1997. SYMBOLIC PROCEDURE CANSQ1 U;
  1998. %Normalizes denominator of standard quotient U where possible
  1999. %returning normalized quotient;
  2000. IF DENR U=1 THEN U
  2001. ELSE IF DOMAINP DENR U AND !:ONEP DENR U THEN NUMR U ./ 1
  2002. ELSE IF NULL DMODE!* OR NULL FLAGP(DMODE!*,'FIELD) THEN U
  2003. ELSE BEGIN SCALAR X;
  2004. X := LNC DENR U;
  2005. IF !:ONEP X THEN RETURN U;
  2006. IF ATOM X THEN X := APPLY(GET(DMODE!*,'I2D),LIST X);
  2007. X := DCOMBINE(1,X,'QUOTIENT);
  2008. U := MULTD(X,NUMR U) ./ MULTD(X,DENR U);
  2009. RETURN IF DOMAINP DENR U AND !:ONEP DENR U THEN NUMR U ./ 1
  2010. ELSE U
  2011. END;
  2012. SYMBOLIC PROCEDURE INVSQ U;
  2013. IF NULL NUMR U THEN REDERR "Zero denominator" ELSE CANONSQ REVPR U;
  2014. %*********************************************************************
  2015. % FUNCTIONS FOR SUBSTITUTING IN STANDARD FORMS
  2016. %********************************************************************;
  2017. SYMBOLIC PROCEDURE SUBF(U,L);
  2018. BEGIN SCALAR X;
  2019. %domain may have changed, so next line uses simpatom;
  2020. IF DOMAINP U THEN RETURN !*D2Q U
  2021. ELSE IF NCMP!* AND NONCOMEXPF U THEN RETURN SUBF1(U,L);
  2022. X := REVERSE XN(FOR EACH Y IN L COLLECT CAR Y,
  2023. KERNORD(U,NIL));
  2024. X := SETKORDER X;
  2025. U := SUBF1(REORDER U,L);
  2026. SETKORDER X;
  2027. RETURN REORDER NUMR U ./ REORDER DENR U
  2028. END;
  2029. SYMBOLIC PROCEDURE NONCOMEXPF U;
  2030. NOT DOMAINP U
  2031. AND (NONCOMP MVAR U OR NONCOMEXPF LC U OR NONCOMEXPF RED U);
  2032. SYMBOLIC PROCEDURE SUBF1(U,L);
  2033. %U is a standard form,
  2034. %L an association list of substitutions of the form
  2035. %(<kernel> . <substitution>).
  2036. %Value is the standard quotient for substituted expression.
  2037. %Algorithm used is essentially the straight method.
  2038. %Procedure depends on explicit data structure for standard form;
  2039. IF DOMAINP U
  2040. THEN IF ATOM U THEN IF NULL DMODE!* THEN U ./ 1 ELSE SIMPATOM U
  2041. ELSE IF DMODE!* EQ CAR U THEN !*D2Q U
  2042. ELSE SIMP PREPF U
  2043. ELSE BEGIN INTEGER N; SCALAR KERN,M,W,X,XEXP,Y,Y1,Z;
  2044. Z := NIL ./ 1;
  2045. A0: KERN := MVAR U;
  2046. IF M := ASSOC(KERN,ASYMPLIS!*) THEN M := CDR M;
  2047. A: IF NULL U OR (N := DEGR(U,KERN))=0 THEN GO TO B
  2048. ELSE IF NULL M OR N<M THEN Y := LT U . Y;
  2049. U := RED U;
  2050. GO TO A;
  2051. B: IF NOT ATOM KERN AND NOT ATOM CAR KERN THEN KERN := PREPF KERN;
  2052. IF NULL L THEN XEXP := IF KERN EQ 'K!* THEN 1 ELSE KERN
  2053. ELSE IF (XEXP := SUBSUBLIS(L,KERN)) = KERN
  2054. AND NOT ASSOC(KERN,ASYMPLIS!*)
  2055. THEN GO TO F;
  2056. C: W := 1 ./ 1;
  2057. N := 0;
  2058. IF Y AND CDAAR Y<0 THEN GO TO H;
  2059. X := SIMP!* XEXP;
  2060. IF NULL L AND KERNP X AND MVAR NUMR X EQ KERN THEN GO TO F
  2061. ELSE IF NULL NUMR X THEN GO TO E; %Substitution of 0;
  2062. FOR EACH J IN Y DO
  2063. <<M := CDAR J;
  2064. W := MULTSQ(EXPTSQ(X,M-N),W);
  2065. N := M;
  2066. Z := ADDSQ(MULTSQ(W,SUBF1(CDR J,L)),Z)>>;
  2067. E: Y := NIL;
  2068. IF NULL U THEN RETURN Z
  2069. ELSE IF DOMAINP U THEN RETURN ADDSQ(!*D2Q U,Z);
  2070. GO TO A0;
  2071. F: SUB2CHK KERN;
  2072. FOR EACH J IN Y DO Z := ADDSQ(MULTPQ(CAR J,SUBF1(CDR J,L)),Z);
  2073. GO TO E;
  2074. H: %Substitution for negative powers;
  2075. X := SIMPRECIP LIST XEXP;
  2076. J: Y1 := CAR Y . Y1;
  2077. Y := CDR Y;
  2078. IF Y AND CDAAR Y<0 THEN GO TO J;
  2079. K: M := -CDAAR Y1;
  2080. W := MULTSQ(EXPTSQ(X,M-N),W);
  2081. N := M;
  2082. Z := ADDSQ(MULTSQ(W,SUBF1(CDAR Y1,L)),Z);
  2083. Y1 := CDR Y1;
  2084. IF Y1 THEN GO TO K ELSE IF Y THEN GO TO C ELSE GO TO E
  2085. END;
  2086. SYMBOLIC PROCEDURE SUBSUBLIS(U,V);
  2087. BEGIN SCALAR X;
  2088. RETURN IF X := ASSOC(V,U) THEN CDR X
  2089. ELSE IF ATOM V THEN V
  2090. ELSE IF NOT IDP CAR V
  2091. THEN FOR EACH J IN V COLLECT SUBSUBLIS(U,J)
  2092. ELSE IF FLAGP(CAR V,'SUBFN) THEN SUBSUBF(U,V)
  2093. ELSE IF GET(CAR V,'DNAME) THEN V
  2094. ELSE FOR EACH J IN V COLLECT SUBSUBLIS(U,J)
  2095. END;
  2096. SYMBOLIC PROCEDURE SUBSUBF(L,EXPN);
  2097. %Sets up a formal SUB expression when necessary;
  2098. BEGIN SCALAR X,Y;
  2099. FOR EACH J IN CDDR EXPN DO
  2100. IF (X := ASSOC(J,L)) THEN <<Y := X . Y; L := DELETE(X,L)>>;
  2101. EXPN := SUBLIS(L,CAR EXPN)
  2102. . FOR EACH J IN CDR EXPN COLLECT SUBSUBLIS(L,J);
  2103. %to ensure only opr and individual args are transformed;
  2104. IF NULL Y THEN RETURN EXPN;
  2105. EXPN := ACONC(FOR EACH J IN REVERSIP Y
  2106. COLLECT LIST('EQUAL,CAR J,CDR J),EXPN);
  2107. RETURN MK!*SQ IF L THEN SIMPSUB EXPN
  2108. ELSE !*P2Q MKSP('SUB . EXPN,1)
  2109. END;
  2110. FLAG('(INT DF),'SUBFN);
  2111. SYMBOLIC PROCEDURE KERNP U;
  2112. DENR U=1 AND NOT DOMAINP(U := NUMR U)
  2113. AND NULL RED U AND ONEP LC U AND LDEG U=1;
  2114. %*********************************************************************
  2115. % FUNCTIONS FOR RAISING CANONICAL FORMS TO A POWER
  2116. %********************************************************************;
  2117. SYMBOLIC PROCEDURE EXPTSQ(U,N);
  2118. BEGIN SCALAR X;
  2119. IF N=1 THEN RETURN U
  2120. ELSE IF N=0
  2121. THEN RETURN IF NULL NUMR U THEN REDERR " 0**0 formed"
  2122. ELSE 1 ./ 1
  2123. ELSE IF NULL NUMR U THEN RETURN U
  2124. ELSE IF N<0 THEN RETURN SIMPEXPT LIST(MK!*SQ U,N)
  2125. ELSE IF NULL !*EXP
  2126. THEN RETURN MKSFPF(NUMR U,N) ./ MKSFPF(DENR U,N)
  2127. ELSE IF KERNP U THEN RETURN MKSQ(MVAR NUMR U,N)
  2128. ELSE IF DOMAINP NUMR U
  2129. THEN RETURN MULTSQ(!:EXPT(NUMR U,N) ./ 1,
  2130. 1 ./ EXPTF(DENR U,N))
  2131. ELSE IF DENR U=1 THEN RETURN EXPTF(NUMR U,N) ./ 1;
  2132. X := U;
  2133. WHILE (N := N-1)>0 DO X := MULTSQ(U,X);
  2134. RETURN X
  2135. END;
  2136. SYMBOLIC PROCEDURE EXPTF(U,N);
  2137. IF DOMAINP U THEN !:EXPT(U,N)
  2138. ELSE IF !*EXP OR KERNLP U THEN EXPTF1(U,N)
  2139. ELSE MKSFPF(U,N);
  2140. SYMBOLIC PROCEDURE EXPTF1(U,N);
  2141. %iterative multiplication seems to be faster than a binary sub-
  2142. %division algorithm, probably because multiplying a small polynomial
  2143. %by a large one is cheaper than multiplying two medium sized ones;
  2144. BEGIN SCALAR X;
  2145. X: = U;
  2146. WHILE (N := N-1)>0 DO X := MULTF(U,X);
  2147. RETURN X
  2148. END;
  2149. %*********************************************************************
  2150. % FUNCTIONS FOR MAKING STANDARD POWERS
  2151. %********************************************************************;
  2152. SYMBOLIC SMACRO PROCEDURE GETPOWER(U,N);
  2153. %U is a list (<kernel> . <properties>), N a positive integer.
  2154. %Value is the standard power of U**N;
  2155. CAR U . N;
  2156. % BEGIN SCALAR V;
  2157. % V := CADR U;
  2158. % IF NULL V THEN RETURN CAAR RPLACA(CDR U,LIST (CAR U . N));
  2159. % A: IF N=CDAR V THEN RETURN CAR V
  2160. % ELSE IF N<CDAR V
  2161. % THEN RETURN CAR RPLACW(V,(CAAR V . N) . (CAR V . CDR V))
  2162. % ELSE IF NULL CDR V
  2163. % THEN RETURN CADR RPLACD(V,LIST (CAAR V . N));
  2164. % V := CDR V;
  2165. % GO TO A
  2166. % END;
  2167. SYMBOLIC PROCEDURE MKSP(U,P);
  2168. %U is a (non-unique) kernel and P a non-zero integer
  2169. %Value is the standard power for U**P;
  2170. GETPOWER(FKERN U,P);
  2171. SYMBOLIC PROCEDURE U TO P;
  2172. %U is a (unique) kernel and P a non-zero integer;
  2173. %Value is the standard power of U**P;
  2174. U . P;
  2175. % GETPOWER(FKERN U,P);
  2176. SYMBOLIC PROCEDURE FKERN U;
  2177. %finds the unique "p-list" reference to the kernel U. The choice of
  2178. %the search and merge used here has a strong influence on some
  2179. %timings. The ordered list used here is also used by Prepsq* to
  2180. %order factors in printed output, so cannot be unilaterally changed;
  2181. BEGIN SCALAR X,Y;
  2182. IF ATOM U THEN RETURN LIST(U,NIL);
  2183. Y := IF ATOM CAR U THEN GET(CAR U,'KLIST) ELSE EXLIST!*;
  2184. IF NOT (X := ASSOC(U,Y))
  2185. THEN <<X := LIST(U,NIL);
  2186. Y := ORDAD(X,Y);
  2187. IF ATOM CAR U
  2188. THEN <<KPROPS!* := UNION(LIST CAR U,KPROPS!*);
  2189. PUT(CAR U,'KLIST,Y)>>
  2190. ELSE EXLIST!* := Y>>;
  2191. RETURN X
  2192. END;
  2193. SYMBOLIC PROCEDURE MKSFPF(U,N);
  2194. %raises form U to power N with EXP off. Returns a form;
  2195. % IF DOMAINP U THEN !:EXPT(U,N)
  2196. % ELSE IF N>=0 AND KERNLP U
  2197. % THEN IF NULL RED U AND ONEP LC U THEN !*P2F MKSP(MVAR U,LDEG U*N)
  2198. % ELSE EXPTF1(U,N)
  2199. % ELSE IF N=1 OR NULL SUBFG!* THEN MKSP!*(U,N)
  2200. % ELSE (LAMBDA X; %IF X AND CDR X<=N THEN NIL ELSE MKSP!*(U,N))
  2201. % ASSOC(U,ASYMPLIS!*);
  2202. EXPTF(MKPROD!* U,N);
  2203. SYMBOLIC PROCEDURE MKSQ(U,N);
  2204. %U is a kernel, N a non-zero integer;
  2205. %Value is a standard quotient of U**N, after making any
  2206. %possible substitutions for U;
  2207. BEGIN SCALAR X,Y,Z;
  2208. IF NULL SUBFG!* THEN GO TO A1
  2209. ELSE IF (Y := ASSOC(U,WTL!*))
  2210. AND NULL CAR(Y := MKSQ('K!*,N*CDR Y)) THEN RETURN Y
  2211. ELSE IF NOT ATOM U THEN GO TO B
  2212. ELSE IF NULL !*NOSUBS AND (Z:= GET(U,'AVALUE)) THEN GO TO D;
  2213. FLAG(LIST U,'USED!*); %tell system U used as algebraic var;
  2214. A: IF !*NOSUBS OR N=1 THEN GO TO A1
  2215. ELSE IF (Z:= ASSOC(U,ASYMPLIS!*)) AND CDR Z<=N
  2216. THEN RETURN NIL ./ 1
  2217. ELSE IF ((Z:= ASSOC(U,POWLIS!*))
  2218. OR NOT ATOM U AND CAR U MEMQ '(EXPT SQRT)
  2219. AND (Z := ASSOC(CADR U,POWLIS!*)))
  2220. AND NOT(N*CADR Z)<0
  2221. %implements explicit sign matching;
  2222. THEN !*SUB2 := T;
  2223. A1: IF NULL X THEN X := FKERN U;
  2224. X := !*P2F GETPOWER(X,N) ./ 1;
  2225. RETURN IF Y THEN MULTSQ(Y,X) ELSE X;
  2226. B: IF NULL !*NOSUBS AND ATOM CAR U
  2227. AND (Z:= ASSOC(U,GET(CAR U,'KVALUE)))
  2228. THEN GO TO C
  2229. ELSE IF NOT('USED!* MEMQ CDDR (X := FKERN U))
  2230. THEN ACONC(X,'USED!*);
  2231. GO TO A;
  2232. C: Z := CDR Z;
  2233. D: %optimization is possible as shown if all expression
  2234. %dependency is known;
  2235. %IF CDR Z THEN RETURN EXPTSQ(CDR Z,N); %value already computed;
  2236. IF NULL !*RESUBS THEN !*NOSUBS := T;
  2237. X := SIMPCAR Z;
  2238. !*NOSUBS := NIL;
  2239. %RPLACD(Z,X); %save simplified value;
  2240. %SUBL!* := Z . SUBL!*;
  2241. RETURN EXPTSQ(X,N)
  2242. END;
  2243. %*********************************************************************
  2244. % FUNCTIONS FOR INTERNAL ORDERING OF EXPRESSIONS
  2245. %********************************************************************;
  2246. SYMBOLIC PROCEDURE ORDAD(A,U);
  2247. IF NULL U THEN LIST A
  2248. ELSE IF ORDP(A,CAR U) THEN A . U
  2249. ELSE CAR U . ORDAD(A,CDR U);
  2250. SYMBOLIC PROCEDURE ORDN U;
  2251. IF NULL U THEN NIL
  2252. ELSE IF NULL CDR U THEN U
  2253. ELSE IF NULL CDDR U THEN ORD2(CAR U,CADR U)
  2254. ELSE ORDAD(CAR U,ORDN CDR U);
  2255. SYMBOLIC PROCEDURE ORD2(U,V);
  2256. IF ORDP(U,V) THEN LIST(U,V) ELSE LIST(V,U);
  2257. SYMBOLIC PROCEDURE ORDP(U,V);
  2258. %returns TRUE if U ordered ahead or equal to V, NIL otherwise.
  2259. %an expression with more structure at a given level is ordered
  2260. %ahead of one with less;
  2261. IF NULL U THEN NULL V
  2262. ELSE IF NULL V THEN T
  2263. ELSE IF ATOM U
  2264. THEN IF ATOM V
  2265. THEN IF NUMBERP U THEN NUMBERP V AND NOT U<V
  2266. ELSE IF NUMBERP V THEN T ELSE ORDERP(U,V)
  2267. ELSE NIL
  2268. ELSE IF ATOM V THEN T
  2269. ELSE IF CAR U=CAR V THEN ORDP(CDR U,CDR V)
  2270. ELSE ORDP(CAR U,CAR V);
  2271. SYMBOLIC PROCEDURE ORDPP(U,V);
  2272. IF CAR U EQ CAR V THEN CDR U>CDR V
  2273. ELSE IF NCMP!* THEN NCMORDP(CAR U,CAR V)
  2274. ELSE ORDOP(CAR U,CAR V);
  2275. SYMBOLIC PROCEDURE ORDOP(U,V);
  2276. BEGIN SCALAR X;
  2277. X := KORD!*;
  2278. A: IF NULL X THEN RETURN ORDP(U,V)
  2279. ELSE IF U EQ CAR X THEN RETURN T
  2280. ELSE IF V EQ CAR X THEN RETURN;
  2281. X := CDR X;
  2282. GO TO A
  2283. END;
  2284. SYMBOLIC PROCEDURE NCMORDP(U,V);
  2285. IF NONCOMP U THEN IF NONCOMP V THEN ORDOP(U,V) ELSE T
  2286. ELSE IF NONCOMP V THEN NIL
  2287. ELSE ORDOP(U,V);
  2288. %*********************************************************************
  2289. % FUNCTIONS FOR REORDERING STANDARD FORMS
  2290. %*********************************************************************;
  2291. SYMBOLIC PROCEDURE REORDER U;
  2292. %reorders a standard form so that current kernel order is used;
  2293. IF DOMAINP U THEN U
  2294. ELSE RADDF(RMULTPF(LPOW U,REORDER LC U),REORDER RED U);
  2295. SYMBOLIC PROCEDURE RADDF(U,V);
  2296. %adds reordered forms U and V;
  2297. IF NULL U THEN V
  2298. ELSE IF NULL V THEN U
  2299. ELSE IF DOMAINP U THEN ADDD(U,V)
  2300. ELSE IF DOMAINP V THEN ADDD(V,U)
  2301. ELSE IF PEQ(LPOW U,LPOW V)
  2302. THEN (LPOW U .* RADDF(LC U,LC V)) .+ RADDF(RED U,RED V)
  2303. ELSE IF ORDPP(LPOW U,LPOW V) THEN LT U . RADDF(RED U,V)
  2304. ELSE LT V . RADDF(U,RED V);
  2305. SYMBOLIC PROCEDURE RMULTPF(U,V);
  2306. %multiplies power U by reordered form V;
  2307. IF NULL V THEN NIL
  2308. ELSE IF DOMAINP V OR ORDOP(CAR U,MVAR V) THEN !*T2F(U .* V)
  2309. ELSE (LPOW V .* RMULTPF(U,LC V)) .+ RMULTPF(U,RED V);
  2310. SYMBOLIC PROCEDURE KORDER U;
  2311. <<KORD!* := IF U = '(NIL) THEN NIL
  2312. ELSE FOR EACH X IN U COLLECT !*A2K X;
  2313. RMSUBS()>>;
  2314. RLISTAT '(KORDER);
  2315. SYMBOLIC PROCEDURE SETKORDER U;
  2316. BEGIN SCALAR V; V := KORD!*; KORD!* := U; RETURN V END;
  2317. %*********************************************************************
  2318. % FUNCTIONS WHICH APPLY BASIC PATTERN MATCHING RULES
  2319. %********************************************************************;
  2320. SYMBOLIC PROCEDURE EMTCH U;
  2321. IF ATOM U THEN U ELSE (LAMBDA X; IF X THEN X ELSE U) OPMTCH U;
  2322. SYMBOLIC PROCEDURE OPMTCH U;
  2323. BEGIN SCALAR X,Y,Z;
  2324. X := GET(CAR U,'OPMTCH);
  2325. IF NULL X THEN RETURN NIL
  2326. ELSE IF NULL SUBFG!* THEN RETURN NIL; %NULL(!*SUB2 := T);
  2327. Z := FOR EACH J IN CDR U COLLECT EMTCH J;
  2328. A: IF NULL X THEN RETURN;
  2329. Y := MCHARG(Z,CAAR X,CAR U);
  2330. B: IF NULL Y THEN GO TO C
  2331. ELSE IF EVAL SUBLA(CAR Y,CDADAR X)
  2332. THEN RETURN SUBLA(CAR Y,CADDAR X);
  2333. Y := CDR Y;
  2334. GO TO B;
  2335. C: X := CDR X;
  2336. GO TO A
  2337. END;
  2338. SYMBOLIC PROCEDURE MCHARG(U,V,W);
  2339. %procedure to determine if an argument list matches given template;
  2340. %U is argument list of operator W;
  2341. %V is argument list template being matched against;
  2342. %if there is no match, value is NIL,
  2343. %otherwise a list of lists of free variable pairings;
  2344. IF NULL U AND NULL V THEN LIST NIL
  2345. ELSE BEGIN INTEGER M,N;
  2346. M := LENGTH U;
  2347. N := LENGTH V;
  2348. IF FLAGP(W,'NARY) AND M>2
  2349. THEN IF M<6 AND FLAGP(W,'SYMMETRIC)
  2350. THEN RETURN MCHCOMB(U,V,W)
  2351. ELSE IF N=2 THEN <<U := CDR MKBIN(W,U); M := 2>>
  2352. ELSE RETURN NIL; %we cannot handle this case;
  2353. RETURN IF M NEQ N THEN NIL
  2354. ELSE IF FLAGP(W,'SYMMETRIC) THEN MCHSARG(U,V)
  2355. ELSE IF MTP V THEN LIST PAIR(V,U)
  2356. ELSE MCHARG2(U,V,LIST NIL)
  2357. END;
  2358. SYMBOLIC PROCEDURE MCHCOMB(U,V,OP);
  2359. BEGIN INTEGER N;
  2360. N := LENGTH U - LENGTH V +1;
  2361. IF N<1 THEN RETURN NIL
  2362. ELSE IF N=1 THEN RETURN MCHSARG(U,V)
  2363. ELSE IF NOT SMEMQLP(FRLIS!*,V) THEN RETURN NIL;
  2364. RETURN FOR EACH X IN COMB(U,N) CONC
  2365. MCHSARG((OP . X) . SETDIFF(U,X),V)
  2366. END;
  2367. SYMBOLIC PROCEDURE COMB(U,N);
  2368. %value is list of all combinations of N elements from the list U;
  2369. BEGIN SCALAR V; INTEGER M;
  2370. IF N=0 THEN RETURN LIST NIL
  2371. ELSE IF (M:=LENGTH U-N)<0 THEN RETURN;
  2372. A: IF M=0 THEN RETURN U . V;
  2373. V := NCONC(V,MAPCONS(COMB(CDR U,N-1),CAR U));
  2374. U := CDR U;
  2375. M := M-1;
  2376. GO TO A
  2377. END;
  2378. SYMBOLIC PROCEDURE MCHARG2(U,V,W);
  2379. %matches compatible list U against template V;
  2380. BEGIN SCALAR Y;
  2381. IF NULL U THEN RETURN W;
  2382. Y := MCHK(CAR U,CAR V);
  2383. U := CDR U;
  2384. V := CDR V;
  2385. RETURN FOR EACH J IN Y
  2386. CONC MCHARG2(U,UPDTEMPLATE(J,V),MAPPEND(W,J))
  2387. END;
  2388. SYMBOLIC PROCEDURE UPDTEMPLATE(U,V);
  2389. BEGIN SCALAR X,Y;
  2390. RETURN FOR EACH J IN V COLLECT
  2391. IF (X := SUBLA(U,J)) = J THEN J
  2392. ELSE IF (Y := REVAL X) NEQ X THEN Y
  2393. ELSE X
  2394. END;
  2395. SYMBOLIC PROCEDURE MCHK(U,V);
  2396. IF U=V THEN LIST NIL
  2397. ELSE IF ATOM V
  2398. THEN IF V MEMQ FRLIS!* THEN LIST LIST (V . U) ELSE NIL
  2399. ELSE IF ATOM U %special check for negative number match;
  2400. THEN IF NUMBERP U AND U<0 THEN MCHK(LIST('MINUS,-U),V)
  2401. ELSE NIL
  2402. ELSE IF CAR U EQ CAR V THEN MCHARG(CDR U,CDR V,CAR U)
  2403. ELSE NIL;
  2404. SYMBOLIC PROCEDURE MKBIN(U,V);
  2405. IF NULL CDDR V THEN U . V ELSE LIST(U,CAR V,MKBIN(U,CDR V));
  2406. SYMBOLIC PROCEDURE MTP V;
  2407. NULL V OR (CAR V MEMQ FRLIS!* AND NOT CAR V MEMBER CDR V
  2408. AND MTP CDR V);
  2409. SYMBOLIC PROCEDURE MCHSARG(U,V);
  2410. REVERSIP IF MTP V
  2411. THEN FOR EACH J IN PERMUTATIONS V COLLECT PAIR(J,U)
  2412. ELSE FOR EACH J IN PERMUTATIONS U CONC MCHARG2(J,V,LIST NIL);
  2413. SYMBOLIC PROCEDURE PERMUTATIONS U;
  2414. IF NULL U THEN LIST U
  2415. ELSE FOR EACH J IN U CONC MAPCONS(PERMUTATIONS DELETE(J,U),J);
  2416. FLAGOP ANTISYMMETRIC,SYMMETRIC;
  2417. FLAG ('(PLUS TIMES CONS),'SYMMETRIC);
  2418. %*********************************************************************
  2419. % FUNCTIONS FOR CONVERTING CANONICAL FORMS INTO PREFIX FORMS
  2420. %********************************************************************;
  2421. SYMBOLIC PROCEDURE PREPSQ U;
  2422. IF NULL NUMR U THEN 0 ELSE SQFORM(U,FUNCTION PREPF);
  2423. SYMBOLIC PROCEDURE SQFORM(U,V);
  2424. (LAMBDA (X,Y); IF Y=1 THEN X ELSE LIST('QUOTIENT,X,Y))
  2425. (APPLY(V,LIST NUMR U),APPLY(V,LIST DENR U));
  2426. SYMBOLIC PROCEDURE PREPF U;
  2427. REPLUS PREPF1(U,NIL);
  2428. SYMBOLIC PROCEDURE PREPF1(U,V);
  2429. IF NULL U THEN NIL
  2430. ELSE IF DOMAINP U
  2431. THEN LIST RETIMES((IF ATOM U
  2432. THEN IF U<0 THEN LIST('MINUS,-U) ELSE U
  2433. ELSE IF APPLY(GET(CAR U,'MINUSP),LIST U)
  2434. THEN LIST('MINUS,PREPD !:MINUS U)
  2435. ELSE PREPD U)
  2436. . EXCHK(V,NIL,NIL))
  2437. ELSE NCONC(PREPF1(LC U,IF MVAR U EQ 'K!* THEN V ELSE LPOW U .* V)
  2438. ,PREPF1(RED U,V));
  2439. SYMBOLIC PROCEDURE PREPD U; APPLY(GET(CAR U,'PREPFN),LIST U);
  2440. SYMBOLIC PROCEDURE EXCHK(U,V,W);
  2441. IF NULL U
  2442. THEN IF NULL W THEN V
  2443. ELSE EXCHK(U,LIST('EXPT,CAAR W,PREPSQX CDAR W) . V,CDR W)
  2444. ELSE IF EQCAR(CAAR U,'EXPT)
  2445. THEN EXCHK(CDR U,V,
  2446. BEGIN SCALAR X,Y;
  2447. X := ASSOC(CADAAR U,W);
  2448. Y := SIMP LIST('TIMES,CDAR U,CADDAR CAR U);
  2449. IF X THEN RPLACD(X,ADDSQ(Y,CDR X))
  2450. ELSE W := (CADAAR U . Y) . W;
  2451. RETURN W
  2452. END)
  2453. ELSE IF CDAR U=1 THEN EXCHK(CDR U, SQCHK CAAR U . V,W)
  2454. ELSE EXCHK(CDR U,LIST('EXPT,SQCHK CAAR U,CDAR U) . V,W);
  2455. SYMBOLIC PROCEDURE REPLUS U;
  2456. IF ATOM U THEN U ELSE IF NULL CDR U THEN CAR U ELSE 'PLUS . U;
  2457. SYMBOLIC PROCEDURE RETIMES U;
  2458. BEGIN SCALAR X,Y;
  2459. A: IF NULL U THEN GO TO D
  2460. ELSE IF ONEP CAR U THEN GO TO C
  2461. ELSE IF NOT EQCAR(CAR U,'MINUS) THEN GO TO B;
  2462. X := NOT X;
  2463. IF ONEP CADAR U THEN GO TO C
  2464. ELSE U := CADAR U . CDR U;
  2465. B: Y := CAR U . Y;
  2466. C: U := CDR U;
  2467. GO TO A;
  2468. D: Y := IF NULL Y THEN 1
  2469. ELSE IF CDR Y THEN 'TIMES . REVERSE Y ELSE CAR Y;
  2470. RETURN IF X THEN LIST('MINUS,Y) ELSE Y
  2471. END;
  2472. SYMBOLIC PROCEDURE SQCHK U;
  2473. IF ATOM U THEN U
  2474. ELSE IF CAR U EQ '!*SQ THEN PREPSQ CADR U
  2475. ELSE IF CAR U EQ 'EXPT AND CADDR U=1 THEN CADR U
  2476. ELSE IF ATOM CAR U THEN U ELSE PREPF U;
  2477. %*********************************************************************
  2478. % BASIC OUTPUT PACKAGE FOR CANONICAL FORMS
  2479. %********************************************************************;
  2480. %Global variables referenced in this section;
  2481. GLOBAL '(VARNAM!* ORIG!* YCOORD!* YMIN!* SPARE!*);
  2482. SPARE!* := 5; %RIGHT MARGIN, TO AVOID TROUBLE WITH PREMATURE
  2483. %LINE-BREAKS INSERTED BY LISP;
  2484. VARNAM!* := 'ANS;
  2485. ORIG!*:=0;
  2486. POSN!* := 0;
  2487. YCOORD!* := 0;
  2488. YMIN!* := 0;
  2489. DEFLIST ('((!*SQ !*SQPRINT)),'SPECPRN);
  2490. SYMBOLIC PROCEDURE !*SQPRINT U; SQPRINT CAR U;
  2491. SYMBOLIC PROCEDURE SQPRINT U;
  2492. %mathprints the standard quotient U;
  2493. BEGIN SCALAR Z;
  2494. Z := ORIG!*;
  2495. IF !*NAT AND POSN!*<20 THEN ORIG!* := POSN!*;
  2496. IF !*PRI OR WTL!* THEN GO TO C
  2497. ELSE IF CDR U NEQ 1 THEN GO TO B
  2498. ELSE XPRINF(CAR U,NIL,NIL);
  2499. A: RETURN (ORIG!* := Z);
  2500. B: PRIN2!* "(";
  2501. XPRINF(CAR U,NIL,NIL);
  2502. PRIN2!* ") / (";;
  2503. XPRINF(CDR U,NIL,NIL);
  2504. PRIN2!* ")";
  2505. GO TO A;
  2506. C: MAPRIN(!*OUTP := U := PREPSQ!* U);
  2507. GO TO A
  2508. END;
  2509. SYMBOLIC PROCEDURE VARPRI(U,V,W);
  2510. BEGIN SCALAR X,Y;
  2511. %U is expression being printed
  2512. %V is a list of expressions assigned to U
  2513. %W is a flag which is true if expr is last in current set;
  2514. IF NULL U THEN U := 0; %allow for unset array elements;
  2515. IF !*NERO AND U=0 THEN RETURN;
  2516. IF W MEMQ '(FIRST ONLY) THEN TERPRI!* T;
  2517. X := TYPL!*;
  2518. A: IF NULL X THEN GO TO B
  2519. ELSE IF APPLY(CAR X,LIST U) AND (Y:= GET(CAR X,'PRIFN))
  2520. THEN RETURN APPLY(Y,LIST(U,V,W));
  2521. X := CDR X;
  2522. GO TO A;
  2523. B: IF !*FORT THEN RETURN FVARPRI(U,V,W)
  2524. ELSE IF NULL V THEN GO TO C;
  2525. INPRINT('SETQ,GET('SETQ,'INFIX),MAPCAR(V,FUNCTION EVAL));
  2526. OPRIN 'SETQ;
  2527. C: MAPRIN U;
  2528. IF NULL W OR W EQ 'FIRST THEN RETURN NIL
  2529. ELSE IF NOT !*NAT THEN PRIN2!* "$";
  2530. TERPRI!*(NOT !*NAT);
  2531. RETURN
  2532. END;
  2533. SYMBOLIC PROCEDURE XPRINF(U,V,W);
  2534. %U is a standard form.
  2535. %V is a flag which is true if a term has preceded current form.
  2536. %W is a flag which is true if form is part of a standard term;
  2537. %Procedure prints the form and returns NIL;
  2538. BEGIN
  2539. A: IF NULL U THEN RETURN NIL
  2540. ELSE IF DOMAINP U THEN RETURN XPRID(U,V,W);
  2541. XPRINT(LT U,V);
  2542. U := RED U;
  2543. V := T;
  2544. GO TO A
  2545. END;
  2546. SYMBOLIC PROCEDURE XPRID(U,V,W);
  2547. %U is a domain element.
  2548. %V is a flag which is true if a term has preceded element.
  2549. %W is a flag which is true if U is part of a standard term.
  2550. %Procedure prints element and returns NIL;
  2551. BEGIN
  2552. IF MINUSF U THEN <<OPRIN 'MINUS; U := !:MINUS U>>
  2553. ELSE IF V THEN OPRIN 'PLUS;
  2554. IF NOT W OR U NEQ 1
  2555. THEN IF ATOM U THEN PRIN2!* U ELSE MAPRIN U
  2556. END;
  2557. SYMBOLIC PROCEDURE XPRINT(U,V);
  2558. %U is a standard term.
  2559. %V is a flag which is true if a term has preceded this term.
  2560. %Procedure prints the term and returns NIL;
  2561. BEGIN SCALAR FLG,W;
  2562. FLG := NOT ATOM TC U AND RED TC U;
  2563. IF NOT FLG THEN GO TO A ELSE IF V THEN OPRIN 'PLUS;
  2564. PRIN2!* "(";
  2565. A: XPRINF(TC U,IF FLG THEN NIL ELSE V,NOT FLG);
  2566. IF FLG THEN PRIN2!* ")";
  2567. IF NOT ATOM TC U OR NOT ABS FIX TC U=1 THEN OPRIN 'TIMES;
  2568. W := TPOW U;
  2569. IF ATOM CAR W THEN PRIN2!* CAR W
  2570. ELSE IF NOT ATOM CAAR W OR CAAR W EQ '!*SQ THEN GO TO C
  2571. ELSE IF CAAR W EQ 'PLUS THEN MAPRINT(CAR W,100)
  2572. ELSE MAPRIN CAR W;
  2573. B: IF CDR W=1 THEN RETURN;
  2574. OPRIN 'EXPT;
  2575. PRIN2!* CDR W;
  2576. IF NOT !*NAT THEN RETURN;
  2577. YCOORD!* := YCOORD!*-1;
  2578. IF YMIN!*>YCOORD!* THEN YMIN!* := YCOORD!*;
  2579. RETURN;
  2580. C: PRIN2!* "(";
  2581. IF NOT ATOM CAAR W THEN XPRINF(CAR W,NIL,NIL)
  2582. ELSE SQPRINT CADAR W;
  2583. PRIN2!* ")";
  2584. GO TO B
  2585. END;
  2586. %*********************************************************************
  2587. % FUNCTIONS FOR PRINTING PREFIX EXPRESSIONS
  2588. %********************************************************************;
  2589. %Global variables referenced in this sub-section;
  2590. GLOBAL '(OBRKP!* PLINE!* !*FORT !*LIST !*NAT YMAX!*);
  2591. OBRKP!* := T;
  2592. PLINE!* := NIL;
  2593. !*FORT:=NIL;
  2594. !*LIST := NIL;
  2595. !*NAT := NAT!*!* := T;
  2596. YMAX!* := 0;
  2597. INITL!* := APPEND('(ORIG!* PLINE!*),INITL!*);
  2598. PUT('ORIG!*,'INITL,0);
  2599. FLAG('(LINELENGTH),'OPFN); %to make it a symbolic operator;
  2600. SYMBOLIC PROCEDURE MATHPRINT L;
  2601. BEGIN TERPRI!* T; MAPRIN L; TERPRI!* T END;
  2602. SYMBOLIC PROCEDURE MAPRIN U;
  2603. MAPRINT(U,0);
  2604. SYMBOLIC PROCEDURE MAPRINT(L,P);
  2605. BEGIN SCALAR X,Y;
  2606. IF NULL L THEN RETURN NIL
  2607. ELSE IF ATOM L THEN GO TO B
  2608. ELSE IF STRINGP L THEN RETURN PRIN2!* L
  2609. ELSE IF NOT ATOM CAR L THEN MAPRINT(CAR L,P)
  2610. ELSE IF X := GET(CAR L,'SPECPRN)
  2611. THEN RETURN APPLY(X,LIST CDR L)
  2612. ELSE IF X := GET(CAR L,'INFIX) THEN GO TO A
  2613. ELSE PRIN2!* CAR L;
  2614. PRIN2!* "(";
  2615. OBRKP!* := NIL;
  2616. IF CDR L THEN INPRINT('!*COMMA!*,0,CDR L);
  2617. OBRKP!* := T;
  2618. E: RETURN PRIN2!* ")";
  2619. B: IF NUMBERP L THEN GO TO D;
  2620. C: RETURN PRIN2!* L;
  2621. D: IF NOT L<0 THEN GO TO C;
  2622. PRIN2!* "(";
  2623. PRIN2!* L;
  2624. GO TO E;
  2625. A: P := NOT X>P;
  2626. IF NOT P THEN GO TO G;
  2627. Y := ORIG!*;
  2628. PRIN2!* "(";
  2629. ORIG!* := IF POSN!*<18 THEN POSN!* ELSE ORIG!*+3;
  2630. G: INPRINT(CAR L,X,CDR L);
  2631. IF NOT P THEN RETURN;
  2632. PRIN2!* ")";
  2633. ORIG!* := Y
  2634. END;
  2635. SYMBOLIC PROCEDURE INPRINT(OP,P,L);
  2636. BEGIN
  2637. IF GET(OP,'ALT) THEN GO TO A
  2638. ELSE IF OP EQ 'EXPT AND !*NAT
  2639. AND FLATSIZEC CAR L+FLATSIZEC CADR L>
  2640. (LINELENGTH NIL-SPARE!*)-POSN!*
  2641. THEN TERPRI!* T; %to avoid breaking exponent over line;
  2642. MAPRINT(CAR L,P);
  2643. A0: L := CDR L;
  2644. A: IF NULL L THEN RETURN NIL
  2645. ELSE IF NOT ATOM CAR L AND OP EQ GET!*(CAAR L,'ALT)
  2646. THEN GO TO B;
  2647. OPRIN OP;
  2648. B: MAPRINT(CAR L,P);
  2649. IF NOT !*NAT OR NOT OP EQ 'EXPT THEN GO TO A0;
  2650. YCOORD!* := YCOORD!*-1;
  2651. IF YMIN!*>YCOORD!* THEN YMIN!* := YCOORD!*;
  2652. GO TO A0
  2653. END;
  2654. SYMBOLIC PROCEDURE FLATSIZEC U;
  2655. IF NULL U THEN 0
  2656. ELSE IF ATOM U THEN LENGTHC U
  2657. ELSE FLATSIZEC CAR U + FLATSIZEC CDR U;
  2658. SYMBOLIC PROCEDURE OPRIN OP;
  2659. (LAMBDA X;
  2660. IF NULL X THEN PRIN2!* OP
  2661. ELSE IF !*FORT THEN PRIN2!* CADR X
  2662. ELSE IF !*LIST AND OBRKP!* AND OP MEMQ '(PLUS MINUS)
  2663. THEN BEGIN TERPRI!* T; PRIN2!* CAR X END
  2664. ELSE IF !*NAT AND OP EQ 'EXPT
  2665. THEN BEGIN
  2666. YCOORD!* := YCOORD!*+1;
  2667. IF YCOORD!*>YMAX!* THEN YMAX!* := YCOORD!*
  2668. END
  2669. ELSE PRIN2!* CAR X)
  2670. GET(OP,'PRTCH);
  2671. SYMBOLIC PROCEDURE PRIN2!* U;
  2672. BEGIN INTEGER M,N;
  2673. IF !*FORT THEN RETURN FPRIN2 U;
  2674. N := LENGTHC U;
  2675. IF N>(LINELENGTH NIL-SPARE!*) THEN GO TO D;
  2676. M := POSN!*+N;
  2677. A: IF M>(LINELENGTH NIL-SPARE!*) THEN GO TO C
  2678. ELSE IF NOT !*NAT THEN PRIN2 U
  2679. ELSE PLINE!* := (((POSN!* . M) . YCOORD!*) . U) . PLINE!*;
  2680. B: RETURN (POSN!* := M);
  2681. C: TERPRI!* T;
  2682. IF (M := POSN!*+N)<=(LINELENGTH NIL-SPARE!*) THEN GO TO A;
  2683. D: %identifier longer than one line;
  2684. IF !*FORT THEN REDERR LIST(U,"too long for FORTRAN");
  2685. %let LISP print the atom;
  2686. TERPRI!* NIL;
  2687. PRIN2T U;
  2688. M := REMAINDER(N,(LINELENGTH NIL-SPARE!*));
  2689. GO TO B
  2690. END;
  2691. SYMBOLIC PROCEDURE TERPRI!* U;
  2692. BEGIN INTEGER N;
  2693. IF !*FORT THEN RETURN FTERPRI(U)
  2694. ELSE IF NOT PLINE!* OR NOT !*NAT THEN GO TO B;
  2695. N := YMAX!*;
  2696. PLINE!* := REVERSE PLINE!*;
  2697. A: SCPRINT(PLINE!*,N);
  2698. TERPRI();
  2699. IF N= YMIN!* THEN GO TO B;
  2700. N := N-1;
  2701. GO TO A;
  2702. B: IF U THEN TERPRI();
  2703. C: PLINE!* := NIL;
  2704. POSN!* := ORIG!*;
  2705. YCOORD!* := YMAX!* := YMIN!* := 0
  2706. END;
  2707. SYMBOLIC PROCEDURE SCPRINT(U,N);
  2708. BEGIN SCALAR M;
  2709. POSN!* := 0;
  2710. A: IF NULL U THEN RETURN NIL
  2711. ELSE IF NOT CDAAR U=N THEN GO TO B
  2712. ELSE IF NOT (M:= CAAAAR U-POSN!*)<0 THEN SPACES M;
  2713. PRIN2 CDAR U;
  2714. POSN!* := CDAAAR U;
  2715. B: U := CDR U;
  2716. GO TO A
  2717. END;
  2718. COMMENT ***** FORTRAN OUTPUT PACKAGE *****;
  2719. GLOBAL '(CARDNO!* FORTWIDTH!*);
  2720. FLAG ('(CARDNO!* FORTWIDTH!*),'SHARE);
  2721. CARDNO!*:=20;
  2722. FORTWIDTH!* := 70;
  2723. FLUID '(FBRKT); %bracket level counter;
  2724. SYMBOLIC PROCEDURE VARNAME U;
  2725. %sets the default variable assignment name;
  2726. VARNAM!* := CAR U;
  2727. RLISTAT '(VARNAME);
  2728. SYMBOLIC PROCEDURE FLENGTH(U,CHARS);
  2729. IF CHARS<0 THEN CHARS
  2730. ELSE IF ATOM U
  2731. THEN CHARS-IF NUMBERP U THEN IF FIXP U THEN FLATSIZEC U+1
  2732. ELSE FLATSIZEC U
  2733. ELSE FLATSIZEC((LAMBDA X; IF X THEN CADR X ELSE U)
  2734. GET(U,'PRTCH))
  2735. ELSE FLENGTH(CAR U,FLENLIS(CDR U,CHARS)-2);
  2736. SYMBOLIC PROCEDURE FLENLIS(U,CHARS);
  2737. IF NULL U THEN CHARS
  2738. ELSE IF CHARS<0 THEN CHARS
  2739. ELSE IF ATOM U THEN FLENGTH(U,CHARS)
  2740. ELSE FLENLIS(CDR U,FLENGTH(CAR U,CHARS));
  2741. SYMBOLIC PROCEDURE FMPRINT(L,P);
  2742. BEGIN SCALAR X;
  2743. IF NULL L THEN RETURN NIL
  2744. ELSE IF ATOM L THEN GO TO B
  2745. ELSE IF STRINGP L THEN RETURN FPRIN2 L
  2746. ELSE IF NOT ATOM CAR L THEN FMPRINT(CAR L,P)
  2747. ELSE IF X := GET(CAR L,'INFIX) THEN GO TO A
  2748. ELSE IF X := GET(CAR L,'SPECPRN)
  2749. THEN RETURN APPLY(X,LIST CDR L) ELSE FPRIN2 CAR L;
  2750. FPRIN2 "(";
  2751. FBRKT := NIL . FBRKT;
  2752. X := !*PERIOD; !*PERIOD := NIL; %turn off . inside an op exp;
  2753. IF CDR L THEN FNPRINT('!*COMMA!*,0,CDR L);
  2754. !*PERIOD := X;
  2755. E: FPRIN2 ")";
  2756. RETURN FBRKT := CDR FBRKT;
  2757. B: IF NUMBERP L THEN GO TO D;
  2758. C: RETURN FPRIN2 L;
  2759. D: IF NOT L<0 THEN GO TO C;
  2760. FPRIN2 "(";
  2761. FBRKT := NIL . FBRKT;
  2762. FPRIN2 L;
  2763. GO TO E;
  2764. A: P := NOT X>P;
  2765. IF P THEN <<FPRIN2 "("; FBRKT := NIL . FBRKT>>;
  2766. FNPRINT(CAR L,X,CDR L);
  2767. IF P THEN <<FPRIN2 ")"; FBRKT := CDR FBRKT>>
  2768. END;
  2769. SYMBOLIC PROCEDURE FNPRINT(OP,P,L);
  2770. BEGIN
  2771. IF OP EQ 'EXPT THEN RETURN FEXPPRI(P,L)
  2772. ELSE IF GET(OP,'ALT) THEN GO TO A;
  2773. FMPRINT(CAR L,P);
  2774. A0: L := CDR L;
  2775. A: IF NULL L THEN RETURN NIL
  2776. ELSE IF NOT ATOM CAR L AND OP EQ GET!*(CAAR L,'ALT)
  2777. THEN GO TO B;
  2778. FOPRIN OP;
  2779. B: FMPRINT(CAR L,P);
  2780. GO TO A0
  2781. END;
  2782. SYMBOLIC PROCEDURE FEXPPRI(P,L);
  2783. BEGIN SCALAR PPERIOD;
  2784. FMPRINT(CAR L,P);
  2785. FOPRIN 'EXPT;
  2786. PPERIOD := !*PERIOD;
  2787. IF NUMBERP CADR L THEN !*PERIOD := NIL ELSE !*PERIOD := T;
  2788. FMPRINT(CADR L,P);
  2789. !*PERIOD := PPERIOD
  2790. END;
  2791. SYMBOLIC PROCEDURE FOPRIN OP;
  2792. (LAMBDA X; IF NULL X THEN FPRIN2 OP ELSE FPRIN2 CADR X)
  2793. GET(OP,'PRTCH);
  2794. FLUID '(COUNTR EXPLIS FVAR NCHARS VAR);
  2795. SYMBOLIC PROCEDURE FVARPRI(U,V,W);
  2796. %prints an assignment in FORTRAN notation;
  2797. BEGIN INTEGER COUNTR,LLENGTH,NCHARS; SCALAR EXPLIS,FVAR,VAR;
  2798. LLENGTH := LINELENGTH NIL;
  2799. LINELENGTH FORTWIDTH!*;
  2800. IF STRINGP U
  2801. THEN RETURN <<FPRIN2 U; IF W EQ 'ONLY THEN FTERPRI(T)>>;
  2802. IF EQCAR(U,'!*SQ) THEN U := PREPSQ!* CADR U;
  2803. COUNTR := 0;
  2804. NCHARS := ((LINELENGTH NIL-SPARE!*)-12)*CARDNO!*;
  2805. %12 is to allow for indentation and end of line effects;
  2806. VAR := VARNAM!*;
  2807. FVAR := IF NULL V THEN VAR ELSE EVAL CAR V;
  2808. IF POSN!*=0 AND W THEN FORTPRI(FVAR,U)
  2809. ELSE <<FMPRINT(U,0); IF W THEN FTERPRI W>>;
  2810. %means that expression preceded by a string;
  2811. LINELENGTH LLENGTH;
  2812. END;
  2813. SYMBOLIC PROCEDURE FORTPRI(FVAR,XEXP);
  2814. BEGIN SCALAR FBRKT;
  2815. IF FLENGTH(XEXP,NCHARS)<0
  2816. THEN XEXP := CAR XEXP . FOUT(CDR XEXP,CAR XEXP);
  2817. POSN!* := 0;
  2818. FPRIN2 " ";
  2819. FMPRINT(FVAR,0);
  2820. FPRIN2 "=";
  2821. FMPRINT(XEXP,0);
  2822. FTERPRI(T)
  2823. END;
  2824. SYMBOLIC PROCEDURE FOUT(ARGS,OP);
  2825. BEGIN INTEGER NCHARSL; SCALAR DISTOP,X,Z;
  2826. NCHARSL := NCHARS;
  2827. IF OP MEMQ '(PLUS TIMES) THEN DISTOP := OP;
  2828. WHILE ARGS DO
  2829. <<X := CAR ARGS;
  2830. IF ATOM X AND (NCHARSL := FLENGTH(X,NCHARSL))
  2831. OR (NULL CDR ARGS OR DISTOP)
  2832. AND (NCHARSL := FLENGTH(X,NCHARSL))>0
  2833. THEN Z := X . Z
  2834. ELSE IF DISTOP AND FLENGTH(X,NCHARS)>0
  2835. THEN <<Z := FOUT1(DISTOP . ARGS) . Z;
  2836. ARGS := LIST NIL>>
  2837. ELSE <<Z := FOUT1 X . Z;
  2838. NCHARSL := FLENGTH(OP,NCHARSL)>>;
  2839. NCHARSL := FLENGTH(OP,NCHARSL);
  2840. ARGS := CDR ARGS>>;
  2841. RETURN REVERSIP Z
  2842. END;
  2843. SYMBOLIC PROCEDURE FOUT1 XEXP;
  2844. BEGIN SCALAR FVAR;
  2845. FVAR := GENVAR();
  2846. EXPLIS := (XEXP . FVAR) . EXPLIS;
  2847. FORTPRI(FVAR,XEXP);
  2848. RETURN FVAR
  2849. END;
  2850. SYMBOLIC PROCEDURE FPRIN2 U;
  2851. % FORTRAN output of U;
  2852. BEGIN INTEGER M,N;
  2853. N := FLATSIZEC U;
  2854. M := POSN!*+N;
  2855. IF NUMBERP U AND FIXP U AND !*PERIOD THEN M := M+1;
  2856. IF M<(LINELENGTH NIL-SPARE!*) THEN POSN!* := M
  2857. ELSE <<TERPRI(); SPACES 5; PRIN2 ". "; POSN!* := N+7>>;
  2858. PRIN2 U;
  2859. IF NUMBERP U AND FIXP U AND !*PERIOD THEN PRIN2 "."
  2860. END;
  2861. SYMBOLIC PROCEDURE FTERPRI(U);
  2862. <<IF NOT POSN!*=0 AND U THEN TERPRI();
  2863. POSN!* := 0>>;
  2864. SYMBOLIC PROCEDURE GENVAR;
  2865. INTERN COMPRESS APPEND(EXPLODE VAR,EXPLODE(COUNTR := COUNTR + 1));
  2866. UNFLUID '(EXPLIS FBRKT FVAR NCHARS);
  2867. %*********************************************************************
  2868. % FOR ALL COMMAND
  2869. %********************************************************************;
  2870. SYMBOLIC PROCEDURE FORALLSTAT;
  2871. BEGIN SCALAR ARBL,CONDS;
  2872. IF CURSYM!* MEMQ LETL!* THEN SYMERR('forall,T);
  2873. FLAG(LETL!*,'DELIM);
  2874. ARBL := REMCOMMA XREAD NIL;
  2875. IF CURSYM!* EQ 'SUCH THEN
  2876. <<IF NOT SCAN() EQ 'THAT THEN SYMERR('let,T);
  2877. CONDS := XREAD NIL>>;
  2878. REMFLAG(LETL!*,'DELIM);
  2879. RETURN IFLET1(ARBL,CONDS)
  2880. END;
  2881. SYMBOLIC PROCEDURE IFLET U; IFLET1(NIL,U);
  2882. SYMBOLIC PROCEDURE IFLET1(ARBL,CONDS);
  2883. IF NOT CURSYM!* MEMQ LETL!* THEN SYMERR('let,T)
  2884. ELSE LIST('FORALL,ARBL,CONDS,XREAD1 T);
  2885. SYMBOLIC PROCEDURE FORMARB(U,VARS,MODE);
  2886. <<ARBL!* := CAR U . ARBL!*; MKQUOTE CAR U>>;
  2887. PUT('ARB,'FORMFN,'FORMARB);
  2888. PUT('FORALL,'STAT,'FORALLSTAT);
  2889. SYMBOLIC FEXPR PROCEDURE FORALL U;
  2890. BEGIN SCALAR X,Y;
  2891. X := FOR EACH J IN CAR U COLLECT NEWVAR J;
  2892. Y := PAIR(CAR U,X);
  2893. MCOND!* := SUBLA(Y,CADR U);
  2894. FRASC!* := Y;
  2895. FRLIS!* := UNION(X,FRLIS!*);
  2896. RETURN EVAL CADDR U
  2897. END;
  2898. SYMBOLIC PROCEDURE FORMFORALL(U,VARS,MODE);
  2899. BEGIN SCALAR ARBL!*,X;
  2900. % VARS := APPEND(CAR U,VARS); %semantics are different;
  2901. IF NULL CADR U THEN X := T ELSE X := FORMBOOL(CADR U,VARS,MODE);
  2902. RETURN LIST('FORALL,UNION(ARBL!*,CAR U),
  2903. X,FORM1(CADDR U,VARS,MODE))
  2904. END;
  2905. PUT('FORALL,'FORMFN,'FORMFORALL);
  2906. SYMBOLIC PROCEDURE NEWVAR U;
  2907. IF NOT IDP U THEN TYPERR(U,"free variable")
  2908. ELSE INTERN COMPRESS APPEND(EXPLODE '!=,EXPLODE U);
  2909. %*********************************************************************
  2910. % 2.19 SUBSTITUTION COMMANDS
  2911. %********************************************************************;
  2912. SYMBOLIC PROCEDURE FORMLET1(U,VARS,MODE);
  2913. 'LIST . FOR EACH X IN U COLLECT
  2914. IF EQEXPR X
  2915. THEN LIST('LIST,MKQUOTE 'EQUAL,FORM1(CADR X,VARS,MODE),
  2916. !*S2ARG(FORM1(CADDR X,VARS,MODE),VARS))
  2917. ELSE ERRPRI2(X,T);
  2918. SYMBOLIC PROCEDURE !*S2ARG(U,VARS);
  2919. %makes all NOCHANGE operators into their listed form;
  2920. IF ATOM U THEN U
  2921. ELSE IF NOT IDP CAR U OR NOT FLAGP(CAR U,'NOCHANGE)
  2922. THEN FOR EACH J IN U COLLECT !*S2ARG(J,VARS)
  2923. ELSE MKARG(U,VARS);
  2924. PUT('LET,'FORMFN,'FORMLET);
  2925. PUT('CLEAR,'FORMFN,'FORMCLEAR);
  2926. PUT('MATCH,'FORMFN,'FORMMATCH);
  2927. SYMBOLIC PROCEDURE FORMCLEAR(U,VARS,MODE);
  2928. LIST('CLEAR,FORMCLEAR1(U,VARS,MODE));
  2929. SYMBOLIC PROCEDURE FORMCLEAR1(U,VARS,MODE);
  2930. 'LIST . FOR EACH X IN U COLLECT FORM1(X,VARS,MODE);
  2931. SYMBOLIC PROCEDURE FORMLET(U,VARS,MODE);
  2932. LIST('LET,FORMLET1(U,VARS,MODE));
  2933. SYMBOLIC PROCEDURE FORMMATCH(U,VARS,MODE);
  2934. LIST('MATCH,FORMLET1(U,VARS,MODE));
  2935. SYMBOLIC PROCEDURE LET U;
  2936. LET0(U,NIL);
  2937. SYMBOLIC PROCEDURE LET0(U,V);
  2938. BEGIN
  2939. FOR EACH X IN U DO LET2(CADR X,CADDR X,V,T);
  2940. MCOND!* := FRASC!* := NIL
  2941. END;
  2942. SYMBOLIC PROCEDURE LET2(U,V,W,B);
  2943. BEGIN SCALAR FLG,X,Y,Z;
  2944. %FLG is set true if free variables are found in following;
  2945. X := SUBLA(FRASC!*,U);
  2946. IF X NEQ U
  2947. THEN IF ATOM X THEN GO TO LER1 %an atom cannot be free;
  2948. ELSE <<FLG := T; U := X>>;
  2949. X := SUBLA(FRASC!*,V);
  2950. IF X NEQ V
  2951. THEN <<V := X;
  2952. IF EQCAR(V,'!*SQ!*) THEN V := PREPSQ!* CADR V>>;
  2953. %to ensure no kernels or powers are copied during
  2954. %pattern matching process;
  2955. %check for unmatched free variables;
  2956. X := SMEMQL(FRLIS!*,MCOND!*);
  2957. Y := SMEMQL(FRLIS!*,U);
  2958. IF (Z := SETDIFF(X,Y))
  2959. OR (Z := SETDIFF(SETDIFF(SMEMQL(FRLIS!*,V),X),
  2960. SETDIFF(Y,X)))
  2961. THEN <<LPRIE ("Unmatched free variable(s)" . Z);
  2962. ERFG!* := 'HOLD;
  2963. RETURN NIL>>
  2964. ELSE IF EQCAR(U,'GETEL) THEN U := EVAL CADR U;
  2965. A: X := U;
  2966. IF NUMBERP X THEN GO TO LER1
  2967. ELSE IF IDP X AND FLAGP(X,'RESERVED)
  2968. THEN REDERR LIST(X,"is a reserved identifier");
  2969. Y := TYPL!*;
  2970. B: IF NULL Y THEN GO TO C
  2971. ELSE IF (Z := APPLY(CAR Y,LIST X)) OR APPLY(CAR Y,LIST V)
  2972. THEN RETURN APPLY(GET(CAR Y,'LETFN),
  2973. LIST(X,V,GET(CAR Y,'NAME),B,Z));
  2974. Y := CDR Y;
  2975. GO TO B;
  2976. C: IF NOT ATOM X THEN GO TO NONATOM;
  2977. IF B OR W THEN GO TO D;
  2978. %We remove all conceivable properties when an atom is cleared;
  2979. REMPROP(X,'AVALUE);
  2980. REMPROP(X,'OPMTCH);
  2981. % REMPROP(X,'KLIST); %since the relevant objects may still
  2982. %exist;
  2983. REMPROP(X,'MATRIX);
  2984. IF ARRAYP X
  2985. THEN <<REMPROP(X,'ARRAY); REMPROP(X,'DIMENSION)>>;
  2986. WTL!* := DELASC(X,WTL!*);
  2987. RMSUBS(); %since all kernel lists are gone;
  2988. RETURN;
  2989. D: X := SIMP0 X;
  2990. IF NOT DENR X=1 OR DOMAINP (X := NUMR X) THEN GO TO LER1;
  2991. D1: IF W OR FLG OR DOMAINP X OR RED X OR LC X NEQ 1 OR LDEG X NEQ 1
  2992. OR EXPTP!*
  2993. THEN GO TO PRODCT;
  2994. Y := MVAR X;
  2995. IF ATOM Y THEN IF FLAGP(Y,'USED!*) THEN RMSUBS() ELSE NIL
  2996. ELSE IF 'USED!* MEMQ CDDR FKERN Y THEN RMSUBS();
  2997. SETK1(Y,V,B);
  2998. RETURN;
  2999. NONATOM: %replacement for non-atomic expression;
  3000. IF NOT IDP CAR X THEN GO TO LER2
  3001. ELSE IF ARRAYP CAR X THEN GO TO ARR
  3002. ELSE IF CAR X EQ 'DF THEN GO TO DIFF
  3003. ELSE IF (Y := GET(CAR X,'MATRIX)) THEN RETURN LETMTR(U,V,Y)
  3004. ELSE IF NOT GET(CAR X,'SIMPFN) THEN GO TO LER3
  3005. ELSE GO TO D;
  3006. PRODCT: %replacement of powers and products;
  3007. IF EXPTP!* THEN W:= T;
  3008. %to allow for normal form for exponent expressions;
  3009. EXPTP!* := NIL;
  3010. RMSUBS();
  3011. IF NULL FLG AND RED X
  3012. THEN RETURN SPLIS!* := XADD(LIST(X,W . T,V,NIL),
  3013. SPLIS!*,U,B);
  3014. Y := KERNLP X;
  3015. IF Y=-1
  3016. THEN BEGIN X:= NEGF X; V:= LIST('MINUS,V) END
  3017. ELSE IF Y NEQ 1 THEN GO TO LER1;
  3018. X := KLISTT X;
  3019. Y := LIST(W . (IF MCOND!* THEN MCOND!* ELSE T),V,NIL);
  3020. IF CDR X
  3021. THEN RETURN (!*MATCH := XADD!*(X . Y,!*MATCH,U,B))
  3022. ELSE IF NULL W AND ONEP CDAR X THEN GO TO P1;
  3023. IF V=0 AND NULL W AND NOT FLG
  3024. THEN <<ASYMPLIS!* := XADD(CAR X,ASYMPLIS!*,U,B);
  3025. POWLIS!* := XADD(CAAR X . CDAR X . Y,POWLIS!*,U,NIL)>>
  3026. ELSE IF W OR NOT CDAR Y EQ T OR FRASC!*
  3027. THEN POWLIS1!* := XADD(CAR X . Y,POWLIS1!*,U,B)
  3028. ELSE IF NULL B AND (Z := ASSOC(CAAR X,ASYMPLIS!*)) AND Z=CAR X
  3029. THEN ASYMPLIS!* := DELASC(CAAR X,ASYMPLIS!*)
  3030. ELSE <<POWLIS!* := XADD(CAAR X . CDAR X . Y,POWLIS!*,U,B);
  3031. ASYMPLIS!* := DELASC(CAAR X,ASYMPLIS!*)>>;
  3032. RETURN;
  3033. P1: X := CAAR X;
  3034. IF ATOM X THEN GO TO LER1;
  3035. RETURN PUT(CAR X,
  3036. 'OPMTCH,
  3037. XADD!*(CDR X . Y,GET(CAR X,'OPMTCH),U,B));
  3038. DIFF: %rules for differentiation;
  3039. IF NULL LETDF(U,V,W,X,B) THEN GO TO D ELSE RETURN;
  3040. ARR: %array replacements;
  3041. SETELV(X,V);
  3042. RETURN;
  3043. LER1:EXPTP!* := NIL;
  3044. RETURN ERRPRI1 U;
  3045. LER2:RETURN ERRPRI2(U,'HOLD);
  3046. LER3:REDMSG(CAR X,"operator");
  3047. MKOP CAR X;
  3048. GO TO A
  3049. END;
  3050. SYMBOLIC PROCEDURE SIMP0 U;
  3051. BEGIN SCALAR X;
  3052. IF EQCAR(U,'!*SQ) THEN RETURN SIMP0 PREPSQ!* CADR U;
  3053. X := SUBFG!* . !*SUB2;
  3054. SUBFG!* := NIL;
  3055. IF ATOM U OR CAR U MEMQ '(EXPT MINUS PLUS TIMES QUOTIENT)
  3056. THEN U := SIMP U
  3057. ELSE U := SIMPIDEN U;
  3058. SUBFG!* := CAR X;
  3059. !*SUB2 := CDR X;
  3060. RETURN U
  3061. END;
  3062. SYMBOLIC PROCEDURE MATCH U;
  3063. LET0(U,T);
  3064. SYMBOLIC PROCEDURE CLEAR U;
  3065. BEGIN
  3066. RMSUBS();
  3067. FOR EACH X IN U DO <<LET2(X,NIL,NIL,NIL); LET2(X,NIL,T,NIL)>>;
  3068. MCOND!* := FRASC!* := NIL
  3069. END;
  3070. SYMBOLIC PROCEDURE SETK(U,V);
  3071. <<LET2(U,V,NIL,T); V>>;
  3072. %U is a literal atom or a pseudo-kernel, V an expression
  3073. %SETK associates value V with U and returns V;
  3074. % IF ATOM U THEN SETK1(U,V,T)
  3075. % ELSE IF ARRAYP CAR U
  3076. % THEN <<SETELV(U,V); %V>>
  3077. % ELSE !*A2K REVOP1 U;
  3078. SYMBOLIC PROCEDURE SETK1(U,V,B);
  3079. BEGIN SCALAR X,Y;
  3080. IF NOT ATOM U THEN GO TO C
  3081. ELSE IF NULL B THEN GO TO B1
  3082. ELSE IF (X := GET(U,'AVALUE)) THEN GO TO A;
  3083. X := NIL . NIL;
  3084. PUT(U,'AVALUE,X);
  3085. A: RPLACD(RPLACA(X,V),NIL);
  3086. RETURN V;
  3087. B1: IF NOT GET(U,'AVALUE) THEN MSGPRI(NIL,U,"not found",NIL,NIL)
  3088. ELSE REMPROP(U,'AVALUE);
  3089. RETURN;
  3090. C: IF NOT ATOM CAR U
  3091. THEN REDERR "Invalid syntax: improper assignment"
  3092. ELSE IF NULL B THEN GO TO B2
  3093. ELSE IF NOT (Y := GET(CAR U,'KVALUE)) THEN GO TO E
  3094. ELSE IF X := ASSOC(U,Y) THEN GO TO D;
  3095. X := NIL . NIL;
  3096. ACONC(Y,U . X);
  3097. GO TO A;
  3098. D: X := CDR X;
  3099. GO TO A;
  3100. E: X := NIL . NIL;
  3101. PUT(CAR U,'KVALUE,LIST(U . X));
  3102. GO TO A;
  3103. B2: IF NOT(Y := GET(CAR U,'KVALUE)) OR NOT (X := ASSOC(U,Y))
  3104. THEN MSGPRI(NIL,U,"not found",NIL,NIL)
  3105. ELSE PUT(CAR U,'KVALUE,DELETE(X,Y));
  3106. RETURN;
  3107. END;
  3108. SYMBOLIC PROCEDURE KLISTT U;
  3109. IF ATOM U THEN NIL ELSE CAAR U . KLISTT CDR CARX(U,'LIST);
  3110. SYMBOLIC PROCEDURE KERNLP U;
  3111. IF DOMAINP U THEN U ELSE IF NULL CDR U THEN KERNLP CDAR U ELSE NIL;
  3112. SYMBOLIC PROCEDURE RMSUBS;
  3113. <<RMSUBS1(); RMSUBS2()>>;
  3114. SYMBOLIC PROCEDURE RMSUBS2;
  3115. BEGIN
  3116. RPLACA(!*SQVAR!*,NIL); !*SQVAR!* := LIST T;
  3117. % WHILE KPROPS!* DO
  3118. % <<REMPROP(CAR KPROPS!*,'KLIST); %KPROPS!* := CDR KPROPS!*>>;
  3119. % EXLIST!* := LIST '(!*);
  3120. %This is too dangerous: someone else may have constructed a
  3121. %standard form;
  3122. ALGLIST!* := NIL
  3123. END;
  3124. SYMBOLIC PROCEDURE RMSUBS1;
  3125. NIL;
  3126. % BEGIN
  3127. % A: IF NULL SUBL!* THEN GO TO B;
  3128. % RPLACD(CAR SUBL!*,NIL);
  3129. % SUBL!* := CDR SUBL!*;
  3130. % GO TO A;
  3131. % B: IF NULL DSUBL!* THEN RETURN;
  3132. % RPLACA(CAR DSUBL!*,NIL);
  3133. % DSUBL!* := CDR DSUBL!*;
  3134. % GO TO B
  3135. % END;
  3136. SYMBOLIC PROCEDURE XADD(U,V,W,B);
  3137. %adds replacement U to table V, with new rule at head;
  3138. BEGIN SCALAR X;
  3139. X := ASSOC(CAR U,V);
  3140. IF NULL X THEN GO TO C;
  3141. V := DELETE(X,V);
  3142. IF B THEN BEGIN RMSUBS1(); V := U . V END;
  3143. A: RETURN V;
  3144. C: IF B THEN V := U . V;
  3145. GO TO A
  3146. END;
  3147. SYMBOLIC PROCEDURE XADD!*(U,V,W,B);
  3148. %adds replacement U to table V, with new rule at head;
  3149. %also checks boolean part for equality;
  3150. BEGIN SCALAR X;
  3151. X := V;
  3152. WHILE X AND NOT(CAR U=CAAR X AND CADR U=CADAR X) DO X := CDR X;
  3153. IF X THEN <<V := DELETE(CAR X,V); IF B THEN RMSUBS1()>>;
  3154. IF B THEN V := U . V;
  3155. RETURN V
  3156. END;
  3157. RLISTAT '(CLEAR LET MATCH);
  3158. FLAG ('(CLEAR LET MATCH),'QUOTE);
  3159. %*********************************************************************
  3160. % VARIOUS DECLARATIONS
  3161. %********************************************************************;
  3162. PUT('OPERATOR,'FORMFN,'FORMOPR);
  3163. SYMBOLIC PROCEDURE FORMOPR(U,VARS,MODE);
  3164. IF MODE EQ 'SYMBOLIC
  3165. THEN MKPROG(NIL,LIST LIST('FLAG,MKQUOTE U,MKQUOTE 'OPFN))
  3166. ELSE LIST('OPERATOR,MKARG(U,VARS));
  3167. SYMBOLIC PROCEDURE OPERATOR U; FOR EACH J IN U DO MKOP J;
  3168. RLISTAT '(OPERATOR);
  3169. SYMBOLIC PROCEDURE DEN U;
  3170. MK!*SQ (DENR SIMP!* U ./ 1);
  3171. SYMBOLIC PROCEDURE NUM U;
  3172. MK!*SQ (NUMR SIMP!* U ./ 1);
  3173. FLAG ('(DEN NUM ABS MAX MIN),'OPFN);
  3174. FLAG('(DEN NUM),'NOVAL);
  3175. PUT('SAVEAS,'FORMFN,'FORMSAVEAS);
  3176. SYMBOLIC PROCEDURE FORMSAVEAS(U,VARS,MODE);
  3177. LIST('SAVEAS,FORMCLEAR1(U,VARS,MODE));
  3178. SYMBOLIC PROCEDURE SAVEAS U;
  3179. LET0(LIST LIST('EQUAL,CAR U,
  3180. IF FRASC!* AND EQCAR(WS,'!*SQ) THEN PREPSQ CADR WS ELSE WS),
  3181. NIL);
  3182. RLISTAT '(SAVEAS);
  3183. SYMBOLIC PROCEDURE TERMS U; TERMSF NUMR SIMP!* U;
  3184. FLAG ('(TERMS),'OPFN);
  3185. FLAG('(TERMS),'NOVAL);
  3186. SYMBOLIC PROCEDURE TERMSF U;
  3187. %U is a standard form.
  3188. %Value is number of terms in U (excluding kernel structure);
  3189. BEGIN INTEGER N;
  3190. N := 0;
  3191. A: IF NULL U THEN RETURN N ELSE IF DOMAINP U THEN RETURN N+1;
  3192. N := N + TERMSF LC U;
  3193. U := RED U;
  3194. GO TO A
  3195. END;
  3196. %*********************************************************************
  3197. %*********************************************************************
  3198. %*********************************************************************
  3199. % SECTION 3
  3200. % SPECIFIC ALGEBRAIC PACKAGES
  3201. %*********************************************************************
  3202. %*********************************************************************
  3203. %********************************************************************;
  3204. %*********************************************************************
  3205. %All these packages except where noted are self-contained and any or
  3206. %all may be omitted as required;
  3207. %********************************************************************;
  3208. %*********************************************************************
  3209. %*********************************************************************
  3210. % DIFFERENTIATION PACKAGE
  3211. %*********************************************************************
  3212. %********************************************************************;
  3213. % REQUIRES EXPRESSION DEPENDENCY MODULE;
  3214. SYMBOLIC PROCEDURE SIMPDF U;
  3215. %U is a list of forms, the first an expression and the remainder
  3216. %kernels and numbers.
  3217. %Value is derivative of first form wrt rest of list;
  3218. BEGIN SCALAR V,X,Y;
  3219. IF NULL SUBFG!* THEN RETURN MKSQ('DF . U,1);
  3220. V := CDR U;
  3221. U := SIMP!* CAR U;
  3222. A: IF NULL V OR NULL NUMR U THEN RETURN U;
  3223. X := IF NULL Y OR Y=0 THEN SIMP!* CAR V ELSE Y;
  3224. IF NULL KERNP X THEN TYPERR(PREPSQ X,"kernel");
  3225. X := CAAAAR X;
  3226. V := CDR V;
  3227. IF NULL V THEN GO TO C;
  3228. Y := SIMP!* CAR V;
  3229. IF NULL NUMR Y THEN <<V := CDR V; Y := NIL; GO TO A>>
  3230. ELSE IF NOT DENR Y=1 OR NOT NUMBERP NUMR Y THEN GO TO C;
  3231. V := CDR V;
  3232. B: FOR I:=1:CAR Y DO U := DIFFSQ(U,X);
  3233. Y := NIL;
  3234. GO TO A;
  3235. C: U := DIFFSQ(U,X);
  3236. GO TO A
  3237. END;
  3238. PUT('DF,'SIMPFN,'SIMPDF);
  3239. SYMBOLIC PROCEDURE DIFFSQ(U,V);
  3240. %U is a standard quotient, V a kernel.
  3241. %Value is the standard quotient derivative of U wrt V.
  3242. %Algorithm: df(x/y,z)= (x'-(x/y)*y')/y;
  3243. MULTSQ(ADDSQ(DIFFF(NUMR U,V),NEGSQ MULTSQ(U,DIFFF(DENR U,V))),
  3244. 1 ./ DENR U);
  3245. SYMBOLIC PROCEDURE DIFFF(U,V);
  3246. %U is a standard form, V a kernel.
  3247. %Value is the standard quotient derivative of U wrt V;
  3248. IF DOMAINP U THEN NIL ./ 1
  3249. ELSE ADDSQ(ADDSQ(MULTPQ(LPOW U,DIFFF(LC U,V)),
  3250. MULTSQ(LC U ./ 1,DIFFP(LPOW U,V))),
  3251. DIFFF(RED U,V));
  3252. SYMBOLIC PROCEDURE DIFFP(U,V);
  3253. %U is a standard power, V a kernel.
  3254. %Value is the standard quotient derivative of U wrt V;
  3255. BEGIN SCALAR W,X,Y,Z; INTEGER N;
  3256. N := CDR U; %integer power;
  3257. U := CAR U; %main variable;
  3258. IF U EQ V AND (W := 1 ./ 1) THEN GO TO E
  3259. ELSE IF ATOM U THEN GO TO F
  3260. %ELSE IF (X := ASSOC(U,DSUBL!*)) AND (X := ATSOC(V,CDR X))
  3261. % AND (W := CDR X) THEN GO TO E %deriv known;
  3262. %DSUBL!* not used for now;
  3263. ELSE IF (NOT ATOM CAR U AND (W:= DIFFF(U,V)))
  3264. OR (CAR U EQ '!*SQ AND (W:= DIFFSQ(CADR U,V)))
  3265. THEN GO TO C %extended kernel found;
  3266. ELSE IF (X:= GET!*(CAR U,'DFN)) THEN NIL
  3267. ELSE IF CAR U EQ 'PLUS AND (W:=DIFFSQ(SIMP U,V))
  3268. THEN GO TO C
  3269. ELSE GO TO H; %unknown derivative;
  3270. Y := X;
  3271. Z := CDR U;
  3272. A: W := DIFFSQ(SIMP CAR Z,V) . W;
  3273. IF CAAR W AND NULL CAR Y THEN GO TO H; %unknown deriv;
  3274. Y := CDR Y;
  3275. Z := CDR Z;
  3276. IF Z AND Y THEN GO TO A
  3277. ELSE IF Z OR Y THEN GO TO H; %arguments do not match;
  3278. Y := REVERSE W;
  3279. Z := CDR U;
  3280. W := NIL ./ 1;
  3281. B: %computation of kernel derivative;
  3282. IF CAAR Y
  3283. THEN W := ADDSQ(MULTSQ(CAR Y,SIMP SUBLA(PAIR(CAAR X,Z),
  3284. CDAR X)),
  3285. W);
  3286. X := CDR X;
  3287. Y := CDR Y;
  3288. IF Y THEN GO TO B;
  3289. C: %save calculated deriv in case it is used again;
  3290. %IF X := ATSOC(U,DSUBL!*) THEN GO TO D
  3291. %ELSE X := U . NIL;
  3292. %DSUBL!* := X . DSUBL!*;
  3293. D: %RPLACD(X,XADD(V . W,CDR X,NIL,T));
  3294. E: %allowance for power;
  3295. %first check to see if kernel has weight;
  3296. IF (X := ATSOC(U,WTL!*))
  3297. THEN W := MULTPQ('K!* TO (-CDR X),W);
  3298. RETURN IF N=1 THEN W ELSE MULTSQ(!*T2Q((U TO (N-1)) .* N),W);
  3299. F: %check for possible unused substitution rule;
  3300. IF NOT DEPENDS(U,V)
  3301. AND (NOT (X:= ATSOC(U,POWLIS!*))
  3302. OR NOT CAR DIFFSQ(SIMP CADDDR X,V))
  3303. THEN RETURN NIL ./ 1;
  3304. W := MKSQ(LIST('DF,U,V),1);
  3305. GO TO E;
  3306. H: %final check for possible kernel deriv;
  3307. IF CAR U EQ 'DF
  3308. THEN IF DEPENDS(CADR U,V)
  3309. THEN W := 'DF . CADR U . DERAD(V,CDDR U)
  3310. ELSE RETURN NIL ./ 1
  3311. ELSE IF DEPENDS(U,V) THEN W := LIST('DF,U,V)
  3312. ELSE RETURN NIL ./ 1;
  3313. W := IF X := OPMTCH W THEN SIMP X ELSE MKSQ(W,1);
  3314. GO TO E
  3315. END;
  3316. SYMBOLIC PROCEDURE DERAD(U,V);
  3317. IF NULL V THEN LIST U
  3318. ELSE IF NUMBERP CAR V THEN CAR V . DERAD(U,CDR V)
  3319. ELSE IF U=CAR V THEN IF CDR V AND NUMBERP CADR V
  3320. THEN U . (CADR V + 1) . CDDR V
  3321. ELSE U . 2 . CDR V
  3322. ELSE IF ORDP(U,CAR V) THEN U . V
  3323. ELSE CAR V . DERAD(U,CDR V);
  3324. SYMBOLIC PROCEDURE LETDF(U,V,W,X,B);
  3325. BEGIN SCALAR Z;
  3326. IF ATOM CADR X THEN GO TO E
  3327. ELSE IF NOT GETTYPE CAADR X EQ 'OPERATOR THEN GO TO LER3;
  3328. A: RMSUBS();
  3329. IF NOT FRLP CDADR X
  3330. OR NULL CDDR X
  3331. OR CDDDR X
  3332. OR NOT FRLP CDDR X
  3333. OR NOT CADDR X MEMBER CDADR X
  3334. THEN GO TO E;
  3335. Z := LPOS(CADDR X,CDADR X);
  3336. IF NOT GET(CAADR X,'DFN)
  3337. THEN PUT(CAADR X,
  3338. 'DFN,
  3339. NLIST(NIL,LENGTH CDADR X));
  3340. W := GET(CAADR X,'DFN);
  3341. B1: IF NULL W OR Z=0 THEN RETURN ERRPRI1 U
  3342. ELSE IF Z NEQ 1 THEN GO TO C
  3343. ELSE IF NULL B THEN GO TO D;
  3344. % ELSE IF CAR W
  3345. % THEN MSGPRI("Assignment for",X,"redefined",NIL,NIL);
  3346. RETURN RPLACA(W,CDADR X . V);
  3347. C: W := CDR W;
  3348. Z := Z-1;
  3349. GO TO B1;
  3350. D: %IF NULL CAR W THEN MSGPRI(NIL,X,"not found",NIL,NIL);
  3351. RETURN RPLACA(W,NIL);
  3352. LER3:REDMSG(CAADR X,"operator");
  3353. MKOP CAADR X;
  3354. GO TO A;
  3355. E: %check for dependency;
  3356. IF CADDR X MEMQ FRLIS!* THEN RETURN NIL
  3357. ELSE IF IDP CADR X AND NOT(CADR X MEMQ FRLIS!*)
  3358. THEN DEPEND1(CADR X,CADDR X,T)
  3359. ELSE IF NOT ATOM CADR X AND IDP CAADR X AND FRLP CDADR X
  3360. THEN DEPEND1(CAADR X,CADDR X,T);
  3361. RETURN NIL
  3362. END;
  3363. SYMBOLIC PROCEDURE FRLP U;
  3364. NULL U OR (CAR U MEMQ FRLIS!* AND FRLP CDR U);
  3365. SYMBOLIC PROCEDURE LPOS(U,V);
  3366. IF U EQ CAR V THEN 1 ELSE LPOS(U,CDR V)+1;
  3367. END;