assist.red 78 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464
  1. module assist; % Header Module for ASSIST package.
  2. % create!-package('(assist switchext baglist genpurfunc control
  3. % polyextensions transfunctions vectoroper grassman
  4. % matrext),
  5. % '(contrib assist));
  6. % % ********************************************************************
  7. %
  8. % Author: H. Caprasse <caprasse@vm1.ulg.ac.be>.
  9. %
  10. % Version and Date: Version 2.0, 30 Mai 1993.
  11. %
  12. % Revision history to versions 1.0, 1.1, 1.2 and 1.3 :
  13. %
  14. % 5 Aug. 1991 : Corrections to RCONS
  15. % Property NUMBER!_OF!_ARGS commented.
  16. % Flag "NOVAL" on REDEXPR and LEADTERM eliminated.
  17. % 1 Sept. 1991 : MAXLIST and MINLIST eliminated since they exist
  18. % now in the basic package.
  19. % 6 Sept. 1991 : Module "transfunctions" rewritten to conform to
  20. % the new syntax for rules.
  21. % FACT function eliminated since in the ARITH
  22. % package under the name FACTORIAL.
  23. % Function SIMPLIFY added to enforce full
  24. % simplification in outputs of EXCALC.
  25. % 12 Sept.1991 : Capabilities of the functions SHOW and SUPPRESS
  26. % enlarged.
  27. % Control of switches extended.
  28. % 10 March.1992 : Correction in MONOM.
  29. % 1 June 1992 : Second correction to MONOM to include constant terms.
  30. % 3 August 1992: LIST2 and LIST3 replaced by LIST.
  31. % 19 August 1992: SPLITPLUSMINUS and SPLITTERMS introduced in module
  32. % PolyExtensions.
  33. % 26 Jan. 1993 : Function MKIDNEW is introduced. It generates a
  34. % fresh identifier from a given already used id.
  35. % 26 Feb. 1993 : Correction to DISTRIBUTE to make it work correctly
  36. % when non-commuting operators are involved.
  37. % Addition of the function DELLASTDIGIT.
  38. % INF2, SUP2 eliminated since in the kernel of
  39. % REDUCE under the names MIN and MAX.
  40. % EVENP eliminated for the same reason.
  41. % 5 March 1993 : Introduction of module GRASSMAN
  42. % Additional functions for LIST-like objects
  43. % 1 April 1993 : Generalization of FUNVAR to arguments which
  44. % : are themselves lists.
  45. % DELPAIR function created.
  46. % : Basic function for deleting all obj of a given
  47. % : given type created.
  48. % 1 May 1993 : Correction to SPLITTERMS and RCONS
  49. % : New functions CYCLICPERMLIST,APPENDN,INSERT_KEEP_ORDER
  50. % : CHECKPROPLIST, EXTRACTLIST, SORTNUMLIST.
  51. % 15 May 1993 : LIST_TO_IDS replaces MKIDN.
  52. % : SORTLIST generalises SORTNUMLIST to sort list of ids.
  53. % : ALG_TO_SYMB et SYMB_TO_ALG created.
  54. % : MERGE_LIST complementary function to INSERT_KEEP_ORDER
  55. % 17 May 1993 : Creation of SYMMETRIZE
  56. % 28 May 1993 : Generalization of SYMMETRIZE and SYMB_TO_ALG
  57. % ********************************************************************
  58. %
  59. endmodule;
  60. module switchext$
  61. fluid '(!*distribute);
  62. switch distribute;
  63. flag('(!*factor !*mcd !*div !*exp !*gcd !*rat !*rational !*rationalize
  64. !*intstr !*reduced !*ratpri !*revpri !*distribute
  65. !*ezgcd !*complex !*reduced !*lcm !*precise),'share)$
  66. endmodule$
  67. module baglist$
  68. global('(!:flaglis !:proplis));
  69. % 1. Functions which works on LIST_like objects.
  70. algebraic procedure frequency lst;
  71. % gives a LIST of PAIRS {{el1,freq1} ...{eln,freqn}}.
  72. % Procedure created by E. Schruefer.
  73. <<clear count!?!?; operator count!?!?; frequency1 lst>>;
  74. algebraic procedure frequency1 lst;
  75. if lst = {} then {}
  76. else begin scalar r,el;
  77. el := first lst;
  78. if numberp count!?!? el
  79. then <<count!?!? el := count!?!? el + 1;
  80. r := frequency1 rest lst>>
  81. else r := {el,count!?!? el} .
  82. <<count!?!? el := 1; frequency1 rest lst>>;
  83. return r
  84. end;
  85. symbolic procedure sequences n;
  86. % Works properly, both in the symbolic and in the algebraic mode.
  87. if !*mode eq 'symbolic then sequsymb n else
  88. algebraic sequalg n;
  89. flag('(sequences),'opfn);
  90. symbolic procedure sequsymb n;
  91. % Corresponds to the one below in the symbolic mode.
  92. if n=1 then list(list(0),list(1))
  93. else for each s in sequsymb (n-1) conc list(0 . s,1 . s);
  94. algebraic procedure sequalg n;
  95. % Gives the list {{0,0 ...,0},{0,0, ..., 1}, ...{1,1, ..., 1}}
  96. % "conc" used in an explicit way.
  97. if n = 1 then {{0},{1}}
  98. else for each s in sequalg(n - 1) conc {0 . s,1 . s};
  99. symbolic procedure rmklis u$
  100. begin scalar s,ss;integer n;
  101. if length u = 2 then
  102. <<s:=reval car u; n:=reval cadr u;
  103. if car s eq 'list then ss:=
  104. append(s,cdr rmklis(list(n+1-length s))) else nil>> else
  105. if length u=1 then
  106. <<n:=reval car u; for j:=1:n do s:=0 . s; ss:='list . s>>
  107. else nil;
  108. return ss end;
  109. put('mklist,'psopfn,'rmklis);
  110. symbolic procedure insert_keep_order(u,l,fn);
  111. if get(fn,'number!-of!-args)=2 and not atom l then
  112. 'list . insert_keep_order1(u,cdr l,fn) else
  113. typerr(list(l,fn),"list and binary function");
  114. flag('(insert_keep_order),'opfn);
  115. symbolic procedure insert_keep_order1(u,l,fn);
  116. % u is any object, l is a list and fn is a BINARY boolean function.
  117. if null l then list u else
  118. if apply(fn,list(u,car l)) then u . l else
  119. car l . insert_keep_order1(u,cdr l,fn);
  120. symbolic procedure merge_list(l1,l2,fn);
  121. % fn is a binary boolean function
  122. 'list . merge_list1(cdr l1,cdr l2,fn);
  123. flag('(merge_list),'opfn);
  124. symbolic procedure merge_list1(l1,l2,fn);
  125. % Returns the (physical) merge of the two sorted lists l1 and l2.
  126. % Example of use :
  127. % l1:=list(1,2,3)$ l2:=list(1,4,5)$
  128. % merge(l1,l2,'lessp); ==> (1 1 2 3 4 5)
  129. % l1 and l2 are destroyed
  130. % This is complementary to the function INSERT_KEEP_ORDER
  131. if null l1 then l2
  132. else if null l2 then l1
  133. else if apply2(fn,car l1,car l2)
  134. then rplacd(l1,merge_list1(cdr l1,l2,fn))
  135. else rplacd(l2,merge_list1(l1,cdr l2,fn));
  136. % 2. Introduction of BAG-like objects.
  137. put('bag,'simpfn,'simpiden);
  138. flag('(bag),'bag)$ % the default bag
  139. flag('(bag),'reserved)$
  140. symbolic (!:flaglis:=union(list list('bag,'bag),!:flaglis))$
  141. symbolic procedure !:delete(u,prop,val)$
  142. if prop then
  143. for each x in !:proplis do if x=list(u,prop,val)
  144. then !:proplis:=delete(x,!:proplis) else nil else
  145. for each x in !:flaglis do if x=list(u,val)
  146. then !:flaglis:=delete(x,!:flaglis);
  147. symbolic procedure !:bagno u; u eq 'list or flagp(u,'boolean);
  148. symbolic procedure !:bagyes u; getd u or
  149. gettype u member list('tvector,'vector) or
  150. flagp( u,'opfn) or
  151. get(u,'simpfn) or get(u,'psopfn) or
  152. get(u,'fdegree) or get(u,'ifdegree);
  153. symbolic procedure simpbagprop u$
  154. % gives the bag property to identifier or baglike-list of identifiers U
  155. % V is T if one creates the property or 0 if one destroys it.
  156. % Use is bagprop(<list of atoms>,T or 0)
  157. % Makes tests to avoid giving this property to an unsuitable object.
  158. begin scalar id,bool;
  159. id:= car u; bool:= if cadr u eq t then t;
  160. if listp id then
  161. << for each x in id do simpbagprop list(x,bool) $
  162. return bool>> else
  163. if idp id and bool=t then
  164. if !:bagno id then typerr (id,"BAG") else
  165. if !:bagyes id then <<flag(list id,'bag),go to l1>> else
  166. <<put(id,'simpfn,'simpiden)$ flag(list id,'bag)$ go to l1>>
  167. else
  168. if idp id and not bool then
  169. <<remflag(list id,'bag); go to l1>>
  170. else rederr("BAD ARGUMENT for bagprop");
  171. l1: if bool then !:flaglis:=union(list list(id,'bag),!:flaglis)
  172. else !:delete(id,nil,'bag) end;
  173. symbolic procedure putbag u; simpbagprop list(u,t);
  174. % gives the bag property to identifier or baglike-list of identifiers u
  175. % V is T to create the bag property.
  176. symbolic procedure clearbag u; simpbagprop list(u,0);
  177. % destroys the bag property of the identifier or the baglike-list u
  178. symbolic rlistat '(putbag clearbag);
  179. symbolic procedure bagp(u)$
  180. % test of the baglike property of U$
  181. not atom u and flagp(car u ,'bag)$
  182. flag('(bagp),'boolean);
  183. symbolic procedure nbglp(u,n)$
  184. %Function which determines if U is not a bag at the level N.
  185. % Used in DEPTH.
  186. if n=0 then not baglistp u else
  187. if atom u or not bglp!:!: car u then nil else
  188. begin scalar uu$ uu:= u$
  189. l1: uu:=cdr uu$
  190. if null uu then return t$
  191. if nbglp(car uu,n-1) then go to l1 else
  192. return nil end$
  193. symbolic procedure bglp!:!: u;
  194. if not atom u then bglp!:!: car u else
  195. if (flagp(u,'bag) or u eq 'list) then t else nil;
  196. symbolic procedure baglistp u;
  197. % This function is supposed to act on a prefix simplified expression.
  198. not atom u and ( car u eq 'list or flagp(car u,'bag));
  199. symbolic procedure nul!: u; baglistp u and null cdr u;
  200. symbolic flag('(baglistp nul!:),'boolean);
  201. algebraic procedure split(u,v);
  202. % split(list(a,b,c),list(1,1,1)); ==> {{A},{B},{C}}
  203. % split(bag(a,b,c,d),list(1,1,2)); ==> {{A},{B},{C,D}}
  204. % etc.
  205. if baglistp u and baglistp v then
  206. begin scalar x;
  207. return for each n in v collect
  208. for i := 1:n collect
  209. <<x := u.1; u := rest u; x>>
  210. end
  211. else lisp rederr(list(u,v,": must be lists or bags"));
  212. symbolic procedure alistp u$
  213. % Not for use in algebraic mode.
  214. if null u then t else
  215. (not atom car u) and alistp cdr u;
  216. symbolic procedure abaglistp u;
  217. % For use in algebraic mode. Recognizes when a bag-like object
  218. % contains bags which themselves contain two and only two objects.
  219. if null baglistp u or null baglistp cadr u then nil else
  220. begin;
  221. l1: u:=cdr u;
  222. if null u then return t ;
  223. if length car u <3 then return nil else go to l1 end;
  224. flag('(abaglistp),'boolean);
  225. % Definitions of operations on lists
  226. symbolic procedure rexplis u;
  227. % THIS PROCEDURE GENERALIZES BAGLIST TO ANY OBJECT AND GIVES A LIST OF
  228. % THE ARGUMENTS OF U.
  229. if atom ( u:=reval car u) then nil else
  230. % if kernp mksq(u,1) then 'list . cdr u ;
  231. if kernp mksq(u,1) then
  232. 'list . for each i in cdr u collect mk!*sq simp!* i ;
  233. put('kernlist,'psopfn,'rexplis);
  234. symbolic procedure rlisbag u$
  235. begin scalar x,prf;
  236. x:=reval car u; prf :=reval cadr u;
  237. if atom x then return nil else
  238. <<simpbagprop list(prf,t) ; x:=prf . cdr x>>;
  239. return x end;
  240. symbolic put('listbag,'psopfn,'rlisbag);
  241. symbolic procedure rfirst li;
  242. if bagp( li:=reval car li) then
  243. if null cdr li then car li . nil else car li . cadr li . nil else
  244. if car li neq 'list then typerr(li,"list or bag")
  245. else if null cdr li then parterr(li,1)
  246. else cadr li;
  247. put('first,'psopfn,'rfirst);
  248. symbolic procedure rsecond li;
  249. if bagp( li:=reval car li) then
  250. if null cdr li or null cddr li then car li . nil
  251. else car li . caddr li . nil
  252. else if car li neq 'list then typerr(li,"list or bag")
  253. else if null cdr li or null cddr li then parterr(li,2)
  254. else caddr li;
  255. put('second,'psopfn,'rsecond);
  256. symbolic procedure rthird li;
  257. if bagp( li:=reval car li) then
  258. if null cdr li or null cddr li or null cdddr li
  259. then car li . nil else car li . cadddr li . nil
  260. else if car li neq 'list then typerr(li,"list or bag")
  261. else if null cdr li or null cddr li or null cdddr li
  262. then parterr(li,3)
  263. else cadddr li;
  264. symbolic procedure rrest li;
  265. if bagp( li:=reval car li) then
  266. if null cdr li then li . nil else car li . cddr li else
  267. if car li neq 'list then typerr(li,"list or bag")
  268. else 'list . if null (li:=cdr li) then li else cdr li;
  269. symbolic put('rest,'psopfn,'rrest);
  270. symbolic procedure rreverse u;
  271. <<u:=reval car u;
  272. if bagp u then car u . reverse cdr u
  273. else if car u neq 'list then typerr(u,"list or bag")
  274. else 'list . reverse cdr u>>;
  275. symbolic put('reverse,'psopfn,'rreverse);
  276. symbolic procedure rlast u;
  277. <<u:=reval car u;
  278. if bagp u then if null cdr u then u else
  279. car u . car reverse cdr u . nil
  280. else if car u neq 'list then typerr(u,"list or bag")
  281. else if null cdr u then nil
  282. else car reverse cdr u>>;
  283. symbolic put('last,'psopfn,'rlast);
  284. symbolic procedure rdc u;
  285. if null cdr u then nil else car u . rdc cdr u;
  286. symbolic procedure rbelast u;
  287. <<u:=reval car u;
  288. if bagp u then if null cdr u then u else car u . rdc cdr u
  289. else if car u neq 'list then typerr(u,"list or bag")
  290. else if null cdr u then u else 'list . rdc cdr u>>;
  291. put('belast,'psopfn,'rbelast);
  292. symbolic procedure rappend u;
  293. begin scalar x,y;
  294. if length u neq 2 then rederr("append has TWO arguments");
  295. x:=reval car u;
  296. y:=reval cadr u;
  297. if baglistp x and baglistp y then
  298. return car x . append(cdr x,cdr y)
  299. else typerr(list(x,y),"list or bag")
  300. end ;
  301. put('append,'psopfn,'rappend);
  302. symbolic procedure rappendn u;
  303. % This append function works for any number of arguments and all
  304. % types of kernels.
  305. begin scalar x,y;
  306. x:= revlis u;
  307. y:=for each i in x collect mkquote if atom i then
  308. rederr("arguments must be kernels or lists") else cdr i;
  309. x:= eval expand(y,'append);
  310. return 'list . x
  311. end ;
  312. put('appendn,'psopfn,'rappendn);
  313. symbolic procedure rcons u;
  314. % Dans ASSIST.RED
  315. % This procedure does not work perfectly well when the package
  316. % HEPHYS is entered because ISIMPA is applied by reval1 on the
  317. % result of RCONS. When it is given by (BAG (LIST A B) C D) it gives
  318. % the output BAG({A,B}) erasing C and D ! It is due to the fact that
  319. % ISIMP1 and ISIMP2 do not accept SQ forms for identifiers.
  320. % So avoid inputs like list(a,b).bag(c,d) when HEPHYS is loaded.
  321. begin scalar x,y,z;
  322. % if (y := getrtypeor(x := revlis u)) eq 'hvector
  323. % then return if get('cons,'opmtch) and (z:=opmtch('cons . x))
  324. % then reval z
  325. % else prepsq simpdot x
  326. if (y := getrtypeor(x := revlis u)) eq 'hvector
  327. then return if get('cons,'opmtch) and (z := opmtch('cons . x))
  328. then reval z
  329. else prepsq subs2 simpdot x
  330. else if getrtype(y:=cadr x) eq 'list
  331. then return 'list . car x . cdadr x
  332. else if bagp y
  333. then return z:=car y . car x . cdr y
  334. else if fixp y
  335. then return z:= if get('rcons,'cleanupfn)
  336. then 'bag . revalpart u
  337. else revalpart u
  338. else typerr(x,"list or bag")
  339. end;
  340. symbolic procedure isimpa(u,v);
  341. if eqcar(u,'list) then u else
  342. if eqcar(u,'bag) then cdr u else !*q2a1(isimpq simp u,v);
  343. flag('(isimpa),'lose);
  344. symbolic put('cons,'setqfn,'(lambda (u v w) (setpart!* u v w)));
  345. symbolic put('cons,'psopfn,'rcons);
  346. symbolic procedure lengthreval u;
  347. begin scalar v,w;
  348. if length u neq 1
  349. then rederr "LENGTH called with wrong number of arguments"
  350. else if idp car u and arrayp car u
  351. then return 'list . get(car u,'dimension)
  352. else if bagp (u:=reval car u)
  353. then return length cdr u;
  354. v := aeval u;
  355. if (w := getrtype v) and (w := get(w,'lengthfn))
  356. then return apply1(w,v)
  357. else if atom v then return 1
  358. else if not idp car v or not(w := get(car v,'lengthfn))
  359. then typerr(u,"length argument")
  360. else return apply1(w,cdr v)
  361. end;
  362. symbolic put('length,'psopfn,'lengthreval);
  363. symbolic put('size,'psopfn,'lengthreval);
  364. symbolic procedure rremove u;
  365. % Allows one to remove the element n of bag u.
  366. % First argument is a bag or list, second is an integer.
  367. if length u neq 2 then
  368. rederr("remove called with wrong number of arguments") else
  369. begin scalar x;integer n;
  370. x:=reval car u; n:=reval cadr u;
  371. if baglistp x then return car x . remove(cdr x,n) else
  372. rederr(" first argument is a list or a bag, second is an integer")
  373. end;
  374. symbolic put('remove,'psopfn,'rremove);
  375. symbolic procedure rdelete u;
  376. begin scalar x,y;
  377. x:=reval car u; y:=reval cadr u;
  378. if baglistp y then return delete(x,y) end;
  379. symbolic put('delete,'psopfn,'rdelete);
  380. % Use is delete(<any>,<bag or list>)
  381. symbolic procedure delete_all(ob,u);
  382. 'list . del_all_obj(ob,cdr u);
  383. flag('(delete_all),'opfn);
  384. symbolic procedure del_all_obj(ob,u);
  385. % Deletes from list u ALL objects ob
  386. if null u then nil else
  387. if car u = ob then del_all_obj(ob,cdr u) else
  388. car u . del_all_obj(ob,cdr u);
  389. symbolic procedure rmember u;
  390. % First argument is anything, second argument is a bag or list.
  391. begin scalar x,y$
  392. x:=reval car u;
  393. y:=reval cadr u;
  394. if baglistp y then
  395. if (x:=member(x,cdr y))
  396. then return car y . x else return nil
  397. else typerr(y,"list or bag") end;
  398. symbolic put('member,'psopfn,'rmember);
  399. % INPUT MUST BE " member (any , < bag OR list> ) ".
  400. symbolic procedure relmult u;
  401. if length u neq 2 then
  402. rederr("elmult called with wrong number of arguments") else
  403. begin scalar x,y; integer n;
  404. x:=reval car u; % It is the object the multiplicity of which one
  405. % wants to compute.
  406. y:=reval cadr u; % IT IS THE list OR bag
  407. if x=y then return 1 else
  408. if baglistp y then
  409. <<y:=cdr y;
  410. while not null (y:=member(x,y)) do <<y:=cdr y;n:=n+1>>>>
  411. else typerr(y,"list or bag");
  412. return n end;
  413. symbolic put('elmult,'psopfn,'relmult);
  414. % Use is " elmult (any , < bag OR list> ) " .
  415. symbolic procedure rpair u$
  416. begin scalar x,y,prf$
  417. if length u neq 2 then
  418. rederr("pair called with wrong number of arguments");
  419. x:=reval car u; y:=reval cadr u$
  420. if not (baglistp x and baglistp y) then
  421. rederr("arguments must be lists or bags") else
  422. prf:=car x;x:=cdr x; y:=cdr y;
  423. y:=pair(x,for each j in y collect list j);
  424. return y:=prf . for each j in y collect prf . j end;
  425. symbolic put('pair,'psopfn,'rpair);
  426. symbolic procedure delpair(elt,u);
  427. 'list .
  428. for each j in delasc(elt,for each i in cdr u collect cdr i)
  429. collect 'list . j ;
  430. flag('(delpair),'opfn);
  431. symbolic procedure depth!: u;
  432. if not atom u and (car u eq 'list or flagp(car u,'bag))
  433. then 1 + depth!: cadr u
  434. else 0;
  435. symbolic procedure rdepth(u)$
  436. % Use is depth(<BAG or LIST>).
  437. begin scalar x; integer n;
  438. x := reval car u;
  439. if nbglp(x,n:=depth!: x) then
  440. return n else return "bag or list of unequal depths" end;
  441. put('depth,'psopfn,'rdepth);
  442. symbolic procedure rinsert u;
  443. % Use is insert(<any>, <list or bag>, <integer>).
  444. begin scalar x,bg,bbg,prf; integer n;
  445. bg:=reval cadr u; n:=reval caddr u;
  446. if not baglistp bg then typerr(bg,"list or bag") else
  447. if n<=0 then rederr("third argument must be positive an integer") else
  448. if (n:=n+1) > length bg then return append(bg,x:=list reval car u);
  449. prf:=car bg; x:=reval car u;
  450. for i:=3:n do <<bg:=cdr bg; bbg:=car bg . bbg>>;
  451. bbg:=reverse bbg;
  452. return bbg:=prf . append(bbg,cons(x,cdr bg))
  453. end;
  454. symbolic put('insert,'psopfn,'rinsert);
  455. symbolic procedure rposition u$
  456. % Use is position(<any>,<LIST or BAG>).
  457. begin scalar el,bg; integer n;
  458. el:=reval car u;
  459. if not baglistp (bg:=reval cadr u) then typerr(bg," list or bag");
  460. n:=length( bg:=cdr bg);
  461. if (bg:=member(el,bg))
  462. then return (n:=n+1-length bg) else
  463. msgpri(nil,el,"is not present in list or bag",nil,nil) end;
  464. put('position,'psopfn,'rposition);
  465. % **********
  466. % The functions below, when applied to objects containing SEVERAL bag
  467. % prefixes have a rule to select them in the output object when this
  468. % one is itself a bag: the first level prefix has priority over all
  469. % other prefixes and will be selected, when needed, as the envelope
  470. % of the output.
  471. symbolic procedure !:assoc u;
  472. if length u neq 2 then
  473. rederr("asfirst called with wrong number of arguments") else
  474. begin scalar x,y,prf;
  475. x:=reval car u; y:=reval cadr u;
  476. if null baglistp y then typerr(y,"list or bag");
  477. prf:=car y; y:=cdr y;
  478. if null alistp y then typerr(y, "association list") else
  479. y:=for each j in y collect cdr j;
  480. return if null (y:=assoc(x,y)) then nil else prf . y end;
  481. symbolic put('asfirst,'psopfn,'!:assoc);
  482. % Use is : asfirst(<key>,<a-list>Y<a-bag>)
  483. symbolic procedure !:rassoc u;
  484. if length u neq 2 then
  485. rederr("assecond called with wrong number of arguments") else
  486. begin scalar x,y,prf;
  487. x:=reval car u; y:=reval cadr u;
  488. if null baglistp y then typerr(y,"list or bag");
  489. prf:=car y; y:=cdr y;
  490. if null alistp y then typerr(y, "association list") else
  491. y:=for each j in y collect cdr j;
  492. return if null (y:=rassoc(list x,y)) then nil else prf . y end;
  493. symbolic put('assecond,'psopfn,'!:rassoc);
  494. % Use is : assecond(<key>,<a-list>Y<a-bag>)
  495. symbolic procedure !:assoc2 u;
  496. if length u neq 2 then
  497. rederr("asrest called with wrong number of arguments") else
  498. begin scalar x,y,prf;
  499. x:=reval car u; y:=reval cadr u;
  500. if null baglistp x or null baglistp y then
  501. typerr(list(x,y),"list or bag");
  502. prf:=car y; y:=cdr y; x:=cdr x;
  503. if null alistp y then typerr(y, "association list") else
  504. y:=for each j in y collect cdr j;
  505. return if null (y:=assoc2(x,y)) then nil else prf . y end;
  506. symbolic put('asrest,'psopfn,'!:assoc2);
  507. % Use is : asrest(<key>,<a-list>Y<a-bag>)
  508. symbolic procedure lastassoc!*(u,v);
  509. % Use is :
  510. % aslast(<key as a last element>,<a-list>Y<a-bag>)
  511. % Finds the sublist in which u is the last element in the
  512. % compound list or bag v, or nil if it is not found.
  513. if null v then nil
  514. else begin scalar vv; vv:=car v;
  515. while length vv > 1 do vv:=cdr vv;
  516. if u = car vv then return car v
  517. else return lastassoc!*(u,cdr v) end;
  518. symbolic procedure !:lassoc u;
  519. if length u neq 2 then
  520. rederr("aslast called with wrong number of arguments") else
  521. begin scalar x,y,prf;
  522. x:=reval car u; y:=reval cadr u;
  523. if null baglistp y then typerr(y,"list or bag");
  524. prf:=car y; y:=cdr y;
  525. if null alistp y then typerr(y, "association list") else
  526. y:=for each j in y collect cdr j;
  527. return if null (y:=lastassoc!*(x,y)) then nil else prf . y end;
  528. symbolic put('aslast,'psopfn,'!:lassoc);
  529. symbolic procedure rasflist u;
  530. % Use is :
  531. % asflist(<key as a first element>,<a-list>Y<a-bag>)
  532. % This procedure gives the LIST (or BAG) associated with the KEY con-
  533. % tained in the first argument. The KEY is here the FIRST element
  534. % of each sublist contained in the association list .
  535. if length u neq 2 then
  536. rederr("ASFLIST called with wrong number of arguments") else
  537. begin scalar x,y,prf,res,aa;
  538. x:=reval car u; y:=reval cadr u; prf:=car y;
  539. if null cdr y then return y;
  540. for each j in cdr y do if car j neq prf then
  541. rederr list("prefix INSIDE the list or bag neq to",prf);
  542. l1: aa:=!:assoc(list(x,y));
  543. if not aa then return prf . reverse res;
  544. res:=aa . res;
  545. y:=delete(aa,y);
  546. go to l1;
  547. end$
  548. symbolic put('asflist,'psopfn,'rasflist);
  549. symbolic procedure rasslist u;
  550. % Use is :
  551. % asslist(<key as the second element>,<a-list>Y<a-bag>)
  552. if length u neq 2 then
  553. rederr("ASSLIST called with wrong number of arguments") else
  554. begin scalar x,y,prf,res,aa;
  555. x:=reval car u; y:=reval cadr u; prf:=car y;
  556. if null cdr y then return y;
  557. for each j in cdr y do if car j neq prf then
  558. rederr list("prefix INSIDE the list or bag neq to",prf);
  559. l1: aa:=!:rassoc(list(x,y));
  560. if not aa then return prf . reverse res;
  561. res:=aa . res;
  562. y:=delete(aa,y);
  563. go to l1;
  564. end$
  565. symbolic put('asslist,'psopfn,'rasslist);
  566. symbolic procedure !:sublis u;
  567. % Use is :
  568. % restaslist(<bag-like object containing keys>,<a-list>Y<a-bag>)
  569. % Output is a list containing the values associated to the selected
  570. % keys.
  571. if length u neq 2 then
  572. rederr("restaslist called with wrong number of arguments") else
  573. begin scalar x,y,yy,prf;
  574. x:=reval car u;
  575. y:=reval cadr u; prf:=car y;
  576. if null baglistp y then typerr(y,"list or bag") else
  577. if null alistp (y:=cdr y) then typerr(y," association list or bag")
  578. else y:=for each j in y collect cdr j;
  579. if baglistp x then <<x:=cdr x; x:=for each j in x collect
  580. if assoc(j,y) then j>>;
  581. y:=sublis(y,x); if atom y then yy:=list y else
  582. for each j in y do if not null j then yy:=j . yy;
  583. yy:=reverse yy;
  584. return prf . for each j in yy collect
  585. if atom j then prf . j . nil else prf . j$
  586. end$
  587. symbolic put('restaslist,'psopfn,'!:sublis);
  588. % Use is :
  589. % restaslist(<bag-like object containing keys>,<a-list>Y<a-bag>)
  590. % Output is a list containing the values associated to the selected
  591. % keys.
  592. % ******* End of functions which may change bag- or list- prefixes.
  593. % FOR SUBSTITUTION OF IDENTIFIERS IT IS CONVENIENT TO USE :
  594. symbolic procedure !:subst u;
  595. reval subst(reval car u,reval cadr u,reval caddr u);
  596. symbolic put('substitute,'psopfn,'!:subst);
  597. % Use is : substitute(<newid>,<oldid>,<in any>).
  598. % May serve to transform ALL bags into lists or vice-versa.
  599. symbolic procedure !:repla u;
  600. if length u neq 2 then
  601. rederr("repfirst called with wrong number of arguments") else
  602. begin scalar x,y,prf;
  603. y:=reval car u; x:= reval cadr u;
  604. if null baglistp x then typerr(x,"list or bag");
  605. prf:= car x; x:=cdr x;
  606. return prf . rplaca(x,y) end;
  607. symbolic put('repfirst,'psopfn,'!:repla);
  608. % Use is : repfirst(<any>, <bag or list>);
  609. symbolic procedure !:repld u;
  610. % Use is : replast(<any>, <bag or list>);
  611. begin scalar x,y,prf;
  612. if length u neq 2 then
  613. rederr("replast called with wrong number of arguments");
  614. y:=reval car u; x:= reval cadr u;
  615. if null baglistp x then typerr(u,"list or bag");
  616. prf:= car x; x:=cdr x;
  617. return prf . rplacd(x,list y) end;
  618. symbolic put('represt,'psopfn,'!:repld);
  619. symbolic procedure rinsert u;
  620. begin scalar x,bg,bbg,prf; integer n;
  621. bg:=reval cadr u; n:=reval caddr u;
  622. if not baglistp bg then typerr(bg,"list or bag") else
  623. if n<=0 then rederr("third argument must be positive integer") else
  624. if (n:=n+1) > length bg then return append(bg,x:=list reval car u);
  625. prf:=car bg; x:=reval car u;
  626. for i:=3:n do <<bg:=cdr bg; bbg:=car bg . bbg>>;
  627. bbg:=reverse bbg;
  628. return bbg:=prf . append(bbg,cons(x,cdr bg))
  629. end;
  630. symbolic put('insert,'psopfn,'rinsert);
  631. % Use is : insert(<any>, <list or bag>, <integer>).
  632. % HERE ARE FUNCTIONS FOR SETS.
  633. symbolic procedure !:union u$
  634. begin scalar x,y,prf;
  635. if length u neq 2 then
  636. rederr("union called with wrong number of arguments");
  637. x:=reval car u; y:=reval cadr u;
  638. if baglistp x and baglistp y then
  639. <<prf:=car y; y:=prf . union(cdr x,cdr y)>> else return nil;
  640. return y end;
  641. symbolic put('union,'psopfn,'!:union);
  642. symbolic procedure setp u;
  643. null repeats u;
  644. symbolic flag('(setp),'boolean);
  645. symbolic procedure !:mkset u$
  646. if null u then nil else if member(car u,cdr u) then !:mkset cdr u
  647. else car u . !:mkset cdr u$
  648. symbolic procedure rmkset u;
  649. begin scalar x,prf$
  650. x:=reval car u; prf:=car x;
  651. if baglistp x then return prf . !:mkset cdr x end;
  652. symbolic put('mkset,'psopfn,'rmkset);
  653. symbolic procedure !:setdiff u$
  654. begin scalar x,y,prf;
  655. if length u neq 2 then
  656. rederr("diffset called with wrong number of arguments");
  657. x:=reval car u; y:=reval cadr u;
  658. if baglistp x and baglistp y then
  659. <<prf:=car y; y:=prf . setdiff(cdr x,cdr y)>> else return nil;
  660. return y end;
  661. symbolic put('diffset,'psopfn,'!:setdiff);
  662. symbolic procedure !:symdiff u$
  663. begin scalar x,y,prf;
  664. if length u neq 2 then
  665. rederr("symdiff called with wrong number of arguments");
  666. x:=reval car u; y:=reval cadr u; prf:=car x;
  667. if setp x and setp y then return
  668. prf . append(setdiff(x:=cdr x,y:=cdr y),setdiff(y,x))
  669. end;
  670. symbolic put('symdiff,'psopfn,'!:symdiff);
  671. symbolic procedure !:xn u$
  672. begin scalar x,y,prf;
  673. if length u neq 2 then
  674. rederr("intersect called with wrong number of arguments");
  675. x:=reval car u; y:=reval cadr u;
  676. if setp x and setp y then return car x . intersection(cdr x,cdr y)
  677. end;
  678. symbolic put('intersect,'psopfn,'!:xn);
  679. endmodule ;
  680. module genpurfunc;
  681. %=====================================================================$
  682. % $
  683. % VARIOUS GENERAL PURPOSE FUNCTIONS $
  684. % $
  685. %=====================================================================$
  686. % 1. GENERALIZATION OF EXISTING FUNCTIONS
  687. symbolic procedure rmkidnew(u);
  688. if null u or null (u:=reval car u) then gensym() else mkid(u,gensym());
  689. put('mkidnew,'psopfn,'rmkidnew); % Usage mkidnew() or mkidnew(<id>).
  690. symbolic procedure list_to_ids l;
  691. if atom l then rederr "argument for list_to_ids must be a list"
  692. else
  693. intern compress for each i in cdr l join explode i;
  694. flag('(list_to_ids),'opfn);
  695. symbolic procedure simpsetf u;
  696. % generalizes the function "set" to kernels.
  697. begin scalar x;
  698. x := simp!* car u;
  699. if not kernp x or fixp (!*q2a x) then
  700. typerr(!*q2a x,"setvalue kernel") else
  701. x:=!*q2a x;
  702. let0 list(list('equal,x,mk!*sq(u := simp!* cadr u)));
  703. return u
  704. end;
  705. put ('setvalue, 'simpfn, 'simpsetf);
  706. newtok '((!= !=) setvalue ! !=!=! );
  707. infix ==;
  708. flag('(prin2 ) ,'opfn); % To make it available in the alg. mode.
  709. % 2. NEW ELEMENTARY FUNCTIONS CLOSELY RELATED TO EXISTING ONES.
  710. symbolic procedure oddp u$
  711. % Tests if integer U is odd. Is also defined in EXCALC;
  712. not evenp u;
  713. flag('(oddp),'boolean);
  714. symbolic procedure followline(n)$
  715. % It allows to go to a new line at the position given by the integer N.
  716. << terpri()$ spaces(n)>>$
  717. symbolic flag('(followline ) ,'opfn);
  718. % 3. NEW GENERAL PURPOSE FUNCTIONS.
  719. symbolic procedure charnump!: x;
  720. if x member list('!0,'!1,'!2,'!3,'!4,'!5,'!6,'!7,'!8,'!9) then t ;
  721. symbolic procedure charnump u;
  722. if null u then t else charnump!: car u and charnump cdr u;
  723. symbolic procedure detidnum u;
  724. % Allows one to extract the index number from the identifier u.
  725. if idp u then
  726. begin scalar uu;
  727. if length(uu:= cdr explode u) =1 then go to l1
  728. else
  729. while not charnump uu do uu:=cdr uu;
  730. l1: uu:= compress uu;
  731. if fixp uu then return uu end;
  732. flag('(detidnum),'opfn);
  733. symbolic procedure dellastdigit u;
  734. % Strips an integer from its last digit.
  735. if fixp u then compress reverse cdr reverse explode u
  736. else typerr(u,"integer");
  737. flag('(dellastdigit),'opfn);
  738. symbolic procedure randomlist(n,trial);
  739. % This procedure gives a list of trials in number "trial" of
  740. % random numbers between 0 and n. For the algorithm see KNUTH vol. 2.
  741. 'list . lisp for j:=1:trial collect random n;
  742. flag('(randomlist),'opfn);
  743. symbolic procedure transpose(l,i,j);
  744. % i,j are integers, l is a list.
  745. % DESTROYS the initial list.
  746. begin scalar tmp;
  747. tmp:=nth(l,i);
  748. nth(l,i):=nth(l,j);
  749. nth(l,j):=tmp;
  750. return l
  751. end;
  752. algebraic procedure combnum(n,nu)$
  753. % Number of combinations of n objects nu to nu.
  754. if nu>n then
  755. rederr "second argument cannot be bigger than first argument"
  756. else factorial(n)/factorial(nu)/factorial(n-nu)$
  757. symbolic procedure cyclicpermlist l;
  758. % Gives all cyclic permutations of elements of the list l.
  759. if atom l then nil else
  760. begin scalar x; integer le;
  761. l:=cdr l;
  762. le:=length l;
  763. x:= ('list . l) . x;
  764. for i:=2:le do x:=('list . (l:=append(cdr l,list car l))) . x;
  765. return 'list . reversip x
  766. end;
  767. flag('(cyclicpermlist),'opfn);
  768. symbolic procedure rpermutation u;
  769. if not baglistp(u:=reval car u) then
  770. nil else if null cdr u then 'list . nil else
  771. begin scalar x,prf$ prf:=car u$
  772. u:=cdr u$
  773. x:=for each j in u
  774. conc mapcons(permutations delete(j,u),j)$
  775. x:=for each j in x collect prf . j$
  776. return prf . x end;
  777. put('permutations,'psopfn,'rpermutation);
  778. symbolic procedure !:comb(u)$
  779. begin scalar x,prf; integer n;
  780. if length u neq 2 then
  781. rederr "combinations called with wrong number of arguments";
  782. x:=reval car u ; if not baglistp x then return nil ;
  783. prf :=car x; x:=cdr x; n:=reval cadr u;
  784. return prf . (for each j in comb(x,n) collect prf . j)
  785. end;
  786. symbolic put('combinations,'psopfn,'!:comb);
  787. put('symmetrize,'simpfn,'simpsumsym);
  788. flag('(symmetrize),'listargp);
  789. symbolic procedure simpsumsym(u);
  790. % The use is SYMMETRIZE(LIST(A,B,...J),operator,perm_function)
  791. % or SYMMETRIZE(LIST(LIST(A,B,C...)),operator,perm_function).
  792. % Works both for OPFN and symbolic procedure functions.
  793. % Does not yet allow odd permutations.
  794. if length u neq 3 then rederr("3 arguments required for symmetrize")
  795. else
  796. begin scalar uu,x,res,oper,fn,bool,boolfn; integer n;
  797. fn:= caddr u;
  798. if not gettype fn eq 'procedure then typerr(fn,"procedure");
  799. uu:=(if flagp(fn,'opfn) then <<boolfn:=t; reval x>>
  800. else cdr reval x) where x=car u;
  801. n:=length uu;
  802. oper:=cadr u;
  803. if not idp oper then typerr(oper,"operator") else
  804. if null flagp(oper,'opfn) then
  805. if null get(oper,'simpfn) then put(oper,'simpfn,'simpiden);
  806. flag(list oper, 'listargp);
  807. % << put(oper,'simpfn,'simpiden); flag(list oper, 'listargp)>>;
  808. x:=if listp car uu and not boolfn then
  809. <<bool:=t;apply1(fn, cdar uu)>> else
  810. if boolfn and listp cadr uu then
  811. <<bool:=t;apply1(fn,cadr uu)>> else
  812. apply1(fn,uu);
  813. if flagp(fn,'opfn) then x:=alg_to_symb x;
  814. n:=length x -1;
  815. if not bool then <<
  816. res:=( oper . car x) .** 1 .* 1 .+ nil;
  817. for i:=1:n do << uu:=cadr x; aconc(res,(oper . uu) .** 1 .* 1 );
  818. delqip(uu,x);>>;
  819. >>
  820. else
  821. << res:=(oper . list('list .
  822. for each i in car x collect
  823. mk!*sq simp!* i)) .** 1 .* 1 .+ nil;
  824. for i:=1:n do << uu:=cadr x;
  825. aconc(res,(oper . list('list .
  826. for each i in uu collect mk!*sq simp!* i))
  827. .** 1 .* 1 );
  828. delqip(uu,x);>>;
  829. >>;
  830. if get(oper,'opmtch) or flagp(oper,'opfn) then
  831. res:=resimp( res ./ 1) else res:=res ./ 1;
  832. return res
  833. end;
  834. symbolic procedure delqip1(u,v);
  835. if not pairp cdr v then nil
  836. else if u eq cadr v then rplacd(v,cddr v)
  837. else delqip1(u,cdr v);
  838. symbolic procedure delqip(u,v);
  839. if not pairp v then v
  840. else if u eq car v then cdr v
  841. else <<delqip1(u,v); v>>;
  842. symbolic procedure extremum(l,fn);
  843. if atom l then l else
  844. (if null x then nil else
  845. maximum3(x ,cadr l,fn))where x=cdr l;
  846. flag('(extremum),'opfn);
  847. symbolic procedure maximum3(l,m,fn);
  848. if null l then m else
  849. if apply2(fn,car l,m) then maximum3(cdr l,car l,fn) else
  850. maximum3(cdr l, m,fn);
  851. symbolic procedure sortnumlist l;
  852. % Procedure valid only for list of integers.
  853. % Returns the sorted list without destroying l.
  854. 'list . (if length x < 10 then bubblesort1 x else
  855. quicksort_i_to_j(x,1,length x))where x=cdr l ;
  856. flag('(sortnumlist),'opfn);
  857. symbolic procedure sortlist(l,fn);
  858. if null cdr l then list('list) else
  859. if numlis cdr l then
  860. if fn eq 'lessp then sortnumlist l else
  861. if fn eq 'geq then
  862. ( 'list . (reverse(if length x <10 then bubblesort1 x else
  863. quicksort_i_to_j(x,1,length x))) where x=cdr l)
  864. else nil else 'list . bubsort1(cdr l,fn);
  865. flag('(sortlist),'opfn);
  866. symbolic procedure bubblesort1 l;
  867. % Elements of l are supposed to be numbers.
  868. begin integer ln;
  869. ln:=length l;
  870. for i:=1:ln do
  871. for j:=i+1:ln do
  872. if i neq j and nth(l,i)>nth(l,j) then
  873. transpose(l,i,j) else nil;
  874. return l
  875. end;
  876. symbolic procedure bubsort1(l,fn);
  877. % Elements of l are numbers or identifiers.
  878. % fn is any ordering function.
  879. begin integer ln;
  880. ln:=length l;
  881. for i:=1:ln do
  882. for j:=i+1:ln do
  883. if i neq j and
  884. apply2(fn,nth(l,j),nth(l,i)) then
  885. transpose(l,i,j) else nil;
  886. return l
  887. end;
  888. symbolic procedure find_pivot_index(l,i,j);
  889. % l is the list, i and j are integers.
  890. begin scalar key; integer k;
  891. key:=nth(l,i);
  892. k:=i+1;
  893. a: if k=J+1 then return -1;
  894. if nth(l,k) > key then return k else
  895. if nth(l,k) < key then return i;
  896. k:=k+1; go to a
  897. end;
  898. symbolic procedure partition(l,i,j,pivot);
  899. % Writes l, all elements less than pivot to the left
  900. % and elements greater or equal to the right of pivot.
  901. % returns the new pivot.
  902. begin integer le,ri;
  903. le:=i; ri:=j;
  904. a: if le>ri then return le;
  905. transpose(l,le,ri);
  906. while nth(l,le) < pivot do le:=le+1;
  907. while nth(l,ri) >= pivot do ri:=ri-1;
  908. go to a
  909. end;
  910. symbolic procedure quicksort_i_to_j(l, i,j);
  911. begin integer k,pi;
  912. pi:=find_pivot_index(l,i,j);
  913. return if pi neq -1 then
  914. <<pi:=nth(l,pi); k:=partition(l,i,j,pi);
  915. quicksort_i_to_j(l,i,k-1);quicksort_i_to_j(l,k,j);l>>
  916. else l
  917. end;
  918. symbolic procedure listofvars u $
  919. if null u or numberp u then nil else
  920. if atom u then list u else
  921. varsinargs if eqcar(u,'list) then cdr reval u else cdr u$
  922. symbolic procedure varsinargs(u)$
  923. if null u then nil else
  924. append(listofvars car u,varsinargs cdr u)$
  925. symbolic procedure rfuncvar(u)$
  926. % U is an arbitrary expression
  927. % Gives a list which contains all the variables whom U depends
  928. % in an ARBITRARY order$
  929. <<if atom (u:=reval car u) then
  930. if not flagp(u,'reserved) then
  931. if depatom u neq u then depatom u else nil
  932. else nil else
  933. begin scalar wi,aa$
  934. aa:=listofvars(u)$
  935. if null cdr aa then return
  936. if flagp(car aa,'reserved) or flagp(car aa,'constant)
  937. then nil else car aa
  938. else aa:=!:mkset aa $ wi:=aa$
  939. while wi do if flagp(car wi ,'reserved) then
  940. <<aa:=delete(car wi ,aa)$ wi:=cdr wi >> else wi:=cdr wi $
  941. return aa:='list . aa end >>;
  942. symbolic put('funcvar,'psopfn ,'rfuncvar);
  943. flag('(e i),'reserved);
  944. symbolic procedure implicit u;
  945. if atom u then u else
  946. begin scalar prf;
  947. prf:=car u;
  948. if get(prf,'simpfn) neq 'simpiden then
  949. rederr list(u,"must be an OPERATOR");
  950. remprop(car u,'simpfn);
  951. depl!*:=union(list (car u . reverse
  952. for each y in cdr u collect implicit y),depl!*);
  953. return prf end;
  954. symbolic procedure depatom a$
  955. %Gives a list of variables declared in DEPEND commands whom A depends
  956. %A must be an atom$
  957. if not atom a then rederr("ARGUMENT MUST BE AN ATOM") else
  958. if null assoc(a,depl!*) then a else
  959. 'list . reverse cdr assoc(a,depl!*);
  960. flag('(depatom),'opfn);
  961. symbolic procedure explicit u$
  962. % U is an atom. It gives a function named A which depends on the
  963. % variables detected by DEPATOM and this to all levels$
  964. begin scalar aa$
  965. aa:=depatom u $
  966. if aa = u then return u$
  967. put(u,'simpfn,'simpiden)$
  968. return u . (for each x in cdr aa collect explicit x) end$
  969. symbolic flag('(implicit explicit),'opfn);
  970. symbolic procedure simplify u;
  971. % Enforces simplifications if necessary.
  972. % u is any expression.
  973. mk!*sq resimp simp!* reval u;
  974. symbolic flag('(simplify),'opfn);
  975. % 4. FUNCTIONS TO DEAL WITH PROPERTIES IN THE ALGEBRAIC MODE.
  976. symbolic procedure checkproplist(l,fn);
  977. % fn may be the name of a function or the expression 'function <name
  978. if atom l then rederr("First argument must be a list") else
  979. checkproplist1(cdr l,fn);
  980. flag('(checkproplist),'boolean);
  981. symbolic procedure checkproplist1(l,fn);
  982. % Checks if the list l has the property defined by the function fn.
  983. % fn should preferably be 'function <name_function>'.
  984. if null l then t else
  985. if fn eq 'numberp then
  986. if apply1(function evalnumberp, car l) then checkproplist1(cdr l,fn)
  987. else nil else
  988. if fn eq 'floatp then
  989. if atom car l then nil else
  990. if apply1(function floatp, cdar l ) then checkproplist1(cdr l,fn)
  991. else nil else
  992. if get(fn,'number!-of!-args)=1 then
  993. if apply1(fn,car l) then checkproplist1(cdr l,fn)
  994. else nil else
  995. if get(fn,'number!-of!-args)=2 then
  996. if apply(fn,list(car l,cadr l)) then checkproplist1(cdr l,fn)
  997. else nil;
  998. symbolic procedure extractlist(l,fn);
  999. if get(fn,'number!-of!-args) > 1 then
  1000. rederr("UNARY booelean function required as argument") else
  1001. 'list . extractlist1(cdr l,fn);
  1002. flag('(extractlist),'opfn);
  1003. symbolic procedure extractlist1(l,fn);
  1004. % fn is a boolean function. Result is a new list which contains the
  1005. % elements satisfying the fn selection criteria.
  1006. % Does NOT work yet for floating point numbers.
  1007. if null l then nil else
  1008. if fn eq 'numberp then
  1009. if apply1(function evalnumberp,car l)
  1010. then car l . extractlist1(cdr l,fn)
  1011. else nil else
  1012. if fn eq 'floatp then
  1013. if atom car l then nil else
  1014. if apply1(function floatp,cdar l)
  1015. then car l . extractlist1(cdr l,fn)
  1016. else nil else
  1017. if apply1(fn,car l) then car l . extractlist1(cdr l,fn)
  1018. else
  1019. extractlist1(cdr l,fn);
  1020. symbolic procedure putflag(u,flg,b)$
  1021. % Allows one to put or erase any FLAG on the identifier U.
  1022. % U is an idf or a list of idfs, FLAG is an idf, B is T or 0.
  1023. if not idp u and not null baglistp u then
  1024. <<for each x in cdr u do putflag(x,flg,b)$ t>>
  1025. else if idp u and b eq t then
  1026. <<flag(list u, flg)$
  1027. !:flaglis:=union(list list(u, flg),!:flaglis)$ flg>>
  1028. else if idp u and b equal 0 then
  1029. <<remflag( list u, flg)$ !:delete(u,nil,flg)$>>
  1030. else rederr "*** VARIABLES ARE (idp OR list of flags, T or 0).";
  1031. symbolic procedure putprop(u,prop,val,b)$
  1032. % Allows to put or erase any PROPERTY on the object U
  1033. % U is an idf or a list of idfs, B is T or 0$
  1034. if not idp u and baglistp u then
  1035. <<for each x in cdr u do putprop(x,prop,val,b)$ t>>
  1036. else if idp u and b eq t then
  1037. <<put(u, prop,val)$
  1038. !:proplis:=union(list list(u,prop,val),!:proplis)$ u>>
  1039. else if idp u and b equal 0 then
  1040. <<remprop( u, prop)$ !:delete(u,prop,val)$ >>
  1041. else rederr "*** VARIABLES ARE (idp OR list of idps, T or 0).";
  1042. symbolic flag('(putflag putprop),'opfn)$
  1043. symbolic procedure rdisplayprop(u)$
  1044. % U is the idf whose properties one wants to display.Result is a
  1045. % list which contains them$
  1046. begin scalar x,val,aa$ x:=reval car u; val:=reval cadr u;
  1047. for each j in !:proplis do if car j eq x and cadr j eq val
  1048. then aa:=('list . cdr j) . aa;
  1049. return if length aa = 1 then car aa else 'list . aa
  1050. end;
  1051. symbolic put('displayprop,'psopfn,'rdisplayprop)$
  1052. symbolic put('displayflag,'psopfn,'rdisplayflag)$
  1053. symbolic procedure rdisplayflag(u)$
  1054. % U is the idf whose properties one wants to display.Result is a
  1055. % list which contains them$
  1056. begin scalar x,aa$ x:=reval car u;
  1057. for each j in !:flaglis do if car j=x then aa:=cons(cadr j,aa)$
  1058. return 'list . aa end;
  1059. symbolic procedure clrflg!: u;
  1060. for each x in !:flaglis do
  1061. if u eq car x then putflag(car x,cadr x,0) ;
  1062. symbolic procedure clearflag u;
  1063. % If u equals "all" all flags are eliminated.
  1064. % If u is a1,a2,a3.....an flags of these identifiers are eliminated.
  1065. if null cdr u and car u eq 'all then for each x in !:flaglis
  1066. do putflag (car x,cadr x,0) else
  1067. if null cdr u then clrflg!: car u else
  1068. for each y in u do clrflg!: y;
  1069. symbolic procedure clrprp!: u;
  1070. for each x in !:proplis do
  1071. if u eq car x then putprop(car x,cadr x,caddr x,0);
  1072. symbolic procedure clearprop u;
  1073. % If u equals "all" all properties are eliminated.
  1074. % If u is a1,a2,a3...an properties of these identifiers are eliminated.
  1075. if null cdr u and car u eq 'all then for each x in !:proplis
  1076. do putprop(car x,cadr x,caddr x,0) else
  1077. if null cdr u then clrprp!: car u else
  1078. for each y in u do clrprp!: y;
  1079. symbolic put('clearflag,'stat,'rlis);
  1080. symbolic put('clearprop,'stat,'rlis);
  1081. endmodule;
  1082. module control;
  1083. % functions which offer a BETTER CONTROL on $
  1084. % various objects and of the ALREADY USED quantities $
  1085. % 1. BOOLEAN functions.
  1086. flag('(null idp flagp),'boolean); % NOT COMMENTED
  1087. symbolic procedure nordp(u,v);
  1088. % TRUE if a>b, FALSE if a=<b.
  1089. not ordp(u,v);
  1090. symbolic procedure depvarp(u,v)$
  1091. % V is an idf. or a kernel$
  1092. if depends(u,v) then t else nil$
  1093. symbolic procedure alatomp(u)$
  1094. % U is any expression . Test if U is an idf. whose only value is its
  1095. % printname or another atom$
  1096. fixp u or idp u$
  1097. symbolic procedure alkernp u$
  1098. % U is any expression . Test if U is a kernel.$
  1099. not stringp u and kernp(simp!* u)$
  1100. symbolic procedure precp(u,v)$
  1101. % Tests if the operator U has precedence over the operator V.
  1102. begin integer nn$scalar uu,vv,aa$
  1103. uu:=u$ vv:=v$aa:=preclis!*$
  1104. if or(not(uu member aa),not(vv member aa)) then return nil$
  1105. nn:=lpos(u,aa)$;
  1106. nn:=nn-lpos(v,aa)$
  1107. if nn geq 0 then return t else return nil end$
  1108. flag('(nordp alatomp alkernp precp depvarp stringp ),'boolean)$
  1109. % THE SUBSEQUENT DECLARATION IS USEFUL FOR "TEACHING PURPOSES".
  1110. flag('(alatomp precp depvarp alkernp depatom ) ,'opfn);
  1111. % 2. MISCELLANEOUS functions.
  1112. symbolic procedure korderlist;
  1113. % gives a list of the user defined internal order of the
  1114. % indeterminates. Just state KORDERLIST; to get it.
  1115. kord!*;
  1116. flag('(korderlist), 'opfn);
  1117. put('korderlist,'stat,'endstat);
  1118. symbolic procedure remsym u;
  1119. % ALLOWS TO ELIMINATE THE DECLARED SYMMETRIES.
  1120. for each j in u do
  1121. if flagp(j,'symmetric) then remflag(list j,'symmetric) else
  1122. if flagp(j,'antisymmetric) then remflag(list j,'antisymmetric);
  1123. put('remsym,'stat,'rlis);
  1124. % 3. Control of SWITCHES.
  1125. symbolic procedure switches;
  1126. %This procedure allows to see the values of the main switches$
  1127. <<terpri();
  1128. prin2 " **** exp:=";prin2 !*exp;prin2 " ............. ";
  1129. prin2 "allfac:= ";prin2 !*allfac;prin2 " ****";terpri(); terpri();
  1130. prin2 " **** ezgcd:=";prin2 !*ezgcd;prin2 " ......... ";
  1131. prin2 "gcd:= ";prin2 !*gcd;prin2 " ****";terpri();terpri();
  1132. prin2 " **** mcd:=";prin2 !*mcd;prin2 " ............. ";
  1133. prin2 "lcm:= ";prin2 !*lcm;prin2 " ****";terpri();terpri();
  1134. prin2 " **** div:=";prin2 !*div;prin2 " ........... ";
  1135. prin2 "rat:= ";prin2 !*rat;prin2 " ****";terpri();terpri();
  1136. prin2 " **** intstr:=";prin2 !*intstr;prin2 " ........ ";
  1137. prin2 "rational:= ";prin2 !*rational;prin2 " ****";terpri();terpri();
  1138. prin2 " **** precise:=";prin2 !*precise;prin2 " ....... ";
  1139. prin2 "reduced:= ";prin2 !*reduced;prin2 " ****";terpri();terpri();
  1140. prin2 " **** complex:=";prin2 !*complex;prin2 " ....... ";
  1141. prin2 "rationalize:= ";prin2 !*rationalize;
  1142. prin2 " ****";terpri();terpri();
  1143. prin2 " **** factor:= "; prin2 !*factor;prin2 " ....... ";
  1144. prin2 "distribute:= ";prin2 !*distribute;prin2 " ***";>>$
  1145. flag('(switches),'opfn)$
  1146. symbolic procedure switchorg$
  1147. %It puts all switches relevant to current algebra calculations to
  1148. % their initial values.
  1149. << !*exp:=t;
  1150. !*allfac:=t;
  1151. !*gcd:=nil;
  1152. !*mcd:=t;
  1153. !*div:=nil;
  1154. !*rat:=nil;
  1155. !*distribute:=nil;
  1156. !*intstr:=nil;
  1157. !*rational:=nil;
  1158. !*ezgcd:=nil;
  1159. !*ratarg:=nil;
  1160. !*precise:=nil;
  1161. !*complex:=nil;
  1162. !*heugcd:=nil;
  1163. !*lcm:=t;
  1164. !*factor:=nil;
  1165. !*ifactor:=nil;
  1166. !*rationalize:=nil;
  1167. !*reduced:=nil;
  1168. !*savestructr:=nil;
  1169. >>;
  1170. flag('(switchorg ),'opfn)$
  1171. deflist('((switches endstat) (switchorg endstat) ),
  1172. 'stat)$
  1173. % 4. Control of USER DEFINED objects.
  1174. % This aims to extract from the history of the run
  1175. % the significant data defined by the user. It DOES NOT give insights on
  1176. % operations done in the SYMBOLIC mode.
  1177. symbolic procedure remvar!:(u,v)$
  1178. % This procedure traces and clear both assigned or saved scalars and
  1179. % lists.
  1180. begin scalar buf,comm,lv;
  1181. buf:=inputbuflis!*;
  1182. for each x in buf do if not atom (comm:=caddr x)
  1183. and car comm = 'setk then
  1184. begin scalar obj;
  1185. l1: if null cddr comm then return lv;
  1186. obj:=cadadr comm;
  1187. if gettype obj eq v then
  1188. lv:=cons(obj,lv);
  1189. comm:=caddr comm;
  1190. go to l1 end;
  1191. lv:= !:mkset lv;
  1192. if null u then
  1193. <<for each x in lv do clear x; return t>> else return lv
  1194. end;
  1195. flag('(displaylst displayscal),'noform);
  1196. symbolic procedure displayscal;
  1197. % Allows to see all scalar variables which have been assigned
  1198. % independently DIRECTLY ON THE CONSOLE. It does not work
  1199. % for assignments introduced THROUGH an input file;
  1200. union(remvar!:(t,'scalar),remsvar!:(t,'scalar));
  1201. symbolic procedure displaylst$
  1202. % Allows to see all list variables which have been assigned
  1203. % independently DIRECTLY ON THE CONSOLE. It does not work
  1204. % for assignments introduced THROUGH an input file;
  1205. union(remvar!:(t,'list),remsvar!:(t,'list)) ;
  1206. symbolic procedure clearscal$
  1207. % Allows to clear all scalar variables introduced
  1208. % DIRECTLY ON THE CONSOLE;
  1209. <<remvar!:(nil,'scalar);remsvar!:(nil,'scalar)>>$
  1210. symbolic procedure clearlst$
  1211. % Allows to clear all list variables introduced
  1212. % DIRECTLY ON THE CONSOLE;
  1213. <<remvar!:(nil,'list);remsvar!:(nil,'list)>>;
  1214. symbolic procedure remsvar!:(u,v)$
  1215. begin scalar buf,comm,lsv,obj;
  1216. buf:= inputbuflis!*;
  1217. for each x in buf do
  1218. if not atom (comm:=caddr x) and car comm eq 'saveas then
  1219. if v eq t then
  1220. if gettype (obj:=cadr cadadr comm)
  1221. member list('scalar,'list,'matrix,'hvector,'tvector)
  1222. then lsv:=cons(obj,lsv)
  1223. else nil
  1224. else if v eq gettype (obj:=cadr cadadr comm)
  1225. then lsv:=cons(obj,lsv);
  1226. lsv:= !:mkset lsv$
  1227. if null u then
  1228. <<for each x in lsv do clear x$ return t>> else return lsv
  1229. end;
  1230. flag('(displaysvar),'noform);
  1231. symbolic procedure displaysvar;
  1232. % Allows to see all variables created by SAVEAS.
  1233. remsvar!:(t,t) ;
  1234. symbolic procedure clearsvar;
  1235. % Allows to clear all variables created.
  1236. % independently DIRECTLY ON THE CONSOLE. It does not work
  1237. % for assignments introduced THROUGH an input file.
  1238. remsvar!:(nil,t);
  1239. symbolic procedure rema!:(u);
  1240. % This function works to trace or to clear arrays.
  1241. begin scalar buf,comm,la$
  1242. buf:=inputbuflis!*$
  1243. for each x in buf do if not atom (comm:=caddr x) and
  1244. car comm eq 'arrayfn then
  1245. begin scalar arl,obj;
  1246. arl:=cdaddr comm;
  1247. l1: if null arl then return la else
  1248. if gettype (obj:=cadadr car arl ) eq 'array then
  1249. la:=cons(obj,la);
  1250. arl:=cdr arl$
  1251. go to l1 end$
  1252. la:= !:mkset la$
  1253. if null u then
  1254. <<for each x in la do clear x$ return t>> else return la
  1255. end;
  1256. flag('(displayar),'noform);
  1257. symbolic procedure displayar;
  1258. % Allows to see all array variables created.
  1259. % independently DIRECTLY ON THE CONSOLE. It does not work
  1260. % for assignments introduced THROUGH an input file.
  1261. rema!:(t)$
  1262. symbolic procedure clearar;
  1263. % Allows to clear array variables introduced
  1264. % DIRECTLY ON THE CONSOLE;
  1265. rema!:(nil)$
  1266. % This file shoul be loaded together with remscal.red
  1267. symbolic procedure remm!:(u)$
  1268. % This function works to trace or to clear matrices. Be CAREFUL to use
  1269. % the declaration MATRIX on input (not m:=mat(...) directly).
  1270. % declaration MATRIX ..
  1271. %x ==> (97 SYMBOLIC (MATRIX (LIST (LIST (QUOTE MM) 1 1))))
  1272. % Declaration MM:=MAT((...))
  1273. % x==>(104 ALGEBRAIC
  1274. % (SETK (QUOTE M2) (AEVAL (LIST (QUOTE MAT) (LIST 1) (LIST 1)))))
  1275. begin scalar buf,comm,lm;
  1276. buf:= inputbuflis!*;
  1277. for each x in buf do if not atom (comm:=caddr x) and
  1278. car comm eq 'matrix then
  1279. begin scalar lob,obj;
  1280. lob:=cdadr comm;
  1281. l1: if null lob then return lm else
  1282. if gettype(obj:=if length car lob = 2 then cadr car lob else
  1283. cadadr car lob) then
  1284. lm:=cons(obj,lm);
  1285. lob:=cdr lob;
  1286. go to l1 end$
  1287. lm :=union(lm,remvar!:(t,'matrix));
  1288. lm:=!:mkset lm;
  1289. if null u then
  1290. <<for each x in lm do clear x$ return t>> else return lm
  1291. end;
  1292. flag('(displaymat),'noform);
  1293. symbolic procedure displaymat$
  1294. % Allows to see all variables of matrix type
  1295. % independently DIRECTLY ON THE CONSOLE. It does not work
  1296. % for assignments introduced THROUGH an input file;
  1297. union( remm!:(t),remsvar!:(t,'matrix));
  1298. symbolic procedure clearmat$
  1299. % Allows to clear all user variables introduced
  1300. % DIRECTLY ON THE CONSOLE;
  1301. <<remm!:(nil);remsvar!:(nil,'matrix)>>;
  1302. symbolic procedure remv!:(u)$
  1303. % This function works to trace or to clear vectors.
  1304. begin scalar buf,av$
  1305. buf:= inputbuflis!*$
  1306. for each x in buf do if not atom (x:=caddr x) and
  1307. car x member list('vector,'tvector,'index)
  1308. then
  1309. begin scalar uu,xx$
  1310. uu:=cdadr x$
  1311. l1: if null uu then return av else
  1312. if gettype(xx:=cadar uu) or get(xx,'fdegree) then
  1313. av:=cons(xx,av);
  1314. uu:=cdr uu$
  1315. go to l1 end$
  1316. av:= !:mkset av$
  1317. if null u then
  1318. <<for each x in av do clear x$ return t>> else return av
  1319. end$
  1320. flag('(displayvec),'noform);
  1321. symbolic procedure displayvec$
  1322. % Allows to see all variables which have been assigned
  1323. % independently DIRECTLY ON THE CONSOLE. It does not work
  1324. % for assignments introduced THROUGH an input file;
  1325. union(remv!:(t),union(remsvar!:(t,'hvector),remsvar!:(t,'tvector)) );
  1326. symbolic procedure clearvec$
  1327. % Allows to clear all user variables introduced
  1328. % DIRECTLY ON THE CONSOLE;
  1329. <<remv!:(nil);remsvar!:(nil,'hvector);remsvar!:(nil,'tvector)>>;
  1330. symbolic procedure remf!:(u)$
  1331. % This function works to trace or to clear arrays.
  1332. begin scalar buf,av$
  1333. buf:= inputbuflis!*$
  1334. for each x in buf do if not atom (x:=caddr x) and
  1335. car x eq 'pform then
  1336. begin scalar uu,xx$
  1337. uu:=cdadr x$
  1338. l1: if null uu then return av else
  1339. if get(xx:=cadadr cdar uu ,'fdegree) or
  1340. (not atom xx and get(xx:=cadr xx,'ifdegree))
  1341. then
  1342. av:=cons(xx,av);
  1343. uu:=cdr uu$
  1344. go to l1 end$
  1345. av:= !:mkset av$
  1346. if null u then
  1347. <<for each x in av do clear x$ return t>> else return av
  1348. end$
  1349. flag('(displayform),'noform);
  1350. symbolic procedure displayform$
  1351. % Allows to see all variables which have been assigned
  1352. % independently DIRECTLY ON THE CONSOLE. It does not work
  1353. % for assignments introduced THROUGH an input file;
  1354. union(remf!:(t),remvar!:(t,'pform));
  1355. symbolic procedure clearform$
  1356. % Allows to clear all user variables introduced
  1357. % DIRECTLY ON THE CONSOLE;
  1358. <<remf!:(nil);remvar!:(nil,'pform)>>;
  1359. symbolic procedure clear!_all;
  1360. <<remvar!: (nil,'scalar); remvar!:(nil,'list); remvar!:(nil,'pform);
  1361. remsvar!:(nil,t);rema!: nil;remv!: nil;remm!: nil; remf!: nil ;t>>;
  1362. symbolic procedure show u;
  1363. begin u:=car u;
  1364. if u eq 'scalars then
  1365. return write "scalars are: ", displayscal()
  1366. else
  1367. if u eq 'lists then
  1368. return write "lists are: ", displaylst()
  1369. else
  1370. if u eq 'arrays then
  1371. return write "arrays are: ", displayar()
  1372. else
  1373. if u eq 'matrices then
  1374. return write "matrices are: ",displaymat()
  1375. else
  1376. if u member list('vectors,'tvectors,'indices) then
  1377. return write "vectors are: ", displayvec()
  1378. else
  1379. if u eq 'forms then
  1380. return write "forms are: ", displayform()
  1381. else
  1382. if u eq 'all then for each i in
  1383. list('scalars,'arrays,'lists,'matrices,'vectors,'forms) do
  1384. <<show list i;lisp terpri()>>;
  1385. end;
  1386. put('show,'stat,'rlis);
  1387. symbolic procedure suppress u;
  1388. begin u:=car u;
  1389. if u member list('vectors,'tvectors,'indices) then
  1390. return clearvec() else
  1391. if u eq 'variables then return clearvar() else
  1392. if u eq 'scalars then return clearscal() else
  1393. if u eq 'lists then return clearlst() else
  1394. if u eq 'saveids then return clearsvar() else
  1395. if u eq 'matrices then return clearmat() else
  1396. if u eq 'arrays then return clearar() else
  1397. if u eq 'forms then return clearform() else
  1398. if u eq 'all then return clear!_all() end;
  1399. put('suppress,'stat,'rlis);
  1400. % 5. Means to CLEAR operators and functions.
  1401. symbolic procedure clearop u;
  1402. <<clear u; remopr u; remprop(u , 'kvalue);remprop(u,'klist)$
  1403. for each x in !:flaglis do
  1404. if u eq car x then putflag(u,cadr x,0) else nil;
  1405. for each x in !:proplis do
  1406. if u eq car x then putprop(u,cadr x,caddr x,0)
  1407. else nil;
  1408. remflag(list u,'used!*); t>>;
  1409. symbolic flag('(clearop),'opfn);
  1410. symbolic procedure clearfunctions u$
  1411. % U is any number of idfs. This function erases properties of non
  1412. % protected functions described by the idfs.
  1413. % It is very convenient but is dangerous if applied to the
  1414. % basic functions of the system since most of them are NOT protected.
  1415. % It clears all properties introduced by PUTFLAG, PUTPROP and DEPEND.
  1416. begin scalar uu,vv$
  1417. l1: uu:=car u$
  1418. vv:=cdr rdisplayflag (list uu )$
  1419. if flagp(uu,'lose) then go to l2 else
  1420. << terpri();spaces(5)$
  1421. write "*** ",uu," is unprotected : Cleared ***"$
  1422. followline(0)>>$
  1423. for each x in !:proplis do
  1424. if u eq car x then putprop(u,cadr x,caddr x,0)
  1425. else nil;
  1426. if get(uu,'simpfn) then <<clearop uu; remprop(uu,'!:ft!:);
  1427. remprop(uu,'!:gf!:)>> else
  1428. if get(uu,'psopfn) then remprop(uu,'psopfn) else
  1429. if get(uu,'expr) then remprop(uu,'expr) else
  1430. if get(uu,'subr) then remd uu$
  1431. remprop(uu,'number!_og!_args);
  1432. remprop(uu,'stat);
  1433. remprop(uu,'dfn);
  1434. remflag(list uu,'opfn)$
  1435. remflag(list uu,'listargp);
  1436. remflag(list uu,'full)$
  1437. remflag(list uu,'odd)$
  1438. remflag(list uu,'even)$
  1439. remflag(list uu,'boolean)$
  1440. remflag(list uu,'used!*)$
  1441. for each x in vv do putflag( uu,x,0)$
  1442. depl!*:=delete(assoc(uu,depl!*),depl!*);
  1443. remflag(list uu,'impfun)$ % to be effective in EXCALC;
  1444. u:= cdr u$ go to l3$
  1445. l2: << spaces(5)$
  1446. write "*** ",uu," is a protected function: NOT cleared ***"$
  1447. terpri(); u:=cdr u>>$
  1448. l3: if null u then <<terpri();
  1449. return "Clearing is complete">> else
  1450. go to l1 end$
  1451. symbolic rlistat '(clearfunctions);
  1452. endmodule;
  1453. module polyextensions;
  1454. %=====================================================================
  1455. % ADDITIONAL FUNCTIONS FOR POLYNOME AND RATIONAL EXPRESSION
  1456. % MANIPULATIONS.
  1457. %=====================================================================
  1458. symbolic procedure alg_to_symb u;
  1459. % transforms standard quotient expressions into prefix symbolic ones.
  1460. % dd => (LIST 1 (!*SQ ((((A . 2) . 1)) . 1) T)
  1461. % (!*SQ ((((A . 1) . 1)) . 1) T)
  1462. % 3 (LIST 4))
  1463. % alg_to_symb dd ==> (1 (EXPT A 2) A 3 (4))
  1464. %
  1465. if null u then nil else
  1466. if atom u then u else
  1467. if car u neq 'list then reval u else
  1468. if car u eq 'list then
  1469. for each i in cdr u collect alg_to_symb i;
  1470. symbolic procedure fix_or_str u;
  1471. fixp u or stringp u;
  1472. symbolic procedure symb_to_alg u;
  1473. % transforms prefix lisp list into an algebraic list.
  1474. if null u then nil else
  1475. if fix_or_str u then u else
  1476. if atom u then mk!*sq simp!* u else
  1477. if listp u and getd car u then mk!*sq simp!* u else
  1478. if atomlis u then 'list . for each i in u collect
  1479. if fix_or_str i then i else mk!*sq simp!* i
  1480. else
  1481. 'list . for each i in u collect symb_to_alg i ;
  1482. %symbolic procedure symb_to_alg u;
  1483. % transforms prefix lisp list into an algebraic list.
  1484. %if null u then nil else
  1485. %if fixp u then u else
  1486. %if atom u then mk!*sq simp!* u else
  1487. %if listp u and getd car u then mk!*sq simp!* u else
  1488. % 'list . for each i in u collect symb_to_alg i ;
  1489. fluid '(!*distribute);
  1490. switch distribute;
  1491. symbolic procedure addfd (u,v);
  1492. % It contains a modification to ADDF to avoid
  1493. % a recursive representation.
  1494. % U and V are standard forms. Value is a standard form.
  1495. if null u then v
  1496. else if null v then u
  1497. else if domainp u then addd(u,v)
  1498. else if domainp v then addd(v,u)
  1499. else if ordpp(lpow u,lpow v)
  1500. then lt u .+ addfd(red u,v)
  1501. else lt v .+ addfd (u,red v);
  1502. symbolic procedure distribute u;
  1503. % Works ONLY when RATIONAL is OFF.
  1504. begin scalar s;
  1505. s:=simp!* u;
  1506. return mk!*sq (distri!_pol(numr s) ./ denr s)
  1507. end;
  1508. % symbolic procedure distribute u;
  1509. % Gives a polynome in distributed form in the algebraic mode.
  1510. % NO LONGER USED
  1511. %list('!*sq,distri!_pol numr simp!* u ./ 1,t);
  1512. symbolic flag('(distribute),'opfn);
  1513. symbolic procedure distri!_pol u;
  1514. % This function assumes that u is a polynomial given
  1515. % as a standard form. It transforms its recursive representation into
  1516. % a distributive representation.
  1517. if null u then nil else
  1518. if atom u then u else
  1519. if red u then
  1520. addfd(distri!_pol !*t2f lt u,distri!_pol red u)
  1521. else
  1522. begin scalar x,y;
  1523. x:=1 ;
  1524. y:=u;
  1525. while not atom y and null red y do
  1526. <<x:=multf(x,!*p2f lpow y); y:=lc y>>;
  1527. if atom y then return multf(x,y) else
  1528. return
  1529. addfd(distri!_pol multf(x,distri!_pol !*t2f lt y),
  1530. distri!_pol multf(x,distri!_pol red y))
  1531. end;
  1532. symbolic procedure leadterm u;
  1533. <<u:=simp!* u; if !*distribute then u:=distri!_pol numr u ./ denr u
  1534. else u; if domainp u then mk!*sq u
  1535. else mk!*sq(!*t2f lt numr u ./ denr u)>>;
  1536. symbolic flag('(leadterm redexpr ),'opfn);
  1537. symbolic procedure redexpr u;
  1538. <<u:=simp!* u; if !*distribute then u:=distri!_pol numr u ./ denr u
  1539. else u; if domainp u then mk!*sq(nil ./ 1) else
  1540. mk!*sq( red numr u ./ denr u)>>;
  1541. symbolic procedure list!_of!_monom u;
  1542. % It takes a polynomial in distributive form.
  1543. % returns a list of monoms.
  1544. % u is numr simp!* (algebraic expression)
  1545. begin scalar exp,lmon,mon;
  1546. exp:=u;
  1547. l: if null exp then return lmon else
  1548. if domainp exp then return exp . lmon ;
  1549. mon:=if atom exp then exp else lt exp;
  1550. lmon:=(!*t2f mon ) . lmon;
  1551. exp:=red exp;
  1552. go to l;
  1553. end;
  1554. symbolic procedure monom y;
  1555. % This procedure works ONLY for polynomials in the strict sense. It is
  1556. % left to generalize it when RATIONAL or RATARG are on but why ...?
  1557. begin scalar x;
  1558. x:=numr simp!* y;
  1559. x:=distri!_pol x;
  1560. x:=reversip list!_of!_monom x;
  1561. x:=for each m in x collect mk!*sq(m ./ 1);
  1562. return 'list . x end;
  1563. symbolic flag('(monom),'opfn);
  1564. symbolic procedure !&dpol u$
  1565. % RETURNS A LIST WHICH CONTAINS THE QUOTIENT POLYNOMIAL and THE
  1566. % REMAINDER.
  1567. if length u neq 2 then rederr "divpol must have two arguments"
  1568. else
  1569. begin scalar poln,pold,aa,ratsav$
  1570. if lisp (!*factor) then off factor; % This restriction is
  1571. % necessary for some implementatins .
  1572. poln:= simp!* car u$
  1573. pold:= simp!* cadr u$
  1574. if denr poln neq 1 or denr pold neq 1 then
  1575. rederr(" arguments must be polynomials")$
  1576. poln:=numr poln$ pold:=numr pold$
  1577. if lc poln neq 1 or lc poln neq lc pold then
  1578. <<ratsav:=lisp (!*rational); on rational>>;
  1579. aa:=qremf(poln,pold)$
  1580. aa:=mksq(list('list ,prepsq!*( car aa . 1), prepsq!*(cdr aa . 1)),1)$
  1581. if not ratsav then off rational;
  1582. return aa end$
  1583. put('divpol,'simpfn,'!&dpol)$
  1584. symbolic procedure lowestdeg(u,v)$
  1585. % IT EXTRACTS THE LOWEST DEGREE IN V OUT OF THE POLYNOMIAL U.
  1586. % U is the POLYNOMIAL. V is an ID or a KERNEL.
  1587. begin scalar x,y,uu,vv,mvy$
  1588. uu:=simp!* u$
  1589. if domainp uu then return 0$
  1590. uu:=!*q2f uu;
  1591. vv:=!*a2k v$
  1592. x:=setkorder list v$
  1593. y:=reorder uu$ setkorder x$
  1594. y:=reverse y$y$
  1595. if fixp y then return 0$
  1596. mvy:=mvar y$
  1597. if not atom mvy then if car mvy eq 'expt then
  1598. rederr("exponents must be integers")$
  1599. if mvy neq vv then return 0 else
  1600. return ldeg y end$
  1601. flag('(lowestdeg),'opfn)$
  1602. % splitting expressions
  1603. % splitterms retuns list of plus-terms and minus-terms.
  1604. symbolic operator splitterms; % necessary to make it algebraic.
  1605. symbolic procedure splitterms u;
  1606. begin scalar a,b;
  1607. if fixp u and evallessp(u, 0) then return
  1608. 'list . ('list . 0 . nil) . ('list . list('minus, u)
  1609. . nil) . nil
  1610. else if
  1611. atom u or not(car u member(list('plus,'minus))) then return
  1612. 'list . ('list . u . nil) . ('list . 0 . nil) . nil
  1613. else if
  1614. car u eq 'minus then return
  1615. 'list . ('list . 0 . nil) . ('list . cdr u) . nil;
  1616. while(u:=cdr u) do
  1617. if atom car u or not (caar u eq 'minus) then a:= car u . a
  1618. else b:=cadar u . b;
  1619. if null a then a:=0 . nil;
  1620. if null b then b:=0 . nil;
  1621. return 'list . ('list . reversip a) . ('list . reversip b) . nil;
  1622. end;
  1623. algebraic procedure splitplusminus(u);
  1624. % Applies to rational functions.
  1625. begin scalar uu;
  1626. uu:=splitterms num u;
  1627. return list((for each j in first uu sum j) /den u,
  1628. - (for each j in second uu sum j)/den u)
  1629. end;
  1630. endmodule;
  1631. module transfunctions;
  1632. algebraic;
  1633. algebraic procedure trigexpand wws;
  1634. wws where { sin(~x+~y) => sin(x)*cos(y)+cos(x)*sin(y),
  1635. cos(~x+~y) => cos(x)*cos(y)-sin(x)*sin(y),
  1636. sin((~n)*~x) => sin(x)*cos((n-1)*x)+cos(x)*sin((n-1)*x)
  1637. when fixp n and n>1,
  1638. cos((~n)*~x) => cos(x)*cos((n-1)*x)-sin(x)*sin((n-1)*x)
  1639. when fixp n and n>1 };
  1640. algebraic procedure hypexpand wws;
  1641. wws where {sinh(~x+~y) => sinh(x)*cosh(y)+cosh(x)*sinh(y),
  1642. cosh(~x+~y) => cosh(x)*cosh(y)+sinh(x)*sinh(y),
  1643. sinh((~n)*~x)=> sinh(x)*cosh((n-1)*x)+cosh(x)*sinh((n-1)*x)
  1644. when fixp n and n>1,
  1645. cosh((~n)*~x)=> cosh(x)*cosh((n-1)*x)+sinh(x)*sinh((n-1)*x)
  1646. when fixp n and n>1 };
  1647. operator !#ei!&; !#ei!&(0):=1;
  1648. trig!#ei!& := {!#ei!&(~x)**(~n) => !#ei!&(n*x),
  1649. !#ei!&(~x)*!#ei!&(~y) => !#ei!&(x+y)};
  1650. let trig!#ei!&;
  1651. algebraic procedure trigreduce wws;
  1652. <<wws:=(wws WHERE {cos(~x) => (!#ei!&(x)+!#ei!&(-x))/2,
  1653. sin(~x) => -i*(!#ei!&(x)-!#ei!&(-x))/2});
  1654. wws:=(wws WHERE {!#ei!&(~x) => cos x +i*sin x})>>;
  1655. algebraic procedure hypreduce wws;
  1656. <<wws:=(wws where {cosh(~x) => (!#ei!&(x)+!#ei!&(-x))/2,
  1657. sinh(~x) => (!#ei!&(x)-!#ei!&(-x))/2});
  1658. wws:=(wws where {!#ei!&(~x) => cosh(x)+sinh(x)})>>;
  1659. algebraic procedure pluslog wws;
  1660. wws:=(wws where {log(~x*(~n)) => log(x)+log(n),
  1661. log(~x/(~n)) => log(x)-log(n),
  1662. log(~x**(~n)) => n*log(x),
  1663. log sqrt(~x) => 1/2*log(x)});
  1664. % realizes the concatenation of "sum over i c(i)*log x(i)".
  1665. operator e!_log!_conc;
  1666. algebraic procedure concsumlog exp;
  1667. % This procedure works properly only in ON EXP only though it may lead
  1668. % to some simplification also in OFF EXP.
  1669. if den exp neq 1 then concsumlog num exp / concsumlog den exp else
  1670. <<exp:=(e!_log!_conc(exp) where
  1671. { e!_log!_conc(~x+~y)=e!_log!_conc(x)*e!_log!_conc(y),
  1672. e!_log!_conc(log(~x)) => x,
  1673. e!_log!_conc(-log(~x)) => 1/x,
  1674. e!_log!_conc(~a*log (~x)) => x**a,
  1675. e!_log!_conc((- ~a)*log(~x)) => 1/x**a });
  1676. exp:=(log exp where
  1677. { log(e!_log!_conc(~y)) => y,
  1678. log(~x*e!_log!_conc(~y)) => log(x)+y,
  1679. log(~x*e!_log!_conc(-~y)) => log(x)-y,
  1680. log(~x*e!_log!_conc(-~y)/(~z)) => log(x/z)-y,
  1681. log(~x*e!_log!_conc(~y)/(~z)) => log(x/z)+y })>>;
  1682. symbolic;
  1683. endmodule;
  1684. module vectoroper;
  1685. % This small module makes basic operation between EXPLICIT vectors
  1686. % available. They are assumed to be represented by BAGS or LISTS.
  1687. % Mixed product is restricted to 3-space vectors.
  1688. % Generalization is still NEEDED. ;
  1689. symbolic procedure depthl1!: u;
  1690. if null u then t else (caar u neq 'list) and depthl1!: cdr u;
  1691. symbolic procedure depthl1 u;
  1692. not null getrtype u and depthl1!: cdr u;
  1693. symbolic procedure !:vect(u,v,bool);
  1694. %returns a list whose elements are the sum of each list elements.
  1695. % null v check not necessary;
  1696. if null u then nil
  1697. else addsq(car u,if null bool then car v else negsq car v)
  1698. . !:vect(cdr u,cdr v,bool);
  1699. symbolic procedure rsumvect(u);
  1700. begin scalar x,y,prf;
  1701. x:=reval car u;y:=reval cadr u; prf:=car x;
  1702. if (rdepth list x = 0) or (rdepth list y = 0) then
  1703. rederr " both arguments must be of depth 1 " else
  1704. x:=cdr x; y:=cdr y;
  1705. if length x neq length y then rederr "vector mismatch";
  1706. x:=for each j in x collect simp!* j;
  1707. y:=for each j in y collect simp!* j;
  1708. return prf . (for each j in !:vect(x,y,nil) collect mk!*sq j) end;
  1709. put('sumvect,'psopfn,'rsumvect);
  1710. symbolic procedure rminvect(u);
  1711. begin scalar x,y,prf;
  1712. x:=reval car u;y:=reval cadr u; prf:=car x;
  1713. if (rdepth list x = 0) or (rdepth list y = 0) then
  1714. rederr " both arguments must be of depth 1 " else
  1715. x:=cdr x; y:=cdr y;
  1716. if length x neq length y then rederr "vector mismatch";
  1717. x:=for each j in x collect simp!* j;
  1718. y:=for each j in y collect simp!* j;
  1719. return prf . (for each j in !:vect(x,y,'minus) collect mk!*sq j) end;
  1720. put('minvect,'psopfn,'rminvect);
  1721. symbolic procedure !:scalprd(u,v);
  1722. %returns scalar product of two lists;
  1723. if null u and null v then nil ./ 1
  1724. else addsq(multsq(car u,car v),!:scalprd(cdr u,cdr v));
  1725. symbolic procedure sscalvect(u);
  1726. begin scalar x,y;
  1727. x:=reval car u;y:=reval cadr u;
  1728. if (rdepth list x = 0) or (rdepth list y = 0) then
  1729. rederr " both arguments must be of depth 1 " else
  1730. if length x neq length y then rederr "vector mismatch";
  1731. x:=cdr x; y:=cdr y;
  1732. x:=for each j in x collect simp!* j;
  1733. y:=for each j in y collect simp!* j;
  1734. return mk!*sq !:scalprd(x,y)
  1735. end;
  1736. symbolic put('scalvect,'psopfn,'sscalvect);
  1737. symbolic procedure !:pvect3 u;
  1738. begin scalar x,y; integer xl;
  1739. if (rdepth list car u = 0) or (rdepth cdr u = 0) then
  1740. rederr " both arguments must be of depth 1 " else
  1741. x:=reval car u;y:=reval cadr u;
  1742. if (xl:=length x) neq 4 then rederr "not 3-space vectors" else
  1743. if xl neq length y then rederr "vector mismatch" ;
  1744. x:=cdr x; y:=cdr y;
  1745. x:=for each j in x collect simp!* j;
  1746. y:=for each j in y collect simp!* j;
  1747. return
  1748. list( addsq(multsq(cadr x,caddr y),negsq multsq(caddr x,cadr y)),
  1749. addsq(multsq(caddr x,car y),negsq multsq(car x,caddr y)),
  1750. addsq(multsq(car x,cadr y),negsq multsq(cadr x,car y)))
  1751. end;
  1752. symbolic procedure rcrossvect u;
  1753. % implemented only with LIST prefix;
  1754. 'list . (for each j in !:pvect3 u collect mk!*sq j);
  1755. symbolic put ('crossvect,'psopfn,'rcrossvect);
  1756. symbolic procedure smpvect u;
  1757. begin scalar x;
  1758. if (rdepth list car u =0) then
  1759. rederr " arguments must be of depth 1 " else
  1760. x:=reval car u; u:=cdr u;
  1761. x:=cdr x;
  1762. if length x neq 3 then rederr " not 3-space vector";
  1763. x:=for each j in x collect simp!* j;
  1764. return mk!*sq !:scalprd(x,!:pvect3 u) end;
  1765. symbolic put('mpvect,'psopfn,'smpvect);
  1766. endmodule;
  1767. module grassman;
  1768. % fichier de manipulation des variables de Grassmann.
  1769. % RATIONAL functions involving Grasman variables inside the
  1770. % denominator NOT ALLOWED.
  1771. %
  1772. symbolic procedure putgrass u;
  1773. % Allows to define Grassmann variables.
  1774. for each i in u do
  1775. if not idp i then typerr(i,"grassman variable")
  1776. else <<flag(list i,'noncom); put(i,'simpfn,'simpiden);
  1777. flag(list i, 'grassman);>> ;
  1778. rlistat '(putgrass remgrass);
  1779. symbolic procedure remgrass u;
  1780. % Erase the Grassman properties of the identifiers in u.
  1781. for each i in u do
  1782. if flagp(i,'grassman) then
  1783. <<remflag(list i,'grassman);remflag(list i ,'noncom);
  1784. clearop i;>>;
  1785. symbolic procedure grassp u;
  1786. not atom u and flagp(car u, 'grassman);
  1787. lisp flag('(grassp),'boolean);
  1788. %symbolic procedure grassparityini u;
  1789. % Not used anymore
  1790. %if grassp u then 1 else 0;
  1791. symbolic procedure grassparity u;
  1792. if atom u then 0 else
  1793. if flagp(car u,'grassman) then 1 else
  1794. if car u eq 'plus then "parity undefined" else
  1795. if car u eq 'minus then grassparity cadr u else
  1796. if car u eq 'times
  1797. then remainder(for each i in cdr u sum grassparity i,2) else
  1798. if car u eq 'expt then if oddp caddr u then grassparity cadr u else 0
  1799. else
  1800. if car u eq 'quotient then grassparity cadr u
  1801. else 0;
  1802. flag('(grassparity ghostfactor),'opfn);
  1803. symbolic procedure ghostfactor(u,v);
  1804. % (-1)^(grassparity u * grassparity v)
  1805. if reval list('times, grassparity u, grassparity v) = 0 then 1 else -1;
  1806. % *****************
  1807. % For the time being we let the explicit manipulation of
  1808. % Grassman variables as matching rules :
  1809. % here is an example of use of the previous functions :
  1810. % to try them erase the %
  1811. % putgrass eta,prond;
  1812. % grasskernel:=
  1813. % {(~x)*(~y) => y*x when grassp x and not grassp y,
  1814. % prond(~x)*eta(~y) => -eta(y)*prond(x),
  1815. % eta(~x)*eta(~y) => -eta y*eta x when nordp(x,y),
  1816. % prond(~x)*prond(~y) => -prond y*prond x when nordp(x,y),
  1817. % (~x)*(~x) => 0 when grassp x};
  1818. % let grasskernel;
  1819. % ***********************
  1820. endmodule;
  1821. module matrext;
  1822. % This module defines additional utility functions for manipulating
  1823. % matrices. Coercions to BAG and LIST structures are defined.
  1824. symbolic procedure natnumlis u;
  1825. % True if U is a list of natural numbers.
  1826. % Taken from MATR.RED for bootstrap purpose.
  1827. null u or numberp car u and fixp car u and car u>0
  1828. and natnumlis cdr u;
  1829. symbolic procedure mkid!:(x,y);
  1830. % creates the ID XY from identifier X and (evaluated) atom Y.
  1831. if not idp x or null getrtype x then typerr(x,"MKID root")
  1832. else if atom y and (idp y or fixp y and not minusp y)
  1833. then intern compress nconc(explode x,explode y)
  1834. else typerr(y,"MKID index");
  1835. symbolic procedure mkidm(u,j);
  1836. % This function allows us to RELATE TWO MATRICES by concatanation of
  1837. % characters. u AND uj should BOTH be matrices.
  1838. matsm cadr get(mkid!:(u,j),'avalue) ;
  1839. symbolic put('mkidm,'rtypefn,'getrtypecar);
  1840. symbolic flag('(mkidm),'matflg);
  1841. symbolic procedure baglmat (u,op);
  1842. % this procedure maps U into the matrix whose name is OP;
  1843. % it cannot REDEFINE the matrix OP.
  1844. % This is to avoid accidental redefinition of a previous matrix;
  1845. if getrtype op then rederr list(op,"should be an identifier")
  1846. else
  1847. begin scalar x,y;
  1848. if atom op then if not(y:=gettype op) then put(op,'rtype,'matrix) else
  1849. typerr(list(y,op),"matrix");
  1850. if rdepth list u neq 2 then rederr("depth of list or bag must be 2");
  1851. x:=cdr u;
  1852. x:= for each j in x collect for each k in cdr j collect k;
  1853. put(op,'avalue,list('matrix,'mat . x));
  1854. return t end;
  1855. symbolic flag('(baglmat),'opfn);
  1856. symbolic procedure rcoercemat u;
  1857. % Transforms a matrix into a bag or list. Argument is a list (mat,idp).
  1858. % idp is the name to be given to the line or column vectors.
  1859. % The idp-envelope of the bag is the same as the one of the one of the
  1860. % subbags$
  1861. begin scalar x,prf;
  1862. x:=reval car u;
  1863. if getrtype x neq 'matrix then rederr list(x,"should be a matrix");
  1864. prf:= cadr u;
  1865. if car x neq 'mat then typerr(x,"matrix") else
  1866. if prf neq 'list then <<prf:=reval prf; simpbagprop list(prf,t)>>;
  1867. x:=cdr x;
  1868. x:= for each j in x collect (prf . j);
  1869. return prf . x end;
  1870. symbolic put('coercemat,'psopfn,'rcoercemat);
  1871. symbolic put('rcoercemat,'number!_of!_args,2);
  1872. symbolic procedure n!-1zero(n,k)$
  1873. if n=0 then nil else
  1874. if k=1 then 1 . nzero(n-1) else
  1875. if k=n then append(nzero(n-1) , (1 . nil)) else
  1876. append(nzero(k-1), (1 . nzero(n-k)))$
  1877. symbolic procedure unitmat u$
  1878. % It creates unit matrices. The argument is of the form A(2),B(5)....$
  1879. begin scalar l,sy,x,aa$
  1880. for each s in u do
  1881. << if idp s or length (l:= revlis cdr s) neq 1 or not natnumlis l
  1882. then errpri2(s,'hold) else
  1883. <<aa:=nil;sy:=car s; x:=gettype sy; if not null x then if x eq 'matrix
  1884. then lprim list(x,sy,"redefined")
  1885. else typerr(list(x,sy),"matrix");
  1886. l:=car l; for n:=1:l do aa:=n!-1zero(l,l-n+1) . aa$
  1887. put(sy,'rtype,'matrix);
  1888. put(sy,'avalue,list('matrix,'mat . aa))>>>>;
  1889. end$
  1890. symbolic put('unitmat,'stat,'rlis);
  1891. symbolic procedure submat (u,nl,nc);
  1892. % Allows to extract from the matrix M the matrix obtained when
  1893. % the row NL and the column NC have been dropped.
  1894. % When NL and NC are out of range gives a copy of M;
  1895. if getrtype u neq 'matrix then rederr list(u,"should be a matrix")
  1896. else
  1897. begin scalar x;
  1898. x:= matsm u;
  1899. if and(nl=0,nc=0) then return x else
  1900. if nl neq 0 then x:=remove(x,nl)$
  1901. if nc neq 0 then
  1902. x:=for each j in x collect remove(j,nc);
  1903. return x end;
  1904. symbolic put('submat,'rtypefn,'getrtypecar);
  1905. symbolic flag('(submat),'matflg);
  1906. symbolic procedure matsubr(m,bgl,nr)$
  1907. if getrtype m neq 'matrix then rederr list(m,"should be a matrix")
  1908. else
  1909. begin scalar x,y,res; integer xl;
  1910. % It allows to replace row NR of the matrix M by the bag or list BGL;
  1911. y:=reval bgl;
  1912. if not baglistp y then typerr(y,"bag or list") else
  1913. if nr leq 0 then rederr " THIRD ARG. MUST BE POSITIVE"
  1914. else
  1915. x:=matsm m$ xl:=length x$
  1916. if length( y:=cdr y) neq xl then rederr " MATRIX MISMATCH"$
  1917. y:= for each j in y collect simp j;
  1918. if nr-xl >0 then rederr " row number is out of range";
  1919. while (nr:=nr-1) >0
  1920. do <<res:=car x . res$ x:=cdr x >>;
  1921. rplaca(x,y) ;
  1922. res:=append( reverse res, x) ;
  1923. return res end;
  1924. symbolic put('matsubr,'rtypefn,'getrtypecar);
  1925. symbolic flag('(matsubr),'matflg);
  1926. symbolic procedure matsubc(m,bgl,nc)$
  1927. if getrtype m neq 'matrix then rederr list(m,"should be a matrix")
  1928. else
  1929. begin scalar x,y,res; integer xl;
  1930. %It allows to replace column NC of the matrix M by the bag or list BGL
  1931. y:=reval bgl;
  1932. if not baglistp y then typerr(y,"bag or list") else
  1933. if nc leq 0 then rederr " THIRD ARG. MUST BE POSITIVE"
  1934. else
  1935. x:=tp1 matsm m$ xl:=length x$
  1936. if length( y:=cdr y) neq xl then rederr " MATRIX MISMATCH"$
  1937. y:= for each j in y collect simp j;
  1938. if nc-xl >0 then rederr " column number is out of range";
  1939. while (nc:=nc-1) >0
  1940. do <<res:=car x . res$ x:=cdr x >>;
  1941. rplaca(x,y) ;
  1942. res:=tp1 append( reverse res, x) ;
  1943. return res end;
  1944. symbolic put('matsubc,'rtypefn,'getrtypecar);
  1945. symbolic flag('(matsubc),'matflg);
  1946. symbolic procedure rmatextr u$
  1947. % This function allows to extract row N from matrix A and
  1948. % to place it inside a bag whose name is LN$
  1949. begin scalar x,y; integer n,nl;
  1950. x:= matsm car u; y:= reval cadr u; n:=reval caddr u;
  1951. if not fixp n then
  1952. rederr "Arguments are: matrix, vector name, line number" else
  1953. if not baglistp list y then simpbagprop list(y, t)$
  1954. nl:=length x;
  1955. if n<= 0 or n>nl then return nil$
  1956. while n>1 do <<x:=cdr x$ n:=n-1>>$
  1957. if null x then return nil$
  1958. return x:=y . ( for each j in car x collect prepsq j) end$
  1959. symbolic procedure rmatextc u$
  1960. % This function allows to extract column N from matrix A and
  1961. % to place it inside a bag whose name is LN$
  1962. begin scalar x,y; integer n,nc;
  1963. x:= tp1 matsm car u; y:= reval cadr u; n:=reval caddr u;
  1964. if not fixp n then
  1965. rederr "Arguments are: matrix, vector name, line number" else
  1966. if not baglistp list y then simpbagprop list(y, t)$
  1967. nc:=length x;
  1968. if n<= 0 or n>nc then return nil$
  1969. while n>1 do <<x:=cdr x$ n:=n-1>>$
  1970. if null x then return nil$
  1971. return x:=y . ( for each j in car x collect prepsq j) end$
  1972. symbolic put('matextr,'psopfn,'rmatextr);
  1973. symbolic put('matextc,'psopfn,'rmatextc);
  1974. symbolic procedure hconcmat(u,v)$
  1975. % Gives the horizontal concatenation of matrices U and V$
  1976. hconcmat!:(matsm u,matsm v );
  1977. symbolic procedure hconcmat!:(u,v)$
  1978. if null u then v else if null v then u else
  1979. append(car u,car v) . hconcmat!:(cdr u,cdr v)$
  1980. symbolic put('hconcmat,'rtypefn,'getrtypecar);
  1981. symbolic flag('(hconcmat),'matflg);
  1982. symbolic procedure vconcmat (u,v)$
  1983. % Gives the vertical concatenation of matrices U and V$
  1984. append(matsm u,matsm v);
  1985. symbolic put('vconcmat,'rtypefn,'getrtypecar);
  1986. symbolic flag('(vconcmat),'matflg);
  1987. symbolic procedure tprodl(u,v)$
  1988. begin scalar aa,ul$
  1989. l1: if null u then return aa$
  1990. ul:=car u$
  1991. ul:=multsm(ul,v)$
  1992. aa:=hconcmat!:(aa,ul)$
  1993. u:=cdr u$
  1994. go to l1$
  1995. end$
  1996. symbolic procedure tpmat(u,v)$
  1997. % Constructs the direct product of two matrices;
  1998. if null gettype u then multsm(simp u,matsm v) else
  1999. if null gettype v then multsm(simp v,matsm u) else
  2000. begin scalar aa,uu,vv$
  2001. uu:=matsm u$ vv:=matsm v$
  2002. for each x in uu do aa:=append (aa,tprodl(x,vv))$
  2003. return aa end;
  2004. infix tpmat$
  2005. put('tpmat,'rtypefn, 'getrtypecar);
  2006. flag('(tpmat),'matflg)$
  2007. algebraic procedure hermat (m,hm);
  2008. % hm must be an identifier with NO value. Returns the
  2009. % Hermitiam Conjugate matrix.
  2010. begin scalar ml,ll; %ll:=length M;
  2011. m:=tp m;
  2012. ml:=coercemat(m,list);
  2013. ll:=list(length first ml,length ml);
  2014. ml:=for j:=1: first ll collect for k:=1:second ll collect
  2015. sub(i=-i,(ml.j).k);
  2016. baglmat(ml,hm);
  2017. return hm end;
  2018. symbolic procedure seteltmat(m,elt,i,j);
  2019. % Sets the matrix element (i,j) to elt. Returns the modified matrix.
  2020. begin scalar res;res:=matsm m;
  2021. rplaca(pnth(nth(res,i),j),simp elt);
  2022. return res end;
  2023. put('seteltmat,'rtypefn,'getrtypecar);
  2024. flag('(seteltmat),'matflg);
  2025. symbolic procedure simpgetelt u;
  2026. % Gets the matrix element (i,j). Returns the element.
  2027. begin scalar mm;
  2028. mm:=matsm car u;
  2029. return nth(nth(mm,cadr u),caddr u) end;
  2030. put('geteltmat, 'simpfn,'simpgetelt);
  2031. endmodule;
  2032. end;