groebner.red 68 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936
  1. module consel;
  2. %/*Constructors and selectors for a distributed polynomial form*/
  3. %/*Authors: R. Gebauer, A. C. Hearn, H. Kredel*/
  4. %/*A distributive polynomial has the following informal syntax:
  5. %
  6. % <dipoly> ::= dipzero
  7. % | <exponent vector> . <base coefficient> . <dipoly>*/
  8. %define dipzero = 'nil;
  9. fluid '(dipzero);
  10. %/*Until we understand how to define something to nil*/
  11. smacro procedure dipzero!? u; null u;
  12. smacro procedure diplbc p;
  13. % /* Distributive polynomial leading base coefficient.
  14. % p is a distributive polynomial. diplbc(p) returns
  15. % the leading base coefficient of p. */
  16. cadr p;
  17. smacro procedure dipmoncomp (a,e,p);
  18. % /* Distributive polynomial monomial composition. a is a base
  19. % coefficient, e is an exponent vector and p is a
  20. % distributive polynomial. dipmoncomp(a,e,p) returns a dis-
  21. % tributive polynomial with p as monomial reductum, e as
  22. % exponent vector of the leading monomial and a as leading
  23. % base coefficient. */
  24. e . a . p;
  25. smacro procedure dipevlmon p;
  26. % /* Distributive polynomial exponent vector leading monomial.
  27. % p is a distributive polynomial. dipevlmon(p) returns the
  28. % exponent vector of the leading monomial of p. */
  29. car p;
  30. smacro procedure dipfmon (a,e);
  31. % /* Distributive polynomial from monomial. a is a base coefficient
  32. % and e is an exponent vector. dipfmon(a,e) returns a
  33. % distributive polynomial with e as exponent vector and
  34. % a as base coefficient. */
  35. e . a . dipzero;
  36. smacro procedure dipnov p;
  37. % /* Distributive polynomial number of variables. p is a distributive
  38. % polynomial. dipnov(p) returns a digit, the number of variables
  39. % of the distributive polynomial p. */
  40. length car p;
  41. smacro procedure dipmred p;
  42. % /* Distributive polynomial reductum. p is a distributive polynomial
  43. % dipmred(p) returns the reductum of the distributive polynomial p,
  44. % a distributive polynomial. */
  45. cddr p;
  46. endmodule;
  47. module bcoeff; % Computation of base coefficients.
  48. %/*Definitions of base coefficient operations for distributive
  49. % polynomial package. We assume that only field elements are used, but
  50. % no check is made for this. In this module, a standard quotient
  51. % coefficient is assumed*/
  52. %/*Authors: R. Gebauer, A. C. Hearn, H. Kredel*/
  53. global '(!*nat);
  54. expr procedure bcless!? (a1,a2);
  55. % /* Base coefficient less. a1 and a2 are base coefficients.
  56. % bcless!?(a1,a2) returns a boolean expression, true if
  57. % a1 is less than a2 else false. */
  58. minusf numr addsq(a1,negsq a2);
  59. smacro procedure bcminus!? u;
  60. % /* Boolean function. Returns true if u is a negative base coeff*/
  61. minusf numr u;
  62. smacro procedure bczero!? u;
  63. % /* Returns a boolean expression, true if the base coefficient u is
  64. % zero*/
  65. null numr u;
  66. expr procedure bccomp (a1,a2);
  67. % /* Base coefficient compare a1 and a2 are base coefficients.
  68. % bccomp(a1,a2) compares the base coefficients a1 and a2 and returns
  69. % a digit 1 if a1 greater than a2, a digit 0 if a1 equals a2 else a
  70. % digit -1. */
  71. (if bczero!? sl then 0
  72. else if bcminus!? sl then -1
  73. else 1)
  74. where sl = bcdif(a1, a2);
  75. expr procedure bcfi a;
  76. % /* Base coefficient from integer. a is an integer. bcfi(a) returns
  77. % the base coefficient a. */
  78. mkbc(a,1);
  79. expr procedure bclcmd(u,v);
  80. % Base coefficient least common multiple of denominators.
  81. % u and v are two base coefficients. bclcmd(u,v) calculates the
  82. % least common multiple of the denominator of u and the
  83. % denominator of v and returns a base coefficient of the form
  84. % 1/lcm(denom u,denom v).
  85. if bczero!? u then mkbc(1,denr v)
  86. else if bczero!? v then mkbc(1,denr u)
  87. else mkbc(1,multf(quotf(denr u,gcdf(denr u,denr v)),denr v));
  88. expr procedure bclcmdprod(u,v);
  89. % Base coefficient least common multiple denominator product.
  90. % u is a basecoefficient of the form 1/integer. v is a base
  91. % coefficient. bclcmdprod(u,v) calculates (denom u/denom v)*nom v/1
  92. % and returns a base coefficient.
  93. mkbc(multf(quotf(denr u,denr v),numr v),1);
  94. expr procedure bcquod(u,v);
  95. % Base coefficient quotient. u and v are base coefficients.
  96. % bcquod(u,v) calculates u/v and returns a base coefficient.
  97. bcprod(u,bcinv v);
  98. expr procedure bcone!? u;
  99. % /* Base coefficient one. u is a base coefficient.
  100. % bcone!?(u) returns a boolean expression, true if the
  101. % base coefficient u is equal 1. */
  102. denr u = 1 and numr u = 1;
  103. expr procedure bcinv u;
  104. % /* Base coefficient inverse. u is a base coefficient.
  105. % bcinv(u) calculates 1/u and returns a base coefficient. */
  106. invsq u;
  107. expr procedure bcneg u;
  108. % /* Base coefficient negative. u is a base coefficient.
  109. % bcneg(u) returns the negative of the base coefficient
  110. % u, a base coefficient. */
  111. negsq u;
  112. expr procedure bcprod (u,v);
  113. % /* Base coefficient product. u and v are base coefficients.
  114. % bcprod(u,v) calculates u*v and returns a base coefficient.
  115. multsq(u,v);
  116. expr procedure mkbc(u,v);
  117. % /* Convert u and v into u/v in lowest terms*/
  118. if v = 1 then u ./ v
  119. else if v<0 then mkbc(negf u,negf v)
  120. else quotf(u,m) ./ quotf(v,m) where m = gcdf(u,v);
  121. expr procedure bcquot (u,v);
  122. % /* Base coefficient quotient. u and v are base coefficients.
  123. % bcquot(u,v) calculates u/v and returns a base coefficient. */
  124. quotsq(u,v);
  125. expr procedure bcsum (u,v);
  126. % /* Base coefficient sum. u and v are base coefficients.
  127. % bcsum(u,v) calculates u+v and returns a base coefficient. */
  128. addsq(u,v);
  129. expr procedure bcdif(u,v);
  130. % /* Base coefficient difference. u and v are base coefficients.
  131. % bcdif(u,v) calculates u-v and returns a base coefficient. */
  132. bcsum(u,bcneg v);
  133. expr procedure bcpow(u,n);
  134. % /*Returns the base coefficient u raised to the nth power, where
  135. % n is an integer*/
  136. exptsq(u,n);
  137. expr procedure a2bc u;
  138. % /*Converts the algebraic (kernel) u into a base coefficient.
  139. simp!* u;
  140. expr procedure bc2a u;
  141. % /* Returns the prefix equivalent of the base coefficient u*/
  142. prepsq u;
  143. expr procedure bcprin u;
  144. % /* Prints a base coefficient in infix form*/
  145. begin scalar nat;
  146. nat := !*nat;
  147. !*nat := nil;
  148. sqprint u;
  149. !*nat := nat
  150. end;
  151. endmodule;
  152. module expvec;
  153. % /*Specific support for distributive polynomial exponent vectors*/
  154. % /* Authors: R. Gebauer, A. C. Hearn, H. Kredel */
  155. % We assume here that an exponent vector is a list of integers. This
  156. % version uses small integer arithmetic on the individual exponents
  157. % and assumes that a compiled function can be dynamically redefined*/
  158. fluid '(dipsortmode!* dipvars!*);
  159. expr procedure evperm (e1,n);
  160. % /* Exponent vector permutation. e1 is an exponent vector, n is a
  161. % index list , a list of digits. evperm(e1,n) returns a list e1
  162. % permuted in respect to n. */
  163. if null n then nil
  164. else evnth(e1, car n) . evperm(e1, cdr n);
  165. expr procedure evcons (e1,e2);
  166. % /* Exponent vector construct. e1 and e2 are exponents. evcons(e1,e2)
  167. % constructs an exponent vector. */
  168. e1 . e2;
  169. expr procedure evnth (e1,n);
  170. % /* Exponent vector n-th element. e1 is an exponent vector, n is a
  171. % digit. evnth(e1,n) returns the n-th element of e1, an exponent. */
  172. if n = 1 then evfirst e1
  173. else evnth(evred e1, n - 1);
  174. expr procedure evred e1;
  175. % /* Exponent vector reductum. e1 is an exponent vector. evred(e1)
  176. % returns the reductum of the exponent vector e1. */
  177. cdr e1;
  178. expr procedure evfirst e1;
  179. % /* Exponent vector first. e1 is an exponent vector. evfirst(e1)
  180. % returns the first element of the exponent vector e1, an exponent. */
  181. car e1;
  182. expr procedure evsum0(n,p);
  183. % exponent vector sum version 0. n is the length of dipvars!*.
  184. % p is a distributive polynomial.
  185. if dipzero!? p then evzero1 n else
  186. evsum(dipevlmon p, evsum0(n,dipmred p));
  187. expr procedure evzero1 n;
  188. % Returns the exponent vector power representation
  189. % of length n for a zero power.
  190. begin scalar x;
  191. for i:=1: n do << x := 0 . x >>;
  192. return x
  193. end;
  194. expr procedure indexcpl(ev,n);
  195. % returns a list of indixes of non zero exponents.
  196. if null ev then ev else ( if car ev = 0 then
  197. indexcpl(cdr ev,n + 1) else
  198. ( n . indexcpl(cdr ev,n + 1)) );
  199. expr procedure evzer1!? e;
  200. % returns a boolean expression. true if e is null else false.
  201. null e;
  202. expr procedure evzero!? e;
  203. % /* Returns a boolean expression. True if all exponents are zero*/
  204. null e or car e = 0 and evzero!? cdr e;
  205. expr procedure evzero;
  206. % /* Returns the exponent vector representation for a zero power*/
  207. % for i := 1:length dipvars!* collect 0;
  208. begin scalar x;
  209. for i := 1:length dipvars!* do <<x := 0 . x>>;
  210. return x
  211. end;
  212. expr procedure mkexpvec u;
  213. % /* Returns an exponent vector with a 1 in the u place*/
  214. if not(u member dipvars!*) then typerr(u,"dipoly variable")
  215. else for each x in dipvars!* collect if x eq u then 1 else 0;
  216. expr procedure evcompless!?(e1,e2);
  217. % /* Exponent vector compare less. e1, e2 are exponent vectors
  218. % in some order. Evcompless? is a boolean function which returns
  219. % true if e1 is ordered less than e2. This function is assigned a
  220. % value by the ordering mechanism, so is dummy for now*/
  221. apply(get(dipsortmode!*,'evcompless!?),list(e1,e2));
  222. expr procedure evlexcompless!?(e1,e2);
  223. % /* Exponent vector lexicographical compare less. e1, e2 are exponent
  224. % vectors in lexicographical order. Evlexcompless?(e1,e2) is a
  225. % boolean function which returns true if e1 is ordered less than e2*/
  226. if null e1 then nil
  227. else if car e1 = car e2 then evlexcompless!?(cdr e1,cdr e2)
  228. else car e1 #> car e2;
  229. expr procedure evcomp (e1,e2);
  230. % /* Exponent vector compare. e1, e2 are exponent vectors in some
  231. % order. Evcomp(e1,e2) returns the digit 0 if exponent vector e1 is
  232. % equal exponent vector e2, the digit 1 if e1 is greater than e2,
  233. % else the digit -1. This function is assigned a value by the
  234. % ordering mechanism, so is dummy for now*/
  235. apply(get(dipsortmode!*,'evcomp),list(e1,e2));
  236. expr procedure evilcompless!?(e1,e2);
  237. % /* Exponent vector inverse lexicographical compare less. e1, e2 are
  238. % exponent vectors in lexicographical order. Evilcompless?(e1,e2) is
  239. % a boolean function which returns true if e1 is ordered less than e2*/
  240. if null e1 then nil
  241. else if car e1 = car e2 then evilcompless!?(cdr e1,cdr e2)
  242. else car e1 #< car e2;
  243. expr procedure evlexcomp(e1,e2);
  244. % /* Exponent vector lexicographical compare. e1, e2 are exponent
  245. % vectors in lexicographical order. Evlexcomp(e1,e2) returns the
  246. % digit 0 if exponent vector e1 is equal exponent vector e2, 1 if e1
  247. % is greater than e2, else the digit -1. */
  248. if null e1 then 0
  249. else if car e1 = car e2 then evlexcomp(cdr e1,cdr e2)
  250. else if car e1 #< car e2 then 1
  251. else -1;
  252. expr procedure evilcomp (e1,e2);
  253. % /* Exponent vector inverse lexicographical compare. The
  254. % exponent vectors e1 and e2 are in inverse lexicographical
  255. % ordering. evilcomp(e1,e2) returns the digit 0 if exponent
  256. % vector e1 is equal exponent vector e2, the digit 1 if e1 is
  257. % greater than e2, else the digit -1. */
  258. if null e1 then 0
  259. else if car e1 = car e2 then evilcomp(cdr e1,cdr e2)
  260. else if car e1 #> car e2 then 1
  261. else -1;
  262. expr procedure evitdcompless!?(e1,e2);
  263. % /* Exponent vector inverse total degree compare less.
  264. % The exponent vectors e1 and e2 are in inverse total degree
  265. % ordering. evitdcompless!?(e1,e2) is a boolean function that
  266. % returns true if exponent vector e1 is ordered less than e2*/
  267. if null e1 then nil
  268. else if car e1 = car e2 then evitdcompless!?(cdr e1, cdr e2)
  269. else (if te1 = te2 then car e1 #< car e2 else te1 #< te2)
  270. where te1 = evtdeg e1, te2 = evtdeg e2;
  271. expr procedure evtdcompless!?(e1,e2);
  272. % /*Exponent vector total degree compare less.*/
  273. if null e1 then nil
  274. else if car e1 = car e2 then evtdcompless!?(cdr e1,cdr e2)
  275. else (if te1 = te2 then car e1 #> car e2 else te1 #< te2)
  276. where te1 = evtdeg e1, te2 = evtdeg e2;
  277. expr procedure evitdcomp (e1,e2);
  278. % /* Exponent vector inverse total degree compare.
  279. % The exponent vectors e1 and e2 are in inverse total degree
  280. % ordering. evitdcomp(e1,e2) returns the digit 0 if exponent
  281. % vector e1 is equal exponent vector e2, the digit 1 if e1 is
  282. % greater than e2, else the digit -1. */
  283. if null e1 then 0
  284. else if car e1 = car e2 then evitdcomp(cdr e1, cdr e2)
  285. else (if te1 = te2 then if car e1 #> car e2 then 1 else -1
  286. else if te1 #> te2 then 1 else -1)
  287. where te1 = evtdeg e1, te2 = evtdeg e2;
  288. expr procedure evtdcomp (e1,e2);
  289. % /* ... */
  290. if null e1 then 0
  291. else if car e1 = car e2 then evtdcomp(cdr e1,cdr e2)
  292. else (if te1 = te2 then if car e1 #< car e2 then 1 else -1
  293. else if te1 #> te2 then 1 else -1)
  294. where te1 = evtdeg e1, te2 = evtdeg e2;
  295. expr procedure evtdeg e1;
  296. % /* Exponent vector total degree. e1 is an exponent vector.
  297. % evtdeg(e1) calculates the total degree of the exponent
  298. % e1 and returns an integer. */
  299. (<<while e1 do <<x := car e1 #+ x; e1 := cdr e1>>; x>>) where x = 0;
  300. expr procedure evlcm (e1,e2);
  301. % /* Exponent vector least common multiple. e1 and e2 are
  302. % exponent vectors. evlcm(e1,e2) computes the least common
  303. % multiple of the exponent vectors e1 and e2, and returns
  304. % an exponent vector. */
  305. % for each lpart in e1 each rpart in e2 collect
  306. % if lpart #> rpart then lpart else rpart;
  307. begin scalar x;
  308. while e1 do
  309. <<x := (if car e1 #> car e2 then car e1 else car e2) . x;
  310. e1 := cdr e1; e2 := cdr e2>>;
  311. return reversip x
  312. end;
  313. expr procedure evmtest!? (e1,e2);
  314. % /* Exponent vector multiple test. e1 and e2 are compatible exponent
  315. % vectors. evmtest!?(e1,e2) returns a boolean expression.
  316. % True if exponent vector e1 is a multiple of exponent
  317. % vector e2, else false. */
  318. null e1 or not(car e1 #< car e2) and evmtest!?(cdr e1,cdr e2);
  319. expr procedure evsum (e1,e2);
  320. % /* Exponent vector sum. e1 and e2 are exponent vectors.
  321. % evsum(e1,e2) calculates the sum of the exponent vectors.
  322. % e1 and e2 componentwise and returns an exponent vector. */
  323. % for each lpart in e1 each rpart in e2 collect lpart #+ rpart;
  324. begin scalar x;
  325. while e1 do
  326. <<x := (car e1 #+ car e2) . x; e1 := cdr e1; e2 := cdr e2>>;
  327. return reversip x
  328. end;
  329. expr procedure evdif (e1,e2);
  330. % /* Exponent vector difference. e1 and e2 are exponent
  331. % vectors. evdif(e1,e2) calculates the difference of the
  332. % exponent vectors e1 and e2 componentwise and returns an
  333. % exponent vector. */
  334. % for each lpart in e1 each rpart in e2 collect lpart #- rpart;
  335. begin scalar x;
  336. while e1 do
  337. <<x := (car e1 #- car e2) . x; e1 := cdr e1; e2 := cdr e2>>;
  338. return reversip x
  339. end;
  340. expr procedure intevprod(n,e);
  341. % /* Multiplies each element of the exponent vector u by the integer n*/
  342. for each x in e collect n #* x;
  343. expr procedure expvec2a e;
  344. % /* Returns list of prefix equivalents of exponent vector e*/
  345. expvec2a1(e,dipvars!*);
  346. expr procedure expvec2a1(u,v);
  347. % /* Sub function of expvec2a */
  348. if null u then nil
  349. else if car u = 0 then expvec2a1(cdr u,cdr v)
  350. else if car u = 1 then car v . expvec2a1(cdr u,cdr v)
  351. else list('expt,car v,car u) . expvec2a1(cdr u,cdr v);
  352. expr procedure dipevlpri(e,v);
  353. % /* Print exponent vector e in infix form. V is a boolean variable
  354. % which is true if an element in a product has preceded this one*/
  355. dipevlpri1(e,dipvars!*,v);
  356. expr procedure dipevlpri1(e,u,v);
  357. % /* Sub function of dipevlpri */
  358. if null e then nil
  359. else if car e = 0 then dipevlpri1(cdr e,cdr u,v)
  360. else <<if v then dipprin2 "*";
  361. dipprin2 car u;
  362. if car e #> 1 then <<dipprin2 "**"; dipprin2 car e>>;
  363. dipevlpri1(cdr e,cdr u,t)>>;
  364. remprop('torder,'stat);
  365. expr procedure torder u;
  366. % algebraic mode interface to dipsortingmode.
  367. dipsortingmode car u;
  368. put('torder,'stat,'rlis);
  369. expr procedure dipsortingmode u;
  370. % /* Sets the exponent vector sorting mode. Returns the previous mode*/
  371. if not idp u or not flagp(u,'dipsortmode)
  372. then typerr(u,"term ordering mode")
  373. else begin scalar x;
  374. x := dipsortmode!*; dipsortmode!* := u; return x
  375. end;
  376. flag('(lex invlex totaldegree invtotaldegree),'dipsortmode);
  377. put('lex,'evcompless!?,'evlexcompless!?);
  378. put('lex,'evcomp,'evlexcomp);
  379. put('invlex,'evcompless!?,'evilcompless!?);
  380. put('invlex,'evcomp,'evilcomp);
  381. put('invtotaldegree,'evcompless!?,'evitdcompless!?);
  382. put('invtotaldegree,'evcomp,'evitdcomp);
  383. put('totaldegree,'evcompless!?,'evtdcompless!?);
  384. put('totaldegree,'evcomp,'evtdcomp);
  385. dipsortingmode 'invlex; % /*Default value*/
  386. endmodule;
  387. module dipoly; % /*Distributive polnomial algorithms*/
  388. %/*Authors: R. Gebauer, A. C. Hearn, H. Kredel*/
  389. fluid '(dipvars!* dipzero);
  390. fexpr procedure polyin p; a2dip car p;
  391. expr procedure dipconst!? p;
  392. not dipzero!? p
  393. and dipzero!? dipmred p
  394. and evzero!? dipevlmon p;
  395. expr procedure dfcprint pl;
  396. % h polynomial factor list of distributive polynomials print.
  397. for each p in pl do dfcprintin p;
  398. expr procedure dfcprintin p;
  399. % factor with exponent print.
  400. ( if cdr p neq 1 then << prin2 " ( "; dipprint1(p1,nil); prin2 " )** ";
  401. prin2 cdr p; terprit 2 >> else << prin2 " "; dipprint p1>> )
  402. where p1:= dipmonic a2dip prepf car p;
  403. expr procedure dfcprin p;
  404. % print content, factors and exponents of factorized polynomial p.
  405. << terpri(); prin2 " content of factorized polynomials = ";
  406. prin2 car p;
  407. terprit 2; dfcprint cdr p >>;
  408. expr procedure diplcm p;
  409. % Distributive polynomial least common multiple of denomiators.
  410. % p is a distributive rational polynomial. diplcm(p) calculates
  411. % the least common multiple of the denominators and returns a
  412. % base coefficient of the form 1/lcm(denom bc1,.....,denom bci).
  413. if dipzero!? p then mkbc(1,1)
  414. else bclcmd(diplbc p, diplcm dipmred p);
  415. expr procedure diprectoint(p,u);
  416. % Distributive polynomial conversion rational to integral.
  417. % p is a distributive rational polynomial, u is a base coefficient
  418. % ( 1/lcm denom p ). diprectoint(p,u) returns a primitive
  419. % associate pseudo integral ( denominators are 1 ) distributive
  420. % polynomial.
  421. if bczero!? u then dipzero
  422. else if bcone!? u then p
  423. else diprectoint1(p,u);
  424. expr procedure diprectoint1(p,u);
  425. % Distributive polynomial conversion rational to integral internall 1.
  426. % diprectoint1 is used in diprectoint.
  427. if dipzero!? p then dipzero
  428. else dipmoncomp(bclcmdprod(u,diplbc p),dipevlmon p,
  429. diprectoint1(dipmred p,u));
  430. expr procedure dipresul(p1,p2);
  431. % test for fast downwards calculation
  432. % p1 and p2 are two bivariate distributive polynomials.
  433. % dipresul(p1,p2) returns the resultant of p1 and p2 with respect
  434. % respect to the first variable of the variable list (car dipvars!*).
  435. begin scalar q1,q2,q,ct;
  436. q1:=dip2a diprectoint(p1,diplcm p1);
  437. q2:=dip2a diprectoint(p2,diplcm p2);
  438. ct := time();
  439. q:= a2dip prepsq simpresultant list(q1,q2,car dipvars!*);
  440. ct := time() - ct;
  441. prin2 " resultant : "; dipprint dipmonic q; terpri();
  442. prin2 " time resultant : "; prin2 ct; terpri();
  443. end;
  444. expr procedure dipbcprod (p,a);
  445. % /* Distributive polynomial base coefficient product.
  446. % p is a distributive polynomial, a is a base coefficient.
  447. % dipbcprod(p,a) computes p*a, a distributive polynomial. */
  448. if bczero!? a then dipzero
  449. else if bcone!? a then p
  450. else dipbcprodin(p,a);
  451. expr procedure dipbcprodin (p,a);
  452. % /* Distributive polynomial base coefficient product internal.
  453. % p is a distributive polynomial, a is a base coefficient,
  454. % where a is not equal 0 and not equal 1.
  455. % dipbcprodin(p,a) computes p*a, a distributive polynomial. */
  456. if dipzero!? p then dipzero
  457. else dipmoncomp(bcprod(a, diplbc p),
  458. dipevlmon p,
  459. dipbcprodin(dipmred p, a));
  460. expr procedure dipdif (p1,p2);
  461. % /* Distributive polynomial difference. p1 and p2 are distributive
  462. % polynomials. dipdif(p1,p2) calculates the difference of the
  463. % two distributive polynomials p1 and p2, a distributive polynomial*/
  464. if dipzero!? p1 then dipneg p2
  465. else if dipzero!? p2 then p1
  466. else ( if sl = 1 then dipmoncomp(diplbc p1,
  467. ep1,
  468. dipdif(dipmred p1, p2) )
  469. else if sl = -1 then dipmoncomp(bcneg diplbc p2,
  470. ep2,
  471. dipdif(p1,dipmred p2))
  472. else ( if bczero!? al
  473. then dipdif(dipmred p1, dipmred p2)
  474. else dipmoncomp(al,
  475. ep1,
  476. dipdif(dipmred p1,
  477. dipmred p2) )
  478. ) where al = bcdif(diplbc p1, diplbc p2)
  479. ) where sl = evcomp(ep1, ep2)
  480. where ep1 = dipevlmon p1, ep2 = dipevlmon p2;
  481. expr procedure diplength p;
  482. % /* Distributive polynomial length. p is a distributive
  483. % polynomial. diplength(p) returns the number of terms
  484. % of the distributive polynomial p, a digit.*/
  485. if dipzero!? p then 0 else 1 + diplength dipmred p;
  486. expr procedure diplistsum pl;
  487. % /* Distributive polynomial list sum. pl is a list of distributive
  488. % polynomials. diplistsum(pl) calculates the sum of all polynomials
  489. % and returns a list of one distributive polynomial. */
  490. if null pl or null cdr pl then pl
  491. else diplistsum(dipsum(car pl, cadr pl) . diplistsum cddr pl);
  492. expr procedure diplmerge (pl1,pl2);
  493. % /* Distributive polynomial list merge. pl1 and pl2 are lists
  494. % of distributive polynomials where pl1 and pl2 are in non
  495. % decreasing order. diplmerge(pl1,pl2) returns the merged
  496. % distributive polynomial list of pl1 and pl2. */
  497. if null pl1 then pl2
  498. else if null pl2 then pl1
  499. else ( if sl >= 0 then cpl1 . diplmerge(cdr pl1, pl2)
  500. else cpl2 . diplmerge(cdr pl2, pl1)
  501. ) where sl = evcomp(ep1, ep2)
  502. where ep1 = dipevlmon cpl1, ep2 = dipevlmon cpl2
  503. where cpl1 = car pl1, cpl2 = car pl2;
  504. expr procedure diplsort pl;
  505. % /* Distributive polynomial list sort. pl is a list of
  506. % distributive polynomials. diplsort(pl) returns the
  507. % sorted distributive polynomial list of pl.
  508. sort(pl, function dipevlcomp);
  509. expr procedure dipevlcomp (p1,p2);
  510. % /* Distributive polynomial exponent vector leading monomial
  511. % compare. p1 and p2 are distributive polynomials.
  512. % dipevlcomp(p1,p2) returns a boolean expression true if the
  513. % distributive polynomial p1 is smaller or equal the distributive
  514. % polynomial p2 else false. */
  515. not evcompless!?(dipevlmon p1, dipevlmon p2);
  516. expr procedure dipmonic p;
  517. % /* Distributive polynomial monic. p is a distributive
  518. % polynomial. dipmonic(p) computes p/lbc(p) if p is
  519. % not equal dipzero and returns a distributive
  520. % polynomial, else dipmonic(p) returns dipzero. */
  521. if dipzero!? p then p
  522. else dipbcprod(p, bcinv diplbc p);
  523. expr procedure dipneg p;
  524. % /* Distributive polynomial negative. p is a distributive
  525. % polynomial. dipneg(p) returns the negative of the distributive
  526. % polynomial p, a distributive polynomial. */
  527. if dipzero!? p then p
  528. else dipmoncomp ( bcneg diplbc p,
  529. dipevlmon p,
  530. dipneg dipmred p );
  531. expr procedure dipone!? p;
  532. % /* Distributive polynomial one. p is a distributive polynomial.
  533. % dipone!?(p) returns a boolean value. If p is the distributive
  534. % polynomial one then true else false. */
  535. not dipzero!? p
  536. and dipzero!? dipmred p
  537. and evzero!? dipevlmon p
  538. and bcone!? diplbc p;
  539. expr procedure dippairsort pl;
  540. % /* Distributive polynomial list pair merge sort. pl is a list
  541. % of distributive polynomials. dippairsort(pl) returns the
  542. % list of merged and in non decreasing order sorted
  543. % distributive polynomials. */
  544. if null pl or null cdr pl then pl
  545. else diplmerge(diplmerge( car(pl) . nil, cadr(pl) . nil ),
  546. dippairsort cddr pl);
  547. expr procedure dipprod (p1,p2);
  548. % /* Distributive polynomial product. p1 and p2 are distributive
  549. % polynomials. dipprod(p1,p2) calculates the product of the
  550. % two distributive polynomials p1 and p2, a distributive polynomial*/
  551. if diplength p1 <= diplength p2 then dipprodin(p1, p2)
  552. else dipprodin(p2, p1);
  553. expr procedure dipprodin (p1,p2);
  554. % /* Distributive polynomial product internal. p1 and p2 are distrib
  555. % polynomials. dipprod(p1,p2) calculates the product of the
  556. % two distributive polynomials p1 and p2, a distributive polynomial*/
  557. if dipzero!? p1 or dipzero!? p2 then dipzero
  558. else ( dipmoncomp(bcprod(bp1, diplbc p2),
  559. evsum(ep1, dipevlmon p2),
  560. dipsum(dipprodin(dipfmon(bp1, ep1),
  561. dipmred p2),
  562. dipprodin(dipmred p1, p2) ) )
  563. ) where bp1 = diplbc p1,
  564. ep1 = dipevlmon p1;
  565. expr procedure dipprodls (p1,p2);
  566. % /* Distributive polynomial product. p1 and p2 are distributive
  567. % polynomials. dipprod(p1,p2) calculates the product of the
  568. % two distributive polynomials p1 and p2, a distributive polynomial
  569. % using distributive polynomials list sum (diplistsum). */
  570. if dipzero!? p1 or dipzero!? p2 then dipzero
  571. else car diplistsum if diplength p1 <= diplength p2
  572. then dipprodlsin(p1, p2)
  573. else dipprodlsin(p2, p1);
  574. expr procedure dipprodlsin (p1,p2);
  575. % /* Distributive polynomial product. p1 and p2 are distributive
  576. % polynomials. dipprod(p1,p2) calculates the product of the
  577. % two distributive polynomials p1 and p2, a distributive polynomial
  578. % using distributive polynomials list sum (diplistsum). */
  579. if dipzero!? p1 or dipzero!? p2 then nil
  580. else ( dipmoncomp(bcprod(bp1, diplbc p2),
  581. evsum(ep1, dipevlmon p2),
  582. car dipprodlsin(dipfmon(bp1, ep1),
  583. dipmred p2))
  584. . dipprodlsin(dipmred p1, p2)
  585. ) where bp1 = diplbc p1,
  586. ep1 = dipevlmon p1;
  587. expr procedure dipsum (p1,p2);
  588. % /* Distributive polynomial sum. p1 and p2 are distributive
  589. % polynomials. dipsum(p1,p2) calculates the sum of the
  590. % two distributive polynomials p1 and p2, a distributive polynomial*/
  591. if dipzero!? p1 then p2
  592. else if dipzero!? p2 then p1
  593. else ( if sl = 1 then dipmoncomp(diplbc p1,
  594. ep1,
  595. dipsum(dipmred p1, p2) )
  596. else if sl = -1 then dipmoncomp(diplbc p2,
  597. ep2,
  598. dipsum(p1,dipmred p2))
  599. else ( if bczero!? al then dipsum(dipmred p1,
  600. dipmred p2)
  601. else dipmoncomp(al,
  602. ep1,
  603. dipsum(dipmred p1,
  604. dipmred p2) )
  605. ) where al = bcsum(diplbc p1, diplbc p2)
  606. ) where sl = evcomp(ep1, ep2)
  607. where ep1 = dipevlmon p1, ep2 = dipevlmon p2;
  608. endmodule;
  609. module dipvars;
  610. %/* Determine distributive polynomial variables in a prefix form*/
  611. %/*Authors: R. Gebauer, A. C. Hearn, H. Kredel*/
  612. expr procedure dipvars u;
  613. % /* Returns list of variables in prefix form u*/
  614. dipvars1(u,nil);
  615. expr procedure dipvars1(u,v);
  616. if atom u then if constantp u or u memq v then v else u . v
  617. else if idp car u and get(car u,'dipfn)
  618. then dipvarslist(cdr u,v)
  619. else if u memq v then v
  620. else u . v;
  621. expr procedure dipvarslist(u,v);
  622. if null u then v
  623. else dipvarslist(cdr u,union(dipvars car u,v));
  624. endmodule;
  625. module a2dip;
  626. %/*Convert an algebraic (prefix) form to distributive polynomial*/
  627. %/*Authors: R. Gebauer, A. C. Hearn, H. Kredel*/
  628. fluid '(dipvars!* dipzero);
  629. expr procedure a2dip u;
  630. % /*Converts the algebraic (prefix) form u to a distributive poly.
  631. % We assume that all variables used have been previously
  632. % defined in dipvars!*, but a check is also made for this*/
  633. if atom u then a2dipatom u
  634. else if not atom car u or not idp car u
  635. then typerr(car u,"dipoly operator")
  636. else (if x then apply(x,list for each y in cdr u collect a2dip y)
  637. else a2dipatom u)
  638. where x = get(car u,'dipfn);
  639. expr procedure a2dipatom u;
  640. % /*Converts the atom (or kernel) u into a distributive polynomial*/
  641. if u=0 then dipzero
  642. else if numberp u or not(u member dipvars!*)
  643. then dipfmon(a2bc u,evzero())
  644. else dipfmon(a2bc 1,mkexpvec u);
  645. expr procedure dipfnsum u;
  646. % /*U is a list of dip expressions. Result is the distributive poly
  647. % representation for the sum*/
  648. (<<for each y in cdr u do x := dipsum(x,y); x>>) where x = car u;
  649. put('plus,'dipfn,'dipfnsum);
  650. put('plus2,'dipfn,'dipfnsum);
  651. expr procedure dipfnprod u;
  652. % /*U is a list of dip expressions. Result is the distributive poly
  653. % representation for the product*/
  654. % /*Maybe we should check for a zero*/
  655. (<<for each y in cdr u do x := dipprod(x,y); x>>) where x = car u;
  656. put('times,'dipfn,'dipfnprod);
  657. put('times2,'dipfn,'dipfnprod);
  658. expr procedure dipfndif u;
  659. % /*U is a list of two dip expressions. Result is the distributive
  660. % polynomial representation for the difference*/
  661. dipsum(car u,dipneg cadr u);
  662. put('difference,'dipfn,'dipfndif);
  663. expr procedure dipfnpow u;
  664. % /*U is a pair of dip expressions. Result is the distributive poly
  665. % representation for the first raised to the second power*/
  666. (if not fixp n or n<0
  667. then typerr(n,"distributive polynomial exponent")
  668. else if n=0 then if dipzero!? v then rederr "0**0 invalid"
  669. else w
  670. else if dipzero!? v or n=1 then v
  671. else if dipzero!? dipmred v
  672. then dipfmon(bcpow(diplbc v,n),intevprod(n,dipevlmon v))
  673. else <<while n>0 do
  674. <<if not evenp n then w := dipprod(w,v);
  675. n := n/2;
  676. if n>0 then v := dipprod(v,v)>>;
  677. w>>)
  678. where n := dip2a cadr u, v := car u,
  679. w := dipfmon(a2bc 1,evzero());
  680. put('expt,'dipfn,'dipfnpow);
  681. expr procedure dipfnneg u;
  682. % /*U is a list of one dip expression. Result is the distributive
  683. % polynomial representation for the negative*/
  684. (if dipzero!? v then v
  685. else dipmoncomp(bcneg diplbc v,dipevlmon v,dipmred v))
  686. where v = car u;
  687. put('minus,'dipfn,'dipfnneg);
  688. expr procedure dipfnquot u;
  689. % /*U is a list of two dip expressions. Result is the distributive
  690. % polynomial representation for the quotient*/
  691. if dipzero!? cadr u or not dipzero!? dipmred cadr u
  692. or not evzero!? dipevlmon cadr u
  693. then typerr(dip2a cadr u,"distributive polynomial denominator")
  694. else dipfnquot1(car u,diplbc cadr u);
  695. expr procedure dipfnquot1(u,v);
  696. if dipzero!? u then u
  697. else dipmoncomp(bcquot(diplbc u,v),
  698. dipevlmon u,
  699. dipfnquot1(dipmred u,v));
  700. put('quotient,'dipfn,'dipfnquot);
  701. endmodule;
  702. module dip2a;
  703. %/* Functions for converting distributive forms into prefix forms*/
  704. %/*Authors: R. Gebauer, A. C. Hearn, H. Kredel*/
  705. expr procedure dip2a u;
  706. % /* Returns prefix equivalent of distributive polynomial u*/
  707. if dipzero!? u then 0 else dipreplus dip2a1 u;
  708. expr procedure dip2a1 u;
  709. if dipzero!? u then nil
  710. else ((if bcminus!? x then list('minus,dipretimes(bc2a bcneg x . y))
  711. else dipretimes(bc2a x . y))
  712. where x = diplbc u, y = expvec2a dipevlmon u)
  713. . dip2a1 dipmred u;
  714. expr procedure dipreplus u;
  715. if atom u then u else if null cdr u then car u else 'plus . u;
  716. expr procedure dipretimes u;
  717. % /* U is a list of prefix expressions the first of which is a number.
  718. % Result is prefix representation for their product*/
  719. if car u = 1 then if cdr u then dipretimes cdr u else 1
  720. else if null cdr u then car u
  721. else 'times . u;
  722. endmodule;
  723. module dipprint; %/* printing routines for distributive polynomials*/
  724. %/*Authors: R. Gebauer, A. C. Hearn, H. Kredel*/
  725. fluid '(dipvars!*);
  726. expr procedure diplprint u;
  727. % /* Prints a list of distributive polynomials using dipprint*/
  728. for each v in u do dipprint v;
  729. expr procedure dipprint u;
  730. % /* Prints a distributive polynomial in infix form*/
  731. <<terpri(); dipprint1(u,nil); terpri(); terpri()>>;
  732. expr procedure dipprint1(u,v);
  733. % /* Prints a distributive polynomial in infix form.
  734. % U is a distributive form. V is a flag which is true if a term
  735. % has preceded current form*/
  736. if dipzero!? u then if null v then dipprin2 0 else nil
  737. else begin scalar bool,w;
  738. w := diplbc u;
  739. if bcminus!? w then <<bool := t; w := bcneg w>>;
  740. if bool then dipprin2 " - " else if v then dipprin2 " + ";
  741. (if not bcone!? w or evzero!? x then <<bcprin w; dipevlpri(x,t)>>
  742. else dipevlpri(x,nil))
  743. where x = dipevlmon u;
  744. dipprint1(dipmred u,t)
  745. end;
  746. expr procedure dipprin2 u;
  747. % /* Prints u, preceding by two EOL's if we have reached column 70*/
  748. <<if posn()>69 then <<terpri(); terpri()>>; prin2 u>>;
  749. endmodule;
  750. module grinterf; % Interface of Groebner package to REDUCE.
  751. % /*Authors: R. Gebauer, A. C. Hearn, M. Moeller.
  752. fluid '(dipvars!*);
  753. expr procedure groebnereval u;
  754. begin integer n;
  755. n := length u;
  756. if n=1 then return groebner(reval car u,nil)
  757. else if n neq 2
  758. then rederr "GROEBNER called with wrong number of arguments"
  759. else return groebner(reval car u,reval cadr u)
  760. end;
  761. put('groebner,'psopfn,'groebnereval);
  762. expr procedure greduce u;
  763. % /* Polynomial reduction modulo a Groebner basis driver. u is an
  764. % expression and v a list of expressions. Greduce calculates the
  765. % polynomial u reduced wrt the list of expressions v reduced to a
  766. % groebner basis modulo using the optional third argument as the
  767. % order of variables.
  768. begin integer n; scalar dipvars!*,v;
  769. n := length u;
  770. v := for each j in getrlist reval cadr u collect
  771. if eqexpr j then !*eqn2a j else j;
  772. if n=2
  773. then dipvars!* := for each j in gvarlis v collect !*a2k j
  774. else if n=3 then dipvars!* := getrlist caddr u
  775. else rederr "GREDUCE called with wrong number of arguments";
  776. v := groebner2 for each j in v collect a2dip j;
  777. if cdr v then errach list("Groebner",u)
  778. else if null cdar v and dip2a caar v = 1
  779. then rederr "Inconsistent Basis";
  780. return dip2a dipnorform(car v,a2dip reval car u)
  781. end;
  782. put('greduce,'psopfn,'greduce);
  783. expr procedure preduce(u,v);
  784. % /* Polynomial reduction driver. u is an expression and v a list of
  785. % expressions. Preduce calculates the polynomial u reduced wrt the list
  786. % of expressions v. */
  787. begin scalar dipvars!*;
  788. v := for each j in getrlist reval v collect
  789. if eqexpr j then !*eqn2a j else j;
  790. dipvars!* := for each j in gvarlis v collect !*a2k j;
  791. return dip2a dipnorform(for each j in v collect a2dip j,
  792. a2dip reval u)
  793. end;
  794. flag('(preduce),'opfn);
  795. endmodule;
  796. module groebner; % Basic Groebner base code using Buchberger algorithm.
  797. % /*Authors: R. Gebauer, A. C. Hearn, M. Moeller.
  798. fluid '(!*groebopt !*groebfac !*hopt !*trgroeb !*trgroebs !*trgroeb0
  799. !*trgroeb1 dipvars!* dipzero);
  800. switch groebopt,groebfac,hopt,trgroeb,trgroebs,trgroeb0,trgroeb1;
  801. % /* option ' groebopt' "optimizes" the given input */
  802. % /* polynomial set ( variable */
  803. % /* ordering ) */
  804. % /* option ' trgroeb' prints intermediate */
  805. % /* results on the output file */
  806. % /* option ' trgroeb1' prints internal representation */
  807. % /* of critical pair list d */
  808. % /* option ' trgroeb0' factorizes the S - polynom */
  809. % /* the S - polynom will not be */
  810. % /* replaced by a factor */
  811. % /* option ' trgroebs ' prints S - polynomials */
  812. % /* on the output file */
  813. % /* option ' hopt ' the H- polynomials are */
  814. % /* optimised using resultant */
  815. % /* and factorisation method */
  816. % /* option ' groebfac ' the H - polynomials are */
  817. % /* factorized. If a H - polynom */
  818. % /* could be factorized, new sub- */
  819. % /* problems are generated and */
  820. % /* option ' fac ' is set to off */
  821. % /* NOTE: this option is not complete */
  822. % /* at the moment and has been suppressed */
  823. % expr procedure bas p; diplprint car groebner(p,dipvars!*);
  824. expr procedure groebner(u,v);
  825. % /* Buchberger algorithm system driver. u is a list of expressions
  826. % and v a list of variables or NIL in which case the variables in u
  827. % are used. Groebner(p) calculates the Groebner basis of the
  828. % expressions wrt the variables. */
  829. begin scalar dipvars!*,w;
  830. w := for each j in getrlist u
  831. collect if eqexpr j then !*eqn2a j else j;
  832. if null w then rederr "Empty list in Groebner"
  833. else if null cdr w then return 'list . w;
  834. if null v then v := gvarlis w else v := getrlist v;
  835. dipvars!* := for each j in v collect !*a2k j;
  836. w := groebner2 for each j in w collect a2dip j;
  837. if cdr w then errach list("Groebner",u,dipvars!*);
  838. return 'list . for each j in car w collect dip2a j
  839. end;
  840. expr procedure gvarlis u;
  841. % Finds variables (kernels) in the list of expressions u.
  842. gvarlis1(u,nil);
  843. expr procedure gvarlis1(u,v);
  844. if null u then v
  845. else union(gvar1(car u,v),gvarlis1(cdr u,v));
  846. expr procedure gvar1(u,v);
  847. if null u or numberp u then v
  848. else if atom u then if u member v then v else u . v
  849. else if car u memq '(plus times expt difference minus)
  850. then gvarlis1(cdr u,v)
  851. else if car u eq 'quotient then gvar1(cadr u,v)
  852. else if u member v then v
  853. else u . v;
  854. expr procedure groebner2 p;
  855. begin scalar tim,spac,spac1,p1;
  856. tim := time(); % terprit 3;
  857. spac := gctime(); p1:= dipgbase p;
  858. spac1 := gctime() - spac;
  859. % prin2 " garbage collection time for test ";
  860. % prin2 spac1;
  861. % prin2 "( not yet available )";
  862. if !*trgroeb then
  863. <<prin2 "Computing time for test ";
  864. prin2(time() - tim - spac1);
  865. % prin2(time() - tim );
  866. prin2t " milliseconds ">>;
  867. return p1
  868. end;
  869. expr procedure dipindexpol(pl,n);
  870. % Distributive polynomial index list. pl is a list of distributive
  871. % polynomials; n is an index, an integer. dipindexpol(pl,n)
  872. % returns a list of distributive polynomials in the form
  873. % ( (n,p1) (n+1,p2) ..... (n+k,pk) ).
  874. if null pl then pl else
  875. list(n,car pl) . dipindexpol(cdr pl, n + 1);
  876. expr procedure dipindexpolspec pl;
  877. % Distributive polynomial special list. pl is a list produced
  878. % by dipindexpol. dipindexpolspec pl constructs a list of lists
  879. % of polynomials in the form ( (p1,.....,pl) (p2,.....,pl)....
  880. % ..(pl-1,,pl) (pl) ).
  881. for each pl0 on pl collect
  882. ( for each pl1 in pl0 collect pl1 );
  883. expr procedure dipcpairlistopt pl;
  884. % Distributive critical pair list optimise. pl is a special list
  885. % ( constructed by dipcpairlist ) of elements used in the
  886. % Groebner calculation. dipcpairlistopt(pl) returns a list which
  887. % is optimised using Buchberger criterion 4.
  888. if pl then ( if buchcrit4(caddr x, cadddr x, cadr x)
  889. then x . dipcpairlistopt cdr pl
  890. else dipcpairlistopt cdr pl
  891. ) where x = car pl else nil;
  892. expr procedure dipcpairlistop(d,d0);
  893. % Distributive polynomial critical pair list optimise.
  894. % dipcpairlistop(d,d0) returns an optimised critical pair
  895. % starting list using the new criteria's.
  896. begin scalar x;
  897. while d do << x:= dipcpairlistopt1(cadar d,d0,d0);
  898. d0:= x; d:= cdr d>>;
  899. return x
  900. end;
  901. expr procedure dipcpairlistopt1(h,d,d0);
  902. % Distributive polynomial critical pair list optimise version 1.
  903. % dipcpairlistopt1(h,d,d0) returns an optimised critical pair
  904. % list.
  905. if null d then d0 else ( if evmtest!?(cadar d,ev1) then
  906. dipcpairlistopt1(h, cdr d,x) else
  907. dipcpairlistopt1(h,cdr d,d0)
  908. ) where x= dipcpairlistopt1in(ev1,cadar d,car d,d0)
  909. where ev1 = dipevlmon h;
  910. expr procedure dipcpairlistopt1in(ev1,ev2,id1,d);
  911. % Distributive polynomial critical pair list optimise version 1.
  912. % internall. dipcpairlistopt1in is used in dipcpairlistopt1.
  913. if ev2 neq evlcm(ev1,dipevlmon caddr id1) and
  914. ev2 neq evlcm(ev1,dipevlmon cadddr id1) then
  915. dipcpairlistopt1in1(id1,d) else d;
  916. expr procedure dipcpairlistopt1in1(d1,d);
  917. % Distributive polynomial critical pair list optimise version 1
  918. % internall version 1. dipcpairlistopt1in1 is used in
  919. % dipcpairlistopt1in.
  920. if null d then nil else if d1 eq car d then
  921. dipcpairlistopt1in1(d1,cdr d) else
  922. car d . dipcpairlistopt1in1(d1,cdr d);
  923. expr procedure dipindexpolrec pl;
  924. % Distributive index polynom list reconstruct. pl is a list of
  925. % polynomials used in the Groebner calculation. dipindexpolrec(pl)
  926. % returns a list of distributive polynomials.
  927. for each p in pl collect cadr p;
  928. expr procedure dipcplist pl;
  929. % Distributive polynomial critical pair list construct.
  930. % dipcplist returns a list of elements where an element has the
  931. % structure ( (ipi,ipj) lcm(epi,epj) pi pj ).
  932. % where ipi is the index of polynomial i, epi is the headterm of
  933. % the polynomial pi.
  934. for each p in pl
  935. conc ( dipcplistopt2(nil, dipcplistin(ep, pi1, reverse cdr p))
  936. ) where ep = dipevlmon cadr pi1 where pi1 = car p;
  937. expr procedure dipcplistin(ep,p1,pl);
  938. % Distributive polynomial critical pair list construct internall.
  939. % dipcplistin is used in dipcplist.
  940. if null pl then pl else
  941. ( list(list(car p1,car p2), evlcm(ep,dipevlmon cadr p2),
  942. cadr p1, cadr p2) . dipcplistin(ep, p1, cdr pl)
  943. ) where p2 = car pl;
  944. expr procedure dipcplistadd(ind,p,pl);
  945. % Distributive polynomial critical pair list add.
  946. % dipcplistadd returns a new critical pair list where all
  947. % combinations of p with pl are added.
  948. if null pl then pl else
  949. ( list(list(car ps,ind),evlcm(dipevlmon p1,
  950. dipevlmon p),p1,p) . dipcplistadd(ind,p,cdr pl)
  951. ) where p1 = cadr ps where ps = car pl;
  952. expr procedure dipcplistopt2in(p1,pl);
  953. % Distributive polynomial critical pair list optimise version 2
  954. % internall use. dipcplistopt2in(pl1,pl) is used in
  955. % dipcplistopt2.
  956. if null pl then dipzero else
  957. ( if evmtest!?(cadr p1, cadr p) then
  958. dipcplistopt2in1(p1,p)
  959. else dipcplistopt2in(p1,cdr pl)
  960. ) where p = car pl;
  961. expr procedure dipcplistopt2in1(p1,p2);
  962. % Distributive polynomial critical pair list optimise version 2
  963. % internall use version 1. dipcplistopt2in1(pl1,pl) is used in
  964. % dipcplistopt2in.
  965. if cadr p1 = cadr p2 then
  966. ( if evilcompless!?(reverse car p1, reverse car p2) then
  967. p1 else p2 )
  968. else p2;
  969. expr procedure dipindexpoloptin(p1,pl);
  970. % Distributive index polynomial list optimise internall use.
  971. % dipindexpoloptin is used in dipindexpolopt.
  972. if null pl then dipzero else
  973. ( if evmtest!?(dipevlmon cadr p1, dipevlmon cadr p) then
  974. dipindexpoloptin1(p1,p)
  975. else dipindexpoloptin(p1,cdr pl)
  976. ) where p = car pl;
  977. expr procedure dipindexpoloptin1(p1,p2);
  978. % Distributive index polynomial list optimise internall version 1.
  979. % dipindexpoloptin1 is used in dipindexpoloptin.
  980. if dipevlmon cadr p1 = dipevlmon cadr p2
  981. then ( if car p1 < car p2 then p1 else p2 )
  982. else p2;
  983. expr procedure dipcplistopt2(pl1,pl2);
  984. % Distributive polynomial critical pair list optimise version 2.
  985. % dipcplistopt2(pl1,pl2) returns the optimised critical pair list.
  986. if null pl2 then pl1 else
  987. ( if dipzero!? dipcplistopt2in(p,pl1)
  988. and dipzero!? dipcplistopt2in(p,pl0)
  989. then dipcplistopt2(cons(p,pl1),pl0)
  990. else dipcplistopt2(pl1,pl0)
  991. ) where p = car pl2, pl0 = cdr pl2;
  992. expr procedure dipindexpolopt(pl1,pl2);
  993. % Distributive index polynomial list optimise. pl1 and pl2
  994. % are lists of polynomials used in the Groebner calculation.
  995. % dipindexpolopt(pl1,pl2) returns an optimised list of polynomials.
  996. if null pl2 then pl1 else
  997. ( if dipzero!? dipindexpoloptin(p,pl1) and
  998. dipzero!? dipindexpoloptin(p,pl0)
  999. then dipindexpolopt(cons(p,pl1),pl0)
  1000. else dipindexpolopt(pl1,pl0)
  1001. ) where p = car pl2, pl0 = cdr pl2;
  1002. expr procedure dipcplistsort pl;
  1003. % Distributive polynomial critical pair list sort. pl is a
  1004. % special list for Groebner calculation. dipcplistsort(pl)
  1005. % returns the sorted list pl;
  1006. begin scalar tree;
  1007. if null pl then return nil;
  1008. tree := list(car pl,nil);
  1009. while pairp(pl:= cdr pl) do dipcplistsortadd(car pl,tree);
  1010. return tree2list(tree,nil)
  1011. end;
  1012. smacro procedure dipcplistevlcomp(p1,p2);
  1013. % Distributive polynomial critical pair list exponent vector
  1014. % compare. p1 and p2 are elements of the critical pair list.
  1015. % dipcplistevlcomp(p1,p2) returns a boolean expression, true
  1016. % if exponent vector of p1 is smaller or equal exponent vector
  1017. % of p2 else false.
  1018. evcompless!?(cadr p1, cadr p2);
  1019. expr procedure dipcplistsortadd(item,node);
  1020. % Distributive polynomial critical pair list sort addition.
  1021. % add item to a node, using dipcplistevlcomp as an order
  1022. % predicate.
  1023. if dipcplistevlcomp(item, car node) then if cadr node then
  1024. dipcplistsortadd(item, cadr node) else
  1025. rplaca(cdr node,list(item,nil)) else
  1026. if cddr node then dipcplistsortadd(item,cddr node) else
  1027. rplacd(cdr node,list(item,nil));
  1028. expr procedure dipcplistmerge(pl1,pl2);
  1029. % Distributive polynomial critical pair list merge. pl1 and pl2
  1030. % are critical pair lists used in the Groebner calculation.
  1031. % dipcplistmerge(pl1,pl2) returns the merged list.
  1032. if null pl1 then pl2 else if null pl2 then pl1
  1033. else ( if sl then cpl1 . dipcplistmerge(cdr pl1,pl2)
  1034. else cpl2 . dipcplistmerge(pl1,cdr pl2)
  1035. ) where sl = evcompless!?(cadr cpl1, cadr cpl2)
  1036. where cpl1 = car pl1, cpl2 = car pl2;
  1037. expr procedure buchcrit4(p1,p2,e);
  1038. % Buchberger criterion 4. p1 and p2 are distributive
  1039. % polynomials. e is the least common multiple of
  1040. % the leading exponent vectors of the distributive
  1041. % polynomials p1 and p2. buchcrit4(p1,p2,e) returns a
  1042. % boolean expression. True if the reduction of the
  1043. % distributive polynomials p1 and p2 is necessary
  1044. % else false.
  1045. e neq evsum( dipevlmon p1, dipevlmon p2);
  1046. expr procedure dipgbase pl;
  1047. % /* Distributive polynomial Groebner base. pl is a list of distributiv
  1048. % polynomials. dipgbase(pl) calculates the Groebner base of the list
  1049. % of distributive polynomials pl and returns a list of distributive
  1050. % polynomials. */
  1051. if null pl then nil
  1052. else if null cdr pl then list pl
  1053. else if !*groebopt then dipgbasein dipvordopt pl
  1054. else dipgbasein pl;
  1055. expr procedure gbprint pl;
  1056. % Groebner basis list of distributive polynomials print.
  1057. for each p in pl do dipprint dipmonic p;
  1058. expr procedure rescheck!?(a,h1,vl);
  1059. length h1 = a and car h1 = vl - 1;
  1060. expr procedure rescheck1!?(a,h1,vl);
  1061. length h1 = a and car h1 = vl - 2 and cadr h1 = vl - 1;
  1062. expr procedure newhpol(p1,p2,x);
  1063. begin scalar q1,q2,q;
  1064. q1:=dip2a diprectoint(p1,diplcm p1);
  1065. q2:=dip2a diprectoint(p2,diplcm p2);
  1066. q:=a2dip prepsq simpresultant list(q1,q2,x);
  1067. return q;
  1068. end;
  1069. expr procedure sqpol p1;
  1070. begin scalar q1,q;
  1071. q1:=dip2a diprectoint(p1,diplcm p1);
  1072. q:=a2dip caar sqfrf q1;
  1073. return q;
  1074. end;
  1075. expr procedure dipnorfor (pl,p);
  1076. % /* Distributive polynom normalform. pl is a list of distributive
  1077. % polynomials, p is a distributive polynomial. dipnorfor(pl,p)
  1078. % calculates a distributive polynomial such that the powerproduct
  1079. % of the distributive
  1080. % polynomial p is reducible to this modulo the distributive
  1081. % polynomial list pl and is in normalform with respect to the
  1082. % distributive polynomial p and returns a distributive polynomial. */
  1083. if dipzero!? p or null pl then p
  1084. else ( if dipzero!? q then p
  1085. else (
  1086. if dipzero!? rq then dipnorfor(pl,dipmred p)
  1087. else dipnorfor(pl,
  1088. dipdif(dipmred p,
  1089. dipprod(rq,
  1090. dipfmon(bcquot(diplbc p,
  1091. diplbc q),
  1092. evdif(ep,
  1093. dipevlmon q) ) ) ) )
  1094. ) where rq = dipmred q
  1095. ) where q = dipnorformsel(ep, pl)
  1096. where ep = dipevlmon p;
  1097. expr procedure dipmingbase pl;
  1098. % Distributive polynomial minimal ordered Groebner base. pl is a
  1099. % list of distributive polynomials. dipmingbase(pl) calculates
  1100. % the minimal normed and ordered Groebner base of the distributive
  1101. % polyomials pl and returns a list of distributive polyomials.
  1102. if null cdr pl then pl
  1103. else dipmingbasein2(nil,dipmingbasein1(nil,pl) );
  1104. expr procedure dipgbasein ql;
  1105. % /* Distributive polynomial Groebner base. pl is a list of distributiv
  1106. % polynomials. dipgbase(pl) calculates the Groebner base of the list
  1107. % of distributive polynomials pl and returns a list of distributive
  1108. % polynomials. */
  1109. begin scalar ql0,u,ql1,w,d,ql22,lql1,ql11,lv,h1h0,d1,d0,p1,
  1110. sp0,n,dl,p2,ct1,sp,h,ct11,h1,h10,hs1,h1h1,h0,hs2;
  1111. u := 1; w := 1; n := 1; ql0 := nil;
  1112. ql1:= dipindexpol(ql,1);
  1113. d:= dipcplistsort dipcpairlistopt dipcplist dipindexpolspec ql1;
  1114. ql22 := ql;
  1115. lql1:= length ql1; ql11:=dipindexpolopt(nil, ql1);
  1116. d:=dipcpairlistop(ql11,d);
  1117. if !*hopt then << lv:=length dipvars!*; h1h0:=nil>>;
  1118. d1:=list list(lql1,ql1,ql11,ql22,d);
  1119. if !*trgroeb1 then <<
  1120. prin2 " list d1 = ";
  1121. prin2 d1; terpri();
  1122. prin2 length d1; terpri() >>;
  1123. while not null d1 do <<
  1124. d0:= car d1; d1:= cdr d1; lql1:= car d0;
  1125. ql1:= cadr d0; ql11:= caddr d0;
  1126. ql22:= cadddr d0; d:= cadddr cdr d0;
  1127. while not null d do <<
  1128. dl:= car d;
  1129. d := cdr d;
  1130. p1:= caddr dl;
  1131. p2:= cadddr dl;
  1132. if !*trgroeb then << ct1 := time() >>;
  1133. sp := dipspolynom(p1,p2);
  1134. if !*trgroebs then <<
  1135. prin2t "S-polynom:";
  1136. dipprint sp; terpri() >>;
  1137. if !*trgroeb0 then << sp0:= dip2a diprectoint(sp,diplcm sp);
  1138. sp0:= factorf !*q2f simp sp0;
  1139. dfcprin sp0; terprit 2 >>;
  1140. h := dipnorform(ql22, sp);
  1141. if !*trgroeb then << ct11 := time() - ct1 >>;
  1142. if dipzero!? h then <<
  1143. if !*trgroeb then << terprit 2; printb 57; terpri();
  1144. prin2 " / reduction of polynom "; prin2 caar dl;
  1145. prin2 " and "; prin2 cadar dl;
  1146. prin2 " leads to 0 "; prin2 " ( ";
  1147. prin2 ct11; prin2 " ms )";
  1148. terpri(); printb 57; terprit 2 >> >>;
  1149. if not dipzero!? h then
  1150. if dipconst!? h
  1151. then <<
  1152. ql11:= list list(lql1,dipmonic h);
  1153. d:=nil >>
  1154. else << h1 := dipmonic h; lql1:= lql1 + 1;
  1155. if !*trgroeb then <<
  1156. prin2 "h-polynom ";
  1157. prin2 lql1; prin2 " pair";
  1158. prin2 " ( "; prin2 caar dl;
  1159. prin2 ","; prin2 cadar dl; prin2t " ) :";
  1160. dipprint h1; terpri();
  1161. prin2 " computing time for h-polynom ";
  1162. prin2 ct11;
  1163. terprit 3 >>;
  1164. % The following option has been suppressed since it is not
  1165. % complete.
  1166. if nil and !*groebfac and u = 1 then << h10:= h1;
  1167. h1:= dip2a diprectoint(h1,diplcm h1);
  1168. h1:= factorf !*q2f simp h1;
  1169. hs1:= reverse diplsort makdiplist cdr h1;
  1170. if !*trgroeb then <<
  1171. prin2 "h-polynom factorized: ";
  1172. terpri();
  1173. dfcprin h1; terpri() >>;
  1174. h1:= dipmonic car hs1; hs1:= reverse cdr hs1;
  1175. if not dipzero!? (dipdif(h1,h10)) then
  1176. << u:= 0 >>;
  1177. if !*trgroeb then << prin2 " new h-polynom ";
  1178. terprit 3; dipprint h1; terprit 2 >> >>;
  1179. if !*hopt and w = 1 then <<
  1180. h1h1:= indexcpl(evsum0(lv,h1),1);
  1181. if !*trgroeb then << prin2 " index: "; prin2 h1h1; terpri();
  1182. prin2 " index: "; prin2 h1h0; terprit 3 >>;
  1183. if h1h1 = h1h0
  1184. and rescheck!?(2,h1h0,lv)
  1185. then <<
  1186. hs2:= reverse diplsort
  1187. newhpo(h1,h0,cadr reverse dipvars!*); w:= 0>>;
  1188. if h1h1 = h1h0
  1189. and rescheck1!?(2,h1h0,lv)
  1190. then <<
  1191. hs2:= reverse diplsort
  1192. newhpo(h1,h0,caddr reverse dipvars!*); w:= 0 >>;
  1193. if null hs2 then << w:= 1 >>
  1194. >>;
  1195. if u = 0 and not null hs1 then <<
  1196. d0:= maklistd1(hs1,lql1,ql1,ql11,ql22,d);
  1197. u:= 2; d1:=nconc(d0,d1) >>;
  1198. %%%%%%% u:= 1; d1:=nconc(d0,d1) >>;
  1199. d:= dipcpairlistopt1(h1,d,d);
  1200. if !*trgroeb then << terpri(); prin2 "Restpairs: ";
  1201. prin2t length d; terpri() >>;
  1202. d:= dipcplistmerge(dipcplistsort
  1203. dipcpairlistopt dipcplistopt2(nil,dipcplistadd(lql1,h1,ql11)),d);
  1204. if !*hopt and w = 1 then << h1h0:=indexcpl(evsum0(lv,h1),1); h0:= h1 >>;
  1205. ql11:= nconc(list list(lql1,h1),ql11);
  1206. ql22:= nconc(list(h1),ql22);
  1207. ql11:= dipindexpolopt(nil,ql11);
  1208. if !*trgroeb1 then << prin2 " *** d = "; prin2 d; terpri();
  1209. prin2t " ql11 "; prin2 ql11; terpri() >>;
  1210. if w = 0 then << h1:= dipmonic car hs2; hs2:= reverse cdr hs2;
  1211. lql1:= lql1 + 1; if not null hs2 then <<
  1212. d0:= maklistd1(hs2,lql1,ql1,ql11,ql22,d);
  1213. w:= 2; d1:= nconc(d0,d1) >>;
  1214. d:= dipcpairlistopt1(h1,d,d);
  1215. d:= dipcplistmerge(dipcplistsort
  1216. dipcpairlistopt dipcplistopt2(nil,dipcplistadd(lql1,h1,ql11)),d);
  1217. ql11:= nconc(list list(lql1,h1),ql11);
  1218. ql22:= nconc(list(h1),ql22);
  1219. ql11:= dipindexpolopt(nil,ql11);
  1220. if !*trgroeb1 then << prin2 " *** d = "; prin2 d; terpri();
  1221. prin2t " ql11 "; prin2 ql11; terpri() >>
  1222. >> >> >>;
  1223. ql11:=dipindexpolrec ql11;
  1224. if !*trgroeb then <<
  1225. prin2t " calculation now in final reduction ";
  1226. terpri(); ct1 := time() >>;
  1227. ql:=dipmingbase diplsort ql11;
  1228. if !*trgroeb then << ct11 := time() - ct1;
  1229. prin2 " computing time for final calculation ";
  1230. prin2 ct11;
  1231. prin2 " milliseconds "; terprit 3;
  1232. prin2 " Number of Groebner Basis Polynomials := ";
  1233. prin2t length ql; terprit 2;
  1234. if n = 1 and null d1 then <<
  1235. prin2t " The Groebner Basis Polynomials "; terpri() >>
  1236. else
  1237. << prin2 " The Groebner Basis Polynomials ( Factor ";
  1238. prin2 n; prin2t " )"; terpri(); n:= n + 1 >>;
  1239. gbprint ql;
  1240. if not null d1 then <<
  1241. prin2 " Calculation for Factor "; prin2t n; terprit 4 >>
  1242. >>; ql0:= ql . ql0 >>;
  1243. return ql0
  1244. end;
  1245. expr procedure makdiplist pl;
  1246. % Make list of distributive polynomials from list of polynomials pl.
  1247. for each p in pl collect a2dip prepf car p;
  1248. expr procedure terprit n;
  1249. % print blank lines.
  1250. for i:=1:n do << terpri() >>;
  1251. expr procedure printb n;
  1252. % print special sign ( - ).
  1253. for i:=1:n do << prin2 "-" >>;
  1254. expr procedure newhpo(h1,h0,x);
  1255. % new h-polynom calculation. newhpo(h1,h2,x) calculates
  1256. % the resultant of the two distributive polynomials h1 and h0
  1257. % with respect to x.
  1258. begin scalar ct00,hh,hh1,hs2;
  1259. if !*trgroeb then << ct00:= time() >>;
  1260. hh:= dipmonic newhpol(h1,h0,x);
  1261. if !*trgroeb then << prin2 " resultant "; terprit 2;
  1262. dipprint hh; terprit 4 >>; hs2:= nil;
  1263. if not dipzero!? hh then << hh1:= dip2a diprectoint(hh,diplcm hh);
  1264. hh1:= factorf !*q2f simp hh1;
  1265. if !*trgroeb then << prin2 " resultant factorized: "; terprit 2;
  1266. dfcprin hh1; terprit 2;
  1267. ct00:= time() - ct00;
  1268. prin2 " special time for h: "; prin2 ct00;
  1269. terpri() >>;
  1270. hs2:= makdiplist cdr hh1 >>;
  1271. return hs2
  1272. end;
  1273. expr procedure maklistd1(x1,x2,x3,x4,x5,x6);
  1274. % make list d1. save part time problems.
  1275. begin scalar x,h1;
  1276. while x1 do << h1:= car x1; x1:= cdr x1;
  1277. x:= list(x2,x3,
  1278. (dipindexpolopt(nil,nconc(list list(x2,h1),x4))),
  1279. (nconc(list h1,x5)),
  1280. (dipcplistmerge(dipcplistsort
  1281. dipcpairlistopt dipcplistopt2(nil,dipcplistadd(x2,h1,x4)),
  1282. dipcpairlistopt1(h1,x6,x6)))) . x >>;
  1283. return x
  1284. end;
  1285. expr procedure dipmingbasein1 (pl1,pl2);
  1286. % /* Distributive polynomial minimal ordered Groebner base internal1.
  1287. % pl1 and pl2 are lists of distributive polynomials.
  1288. % dipmingbasein1(pl1,pl2) is used in dipmingbase and returns a list
  1289. % of distributive polynomials. */
  1290. if null pl2 then pl1
  1291. else ( if dipzero!? dipnorformsel(ep, pl1)
  1292. and dipzero!? dipnorformsel(ep,cpl2)
  1293. then dipmingbasein1( cons(p, pl1), cpl2)
  1294. else dipmingbasein1( pl1, cpl2)
  1295. ) where ep = dipevlmon p,
  1296. cpl2 = cdr pl2
  1297. where p = car pl2;
  1298. expr procedure dipmingbasein2 (pl1,pl2);
  1299. % /* Distributive polynomial minimal ordered Groebner base internal2.
  1300. % pl1 and pl2 are lists of distributive polynomials.
  1301. % dipmingbasein2(pl1,pl2) is used in dipmingbase and returns a list
  1302. % of distributive polynomials. */
  1303. if null pl2 then pl1
  1304. else ( dipmingbasein2(dipnorform(pl1,dipnorform(rp, p)) . pl1,
  1305. rp) )
  1306. where p = car pl2,
  1307. rp = cdr pl2;
  1308. expr procedure dipnorform (pl,p);
  1309. % /* Distributive polynom normalform. pl is a list of distributive
  1310. % polynomials, p is a distributive polynomial. dipnorform(pl,p)
  1311. % calculates a distributive polynomial such that the distributive
  1312. % polynomial p is reducible to this modulo the distributive
  1313. % polynomial list pl and is in normalform with respect to the
  1314. % distributive polynomial p and returns a distributive polynomial. */
  1315. if dipzero!? p or null pl then p
  1316. else ( if dipzero!? q then dipmoncomp(diplbc p,
  1317. ep,
  1318. dipnorform(pl,
  1319. dipmred p) )
  1320. else ( if dipzero!? rq then dipnorform(pl, dipmred p)
  1321. else dipnorform(pl,
  1322. dipdif(dipmred p,
  1323. dipprod(rq,
  1324. dipfmon(bcquot(diplbc p,
  1325. diplbc q),
  1326. evdif(ep,
  1327. dipevlmon q) ) ) ) )
  1328. ) where rq = dipmred q
  1329. ) where q = dipnorformsel(ep, pl)
  1330. where ep = dipevlmon p;
  1331. expr procedure dipnorformsel (ep,pl);
  1332. % /* Distributive polynom normalform select. ep is an exponent vector
  1333. % of a distributive polynomial. pl is a list of distributive
  1334. % polynomials. dipnorformsel(ep,pl) returns a distributive
  1335. % polynomial of pl where ep is a multiple of the leading
  1336. % exponent vector else dipzero. */
  1337. if null pl then dipzero
  1338. else ( if evmtest!?(ep, dipevlmon q) then q
  1339. else dipnorformsel(ep, cdr pl)
  1340. ) where q = car pl;
  1341. expr procedure dipspolynom (p1,p2);
  1342. % /* Distributive polynom S polynom. p1 and p2 are distributive
  1343. % polynomials. dipspolynom(p1,p2) calculates the S polynom of the
  1344. % distributive polynomials p1 and p2 and returns a distributive
  1345. % polynomial. */
  1346. if dipzero!? p1 or dipzero!? p2 then dipzero
  1347. else ( if dipzero!? rp1 and dipzero!? rp2 then rp1
  1348. else ( if dipzero!? rp1 then
  1349. dipprod(rp2,
  1350. dipfmon(bcneg diplbc p1,
  1351. evdif(ep, ep2) ) )
  1352. else if dipzero!? rp2 then
  1353. dipprod(rp1,
  1354. dipfmon(diplbc p2,
  1355. evdif(ep, ep1) ) )
  1356. else dipdif(
  1357. dipprod(rp2,
  1358. dipfmon(diplbc p1,
  1359. evdif(ep, ep2) ) ),
  1360. dipprod(rp1,
  1361. dipfmon(diplbc p2,
  1362. evdif(ep, ep1) ) )
  1363. )
  1364. ) where ep = evlcm(ep1, ep2)
  1365. where ep1 = dipevlmon p1,
  1366. ep2 = dipevlmon p2
  1367. ) where rp1 = dipmred p1,
  1368. rp2 = dipmred p2;
  1369. expr procedure delqip1(u,v);
  1370. if pairp cdr v
  1371. then if u eq cadr v then rplacd(v,cddr v) else delqip1(u,cdr v);
  1372. expr procedure delqip(u,v);
  1373. % /*Destructive delete of first occurrence of u in v*/
  1374. if not pairp v then v
  1375. else if u eq car v then cdr v
  1376. else <<delqip1(u,v); v>>;
  1377. endmodule;
  1378. module dipopt;
  1379. % /* Authors: R. Gebauer, A. C. Hearn, H. Kredel */
  1380. fluid '(!*trbas dipvars!*);
  1381. %define ezero = 'nil;
  1382. fluid '(dipzero ezero);
  1383. %/*Until we understand how to define something to nil*/
  1384. expr procedure dipoptmat1 (el,dpl);
  1385. % /* Distributive optimisation matrix subfunction 1. el is an
  1386. % exponent vector, dpl is a degree matix. dipoptmat1(el,dpl)
  1387. % returns the addition of el to dpl. */
  1388. if null el then dpl
  1389. else dipsum ( dipfmon (bcfi 1,
  1390. evcons(evfirst el, ezero)), car dpl)
  1391. . dipoptmat1(evred el, cdr dpl);
  1392. expr procedure dipoptmat2 (p,pl);
  1393. % /* Distributive optimisation matrix subfunction 2. p is a
  1394. % distributive polynomial, pl is a list of distributive
  1395. % polynomials. dipoptmat1 is used. */
  1396. if dipzero!? p then pl
  1397. else dipoptmat2(dipmred p, dipoptmat1(dipevlmon p, pl));
  1398. expr procedure dipoptmat3 (p,pl);
  1399. % /* Distributive optimisation matrix subfunction 3. p is a
  1400. % distributive polynomial, pl is a list of distributive
  1401. % polynomials. dipoptmat2 is used. */
  1402. if null p then pl
  1403. else dipoptmat3(cdr p, dipoptmat2(car p, pl));
  1404. expr procedure dipoptmat pl;
  1405. % /* Distributive optimisation matrix. pl is a list of distributive
  1406. % polynomials. dipoptmat(pl) returns the optimisation matrix
  1407. % ( a degree matrix ) of pl, a list of univariate distributive
  1408. % polynomials. */
  1409. if null pl then nil
  1410. else dipoptmat3(pl, for each x in dipvars!* collect dipzero);
  1411. expr procedure dipless!? (p1,p2);
  1412. % /* Distributive polynomial less. p1 and p2 are distributive
  1413. % polynomials. dipless!?(p1,p2) returns a boolean expression,
  1414. % true if p1 is less than p2 else false. */
  1415. if dipzero!? p1 and dipzero!? p2 then nil
  1416. else if not dipzero!? p1 then
  1417. if not dipzero!? p2 then
  1418. ( if sl < 0 then t
  1419. else if sl > 0 then nil
  1420. else ( if bl < 0 then t
  1421. else if bl > 0 then nil
  1422. else dipless!?(dipmred p1, dipmred p2)
  1423. ) where bl = bccomp(diplbc p1, diplbc p2)
  1424. ) where sl = evcomp(dipevlmon p1, dipevlmon p2)
  1425. else t
  1426. else nil;
  1427. expr procedure pvdema pl;
  1428. % /* Permutation vector degree matrix. pl is a list of univariate
  1429. % polynomials in distributive representation. pvdema(pl) returns
  1430. % a list ( indexlist ) where the elements are digits.*/
  1431. pvdema2 sort(pvdema1(pl, 1), 'pvdema3);
  1432. expr procedure pvdema1(pl,n);
  1433. % /* Permutation vector degree matrix subfunction 1. pl is a list
  1434. % of univariate distributive polynomials, n is a digit.
  1435. % pvdema1 changes the internal structure ( add index for each
  1436. % polynomial ) and is used in pvdema. */
  1437. if null pl then pl
  1438. else list(car pl, n) . pvdema1(cdr pl, n + 1);
  1439. expr procedure pvdema2(pl);
  1440. % /* Permutation vector degree matrix subfunction 2. pl is a list of
  1441. % univariate distributive polynomials. pvdema2(pl) changes the
  1442. % internal structure ( delete index for each polynomial ) and
  1443. % is used in pvdema. */
  1444. if null pl then pl
  1445. else nconc(cdar pl, pvdema2(cdr pl));
  1446. expr procedure pvdema3 (p1,p2);
  1447. % /* Permutation vector degree matrix subfunction 3. p1 and p2 are
  1448. % distributive univariate polynomials. pvdema3(p1,p2) returns
  1449. % a boolean expression, true if the distributive polynomial p1
  1450. % is less than the distributive polynomial p2 else false. */
  1451. dipless!?(car p1, car p2);
  1452. expr procedure listperm (v,n);
  1453. % /* List permutation. v is a list ( any kind ) and n is an indexlist.
  1454. % listperm(v,n) permutates v in respect to n and returns a
  1455. % permutated list v. */
  1456. if null n then nil
  1457. else nth(v, car n) . listperm(v, cdr n);
  1458. expr procedure dipreorder (p,n);
  1459. % /* Distributive polynomial reorder. p is a distributive polynomial,
  1460. % n is an indexlist. dipreorder(p,n) reorders the exponent vectors
  1461. % of each term of p in respect to the indexlist n and returns a
  1462. % distributive polynomial. */
  1463. if dipzero!? p then nil
  1464. else dipsum(dipfmon(diplbc p, evperm(dipevlmon p, n)),
  1465. dipreorder(dipmred p, n));
  1466. expr procedure diplreorder (pl,n);
  1467. % /* Distributive polynomial list reorder. pl is a list of distributive
  1468. % polynomials and n is an indexlist. diplreorder(pl,n) reorders the
  1469. % exponent vectors of each term of each polynomial in the list pl in
  1470. % respect to the indexlist n and returns a list of distributive
  1471. % polynomials.*/
  1472. for each x in pl collect dipreorder(x, n);
  1473. expr procedure dipvordopt pl;
  1474. % /* Distributive polynomial variable ordering optimisation.
  1475. % pl is a list of distributive polynomials. dipvordopt(pl)
  1476. % calculates the " optimal representation " and returns a list
  1477. % of distributive polynomials.
  1478. % NOTE: dipvordopt can change the global variable list dipvars!* */
  1479. begin scalar n,olddipvars,pl1;
  1480. n := pvdema diopmatin pl;
  1481. if !*trbas then << prin2t " The new index list :";
  1482. terprit 2; prin2t n; terprit 2 >>;
  1483. olddipvars := dipvars!*;
  1484. dipvars!* := listperm(dipvars!*, n);
  1485. if !*trbas then << prin2t " The new variable list :";
  1486. terprit 2; prin2t dipvars!*; terprit 2 >>;
  1487. pl1 := diplreorder(pl, n);
  1488. if !*trbas then << prin2t " The new polynomial list :";
  1489. terprit 2; diplprint pl1; terprit 2 >>;
  1490. % dipvars!* := olddipvars;
  1491. return pl1
  1492. end;
  1493. expr procedure diopmatin pl;
  1494. % print univariate polynomials.
  1495. begin scalar n1;
  1496. << if !*trbas then << prin2t " The variable list :";
  1497. terprit 2; prin2t dipvars!*; terprit 2;
  1498. prin2t " The univariate polynomials in each variable :";
  1499. terprit 2 >>; n1:=dipoptmat pl;
  1500. if !*trbas then << dioprin(n1,dipvars!*) >> >>;
  1501. return n1
  1502. end;
  1503. expr procedure dioprin(pl,d);
  1504. % print variables.
  1505. begin scalar dipvars!*;
  1506. for each x in pair(pl,d)
  1507. do << dipvars!* := list cdr x; dipprint car x >>
  1508. end;
  1509. endmodule;
  1510. end;