dipoly.red 80 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487
  1. module dipoly; % Header module for dipoly package.
  2. %/*Authors: R. Gebauer, A. C. Hearn, H. Kredel*/
  3. % For the time being, this contains the smacros that used to be in
  4. % consel, and repeats those in bcoeff.
  5. %/*Constructors and selectors for a distributed polynomial form*/
  6. %/*A distributive polynomial has the following informal syntax:
  7. %
  8. % <dipoly> ::= dipzero
  9. % | <exponent vector> . <base coefficient> . <dipoly>*/
  10. % Vdp2dip modules included. They could be in a separate package.
  11. create!-package('(dipoly a2dip bcoeff dip2a dipoly1 dipvars
  12. expvec torder vdp2dip vdpcom),
  13. '(contrib dipoly));
  14. %define dipzero = 'nil;
  15. fluid '(dipzero);
  16. %/*Until we understand how to define something to nil*/
  17. smacro procedure dipzero!? u; null u;
  18. smacro procedure diplbc p;
  19. % /* Distributive polynomial leading base coefficient.
  20. % p is a distributive polynomial. diplbc(p) returns
  21. % the leading base coefficient of p. */
  22. cadr p;
  23. smacro procedure dipmoncomp (a,e,p);
  24. % /* Distributive polynomial monomial composition. a is a base
  25. % coefficient, e is an exponent vector and p is a
  26. % distributive polynomial. dipmoncomp(a,e,p) returns a dis-
  27. % tributive polynomial with p as monomial reductum, e as
  28. % exponent vector of the leading monomial and a as leading
  29. % base coefficient. */
  30. e . a . p;
  31. smacro procedure dipevlmon p;
  32. % /* Distributive polynomial exponent vector leading monomial.
  33. % p is a distributive polynomial. dipevlmon(p) returns the
  34. % exponent vector of the leading monomial of p. */
  35. car p;
  36. smacro procedure dipfmon (a,e);
  37. % /* Distributive polynomial from monomial. a is a base coefficient
  38. % and e is an exponent vector. dipfmon(a,e) returns a
  39. % distributive polynomial with e as exponent vector and
  40. % a as base coefficient. */
  41. e . a . dipzero;
  42. smacro procedure dipnov p;
  43. % /* Distributive polynomial number of variables. p is a distributive
  44. % polynomial. dipnov(p) returns a digit, the number of variables
  45. % of the distributive polynomial p. */
  46. length car p;
  47. smacro procedure dipmred p;
  48. % /* Distributive polynomial reductum. p is a distributive polynomial
  49. % dipmred(p) returns the reductum of the distributive polynomial p,
  50. % a distributive polynomial. */
  51. cddr p;
  52. % These smacros are also in bcoeff.
  53. smacro procedure bcminus!? u;
  54. % /* Boolean function. Returns true if u is a negative base coeff*/
  55. minusf numr u;
  56. smacro procedure bczero!? u;
  57. % /* Returns a boolean expression, true if base coefficient u is zero*/
  58. null numr u;
  59. endmodule;
  60. module a2dip;
  61. %/*Convert an algebraic (prefix) form to distributive polynomial*/
  62. %/*Authors: R. Gebauer, A. C. Hearn, H. Kredel*/
  63. fluid '(dipvars!* dipzero);
  64. expr procedure a2dip u;
  65. % /*Converts the algebraic (prefix) form u to a distributive poly.
  66. % We assume that all variables used have been previously
  67. % defined in dipvars!*, but a check is also made for this*/
  68. if atom u then a2dipatom u
  69. else if not atom car u or not idp car u
  70. then typerr(car u,"dipoly operator")
  71. else (if x then apply(x,list for each y in cdr u collect a2dip y)
  72. else a2dipatom u)
  73. where x = get(car u,'dipfn);
  74. expr procedure a2dipatom u;
  75. % /*Converts the atom (or kernel) u into a distributive polynomial*/
  76. if u=0 then dipzero
  77. else if numberp u or not(u member dipvars!*)
  78. then dipfmon(a2bc u,evzero())
  79. else dipfmon(a2bc 1,mkexpvec u);
  80. expr procedure dipfnsum u;
  81. % /*U is a list of dip expressions. Result is the distributive poly
  82. % representation for the sum*/
  83. (<<for each y in cdr u do x := dipsum(x,y); x>>) where x = car u;
  84. put('plus,'dipfn,'dipfnsum);
  85. put('plus2,'dipfn,'dipfnsum);
  86. expr procedure dipfnprod u;
  87. % /*U is a list of dip expressions. Result is the distributive poly
  88. % representation for the product*/
  89. % /*Maybe we should check for a zero*/
  90. (<<for each y in cdr u do x := dipprod(x,y); x>>) where x = car u;
  91. put('times,'dipfn,'dipfnprod);
  92. put('times2,'dipfn,'dipfnprod);
  93. expr procedure dipfndif u;
  94. % /*U is a list of two dip expressions. Result is the distributive
  95. % polynomial representation for the difference*/
  96. dipsum(car u,dipneg cadr u);
  97. put('difference,'dipfn,'dipfndif);
  98. expr procedure dipfnpow u;
  99. % /*U is a pair of dip expressions. Result is the distributive poly
  100. % representation for the first raised to the second power*/
  101. (if not fixp n or n<0
  102. then typerr(n,"distributive polynomial exponent")
  103. else if n=0 then if dipzero!? v then rerror(dipoly,1,"0**0 invalid")
  104. else w
  105. else if dipzero!? v or n=1 then v
  106. else if dipzero!? dipmred v
  107. then dipfmon(bcpow(diplbc v,n),intevprod(n,dipevlmon v))
  108. else <<while n>0 do
  109. <<if not evenp n then w := dipprod(w,v);
  110. n := n/2;
  111. if n>0 then v := dipprod(v,v)>>;
  112. w>>)
  113. where n := dip2a cadr u, v := car u,
  114. w := dipfmon(a2bc 1,evzero());
  115. put('expt,'dipfn,'dipfnpow);
  116. expr procedure dipfnneg u;
  117. % /*U is a list of one dip expression. Result is the distributive
  118. % polynomial representation for the negative*/
  119. (if dipzero!? v then v
  120. else dipmoncomp(bcneg diplbc v,dipevlmon v,dipmred v))
  121. where v = car u;
  122. put('minus,'dipfn,'dipfnneg);
  123. expr procedure dipfnquot u;
  124. % /*U is a list of two dip expressions. Result is the distributive
  125. % polynomial representation for the quotient*/
  126. if dipzero!? cadr u or not dipzero!? dipmred cadr u
  127. or not evzero!? dipevlmon cadr u
  128. then typerr(dip2a cadr u,"distributive polynomial denominator")
  129. else dipfnquot1(car u,diplbc cadr u);
  130. expr procedure dipfnquot1(u,v);
  131. if dipzero!? u then u
  132. else dipmoncomp(bcquot(diplbc u,v),
  133. dipevlmon u,
  134. dipfnquot1(dipmred u,v));
  135. put('quotient,'dipfn,'dipfnquot);
  136. endmodule;
  137. module bcoeff; % Computation of base coefficients.
  138. %/*Definitions of base coefficient operations for distributive
  139. % polynomial package. We assume that only field elements are used, but
  140. % no check is made for this. In this module, a standard quotient
  141. % coefficient is assumed*/
  142. %/*Authors: R. Gebauer, A. C. Hearn, H. Kredel*/
  143. % H. Melenk: added routines for faster handling of standard case
  144. % of standard quotients representing integers.
  145. fluid '(dmode!*);
  146. symbolic procedure bcint2op(a1,a2,op);
  147. null dmode!* and
  148. 1=denr a1 and numberp (a1:=numr a1) and
  149. 1=denr a2 and numberp (a2:=numr a2) and
  150. (a1 := apply(op,list(a1,a2))) and
  151. ((if a1=0 then nil else a1) ./ 1);
  152. fluid '(!*nat);
  153. symbolic procedure bcless!? (a1,a2);
  154. % /* Base coefficient less. a1 and a2 are base coefficients.
  155. % bcless!?(a1,a2) returns a boolean expression, true if
  156. % a1 is less than a2 else false. */
  157. minusf numr addsq(a1,negsq a2);
  158. smacro procedure bcminus!? u;
  159. % /* Boolean function. Returns true if u is a negative base coeff*/
  160. minusf numr u;
  161. smacro procedure bczero!? u;
  162. % /* Returns a boolean expression, true if the base coefficient u is
  163. % zero*/
  164. null numr u;
  165. symbolic procedure bccomp (a1,a2);
  166. % /* Base coefficient compare a1 and a2 are base coefficients.
  167. % bccomp(a1,a2) compares the base coefficients a1 and a2 and returns
  168. % a digit 1 if a1 greater than a2, a digit 0 if a1 equals a2 else a
  169. % digit -1. */
  170. (if bczero!? sl then 0
  171. else if bcminus!? sl then -1
  172. else 1)
  173. where sl = bcdif(a1, a2);
  174. symbolic procedure bcfi a;
  175. % /* Base coefficient from integer. a is an integer. bcfi(a) returns
  176. % the base coefficient a. */
  177. mkbc(a,1);
  178. symbolic procedure bclcmd(u,v);
  179. % Base coefficient least common multiple of denominators.
  180. % u and v are two base coefficients. bclcmd(u,v) calculates the
  181. % least common multiple of the denominator of u and the
  182. % denominator of v and returns a base coefficient of the form
  183. % 1/lcm(denom u,denom v).
  184. if bczero!? u then mkbc(1,denr v)
  185. else if bczero!? v then mkbc(1,denr u)
  186. else mkbc(1,multf(quotf(denr u,gcdf(denr u,denr v)),denr v));
  187. symbolic procedure bclcmdprod(u,v);
  188. % Base coefficient least common multiple denominator product.
  189. % u is a basecoefficient of the form 1/integer. v is a base
  190. % coefficient. bclcmdprod(u,v) calculates (denom u/denom v)*nom v/1
  191. % and returns a base coefficient.
  192. mkbc(multf(quotf(denr u,denr v),numr v),1);
  193. symbolic procedure bcquod(u,v);
  194. % Base coefficient quotient. u and v are base coefficients.
  195. % bcquod(u,v) calculates u/v and returns a base coefficient.
  196. bcprod(u,bcinv v);
  197. symbolic procedure bcone!? u;
  198. % /* Base coefficient one. u is a base coefficient.
  199. % bcone!?(u) returns a boolean expression, true if the
  200. % base coefficient u is equal 1. */
  201. denr u = 1 and numr u = 1;
  202. symbolic procedure bcinv u;
  203. % /* Base coefficient inverse. u is a base coefficient.
  204. % bcinv(u) calculates 1/u and returns a base coefficient. */
  205. invsq u;
  206. symbolic procedure bcneg u;
  207. % /* Base coefficient negative. u is a base coefficient.
  208. % bcneg(u) returns the negative of the base coefficient
  209. % u, a base coefficient. */
  210. negsq u;
  211. symbolic procedure bcprod (u,v);
  212. % /* Base coefficient product. u and v are base coefficients.
  213. % bcprod(u,v) calculates u*v and returns a base coefficient.
  214. bcint2op(u,v,'bcnumtimes) or multsq(u,v);
  215. symbolic procedure bcnumtimes(u,v); u*v;
  216. symbolic procedure mkbc(u,v);
  217. % /* Convert u and v into u/v in lowest terms*/
  218. if v = 1 then u ./ v
  219. else if minusf v then mkbc(negf u,negf v)
  220. else quotf(u,m) ./ quotf(v,m) where m = gcdf(u,v);
  221. symbolic procedure bcquot (u,v);
  222. % /* Base coefficient quotient. u and v are base coefficients.
  223. % bcquot(u,v) calculates u/v and returns a base coefficient. */
  224. quotsq(u,v);
  225. symbolic procedure bcsum (u,v);
  226. % /* Base coefficient sum. u and v are base coefficients.
  227. % bcsum(u,v) calculates u+v and returns a base coefficient. */
  228. bcint2op(u,v,'bcnumplus) or addsq(u,v);
  229. symbolic procedure bcnumplus(u,v); u+v;
  230. symbolic procedure bcdif(u,v);
  231. % /* Base coefficient difference. u and v are base coefficients.
  232. % bcdif(u,v) calculates u-v and returns a base coefficient. */
  233. bcint2op(u,v,'bcnumdifference) or bcsum(u,bcneg v);
  234. symbolic procedure bcnumdifference(u,v); u-v;
  235. symbolic procedure bcpow(u,n);
  236. % /*Returns the base coefficient u raised to the nth power, where
  237. % n is an integer*/
  238. exptsq(u,n);
  239. symbolic procedure a2bc u;
  240. % /*Converts the algebraic (kernel) u into a base coefficient.
  241. simp!* u;
  242. symbolic procedure bc2a u;
  243. % /* Returns the prefix equivalent of the base coefficient u*/
  244. prepsq u;
  245. fluid '(!*groebigpos !*groebigneg !*groescale);
  246. !*groescale := 20;
  247. !*groebigpos:= 10** !*groescale; !*groebigneg := - 10** !*groescale;
  248. symbolic procedure bcprin u;
  249. % /* Prints a base coefficient in infix form*/
  250. begin scalar nat;
  251. nat := !*nat;
  252. !*nat := nil;
  253. if cdr u = 1 and
  254. numberp car u and
  255. (car u>!*groebigpos or car u<!*groebigneg)
  256. then bcprin2big car u
  257. else
  258. sqprint u;
  259. !*nat := nat
  260. end;
  261. symbolic procedure bcprin2big u;
  262. << if u<0 then<< prin2 "-"; u:= -u>>;
  263. bcprin2big1(u,0)>>;
  264. symbolic procedure bcprin2big1 (u,n);
  265. if u>!*groebigpos then
  266. bcprin2big1 (u/!*groebigpos,n#+!*groescale)
  267. else <<prin2 u; prin2 "e"; prin2 n>>;
  268. endmodule;
  269. module dip2a;
  270. %/* Functions for converting distributive forms into prefix forms*/
  271. %/*Authors: R. Gebauer, A. C. Hearn, H. Kredel*/
  272. expr procedure dip2a u;
  273. % /* Returns prefix equivalent of distributive polynomial u*/
  274. if dipzero!? u then 0 else dipreplus dip2a1 u;
  275. expr procedure dip2a1 u;
  276. if dipzero!? u then nil
  277. else ((if bcminus!? x then list('minus,dipretimes(bc2a bcneg x . y))
  278. else dipretimes(bc2a x . y))
  279. where x = diplbc u, y = expvec2a dipevlmon u)
  280. . dip2a1 dipmred u;
  281. expr procedure dipreplus u;
  282. if atom u then u else if null cdr u then car u else 'plus . u;
  283. expr procedure dipretimes u;
  284. % /* U is a list of prefix expressions the first of which is a number.
  285. % Result is prefix representation for their product*/
  286. if car u = 1 then if cdr u then dipretimes cdr u else 1
  287. else if null cdr u then car u
  288. else 'times . u;
  289. endmodule;
  290. module dipoly; % /*Distributive polnomial algorithms*/
  291. %/*Authors: R. Gebauer, A. C. Hearn, H. Kredel*/
  292. % modification for REDUCE 3.4: H. Melenk.
  293. fluid '(dipvars!* dipzero);
  294. symbolic procedure dipconst!? p;
  295. not dipzero!? p
  296. and dipzero!? dipmred p
  297. and evzero!? dipevlmon p;
  298. symbolic procedure dfcprint pl;
  299. % h polynomial factor list of distributive polynomials print.
  300. for each p in pl do dfcprintin p;
  301. symbolic procedure dfcprintin p;
  302. % factor with exponent print.
  303. ( if cdr p neq 1 then << prin2 " ( "; dipprint1(p1,nil); prin2 " )** ";
  304. prin2 cdr p; terprit 2 >> else << prin2 " "; dipprint p1>> )
  305. where p1:= dipmonic a2dip prepf car p;
  306. symbolic procedure dfcprin p;
  307. % print content, factors and exponents of factorized polynomial p.
  308. << terpri(); prin2 " content of factorized polynomials = ";
  309. prin2 car p;
  310. terprit 2; dfcprint cdr p >>;
  311. symbolic procedure diplcm p;
  312. % Distributive polynomial least common multiple of denomiators.
  313. % p is a distributive rational polynomial. diplcm(p) calculates
  314. % the least common multiple of the denominators and returns a
  315. % base coefficient of the form 1/lcm(denom bc1,.....,denom bci).
  316. if dipzero!? p then mkbc(1,1)
  317. else bclcmd(diplbc p, diplcm dipmred p);
  318. symbolic procedure diprectoint(p,u);
  319. % Distributive polynomial conversion rational to integral.
  320. % p is a distributive rational polynomial, u is a base coefficient
  321. % ( 1/lcm denom p ). diprectoint(p,u) returns a primitive
  322. % associate pseudo integral ( denominators are 1 ) distributive
  323. % polynomial.
  324. if bczero!? u then dipzero
  325. else if bcone!? u then p
  326. else diprectoint1(p,u);
  327. symbolic procedure diprectoint1(p,u);
  328. % Distributive polynomial conversion rational to integral internall 1.
  329. % diprectoint1 is used in diprectoint.
  330. if dipzero!? p then dipzero
  331. else dipmoncomp(bclcmdprod(u,diplbc p),dipevlmon p,
  332. diprectoint1(dipmred p,u));
  333. symbolic procedure dipresul(p1,p2);
  334. % test for fast downwards calculation
  335. % p1 and p2 are two bivariate distributive polynomials.
  336. % dipresul(p1,p2) returns the resultant of p1 and p2 with respect
  337. % respect to the first variable of the variable list (car dipvars!*).
  338. begin scalar q1,q2,q,ct;
  339. q1:=dip2a diprectoint(p1,diplcm p1);
  340. q2:=dip2a diprectoint(p2,diplcm p2);
  341. ct := time();
  342. q:= a2dip prepsq simpresultant list(q1,q2,car dipvars!*);
  343. ct := time() - ct;
  344. prin2 " resultant : "; dipprint dipmonic q; terpri();
  345. prin2 " time resultant : "; prin2 ct; terpri();
  346. end;
  347. symbolic procedure dipbcprod (p,a);
  348. % /* Distributive polynomial base coefficient product.
  349. % p is a distributive polynomial, a is a base coefficient.
  350. % dipbcprod(p,a) computes p*a, a distributive polynomial. */
  351. if bczero!? a then dipzero
  352. else if bcone!? a then p
  353. else dipbcprodin(p,a);
  354. symbolic procedure dipbcprodin (p,a);
  355. % /* Distributive polynomial base coefficient product internal.
  356. % p is a distributive polynomial, a is a base coefficient,
  357. % where a is not equal 0 and not equal 1.
  358. % dipbcprodin(p,a) computes p*a, a distributive polynomial. */
  359. if dipzero!? p then dipzero
  360. else dipmoncomp(bcprod(a, diplbc p),
  361. dipevlmon p,
  362. dipbcprodin(dipmred p, a));
  363. symbolic procedure dipdif (p1,p2);
  364. % /* Distributive polynomial difference. p1 and p2 are distributive
  365. % polynomials. dipdif(p1,p2) calculates the difference of the
  366. % two distributive polynomials p1 and p2, a distributive polynomial*/
  367. if dipzero!? p1 then dipneg p2
  368. else if dipzero!? p2 then p1
  369. else ( if sl = 1 then dipmoncomp(diplbc p1,
  370. ep1,
  371. dipdif(dipmred p1, p2) )
  372. else if sl = -1 then dipmoncomp(bcneg diplbc p2,
  373. ep2,
  374. dipdif(p1,dipmred p2))
  375. else ( if bczero!? al
  376. then dipdif(dipmred p1, dipmred p2)
  377. else dipmoncomp(al,
  378. ep1,
  379. dipdif(dipmred p1,
  380. dipmred p2) )
  381. ) where al = bcdif(diplbc p1, diplbc p2)
  382. ) where sl = evcomp(ep1, ep2)
  383. where ep1 = dipevlmon p1, ep2 = dipevlmon p2;
  384. symbolic procedure diplength p;
  385. % /* Distributive polynomial length. p is a distributive
  386. % polynomial. diplength(p) returns the number of terms
  387. % of the distributive polynomial p, a digit.*/
  388. if dipzero!? p then 0 else 1 + diplength dipmred p;
  389. symbolic procedure diplistsum pl;
  390. % /* Distributive polynomial list sum. pl is a list of distributive
  391. % polynomials. diplistsum(pl) calculates the sum of all polynomials
  392. % and returns a list of one distributive polynomial. */
  393. if null pl or null cdr pl then pl
  394. else diplistsum(dipsum(car pl, cadr pl) . diplistsum cddr pl);
  395. symbolic procedure diplmerge (pl1,pl2);
  396. % /* Distributive polynomial list merge. pl1 and pl2 are lists
  397. % of distributive polynomials where pl1 and pl2 are in non
  398. % decreasing order. diplmerge(pl1,pl2) returns the merged
  399. % distributive polynomial list of pl1 and pl2. */
  400. if null pl1 then pl2
  401. else if null pl2 then pl1
  402. else ( if sl >= 0 then cpl1 . diplmerge(cdr pl1, pl2)
  403. else cpl2 . diplmerge(cdr pl2, pl1)
  404. ) where sl = evcomp(ep1, ep2)
  405. where ep1 = dipevlmon cpl1, ep2 = dipevlmon cpl2
  406. where cpl1 = car pl1, cpl2 = car pl2;
  407. symbolic procedure diplsort pl;
  408. % /* Distributive polynomial list sort. pl is a list of
  409. % distributive polynomials. diplsort(pl) returns the
  410. % sorted distributive polynomial list of pl.
  411. sort(pl, function dipevlcomp);
  412. symbolic procedure dipevlcomp (p1,p2);
  413. % /* Distributive polynomial exponent vector leading monomial
  414. % compare. p1 and p2 are distributive polynomials.
  415. % dipevlcomp(p1,p2) returns a boolean expression true if the
  416. % distributive polynomial p1 is smaller or equal the distributive
  417. % polynomial p2 else false. */
  418. not evcompless!?(dipevlmon p1, dipevlmon p2);
  419. symbolic procedure dipmonic p;
  420. % /* Distributive polynomial monic. p is a distributive
  421. % polynomial. dipmonic(p) computes p/lbc(p) if p is
  422. % not equal dipzero and returns a distributive
  423. % polynomial, else dipmonic(p) returns dipzero. */
  424. if dipzero!? p then p
  425. else dipbcprod(p, bcinv diplbc p);
  426. symbolic procedure dipneg p;
  427. % /* Distributive polynomial negative. p is a distributive
  428. % polynomial. dipneg(p) returns the negative of the distributive
  429. % polynomial p, a distributive polynomial. */
  430. if dipzero!? p then p
  431. else dipmoncomp ( bcneg diplbc p,
  432. dipevlmon p,
  433. dipneg dipmred p );
  434. symbolic procedure dipone!? p;
  435. % /* Distributive polynomial one. p is a distributive polynomial.
  436. % dipone!?(p) returns a boolean value. If p is the distributive
  437. % polynomial one then true else false. */
  438. not dipzero!? p
  439. and dipzero!? dipmred p
  440. and evzero!? dipevlmon p
  441. and bcone!? diplbc p;
  442. symbolic procedure dippairsort pl;
  443. % /* Distributive polynomial list pair merge sort. pl is a list
  444. % of distributive polynomials. dippairsort(pl) returns the
  445. % list of merged and in non decreasing order sorted
  446. % distributive polynomials. */
  447. if null pl or null cdr pl then pl
  448. else diplmerge(diplmerge( car(pl) . nil, cadr(pl) . nil ),
  449. dippairsort cddr pl);
  450. symbolic procedure dipprod (p1,p2);
  451. % /* Distributive polynomial product. p1 and p2 are distributive
  452. % polynomials. dipprod(p1,p2) calculates the product of the
  453. % two distributive polynomials p1 and p2, a distributive polynomial*/
  454. if diplength p1 <= diplength p2 then dipprodin(p1, p2)
  455. else dipprodin(p2, p1);
  456. symbolic procedure dipprodin (p1,p2);
  457. % /* Distributive polynomial product internal. p1 and p2 are distrib
  458. % polynomials. dipprod(p1,p2) calculates the product of the
  459. % two distributive polynomials p1 and p2, a distributive polynomial*/
  460. if dipzero!? p1 or dipzero!? p2 then dipzero
  461. else ( dipmoncomp(bcprod(bp1, diplbc p2),
  462. evsum(ep1, dipevlmon p2),
  463. dipsum(dipprodin(dipfmon(bp1, ep1),
  464. dipmred p2),
  465. dipprodin(dipmred p1, p2) ) )
  466. ) where bp1 = diplbc p1,
  467. ep1 = dipevlmon p1;
  468. symbolic procedure dipprodls (p1,p2);
  469. % /* Distributive polynomial product. p1 and p2 are distributive
  470. % polynomials. dipprod(p1,p2) calculates the product of the
  471. % two distributive polynomials p1 and p2, a distributive polynomial
  472. % using distributive polynomials list sum (diplistsum). */
  473. if dipzero!? p1 or dipzero!? p2 then dipzero
  474. else car diplistsum if diplength p1 <= diplength p2
  475. then dipprodlsin(p1, p2)
  476. else dipprodlsin(p2, p1);
  477. symbolic procedure dipprodlsin (p1,p2);
  478. % /* Distributive polynomial product. p1 and p2 are distributive
  479. % polynomials. dipprod(p1,p2) calculates the product of the
  480. % two distributive polynomials p1 and p2, a distributive polynomial
  481. % using distributive polynomials list sum (diplistsum). */
  482. if dipzero!? p1 or dipzero!? p2 then nil
  483. else ( dipmoncomp(bcprod(bp1, diplbc p2),
  484. evsum(ep1, dipevlmon p2),
  485. car dipprodlsin(dipfmon(bp1, ep1),
  486. dipmred p2))
  487. . dipprodlsin(dipmred p1, p2)
  488. ) where bp1 = diplbc p1,
  489. ep1 = dipevlmon p1;
  490. symbolic procedure dipsum (p1,p2);
  491. % /* Distributive polynomial sum. p1 and p2 are distributive
  492. % polynomials. dipsum(p1,p2) calculates the sum of the
  493. % two distributive polynomials p1 and p2, a distributive polynomial*/
  494. if dipzero!? p1 then p2
  495. else if dipzero!? p2 then p1
  496. else ( if sl = 1 then dipmoncomp(diplbc p1,
  497. ep1,
  498. dipsum(dipmred p1, p2) )
  499. else if sl = -1 then dipmoncomp(diplbc p2,
  500. ep2,
  501. dipsum(p1,dipmred p2))
  502. else ( if bczero!? al then dipsum(dipmred p1,
  503. dipmred p2)
  504. else dipmoncomp(al,
  505. ep1,
  506. dipsum(dipmred p1,
  507. dipmred p2) )
  508. ) where al = bcsum(diplbc p1, diplbc p2)
  509. ) where sl = evcomp(ep1, ep2)
  510. where ep1 = dipevlmon p1, ep2 = dipevlmon p2;
  511. endmodule;
  512. module dipvars;
  513. %/* Determine distributive polynomial variables in a prefix form*/
  514. %/*Authors: R. Gebauer, A. C. Hearn, H. Kredel*/
  515. expr procedure dipvars u;
  516. % /* Returns list of variables in prefix form u*/
  517. dipvars1(u,nil);
  518. expr procedure dipvars1(u,v);
  519. if atom u then if constantp u or u memq v then v else u . v
  520. else if idp car u and get(car u,'dipfn)
  521. then dipvarslist(cdr u,v)
  522. else if u memq v then v
  523. else u . v;
  524. expr procedure dipvarslist(u,v);
  525. if null u then v
  526. else dipvarslist(cdr u,union(dipvars car u,v));
  527. endmodule;
  528. module expvec;
  529. % /*Specific support for distributive polynomial exponent vectors*/
  530. % /* Authors: R. Gebauer, A. C. Hearn, H. Kredel */
  531. % We assume here that an exponent vector is a list of integers. This
  532. % version uses small integer arithmetic on the individual exponents
  533. % and assumes that a compiled function can be dynamically redefined*/
  534. % Modification H. Melenk (August 1988)
  535. % 1. Most ev-routines handle exponent vectors with variable length:
  536. % the convention is, that trailing zeros may be omitted.
  537. % 2. evcompless!? is mapped to evcomp such that each term order mode
  538. % is supported by exactly one procedure entry.
  539. % 3. complete exponent vector compare collected in separate module
  540. % TORDER (TORD33)
  541. fluid '(dipsortmode!* dipvars!*);
  542. expr procedure evperm (e1,n);
  543. % /* Exponent vector permutation. e1 is an exponent vector, n is a
  544. % index list , a list of digits. evperm(e1,n) returns a list e1
  545. % permuted in respect to n. */
  546. if null n then nil
  547. else evnth(e1, car n) . evperm(e1, cdr n);
  548. expr procedure evcons (e1,e2);
  549. % /* Exponent vector construct. e1 and e2 are exponents. evcons(e1,e2)
  550. % constructs an exponent vector. */
  551. e1 . e2;
  552. expr procedure evnth (e1,n);
  553. % /* Exponent vector n-th element. e1 is an exponent vector, n is a
  554. % digit. evnth(e1,n) returns the n-th element of e1, an exponent. */
  555. if null e1 then 0 else
  556. if n = 1 then evfirst e1 else evnth(evred e1, n - 1);
  557. expr procedure evred e1;
  558. % /* Exponent vector reductum. e1 is an exponent vector. evred(e1)
  559. % returns the reductum of the exponent vector e1. */
  560. if e1 then cdr e1 else nil;
  561. expr procedure evfirst e1;
  562. % /* Exponent vector first. e1 is an exponent vector. evfirst(e1)
  563. % returns the first element of the exponent vector e1, an exponent. */
  564. if e1 then car e1 else 0;
  565. expr procedure evsum0(n,p);
  566. % exponent vector sum version 0. n is the length of dipvars!*.
  567. % p is a distributive polynomial.
  568. if dipzero!? p then evzero1 n else
  569. evsum(dipevlmon p, evsum0(n,dipmred p));
  570. expr procedure evzero1 n;
  571. % Returns the exponent vector power representation
  572. % of length n for a zero power.
  573. begin scalar x;
  574. for i:=1: n do << x := 0 . x >>;
  575. return x
  576. end;
  577. expr procedure indexcpl(ev,n);
  578. % returns a list of indexes of non zero exponents.
  579. if null ev then ev else ( if car ev = 0 then
  580. indexcpl(cdr ev,n + 1) else
  581. ( n . indexcpl(cdr ev,n + 1)) );
  582. expr procedure evzer1!? e;
  583. % returns a boolean expression. true if e is null else false.
  584. null e;
  585. expr procedure evzero!? e;
  586. % /* Returns a boolean expression. True if all exponents are zero*/
  587. null e or car e = 0 and evzero!? cdr e;
  588. expr procedure evzero;
  589. % /* Returns the exponent vector representation for a zero power*/
  590. % for i := 1:length dipvars!* collect 0;
  591. begin scalar x;
  592. for i := 1:length dipvars!* do <<x := 0 . x>>;
  593. return x
  594. end;
  595. expr procedure mkexpvec u;
  596. % /* Returns an exponent vector with a 1 in the u place*/
  597. if not(u member dipvars!*) then typerr(u,"dipoly variable")
  598. else for each x in dipvars!* collect if x eq u then 1 else 0;
  599. expr procedure evlcm (e1,e2);
  600. % /* Exponent vector least common multiple. e1 and e2 are
  601. % exponent vectors. evlcm(e1,e2) computes the least common
  602. % multiple of the exponent vectors e1 and e2, and returns
  603. % an exponent vector. */
  604. % for each lpart in e1 each rpart in e2 collect
  605. % if lpart #> rpart then lpart else rpart;
  606. begin scalar x;
  607. while e1 and e2 do
  608. <<x := (if car e1 #> car e2 then car e1 else car e2) . x;
  609. e1 := cdr e1; e2 := cdr e2>>;
  610. return reversip x
  611. end;
  612. symbolic procedure evmtest!? (e1,e2);
  613. % /* Exponent vector multiple test. e1 and e2 are compatible exponent
  614. % vectors. evmtest!?(e1,e2) returns a boolean expression.
  615. % True if exponent vector e1 is a multiple of exponent
  616. % vector e2, else false. */
  617. if e1 and e2 then not(car e1 #< car e2) and evmtest!?(cdr e1,cdr e2)
  618. else evzero!? e2 ;
  619. expr procedure evsum (e1,e2);
  620. % /* Exponent vector sum. e1 and e2 are exponent vectors.
  621. % evsum(e1,e2) calculates the sum of the exponent vectors.
  622. % e1 and e2 componentwise and returns an exponent vector. */
  623. % for each lpart in e1 each rpart in e2 collect lpart #+ rpart;
  624. begin scalar x;
  625. while e1 and e2 do
  626. <<x := (car e1 #+ car e2) . x; e1 := cdr e1; e2 := cdr e2>>;
  627. x := reversip x;
  628. return if e1 then nconc(x,e1) else
  629. if e2 then nconc(x,e2) else x;
  630. end;
  631. expr procedure evdif (e1,e2);
  632. % /* Exponent vector difference. e1 and e2 are exponent
  633. % vectors. evdif(e1,e2) calculates the difference of the
  634. % exponent vectors e1 and e2 componentwise and returns an
  635. % exponent vector. */
  636. % for each lpart in e1 each rpart in e2 collect lpart #- rpart;
  637. begin scalar x;
  638. while e2 do
  639. <<if null e1 then e1 := '(0);
  640. x := (car e1 #- car e2) . x; e1 := cdr e1; e2 := cdr e2>>;
  641. return nconc (reversip x,e1);
  642. end;
  643. expr procedure intevprod(n,e);
  644. % /* Multiplies each element of the exponent vector u by the integer n*/
  645. for each x in e collect n #* x;
  646. expr procedure expvec2a e;
  647. % /* Returns list of prefix equivalents of exponent vector e*/
  648. expvec2a1(e,dipvars!*);
  649. expr procedure expvec2a1(u,v);
  650. % /* Sub function of expvec2a */
  651. if null u then nil
  652. else if car u = 0 then expvec2a1(cdr u,cdr v)
  653. else if car u = 1 then car v . expvec2a1(cdr u,cdr v)
  654. else list('expt,car v,car u) . expvec2a1(cdr u,cdr v);
  655. expr procedure dipevlpri(e,v);
  656. % /* Print exponent vector e in infix form. V is a boolean variable
  657. % which is true if an element in a product has preceded this one*/
  658. dipevlpri1(e,dipvars!*,v);
  659. expr procedure dipevlpri1(e,u,v);
  660. % /* Sub function of dipevlpri */
  661. if null e then nil
  662. else if car e = 0 then dipevlpri1(cdr e,cdr u,v)
  663. else <<if v then dipprin2 "*";
  664. dipprin2 car u;
  665. if car e #> 1 then <<dipprin2 "**"; dipprin2 car e>>;
  666. dipevlpri1(cdr e,cdr u,t)>>;
  667. endmodule;
  668. module torder; % Term order modes for distributive polynomials.
  669. % New interface, based on one routine per order
  670. % mode.
  671. % H. Melenk, ZIB Berlin
  672. fluid '(dipsortmode!* dipsortevcomp!* olddipsortmode!*);
  673. fluid '(vdpsortmode!* vdpsortextension!*);
  674. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  675. % switching between term order modes: TORDER statement.
  676. %
  677. symbolic procedure torder u;
  678. begin scalar oldmode,oldex;
  679. oldmode := vdpsortmode!*; oldex := vdpsortextension!*;
  680. vdpsortmode!* := reval car u;
  681. vdpsortextension!* := for each x in cdr u collect reval x;
  682. return if null oldex then oldmode
  683. else 'list . oldmode . oldex;
  684. end;
  685. put('torder,'stat,'rlis);
  686. symbolic procedure dipsortingmode u;
  687. % /* Sets the exponent vector sorting mode. Returns the previous mode*/
  688. begin scalar x,y,z;
  689. if not idp u or
  690. (not flagp(u,'dipsortmode)
  691. and null (y:= assoc(u,olddipsortmode!*)))
  692. then return typerr(u,"term ordering mode");
  693. if y then
  694. <<prin2 "**** warning: TORDER ";
  695. prin2 u;
  696. prin2 " no longer supported; using ";
  697. prin2 cdr y;
  698. prin2t " instead";
  699. u := cdr y>>;
  700. x := dipsortmode!*; dipsortmode!* := u;
  701. % saves thousands of calls to GET;
  702. dipsortevcomp!* := get(dipsortmode!*,'evcomp);
  703. if not getd dipsortevcomp!* then
  704. rerror(dipoly,2,
  705. "No compare routine for term order mode found");
  706. if (z:=get(dipsortmode!*,'evcompinit)) then apply(z,nil);
  707. return x
  708. end;
  709. olddipsortmode!*:= '((invlex . lex)(invtotaldegree . totaldegree)
  710. (totaldegree . revgradlex));
  711. flag('(lex gradlex revgradlex),'dipsortmode);
  712. put('lex,'evcomp,'evlexcomp);
  713. put('gradlex,'evcomp,'evgradlexcomp);
  714. put('revgradlex,'evcomp,'evrevgradlexcomp);
  715. symbolic procedure evcompless!?(e1,e2);
  716. % Exponent vector compare less. e1, e2 are exponent vectors
  717. % in some order. Evcompless? is a boolean function which returns
  718. % true if e1 is ordered less than e2.
  719. % Mapped to evcomp
  720. 1 = evcomp(e2,e1);
  721. symbolic procedure evcomp (e1,e2);
  722. % Exponent vector compare. e1, e2 are exponent vectors in some
  723. % order. Evcomp(e1,e2) returns the digit 0 if exponent vector e1 is
  724. % equal exponent vector e2, the digit 1 if e1 is greater than e2,
  725. % else the digit -1. This function is assigned a value by the
  726. % ordering mechanism, so is dummy for now.
  727. % IDapply would be better here, but is not within standard LISP!
  728. apply(dipsortevcomp!*,list(e1,e2));
  729. symbolic procedure evlexcomp (e1,e2);
  730. % /* Exponent vector lexicographical compare. The
  731. % exponent vectors e1 and e2 are in lexicographical
  732. % ordering. evLexComp(e1,e2) returns the digit 0 if exponent
  733. % vector e1 is equal exponent vector e2, the digit 1 if e1 is
  734. % greater than e2, else the digit -1. */
  735. if null e1 then 0
  736. else if null e2 then evlexcomp(e1,'(0))
  737. else if car e1 #- car e2 =0 then evlexcomp(cdr e1,cdr e2)
  738. else if car e1 #> car e2 then 1
  739. else -1;
  740. symbolic procedure evgradlexcomp (e1,e2);
  741. % /* Exponent vector graduated lex compare.
  742. % The exponent vectors e1 and e2 are in graduated lex
  743. % ordering. evGradLexComp(e1,e2) returns the digit 0 if exponent
  744. % vector e1 is equal exponent vector e2, the digit 1 if e1 is
  745. % greater than e2, else the digit -1. */
  746. if null e1 then 0
  747. else if null e2 then evgradlexcomp(e1,'(0))
  748. else if car e1 #- car e2 =0 then evgradlexcomp(cdr e1, cdr e2)
  749. else (if te1#-te2=0 then if car e1 #> car e2 then 1 else -1
  750. else if te1 #> te2 then 1 else -1)
  751. where te1 = evtdeg e1, te2 = evtdeg e2;
  752. symbolic procedure evrevgradlexcomp (e1,e2);
  753. % /* Exponent vector reverse graduated lex compare.
  754. % The exponent vectors e1 and e2 are in reverse graduated lex
  755. % ordering. evRevGradLexcomp(e1,e2) returns the digit 0 if exponent
  756. % vector e1 is equal exponent vector e2, the digit 1 if e1 is
  757. % greater than e2, else the digit -1. */
  758. if null e1 then 0
  759. else if null e2 then evrevgradlexcomp(e1,'(0))
  760. else if car e1 = car e2 then evrevgradlexcomp(cdr e1, cdr e2)
  761. else (if te1 = te2 then evlexcomp(e2,e1) % here lex reversed
  762. else if te1 #> te2 then 1 else -1)
  763. where te1 = evtdeg e1, te2 = evtdeg e2;
  764. symbolic procedure evtdeg e1;
  765. % /* Exponent vector total degree. e1 is an exponent vector.
  766. % evtdeg(e1) calculates the total degree of the exponent
  767. % e1 and returns an integer. */
  768. (<<while e1 do <<x := car e1 #+ x; e1 := cdr e1>>; x>>) where x = 0;
  769. % The following secion contains additional term order modes.
  770. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  771. %
  772. % gradlexgradlex
  773. %
  774. % this order can have several steps
  775. % torder gradlexgradlex,3,2,4;
  776. %
  777. flag ('(gradlexgradlex),'dipsortmode);
  778. flag ('(gradlexgradlex),'dipsortextension);
  779. put('gradlexgradlex,'evcomp,'evgradgradcomp);
  780. symbolic procedure evgradgradcomp (e1,e2);
  781. evgradgradcomp1 (e1,e2,car vdpsortextension!*,
  782. cdr vdpsortextension!*);
  783. symbolic procedure evgradgradcomp1 (e1,e2,n,nl);
  784. if null e1 then 0
  785. else if null e2 then evgradgradcomp1(e1,'(0),n,nl)
  786. else if n=0 then if null nl then evgradlexcomp(e1,e2)
  787. else evgradgradcomp1 (e1,e2,car nl,cdr nl)
  788. else if car e1 = car e2 then
  789. evgradgradcomp1(cdr e1,cdr e2,n#-1,nl)
  790. else (if te1 = te2 then if car e1 #< car e2 then 1 else -1
  791. else if te1 #> te2 then 1 else -1)
  792. where te1 = evpartdeg(e1,n), te2 = evpartdeg(e2,n);
  793. symbolic procedure evpartdeg(e1,n); evpartdeg1(e1,n,0);
  794. symbolic procedure evpartdeg1(e1,n,sum);
  795. if n = 0 or null e1 then sum
  796. else evpartdeg1(cdr e1,n #-1, car e1 #+ sum);
  797. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  798. %
  799. % gradlexrevgradlex
  800. %
  801. %
  802. flag ('(gradlexrevgradlex),'dipsortmode);
  803. flag ('(gradlexrevgradlex),'dipsortextension);
  804. put('gradlexrevgradlex,'evcomp,'evgradrevgradcomp);
  805. symbolic procedure evgradrevgradcomp (e1,e2);
  806. evgradrevgradcomp1 (e1,e2,car vdpsortextension!*);
  807. symbolic procedure evgradrevgradcomp1 (e1,e2,n);
  808. if null e1 then 0
  809. else if null e2 then evgradrevgradcomp1(e1,'(0),n)
  810. else if n=0 then evrevgradlexcomp(e1,e2)
  811. else if car e1 = car e2 then evgradrevgradcomp1(cdr e1,cdr e2,n#-1)
  812. else (if te1 = te2 then if car e1 #< car e2 then 1 else -1
  813. else if te1 #> te2 then 1 else -1)
  814. where te1 = evpartdeg(e1,n), te2 = evpartdeg(e2,n);
  815. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  816. %
  817. % LEXGRADLEX
  818. %
  819. %
  820. flag ('(lexgradlex),'dipsortmode);
  821. flag ('(lexgradlex),'dipsortextension);
  822. put('lexgradlex,'evcomp,'evlexgradlexcomp);
  823. symbolic procedure evlexgradlexcomp (e1,e2);
  824. evlexgradlexcomp1 (e1,e2,car vdpsortextension!*);
  825. symbolic procedure evlexgradlexcomp1 (e1,e2,n);
  826. if null e1 then (if evzero!? e2 then 0 else -1)
  827. else if null e2 then evlexgradlexcomp1(e1,'(0),n)
  828. else if n=0 then evgradlexcomp(e1,e2)
  829. else if car e1 = car e2 then evlexgradlexcomp1(cdr e1,cdr e2,n#-1)
  830. else if car e1 #> car e2 then 1 else -1;
  831. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  832. %
  833. % LEXREVGRADLEX
  834. %
  835. %
  836. flag ('(lexrevgradlex),'dipsortmode);
  837. flag ('(lexrevgradlex),'dipsortextension);
  838. put('lexrevgradlex,'evcomp,'evlexrevgradlexcomp);
  839. symbolic procedure evlexrevgradlexcomp (e1,e2);
  840. evlexrevgradlexcomp1 (e1,e2,car vdpsortextension!*);
  841. symbolic procedure evlexrevgradlexcomp1 (e1,e2,n);
  842. if null e1 then (if evzero!? e2 then 0 else -1)
  843. else if null e2 then evlexrevgradlexcomp1(e1,'(0),n)
  844. else if n=0 then evrevgradlexcomp(e1,e2)
  845. else if car e1 = car e2 then
  846. evlexrevgradlexcomp1(cdr e1,cdr e2,n#-1)
  847. else if car e1 #> car e2 then 1 else -1;
  848. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  849. %
  850. % WEIGHTED
  851. %
  852. %
  853. flag ('(weighted),'dipsortmode);
  854. flag ('(weighted),'dipsortextension);
  855. put('weighted,'evcomp,'evweightedcomp);
  856. symbolic procedure evweightedcomp (e1,e2);
  857. (if dg1 = dg2 then evlexcomp(e1,e2) else
  858. if dg1 #> dg2 then 1 else -1
  859. ) where dg1=evweightedcomp1(e1,vdpsortextension!*),
  860. dg2=evweightedcomp1(e2,vdpsortextension!*);
  861. symbolic procedure evweightedcomp1 (e,w);
  862. % scalar product of exponent and weight vector
  863. if null e then 0 else
  864. if null w then evweightedcomp1 (e,'(1 1 1 1 1)) else
  865. car e #* car w #+ evweightedcomp1(cdr e,cdr w);
  866. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  867. %
  868. % PRIVATE
  869. %
  870. %
  871. fluid '(dipvars!*);
  872. flag ('(private),'dipsortmode);
  873. flag ('(lexgradlex),'dipsortextension);
  874. put('private,'evcomp,'evprivatecomp);
  875. put('private,'evcompinit,'evprivateinit);
  876. fluid '(evprivate1!*,evprivate2!*,evprivatel!*,evprivatefn!*);
  877. symbolic procedure evprivateinit();
  878. begin integer n; scalar m,v1,v2,v3;
  879. n:=length dipvars!*;
  880. evprivatefn!* := car vdpsortextension!*;
  881. if null getd evprivatefn!* then
  882. rerror(dipoly,3,
  883. "Second parameter for private torder is not a function");
  884. evprivatel!* := n;
  885. evprivate1!* := mkvect n;
  886. evprivate2!* := mkvect n;
  887. % compatibility test
  888. v1 := for i:=1:n collect 1+random(50);
  889. while (null v2 or v1=v2) do
  890. v2 := for i:=1:n collect 1+random(50);
  891. v3 := ((car v1) + 1 ) . cdr v1;
  892. m := list(
  893. evprivatecomp (v1,v1),
  894. evprivatecomp (v2,v2),
  895. evprivatecomp (v1,v3),
  896. evprivatecomp (v3,v1),
  897. evprivatecomp (reverse v1,reverse v3),
  898. evprivatecomp (reverse v3,reverse v1),
  899. evprivatecomp (v1,v2)*evprivatecomp (v2,v1));
  900. if not(m='(0 0 -1 1 -1 1 -1))then
  901. rerror(dipoly,4,"Private order not admissible")
  902. end;
  903. symbolic procedure evprivatecomp (e1,e2);
  904. <<evprivatespread(e1,e2,1);
  905. apply(evprivatefn!*,list(evprivate1!*,evprivate2!*))>>;
  906. symbolic procedure evprivatespread (e1,e2,n);
  907. if n #> evprivatel!* then nil
  908. else (<<putv(evprivate1!*,n,x1);putv(evprivate2!*,n,x2);
  909. evprivatespread (y1,y2,n#+1)>>)
  910. where x1 = if e1 then car e1 else 0,
  911. x2 = if e2 then car e2 else 0,
  912. y1 = if e1 then cdr e1 else nil,
  913. y2 = if e2 then cdr e2 else nil;
  914. % symbolic procedure specimen(v1,v2);
  915. % % simulating a 2 dim lex ordering.
  916. % if getv(v1,1) < getv(v2,1) then -1 else
  917. % if getv(v1,1) > getv(v2,1) then 1 else
  918. % if getv(v1,2) < getv(v2,2) then -1 else
  919. % if getv(v1,2) > getv(v2,2) then 1 else 0;
  920. %
  921. % torder private,specimen;
  922. endmodule;
  923. module vdp2dip;
  924. imports dipoly;
  925. % create!-package('(vdp2dip vdpcom vdp2dip1),
  926. % '(contrib dipoly));
  927. % load!-package 'dipoly;
  928. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  929. %
  930. % interface for Virtual Distributive Polynomials (VDP)
  931. %
  932. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  933. % "Distributive representation" with respect to a given set of
  934. % variables ("vdpvars") means for a polynomial, that the polynomial
  935. % is regarded as a sequence of monomials, each of which is a
  936. % product of a "coefficient" and of some powers of the variables.
  937. % This internal representation is very closely connected to the
  938. % standard external (printed) representation of a polynomial in
  939. % REDUCE if nothing is factored out. The monomials are locically
  940. % ordered by a term order mode based on the ordering which is
  941. % given bye the sequence "vdpvars"; with respect to this ordering
  942. % the representation of a polynomial is unique. The "highest" term
  943. % is the car one. Monomials are represented by their coefficient
  944. % ("vbc") and by a vector of the exponents("vev") (in the order
  945. % corresponding to the vector vars). The distributive representation
  946. % is good for those algorithms, which base their decisions on the
  947. % complete ledading monomial: this representation guarantees a
  948. % fast and uniform access to the car monomial and to the reductum
  949. % (the cdr of the polynomial beginning with the cadr monomial).
  950. % The algorithms of the Groebner package are of this type. The
  951. % interface defines the distributive polynomials as abstract data
  952. % objects via their acess functions. These functions map the
  953. % distributive operations to an arbitrary real data structure
  954. % ("virtual"). The mapping of the access functions to an actual
  955. % data structure is cdrricted only by the demand, that the typical
  956. % "distributive operations" be efficient. Additionally to the
  957. % algebraic value a VDP object has a property list. So the algorithms
  958. % using the VDP interface can assign name-value-pairs to individual
  959. % polynomials. The interface is defined by a set of routines which
  960. % create and handle the distributive polynomials. In general the
  961. % car letters of the routine name classifies the data its works on:
  962. % vdp... complete virt. polynomial objects
  963. % vbc... virt. base coefficients
  964. % vev... virt. exponent vectors
  965. % 0. general control
  966. %
  967. % vdpinit(dv) initialises the vdp package for the variables
  968. % given in the list "dv". vdpinit modifies the
  969. % torder and returns the prvevious torder as its
  970. % result. vdpinit sets the global variable
  971. % vdpvars!*;
  972. % 1. conversion
  973. %
  974. % a2vdp algebraic (prefix) to vdp
  975. % f2vdp standard form to vdp
  976. % a2vbc algebraic (prefix) to vbc
  977. % vdp2a vdp to algebraic (prefix)
  978. % vdp2f vdp to standard form
  979. % vbc2a vbc to algebraic (prefix)
  980. % 2. composing/decomposing
  981. %
  982. % vdpfmon make a vdp from a vbc and an vev
  983. % vdpMonComp add a monomial (vbc and vev) to the front of a vdp
  984. % vdpAppendMon add a monomial (vbc and vev) to the bottom of a vdp
  985. % vdpMonAdd add a monomial (vbc and vev) to a vdp, not yet
  986. % knowing the place of the insertion
  987. % vdpAppendVdp concat two vdps
  988. %
  989. % vdpLbc extract leading vbc
  990. % vdpevlmon extract leading vev
  991. % vdpred reductum of vbc
  992. % vevnth nth element from exponent vector
  993. % 3. testing
  994. %
  995. % vdpZero? test vdp = 0
  996. % vdpredZero!? test rductum of vdp = 0
  997. % vdpOne? test vdp = 1
  998. % vevZero? test vev = (0 0 ... 0)
  999. % vbczero? test vbc = 0
  1000. % vbcminus? test vbc <= 0 (not decidable for algebraic vbcs)
  1001. % vbcplus? test vbc >= 0 (not decidable for algebraic vbcs)
  1002. % vbcone!? test vbc = 1
  1003. % vbcnumberp test vbc is a numeric value
  1004. % vevdivides? test if vev1 < vev2 elementwise
  1005. % vevlcompless? test ordering vev1 < vev2
  1006. % vdpvevlcomp calculate ordering vev1 / vev1: -1, 0 or +1
  1007. % vdpEqual test vdp1 = vdp2
  1008. % vdpMember member based on "vdpEqual"
  1009. % vevequal test vev1 = vev2
  1010. % 4. arithmetic
  1011. %
  1012. % 4.1 vdp arithmetic
  1013. %
  1014. % vdpsum vdp + vdp
  1015. % special routines for monomials: see above (2.)
  1016. % vdpdif vdp - vdp
  1017. % vdpprod vdp * vdp
  1018. % vdpvbcprod vbc * vdp
  1019. % vdpDivMon vdp / (vbc,vev) divisability presumed
  1020. % vdpCancelvev substitute all multiples of monomial (1,vev) in vdp by 0
  1021. % vdpLcomb1 vdp1*(vbc1,vev1) + vdp2*(vbc2,vev2)
  1022. % vdpContent calculate gcd over all vbcs
  1023. % 4.2 vbc arithmetic
  1024. %
  1025. % vbcsum vbc1 + vbc2
  1026. % vbcdif vbc1 - vbc2
  1027. % vbcneg - vbc
  1028. % vbcprod vbc1 * vbc2
  1029. % vbcquot vbc1 / vbc2 divisability assumed if domain = ring
  1030. % vbcinv 1 / vbc only usable in field
  1031. % vbcgcd gcd(vbc1,vbc2) only usable in Euclidean field
  1032. % 4.2 vev arithmetic
  1033. %
  1034. % vevsum vev1 + vev2 elementwise
  1035. % vevdif vev1 - vev2 elementwise
  1036. % vevtdeg sum over all exponents
  1037. % vevzero generate a zero vev
  1038. % 5, auxiliary
  1039. %
  1040. % vdpPutProp assign indicator-value-pair to vdp
  1041. % the property "number" is used for printing.
  1042. % vdpGetProp read value of indicator from vdp
  1043. % vdplSort sort list of polynomials with respect to ordering
  1044. % vdplSortIn sort a vdp into a sorted list of vdps
  1045. % vdpprint print a vdp together with its number
  1046. % vdpprin2t print a vdp "naked"
  1047. % vdpprin3t print a vdp with closing ";"
  1048. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1049. %
  1050. % RECCORD STRUCTURE
  1051. %
  1052. % a virtual polynomial here is a record (list) with the entries
  1053. % ('vdp <vdpevlmon> <vdplbc> <form> <plist>)
  1054. %
  1055. % 'vdp a type tag
  1056. % <vdpevlmon> the exponents of the variables in the leading
  1057. % leading monomial; the positions correspond to
  1058. % the positions in vdpvars!*. Trailing zeroes
  1059. % can be omitted.
  1060. %
  1061. % <lcoeff> the "coeffcient" of the leading monomial, which
  1062. % in general is a standard form.
  1063. %
  1064. % <form> the complete polynomial,e.g.as REDUCE standard form.
  1065. %
  1066. % <plist> an asso list for the properties of the polynomial
  1067. %
  1068. % The components should not be manipulated only via the interface
  1069. % functions and macros, so that application programs remain
  1070. % independent from the internal representation.
  1071. % The only general assumption made on <form> is, that the zero
  1072. % polynomial is represented as NIL. That is the case e.g. for both,
  1073. % REDUCE standard forms and DIPOLYs.
  1074. % Conventions for the usage:
  1075. % -------------------------
  1076. %
  1077. % vdpint has to be called prveviously to all vdp calls. The list of
  1078. % vdp paraemters is passed to vdpinit. The value of vdpvars!*
  1079. % and the current torder must remain unmodfied afterwards.
  1080. % usual are simple id's, e.g.
  1081. %
  1082. %
  1083. % Modifications to vdpvars!* during calculations
  1084. % ----------------------------------------------
  1085. %
  1086. % This mapping of vdp operations to standard forms offers the
  1087. % ability to enlarge vdpvars during the calculation in order
  1088. % to add new (intermediate) variables. Basis is the convention,
  1089. % that exponent vectors logically have an arbitrary number
  1090. % of trailing zeros. All routines processing exponent vectors
  1091. % are able to handle varying length of exponent vectors.
  1092. % A new call to vdpinit is necessary.
  1093. %
  1094. % During calculation vdpvars may be enlarged (new variables
  1095. % suffixed) without needs to modify existing polynomials; only
  1096. % korder has to be set to the new variable sequence.
  1097. % modifications to the sequence in vdpvars requires a
  1098. % new call to vdpinit and a reordering of exisiting
  1099. % polynomials, e.g. by
  1100. % vdpint newvdpvars;
  1101. % f2vdp vdp2f p1; f2vdp vdp2f p2; .....
  1102. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1103. %
  1104. % DECLARATION SECTION
  1105. %
  1106. % this module must be present during code generation for modules
  1107. % using the vdp - sf interface
  1108. fluid '(vdpvars!* intvdpvars!* secondvalue!* vdpsortmode!* !*groebrm
  1109. !*vdpinteger !*trgroeb !*trgroebs !*groebdivide pcount!*);
  1110. global '(vdpprintmax groebmonfac);
  1111. flag('(vdpprintmax),'share);
  1112. % basic internal constructor of vdp-record
  1113. smacro procedure makevdp (vbc,vev,form); list('vdp,vev,vbc,form,nil);
  1114. % basic selectors (conversions)
  1115. smacro procedure vdppoly u; cadr cddr u;
  1116. smacro procedure vdplbc u; caddr u;
  1117. smacro procedure vdpevlmon u; cadr u;
  1118. % basic tests
  1119. smacro procedure vdpzero!? u;
  1120. null u or null vdppoly u;
  1121. smacro procedure vevzero!? u;
  1122. null u or (car u = 0 and vevzero!?1 cdr u);
  1123. smacro procedure vdpone!? p;
  1124. not vdpzero!? p and vevzero!? vdpevlmon p;
  1125. % base coefficients
  1126. % manipulating of exponent vectors
  1127. smacro procedure vevdivides!? (vev1,vev2); vevmtest!? (vev2,vev1);
  1128. smacro procedure vevzero();
  1129. vevmaptozero1(vdpvars!*,nil);
  1130. smacro procedure vdpnumber f; vdpgetprop(f,'number) ;
  1131. % the code for checkpointing is factored out
  1132. % This version: NO CHECKPOINT FACILITY
  1133. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1134. %
  1135. % interface for DIPOLY polynomials as records (objects).
  1136. %
  1137. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1138. %
  1139. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1140. %
  1141. fluid '(intvdpvars!* vdpvars!* secondvalue!* vdpsfsortmode!* !*groebrm
  1142. !*vdpinteger !*trgroeb !*trgroebs !*groebdivide pcount!*
  1143. !*groebsubs);
  1144. fluid '(vdpsortmode!*);
  1145. global '(vdpprintmax groebmonfac);
  1146. flag('(vdpprintmax),'share);
  1147. fluid '(dipvars!* !*vdpinteger);
  1148. symbolic procedure dip2vdp u;
  1149. % is unsed when u can be empty
  1150. (if dipzero!? uu then makevdp(a2bc 0,nil,nil)
  1151. else makevdp(diplbc uu,dipevlmon uu,uu))
  1152. where uu = if !*groebsubs then dipsubs2 u else u;
  1153. % some simple mappings
  1154. smacro procedure makedipzero(); nil;
  1155. symbolic procedure vdpredzero!? u; dipzero!? dipmred vdppoly u;
  1156. symbolic procedure vbczero!? u; bczero!? u;
  1157. symbolic procedure vbcnumber u;
  1158. if pairp u and numberp car u and 1=cdr u then cdr u else nil;
  1159. symbolic procedure vbcfi u; bcfi u;
  1160. symbolic procedure a2vbc u; a2bc u;
  1161. symbolic procedure vbcquot(u,v); bcquot(u,v);
  1162. symbolic procedure vbcneg u; bcneg u;
  1163. symbolic procedure vbcabs u; if vbcminus!? u then bcneg u else u;
  1164. symbolic procedure vbcone!? u; bcone!? u;
  1165. symbolic procedure vbcprod (u,v); bcprod(u,v);
  1166. % initializing vdp-dip polynomial package
  1167. symbolic procedure vdpinit2(vars);
  1168. begin scalar oldorder;
  1169. oldorder := kord!*;
  1170. if null vars then rerror(dipoly,8,"Vdpinit: vdpvars not set");
  1171. vdpvars!* := dipvars!* := vars;
  1172. torder2 vdpsortmode!*;
  1173. return oldorder;
  1174. end;
  1175. symbolic procedure vdpred u;
  1176. (if dipzero!? r then makevdp(nil ./ nil,nil,makedipzero())
  1177. else makevdp(diplbc r,dipevlmon r,r))
  1178. where r = dipmred vdppoly u;
  1179. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1180. %
  1181. % coefficient handling; here we assume that coefficients are
  1182. % standard quotients;
  1183. %
  1184. symbolic procedure vbcgcd (u,v);
  1185. if denr u = 1 and denr v = 1 then
  1186. if fixp u and fixp numr v then gcdn(numr u,numr v) ./ 1
  1187. else gcdf!*(numr u,numr v) ./ 1
  1188. else 1 ./ 1;
  1189. % the following functions must be redefinable
  1190. symbolic procedure vbcplus!? u; (numberp v and v>0) where v = numr u;
  1191. symbolic procedure bcplus!? u; (numberp v and v>0) where v = numr u;
  1192. symbolic procedure vbcminus!? u;
  1193. (numberp v and v<0) where v = numr u;
  1194. symbolic procedure vbcinv u; bcinv u;
  1195. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1196. %
  1197. % conversion between forms, vdps and prefix expressions
  1198. %
  1199. % prefix to vdp
  1200. symbolic procedure a2vdp u;
  1201. if u=0 or null u then makevdp(nil ./ nil,nil,makedipzero())
  1202. else (makevdp(diplbc r,dipevlmon r,r) where r = a2dip u);
  1203. % vdp to prefix
  1204. symbolic procedure vdp2a u; dip2a vdppoly u;
  1205. symbolic procedure vbc2a u; bc2a u;
  1206. % form to vdp
  1207. symbolic procedure f2vdp(u);
  1208. if u=0 or null u then makevdp(nil ./ nil,nil,makedipzero())
  1209. else (makevdp(diplbc r,dipevlmon r,r) where r = f2dip u);
  1210. % vdp to form
  1211. symbolic procedure vdp2f u; dip2f vdppoly u;
  1212. % vdp from monomial
  1213. symbolic procedure vdpfmon (coef,vev);
  1214. makevdp(coef,vev,dipfmon(coef,vev));
  1215. % add a monomial to a vdp in front (new vev and coeff)
  1216. symbolic procedure vdpmoncomp(coef,vev,vdp);
  1217. if vdpzero!? vdp then vdpfmon(coef,vev)
  1218. else
  1219. if vbczero!? coef then vdp
  1220. else
  1221. makevdp(coef,vev,dipmoncomp(coef,vev,vdppoly vdp));
  1222. %add a monomial to the end of a vdp (vev remains unchanged)
  1223. symbolic procedure vdpappendmon(vdp,coef,vev);
  1224. if vdpzero!? vdp then vdpfmon(coef,vev)
  1225. else
  1226. if vbczero!? coef then vdp
  1227. else
  1228. makevdp(vdplbc vdp,vdpevlmon vdp,
  1229. dipsum(vdppoly vdp,dipfmon(coef,vev)));
  1230. % add monomial to vdp, place of new monomial still unknown
  1231. symbolic procedure vdpmonadd(coef,vev,vdp);
  1232. if vdpzero!? vdp then vdpfmon(coef,vev) else
  1233. (if c = 1 then vdpmoncomp(coef,vev,vdp) else
  1234. if c = -1 then makevdp (vdplbc vdp,vdpevlmon vdp,
  1235. dipsum(vdppoly vdp,dipfmon(coef,vev)))
  1236. else vdpsum(vdp,vdpfmon(coef,vev))
  1237. ) where c = vevcomp(vev,vdpevlmon vdp);
  1238. symbolic procedure vdpzero(); a2vdp 0;
  1239. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1240. %
  1241. % comparing of exponent vectors
  1242. %
  1243. %
  1244. symbolic procedure vdpvevlcomp (p1,p2);
  1245. dipevlcomp (vdppoly p1,vdppoly p2);
  1246. symbolic procedure vevilcompless!?(e1,e2); 1 = evilcomp(e2,e1);
  1247. symbolic procedure vevilcomp (e1,e2); evilcomp (e1,e2);
  1248. symbolic procedure vevcompless!?(e1,e2); 1 = evcomp(e2,e1);
  1249. symbolic procedure vevcomp (e1,e2); evcomp (e1,e2);
  1250. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1251. %
  1252. % routines traversing the "coefficients"
  1253. %
  1254. % CONTENT of a vdp
  1255. % The content is the gcd of all coefficients.
  1256. symbolic procedure vdpcontent d;
  1257. if vdpzero!? d then a2bc 0 else
  1258. <<d := vdppoly d;
  1259. dipnumcontent(dipmred d,diplbc d)>>;
  1260. symbolic procedure vdpcontent1(d,c); dipnumcontent(vdppoly d,c);
  1261. symbolic procedure dipnumcontent(d,c);
  1262. if bcone!? c or dipzero!? d then c
  1263. else dipnumcontent(dipmred d,vbcgcd(c,diplbc d));
  1264. symbolic procedure dipcontenti p;
  1265. % the content is a pair of the lcm of the coefficients and the
  1266. % exponent list of the common monomial factor.
  1267. if dipzero!? p then 1 else
  1268. (if dipzero!? rp then diplbc p .
  1269. (if !*groebrm then dipevlmon p else nil)
  1270. else
  1271. dipcontenti1(diplbc p,
  1272. if !*groebrm then dipevlmon p else nil,rp) )
  1273. where rp=dipmred p;
  1274. symbolic procedure dipcontenti1 (n,ev,p1);
  1275. if dipzero!? p1 then n . ev
  1276. else begin scalar nn;
  1277. nn := vbcgcd (n,diplbc p1);
  1278. if ev then ev := dipcontevmin(dipevlmon p1,ev);
  1279. if bcone!? nn and null ev then return nn . nil
  1280. else return dipcontenti1 (nn,ev,dipmred p1)
  1281. end;
  1282. % CONTENT and MONFAC (if groebrm on)
  1283. symbolic procedure vdpcontenti d;
  1284. vdpcontent d . if !*groebrm then vdpmonfac d else nil;
  1285. symbolic procedure vdpmonfac d; dipmonfac vdppoly d;
  1286. symbolic procedure dipmonfac p;
  1287. % exponent list of the common monomial factor.
  1288. if dipzero!? p or not !*groebrm then evzero()
  1289. else (if dipzero!? rp then dipevlmon p
  1290. else dipmonfac1(dipevlmon p,rp) ) where rp=dipmred p;
  1291. symbolic procedure dipmonfac1(ev,p1);
  1292. if dipzero!? p1 or evzero!? ev then ev
  1293. else dipmonfac1(dipcontevmin(ev,dipevlmon p1),dipmred p1);
  1294. % vdpCoeffcientsFromDomain!?
  1295. symbolic procedure vdpcoeffcientsfromdomain!? w;
  1296. dipcoeffcientsfromdomain!? vdppoly w;
  1297. symbolic procedure dipcoeffcientsfromdomain!? w;
  1298. if dipzero!? w then t else
  1299. (if denr v = 1 and domainp numr v then
  1300. dipcoeffcientsfromdomain!? dipmred w
  1301. else nil) where v =diplbc w;
  1302. symbolic procedure vdplength f; diplength vdppoly f;
  1303. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1304. %
  1305. % polynomial operations:
  1306. % coefficient normalization and reduction of monomial
  1307. % factors
  1308. %
  1309. symbolic procedure vdpequal(p1,p2);
  1310. p1 eq p2
  1311. or (n1 and n1 = n2 % number comparison is faster most times
  1312. or dipequal(vdppoly p1,vdppoly p2)
  1313. where n1 = vdpgetprop(p1,'number),
  1314. n2 = vdpgetprop(p2,'number));
  1315. symbolic procedure dipequal(p1,p2);
  1316. if dipzero!? p1 then dipzero!? p2
  1317. else if dipzero!? p2 then nil
  1318. else diplbc p1 = diplbc p2
  1319. and evequal(dipevlmon p1,dipevlmon p2)
  1320. and dipequal(dipmred p1,dipmred p2);
  1321. symbolic procedure evequal(e1,e2);
  1322. % test equality with variable length exponent vectors
  1323. if null e1 and null e2 then t
  1324. else if null e1 then evequal('(0),e2)
  1325. else if null e2 then evequal(e1,'(0))
  1326. else 0=(car e1 #- car e2) and evequal(cdr e1,cdr e2);
  1327. symbolic procedure vdplcm p; diplcm vdppoly p;
  1328. symbolic procedure vdprectoint(p,q); dip2vdp diprectoint(vdppoly p,q);
  1329. symbolic procedure vdpsimpcont(p);
  1330. begin scalar r;
  1331. r := vdppoly p;
  1332. if dipzero!? r then return p;
  1333. r := dipsimpcont r;
  1334. p := dip2vdp cdr r; % the polynomial
  1335. r := car r; % the monomial factor if any
  1336. if not evzero!? r then vdpputprop(p,'monfac,r);
  1337. return p;
  1338. end;
  1339. symbolic procedure dipsimpcont (p);
  1340. if !*vdpinteger or not !*groebdivide then dipsimpconti p
  1341. else dipsimpcontr p;
  1342. % routines for integer coefficient case:
  1343. % calculation of contents and dividing all coefficients by it
  1344. symbolic procedure dipsimpconti (p);
  1345. % calculate the contents of p and divide all coefficients by it
  1346. begin scalar co,lco,res,num;
  1347. if dipzero!? p then return nil . p;
  1348. co := bcfi 1;
  1349. co := if !*groebdivide then dipcontenti p
  1350. else if !*groebrm then co . dipmonfac p
  1351. else co . nil;
  1352. num := car co;
  1353. if not bcplus!? num then num := bcneg num;
  1354. if not bcplus!? diplbc p then num := bcneg num;
  1355. if bcone!? num and cdr co = nil then return nil . p;
  1356. lco := cdr co;
  1357. if groebmonfac neq 0 then lco := dipcontlowerev cdr co;
  1358. res := p;
  1359. if not(bcone!? num and lco = nil) then
  1360. res := dipreduceconti (p,num,lco);
  1361. if null cdr co then return nil . res;
  1362. lco := evdif(cdr co,lco);
  1363. return(if lco and not evzero!? evdif(dipevlmon res,lco)
  1364. then lco else nil).res;
  1365. end;
  1366. symbolic procedure vdpreduceconti (p,co,vev);
  1367. % divide polynomial p by monomial from co and vev
  1368. vdpdivmon(p,co,vev);
  1369. % divide all coefficients of p by cont
  1370. symbolic procedure dipreduceconti (p,co,ev);
  1371. if dipzero!? p
  1372. then makedipzero()
  1373. else
  1374. dipmoncomp ( bcquot (diplbc p,co),
  1375. if ev then evdif(dipevlmon p,ev)
  1376. else dipevlmon p,
  1377. dipreduceconti (dipmred p,co,ev));
  1378. % routines for rational coefficient case:
  1379. % calculation of contents and dividing all coefficients by it
  1380. symbolic procedure dipsimpcontr (p);
  1381. % calculate the contents of p and divide all coefficients by it
  1382. begin scalar co,lco,res;
  1383. if dipzero!? p then return nil . p;
  1384. co := dipcontentr p;
  1385. if bcone!? diplbc p and co = nil then return nil . p;
  1386. lco := dipcontlowerev co;
  1387. res := p;
  1388. if not(bcone!? diplbc p and lco = nil) then
  1389. res := dipreducecontr (p,bcinv diplbc p,lco);
  1390. return (if co then evdif(co,lco) else nil) . res;
  1391. end;
  1392. symbolic procedure dipcontentr p;
  1393. % the content is the exponent list of the common monomial factor.
  1394. (if dipzero!? rp then
  1395. (if !*groebrm then dipevlmon p else nil)
  1396. else
  1397. dipcontentr1(if !*groebrm then dipevlmon p else nil,rp) )
  1398. where rp=dipmred p;
  1399. symbolic procedure dipcontentr1 (ev,p1);
  1400. if dipzero!? p1 then ev
  1401. else begin
  1402. if ev then ev := dipcontevmin(dipevlmon p1,ev);
  1403. if null ev then return nil
  1404. else return dipcontentr1 (ev,dipmred p1)
  1405. end;
  1406. % divide all coefficients of p by cont
  1407. symbolic procedure dipreducecontr (p,co,ev);
  1408. if dipzero!? p
  1409. then makedipzero()
  1410. else
  1411. dipmoncomp ( bcprod (diplbc p,co),
  1412. if ev then evdif(dipevlmon p,ev)
  1413. else dipevlmon p,
  1414. dipreducecontr (dipmred p,co,ev));
  1415. symbolic procedure dipcontevmin (e1,e2);
  1416. % calculates the minimum of two exponents; if one is shorter, trailing
  1417. % zeroes are assumed.
  1418. % e1 is an exponent vector. e2 is a list of exponents
  1419. begin scalar res;
  1420. while e1 and e2 do
  1421. <<res := (if ilessp(car e1,car e2) then car e1 else car e2)
  1422. . res;
  1423. e1 := cdr e1; e2 := cdr e2>>;
  1424. while res and 0=car res do res := cdr res;
  1425. return reversip res;
  1426. end;
  1427. symbolic procedure dipcontlowerev (e1);
  1428. % subtract a 1 from those elements of an exponent vector which
  1429. % are greater than 1.
  1430. % e1 is a list of exponents, the result is an exponent vector.
  1431. begin scalar res;
  1432. while e1 do
  1433. <<res := (if igreaterp(car e1,0) then car e1 - 1 else 0)
  1434. . res;
  1435. e1 := cdr e1>>;
  1436. while res and 0 = car res do res := cdr res;
  1437. if res and !*trgroebs then
  1438. <<prin2 "***** exponent reduction:";
  1439. prin2t reverse res>>;
  1440. return reversip res;
  1441. end;
  1442. symbolic procedure dipappendmon(dip,bc,ev);
  1443. append(dip,dipfmon(bc,ev));
  1444. smacro procedure dipnconcmon(dip,bc,ev);
  1445. nconc(dip,dipfmon(bc,ev));
  1446. smacro procedure dipappenddip(dip1,dip2); append(dip1,dip2);
  1447. smacro procedure dipnconcdip(dip1,dip2); nconc(dip1,dip2);
  1448. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1449. %
  1450. % basic polynomial arithmetic:
  1451. %
  1452. symbolic procedure vdpsum(d1,d2);
  1453. dip2vdp dipsum(vdppoly d1,vdppoly d2);
  1454. symbolic procedure vdpdif(d1,d2);
  1455. dip2vdp dipdif(vdppoly d1,vdppoly d2);
  1456. symbolic procedure vdpprod(d1,d2);
  1457. dip2vdp dipprod(vdppoly d1,vdppoly d2);
  1458. % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
  1459. %
  1460. % linear combination: the Buchberger Workhorse
  1461. %
  1462. % LCOMB1: calculate mon1 * vdp1 + mon2 * vdp2
  1463. symbolic procedure vdpilcomb1(d1,vbc1,vev1,d2,vbc2,vev2);
  1464. dip2vdp dipilcomb1 (vdppoly d1,vbc1,vev1,vdppoly d2,vbc2,vev2);
  1465. symbolic procedure dipilcomb1 (p1,bc1,ev1,p2,bc2,ev2);
  1466. % same asl dipILcomb, exponent vectors multiplied in already
  1467. begin scalar ep1,ep2,sl,res,sum,z1,z2,p1new,p2new,lptr,bptr;
  1468. z1 := not evzero!? ev1; z2 := not evzero!? ev2;
  1469. p1new := p2new := t;
  1470. lptr := bptr := res := makedipzero();
  1471. loop:
  1472. if p1new then
  1473. << if dipzero!? p1 then
  1474. return if dipzero!? p2 then res else
  1475. dipnconcdip(res, dipprod(p2,dipfmon(bc2,ev2)));
  1476. ep1 := dipevlmon p1;
  1477. if z1 then ep1 := evsum(ep1,ev1);
  1478. p1new := nil;>>;
  1479. if p2new then
  1480. << if dipzero!? p2 then
  1481. return dipnconcdip(res, dipprod(p1,dipfmon(bc1,ev1)));
  1482. ep2 := dipevlmon p2;
  1483. if z2 then ep2 := evsum(ep2,ev2);
  1484. p2new := nil; >>;
  1485. sl := evcomp(ep1, ep2);
  1486. if sl = 1 then
  1487. << lptr := dipnconcmon (bptr,
  1488. bcprod(diplbc p1,bc1),
  1489. ep1);
  1490. bptr := dipmred lptr;
  1491. p1 := dipmred p1; p1new := t;
  1492. >>
  1493. else if sl = -1 then
  1494. << lptr := dipnconcmon (bptr,
  1495. bcprod(diplbc p2,bc2),
  1496. ep2);
  1497. bptr := dipmred lptr;
  1498. p2 := dipmred p2; p2new := t;
  1499. >>
  1500. else
  1501. << sum := bcsum (bcprod(diplbc p1,bc1),
  1502. bcprod(diplbc p2,bc2));
  1503. if not bczero!? sum then
  1504. << lptr := dipnconcmon(bptr,sum,ep1);
  1505. bptr := dipmred lptr>>;
  1506. p1 := dipmred p1; p2 := dipmred p2;
  1507. p1new := p2new := t;
  1508. >>;
  1509. if dipzero!? res then <<res := bptr := lptr>>; % initial
  1510. goto loop;
  1511. end;
  1512. symbolic procedure vdpvbcprod(p,a); dip2vdp dipbcprod(vdppoly p,a);
  1513. symbolic procedure vdpdivmon(p,c,vev);
  1514. dip2vdp dipdivmon(vdppoly p,c,vev);
  1515. symbolic procedure dipdivmon(p,bc,ev);
  1516. % divides a polynomial by a monomial
  1517. % we are sure that the monomial ev is a factor of p
  1518. if dipzero!? p
  1519. then makedipzero()
  1520. else
  1521. dipmoncomp ( bcquot(diplbc p,bc),
  1522. evdif(dipevlmon p,ev),
  1523. dipdivmon (dipmred p,bc,ev));
  1524. symbolic procedure vdpcancelmvev(f,vev);
  1525. dip2vdp dipcancelmev(vdppoly f,vev);
  1526. symbolic procedure dipcancelmev(f,ev);
  1527. % cancels all monomials in f which are multiples of ev
  1528. dipcancelmev1(f,ev,makedipzero());
  1529. symbolic procedure dipcancelmev1(f,ev,res);
  1530. if dipzero!? f then res
  1531. else if evmtest!?(dipevlmon f,ev) then
  1532. dipcancelmev1(dipmred f,ev,res)
  1533. else dipcancelmev1(dipmred f,ev,
  1534. % dipAppendMon(res,diplbc f,dipevlmon f));
  1535. dipnconcmon(res,diplbc f,dipevlmon f));
  1536. % some prehistoric routines needed in resultant operation
  1537. symbolic procedure vevsum0(n,p);
  1538. % exponent vector sum version 0. n is the length of vdpvars!*.
  1539. % p is a distributive polynomial.
  1540. if vdpzero!? p then vevzero1 n else
  1541. vevsum(vdpevlmon p, vevsum0(n,vdpred p));
  1542. symbolic procedure vevzero1 n;
  1543. % Returns the exponent vector power representation
  1544. % of length n for a zero power.
  1545. begin scalar x;
  1546. for i:=1: n do << x := 0 . x >>;
  1547. return x
  1548. end;
  1549. symbolic procedure vdpresimp u;
  1550. % fi domain changes, the coefficients have to be resimped
  1551. dip2vdp dipresimp vdppoly u;
  1552. symbolic procedure dipresimp u;
  1553. if null u then nil else
  1554. (for each x in u collect
  1555. <<toggle := not toggle;
  1556. if toggle then simp prepsq x else x>>
  1557. ) where toggle = t;
  1558. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1559. %
  1560. % printing of polynomials
  1561. %
  1562. symbolic procedure vdpprin2t u; << vdpprint1(u,nil,9999); terpri()>>;
  1563. symbolic procedure vdpprin3t u;
  1564. << vdpprint1(u,nil,9999); prin2t ";">>;
  1565. symbolic procedure vdpprint u;
  1566. <<vdpprin2 u; terpri()>>;
  1567. symbolic procedure vdpprin2 u;
  1568. <<(if x then <<prin2 "P("; prin2 x; prin2 "): ">>)
  1569. where x=vdpgetprop(u,'number);
  1570. vdpprint1(u,nil,vdpprintmax)>>;
  1571. symbolic procedure vdpprint1(u,v,max); vdpprint1x(vdppoly u,v,max);
  1572. symbolic procedure vdpprint1x(u,v,max);
  1573. % /* Prints a distributive polynomial in infix form.
  1574. % U is a distributive form. V is a flag which is true if a term
  1575. % has preceded current form
  1576. % max limits the number of terms to be printed
  1577. if dipzero!? u then if null v then dipprin2 0 else nil
  1578. else if max = 0 then % maximum of terms reached
  1579. << terpri();
  1580. prin2 " ### etc (";
  1581. prin2 diplength u;
  1582. prin2 " terms) ###";
  1583. terpri();>>
  1584. else begin scalar bool,w;
  1585. w := diplbc u;
  1586. if bcminus!? w then <<bool := t; w := bcneg w>>;
  1587. if bool then dipprin2 " - " else if v then dipprin2 " + ";
  1588. (if not bcone!? w or evzero!? x then<<bcprin w; dipevlpri(x,t)>>
  1589. else dipevlpri(x,nil))
  1590. where x = dipevlmon u;
  1591. vdpprint1x(dipmred u,t, max - 1)
  1592. end;
  1593. symbolic procedure dipprin2 u;
  1594. <<if posn()>69 then terprit 2 ; prin2 u>>;
  1595. symbolic procedure vdpsave u; u;
  1596. % switching between term order modes
  1597. symbolic procedure torder2 u; dipsortingmode u;
  1598. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1599. %
  1600. % additional conversion utilities
  1601. % conversion dip to standard form / standard quotient
  1602. symbolic procedure dip2f u;
  1603. (if denr v neq 1 then
  1604. <<print u;
  1605. rerror(dipoly,9,
  1606. "Distrib. poly. with rat coeff cannot be converted")>>
  1607. else numr v) where v = dip2sq u;
  1608. symbolic procedure dip2sq u;
  1609. % convert a dip into a standard quotient.
  1610. if dipzero!? u then nil ./ 1
  1611. else addsq(diplmon2sq(diplbc u,dipevlmon u),dip2sq dipmred u);
  1612. symbolic procedure diplmon2sq(bc,ev);
  1613. %convert a monomial into a standard quotient.
  1614. multsq(bc,dipev2f(ev,dipvars!*) ./ 1);
  1615. symbolic procedure dipev2f(ev,vars);
  1616. if null ev then 1
  1617. else if car ev = 0 then dipev2f(cdr ev,cdr vars)
  1618. else multf(car vars .** car ev .* 1 .+ nil,
  1619. dipev2f(cdr ev,cdr vars));
  1620. % evaluate SUBS2 for the coefficients of a dip
  1621. symbolic procedure dipsubs2 u;
  1622. begin scalar v,secondvalue!*;
  1623. secondvalue!* := 1 ./ 1;
  1624. v := dipsubs21 u;
  1625. return diprectoint(v,secondvalue!*);
  1626. end;
  1627. symbolic procedure dipsubs21 u;
  1628. begin scalar c;
  1629. if dipzero!? u then return u;
  1630. c := groebsubs2 diplbc u;
  1631. if null numr c then return dipsubs21 dipmred u;
  1632. if not(denr c = 1) then
  1633. secondvalue!* := bclcmd(c,secondvalue!*);
  1634. return dipmoncomp(c,dipevlmon u,dipsubs21 dipmred u);
  1635. end;
  1636. % conversion standard form to dip
  1637. symbolic procedure f2dip u; f2dip1(u,evzero(),1 ./ 1);
  1638. symbolic procedure f2dip1 (u,ev,bc);
  1639. % f to dip conversion: scan the standard form. ev
  1640. % and bc are the exponent and coefficient parts collected
  1641. % so far from higher parts.
  1642. if null u then nil
  1643. else if domainp u then dipfmon(multsq(bc,u ./ 1),ev)
  1644. else dipsum(f2dip2(mvar u,ldeg u,lc u,ev,bc),
  1645. f2dip1(red u,ev,bc));
  1646. symbolic procedure f2dip2(var,dg,c,ev,bc);
  1647. % f to dip conversion:
  1648. % multiply leading power either into exponent vector
  1649. % or into the base coefficient.
  1650. <<if ev1 then ev := ev1
  1651. else bc := multsq(bc,var.**dg.*1 .+nil./1);
  1652. f2dip1(c,ev,bc)>>
  1653. where ev1=if memq(var,dipvars!*) then
  1654. evinsert(ev,var,dg,dipvars!*) else nil;
  1655. symbolic procedure evinsert(ev,v,dg,vars);
  1656. % f to dip conversion:
  1657. % Insert the "dg" into the ev in the place of variable v.
  1658. if null ev or null vars then nil
  1659. else if car vars eq v then dg . cdr ev
  1660. else car ev . evinsert(cdr ev,v,dg,cdr vars);
  1661. endmodule;
  1662. module vdpcom;
  1663. % common routines to all vdp mappings
  1664. fluid '(intvdpvars!* vdpvars!* secondvalue!* vdpsortmode!* !*groebrm
  1665. !*vdpinteger !*trgroeb !*groebdivide pcount!*
  1666. vdpsortextension!* );
  1667. global '(vdpprintmax);
  1668. flag('(vdpprintmax),'share);
  1669. vdpprintmax := 5;
  1670. % Repeat of smacros defined in vdp2dip.
  1671. smacro procedure vdppoly u; cadr cddr u;
  1672. smacro procedure vdpzero!? u;
  1673. null u or null vdppoly u;
  1674. smacro procedure vdpevlmon u; cadr u;
  1675. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1676. %
  1677. % manipulating of exponent vectors
  1678. %
  1679. symbolic procedure vevnth (a,n);
  1680. % extract nth element from a
  1681. if null a then 0 else if n=1 then car a else vevnth(cdr a,n #- 1);
  1682. % unrolled code for zero test (very often called)
  1683. smacro procedure vevzero!? u;
  1684. null u or (car u = 0 and vevzero!?1 cdr u);
  1685. symbolic procedure vevzero!?1 u;
  1686. null u or (car u = 0 and vevzero!? cdr u);
  1687. symbolic procedure veveq(vev1,vev2);
  1688. if null vev1 then vevzero!? vev2
  1689. else if null vev2 then vevzero!? vev1
  1690. else (car vev1 = car vev2 and vevequal(cdr vev1,vev2));
  1691. symbolic procedure vevmaptozero e;
  1692. % generate an exponent vector with same length as e and zeros only
  1693. vevmaptozero1(e,nil);
  1694. symbolic procedure vevmaptozero1(e,vev);
  1695. if null e then vev else vevmaptozero1(cdr e, 0 . vev);
  1696. symbolic procedure vevmtest!? (e1,e2);
  1697. % /* Exponent vector multiple test. e1 and e2 are compatible exponent
  1698. % vectors. vevmtest?(e1,e2) returns a boolean expression.
  1699. % True if exponent vector e1 is a multiple of exponent
  1700. % vector e2, else false. */
  1701. if null e2 then t
  1702. else if null e1 then if vevzero!? e2 then t else nil
  1703. else not(car e1 #<car e2)and vevmtest!?(cdr e1,cdr e2);
  1704. symbolic procedure vevlcm (e1,e2);
  1705. % /* Exponent vector least common multiple. e1 and e2 are
  1706. % exponent vectors. vevlcm(e1,e2) computes the least common
  1707. % multiple of the exponent vectors e1 and e2, and returns
  1708. % an exponent vector. */
  1709. begin scalar x;
  1710. while e1 and e2 do
  1711. <<x := (if car e1 #> car e2 then car e1 else car e2) . x;
  1712. e1 := cdr e1; e2 := cdr e2>>;
  1713. x := reversip x;
  1714. if e1 then x := nconc(x,e1)
  1715. else if e2 then x := nconc(x,e2);
  1716. return x;
  1717. end;
  1718. symbolic procedure vevmin (e1,e2);
  1719. % Exponent vector minima
  1720. begin scalar x;
  1721. while e1 and e2 do
  1722. <<x := (if car e1 #< car e2 then car e1 else car e2) . x;
  1723. e1 := cdr e1; e2 := cdr e2>>;
  1724. while x and 0=car x do x := cdr x; % cut trailing zeros
  1725. return reversip x;
  1726. end;
  1727. symbolic procedure vevsum (e1,e2);
  1728. % /* Exponent vector sum. e1 and e2 are exponent vectors.
  1729. % vevsum(e1,e2) calculates the sum of the exponent vectors.
  1730. % e1 and e2 componentwise and returns an exponent vector. */
  1731. begin scalar x;
  1732. while e1 and e2 do
  1733. <<x := (car e1 #+ car e2) . x;e1 := cdr e1; e2 := cdr e2>>;
  1734. x := reversip x;
  1735. if e1 then x := nconc(x,e1)
  1736. else if e2 then x := nconc(x,e2);
  1737. return x;
  1738. end;
  1739. symbolic procedure vevtdeg u;
  1740. % calculate the total degree of u
  1741. if null u then 0 else car u #+ vevtdeg cdr u;
  1742. symbolic procedure vevdif (ee1,ee2);
  1743. % Exponent vector difference. e1 and e2 are exponent
  1744. % vectors. vevdif(e1,e2) calculates the difference of the
  1745. % exponent vectors e1 and e2 componentwise and returns an
  1746. % exponent vector.
  1747. begin scalar x,y,break,e1,e2;
  1748. e1 := ee1; e2 := ee2;
  1749. while e1 and e2 and not break do
  1750. <<y := (car e1 #- car e2); x := y . x;
  1751. break := y #< 0;
  1752. e1 := cdr e1; e2 := cdr e2>>;
  1753. if break or (e2 and not vevzero!? e2) then
  1754. <<print ee1; print ee2;
  1755. if getd 'backtrace then backtrace();
  1756. return rerror(dipoly,5,"Vevdif, difference would be < 0")>>;
  1757. return nconc(reversip x,e1);
  1758. end;
  1759. symbolic procedure vevdivides!?(e1,e2);
  1760. % test if e2 is a multiple of e1
  1761. null e1
  1762. or (null e2 and vevzero!? e1)
  1763. or (car e1 leq car e2 and vevdivides!?(cdr e1,cdr e2));
  1764. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1765. %
  1766. % numbering of polynomials
  1767. %
  1768. symbolic procedure vdpenumerate f;
  1769. % f is a temporary result. Prepare it for medium range storage
  1770. % and ssign a number
  1771. if vdpzero!? f then f else
  1772. << f := vdpsave f;
  1773. if not vdpgetprop(f,'number) then
  1774. f := vdpputprop(f,'number,(pcount!* := pcount!* #+ 1));
  1775. f>>;
  1776. %smacro procedure vdpNumber f;
  1777. % vdpGetProp(f,'NUMBER) ;
  1778. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1779. %
  1780. % operations on sets of polynomials
  1781. %
  1782. symbolic procedure vdpmember(p1,l);
  1783. % test membership of a polynomial in a list of polys
  1784. if null l then nil
  1785. else
  1786. if vdpequal(p1,car l) then l
  1787. else
  1788. vdpmember(p1,cdr l);
  1789. symbolic procedure vdpunion (s1,s2);
  1790. % s1 and s2 are two sets of polynomials.
  1791. % union of the sets using vdpMember as crit
  1792. if null s1 then s2
  1793. else
  1794. if vdpmember(car s1,s2) then vdpunion(cdr s1,s2)
  1795. else car s1 . vdpunion(cdr s1,s2);
  1796. symbolic procedure vdpintersection (s1,s2);
  1797. % s1 and s2 are two sets of polynomials.
  1798. % intersection of the sets using vdpMember as crit
  1799. if null s1 then nil
  1800. else
  1801. if vdpmember(car s1,s2) then car s1 . vdpunion(cdr s1,s2)
  1802. else vdpunion(cdr s1,s2);
  1803. symbolic procedure vdpsetequal!?(s1,s2);
  1804. % tests if s1 and s2 have the same polynomials as members
  1805. if not (length s1 = length s2) then nil
  1806. else vdpsetequal!?1(s1,append(s2,nil));
  1807. symbolic procedure vdpsetequal!?1(s1,s2);
  1808. % destroys its second parameter (is therefor copied when called)
  1809. if null s1 and null s2 then t
  1810. else
  1811. if null s1 or null s2 then nil
  1812. else
  1813. (if hugo then vdpsetequal!?1(cdr s1,groedeletip(car hugo,s2))
  1814. else nil) where hugo = vdpmember(car s1,s2);
  1815. symbolic procedure vdpsortedsetequal!?(s1,s2);
  1816. % tests if s1 and s2 have the same polynomials as members
  1817. % here assuming, that both sets are sorted by the same
  1818. % principles
  1819. if null s1 and null s2 then t
  1820. else
  1821. if null s1 or null s2 then nil
  1822. else
  1823. if vdpequal(car s1,car s2) then
  1824. vdpsortedsetequal!?(cdr s1,cdr s2)
  1825. else nil;
  1826. symbolic procedure vdpdisjoint!? (s1,s2);
  1827. % s1 and s2 are two sets of polynomials.
  1828. % test that there are no common members
  1829. if null s1 then t
  1830. else
  1831. if vdpmember(car s1,s2) then nil
  1832. else vdpdisjoint!?(cdr s1,s2);
  1833. symbolic procedure vdpsubset!? (s1,s2);
  1834. not length s1 > length s2 and vdpsubset!?1(s1,s2);
  1835. symbolic procedure vdpsubset!?1 (s1,s2);
  1836. % s1 and s2 are two sets of polynomials.
  1837. % test if s1 is subset of s2
  1838. if null s1 then t
  1839. else
  1840. if vdpmember(car s1,s2) then vdpsubset!?1 (cdr s1,s2)
  1841. else nil;
  1842. symbolic procedure vdpdeletemember(p,l);
  1843. % delete polynomial p from list l
  1844. if null l then nil
  1845. else
  1846. if vdpequal(p,car l) then vdpdeletemember(p,cdr l)
  1847. else car l . vdpdeletemember(p,cdr l);
  1848. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1849. %
  1850. % sorting of polynomials
  1851. %
  1852. symbolic procedure vdplsort pl;
  1853. % /* Distributive polynomial list sort. pl is a list of
  1854. % distributive polynomials. vdplsort(pl) returns the
  1855. % sorted distributive polynomial list of pl.
  1856. sort(pl, function vdpvevlcomp);
  1857. symbolic procedure vdplsortin (po,pl);
  1858. % po is a polynomial, pl is a list of polynomials.
  1859. % po is inserted into pl at its place determined by vevlcompless?.
  1860. % the result is the updated pl;
  1861. if null pl then list po
  1862. else if vevcompless!? (vdpevlmon po, vdpevlmon car pl)
  1863. then car pl . vdplsortin (po, cdr pl)
  1864. else po . pl;
  1865. symbolic procedure vdplsortinreplacing (po,pl);
  1866. % po is a polynomial, pl is a list of polynomials.
  1867. % po is inserted into pl at its place determined by vevlcompless?.
  1868. % if there is a multiple of the exponent of pl, this is deleted
  1869. % the result is the updated pl;
  1870. if null pl then list po
  1871. else if vevdivides!? (vdpevlmon po, vdpevlmon car pl)
  1872. then vdplsortinreplacing (po, cdr pl)
  1873. else if vevcompless!? (vdpevlmon po, vdpevlmon car pl)
  1874. then car pl . vdplsortinreplacing (po, cdr pl)
  1875. else po . pl;
  1876. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1877. %
  1878. % property lists for polynomials
  1879. %
  1880. symbolic procedure vdpputprop (poly,prop,val);
  1881. begin scalar c,p;
  1882. if not pairp poly or not pairp (c := cdr poly)
  1883. or not pairp (c := cdr c)
  1884. or not pairp (c := cdr c)
  1885. or not pairp (c := cdr c )
  1886. then rerror(dipoly,6,
  1887. list("vdpPutProp given a non-vdp as 1st parameter",
  1888. poly,prop,val));
  1889. p := assoc(prop,car c);
  1890. if p then rplacd(p,val)
  1891. else rplaca(c,(prop . val) . car c);
  1892. return poly;
  1893. end;
  1894. symbolic procedure vdpgetprop (poly,prop);
  1895. if null poly then nil % nil is a legal variant of vdp=0
  1896. else
  1897. if not eqcar(poly,'vdp)
  1898. then rerror(dipoly,7,
  1899. list("vdpGetProp given a non-vdp as 1st parameter",
  1900. poly,prop))
  1901. else
  1902. (if p then cdr p else nil)
  1903. where p=assoc(prop,cadr cdddr poly);
  1904. symbolic procedure vdpremallprops u;
  1905. begin scalar c;
  1906. if not pairp u or not pairp (c := cdr u)
  1907. or not pairp (c := cdr c)
  1908. or not pairp (c := cdr c)
  1909. or not pairp (c := cdr c)
  1910. then return u;
  1911. rplaca(c,nil); return u;
  1912. end;
  1913. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1914. %
  1915. % Groebner interface to power substitution
  1916. fluid '(!*sub2);
  1917. symbolic procedure groebsubs2 q;
  1918. (subs2 q) where !*sub2=t;
  1919. % and a special print
  1920. symbolic procedure vdpprintshort u;
  1921. begin scalar m;
  1922. m := vdpprintmax;
  1923. vdpprintmax:= 2;
  1924. vdpprint u;
  1925. vdpprintmax:=m;
  1926. end;
  1927. endmodule;
  1928. end;