torder.red 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. module torder; % Term order modes for distributive polynomials.
  2. % H. Melenk, ZIB Berlin.
  3. % The routines of this module should be coded as efficiently as
  4. % possible.
  5. fluid '(dipsortmode!* dipsortevcomp!* olddipsortmode!* dipvars!*);
  6. fluid '(vdpsortmode!* vdpsortextension!* vdpmatrix!* global!-dipvars!*
  7. compiled!-orders!*);
  8. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  9. % switching between term order modes: TORDER statement.
  10. %
  11. global!-dipvars!*:='(list);
  12. symbolic procedure torder u;
  13. begin scalar oldmode,oldex,oldvars,w;
  14. oldmode := vdpsortmode!*; oldex := vdpsortextension!*;
  15. oldvars := global!-dipvars!*;
  16. global!-dipvars!* := '(list);
  17. a:
  18. w:=reval car u; u:=cdr u;
  19. if eqcar(w,'list) and null u then<<u:=cdr w; goto a>>;
  20. if eqcar(w,'list) then
  21. <<global!-dipvars!*:=w; w:=reval car u; u:=cdr u>>;
  22. vdpsortmode!* := w;
  23. % dipsortevcomp!* := get(w, 'evcomp);
  24. vdpsortextension!* := for each x in u join
  25. (if eqcar(x:=reval x,'list) then cdr x else {x});
  26. if flagp(vdpsortmode!*,'dipsortextension) and null vdpsortextension!*
  27. then rederr "term order needs additional parameter(s)";
  28. return 'list . oldvars . oldmode . oldex;
  29. end;
  30. remprop('torder,'number!-of!-args);
  31. put('torder,'psopfn,'torder);
  32. symbolic procedure dipsortingmode u;
  33. % /* Sets the exponent vector sorting mode. Returns the previous mode*/
  34. begin scalar x,z;
  35. if not idp u or not flagp(u,'dipsortmode)
  36. then return typerr(u,"term ordering mode");
  37. x := dipsortmode!*; dipsortmode!* := u;
  38. % saves thousands of calls to GET;
  39. dipsortevcomp!* := get(dipsortmode!*,'evcomp);
  40. if not getd dipsortevcomp!* then
  41. rerror(dipoly,2,
  42. "No compare routine for term order mode found");
  43. if (z:=get(dipsortmode!*,'evcompinit)) then apply(z,nil);
  44. if (z:=get(dipsortmode!*,'evlength)) and z neq length dipvars!*
  45. then rederr
  46. "wrong variable number for fixed length term order";
  47. return x
  48. end;
  49. flag('(lex gradlex revgradlex),'dipsortmode);
  50. put('lex,'evcomp,'evlexcomp);
  51. put('gradlex,'evcomp,'evgradlexcomp);
  52. put('revgradlex,'evcomp,'evrevgradlexcomp);
  53. symbolic procedure evcompless!?(e1,e2);
  54. % Exponent vector compare less. e1, e2 are exponent vectors
  55. % in some order. Evcompless? is a boolean function which returns
  56. % true if e1 is ordered less than e2.
  57. % Mapped to evcomp
  58. 1 = evcomp(e2,e1);
  59. symbolic procedure evcomp (e1,e2);
  60. % Exponent vector compare. e1, e2 are exponent vectors in some
  61. % order. Evcomp(e1,e2) returns the digit 0 if exponent vector e1 is
  62. % equal exponent vector e2, the digit 1 if e1 is greater than e2,
  63. % else the digit -1. This function is assigned a value by the
  64. % ordering mechanism, so is dummy for now.
  65. % IDapply would be better here, but is not within standard LISP!
  66. apply(dipsortevcomp!*,list(e1,e2));
  67. symbolic procedure evlexcomp (e1,e2);
  68. % /* Exponent vector lexicographical compare. The
  69. % exponent vectors e1 and e2 are in lexicographical
  70. % ordering. evLexComp(e1,e2) returns the digit 0 if exponent
  71. % vector e1 is equal exponent vector e2, the digit 1 if e1 is
  72. % greater than e2, else the digit -1. */
  73. if null e1 then 0
  74. else if null e2 then evlexcomp(e1,'(0))
  75. else if car e1 #= car e2 then evlexcomp(cdr e1,cdr e2)
  76. else if car e1 #> car e2 then 1
  77. else -1;
  78. symbolic procedure evinvlexcomp (e1,e2);
  79. % Exponent vector inverse lexicographical compare.
  80. if null e1 then
  81. if null e2 then 0 else evinvlexcomp('(0),e2)
  82. else if null e2 then evlexcomp(e1,'(0))
  83. else if car e1 #= car e2 then evinvlexcomp(cdr e1,cdr e2)
  84. else (if not(n#=0) then n
  85. else if car e2 eq car e1 then 0
  86. else if car e2 #> car e1 then 1
  87. else -1) where n = evinvlexcomp(cdr e1,cdr e2);
  88. symbolic procedure evgradlexcomp (e1,e2);
  89. % /* Exponent vector graduated lex compare.
  90. % The exponent vectors e1 and e2 are in graduated lex
  91. % ordering. evGradLexComp(e1,e2) returns the digit 0 if exponent
  92. % vector e1 is equal exponent vector e2, the digit 1 if e1 is
  93. % greater than e2, else the digit -1. */
  94. if null e1 then 0
  95. else if null e2 then evgradlexcomp(e1,'(0))
  96. else if car e1 #= car e2 then evgradlexcomp(cdr e1, cdr e2)
  97. else (if te1#=te2 then if car e1 #> car e2 then 1 else -1
  98. else if te1 #> te2 then 1 else -1)
  99. where te1 = evtdeg e1, te2 = evtdeg e2;
  100. symbolic procedure evrevgradlexcomp (e1,e2);
  101. % /* Exponent vector reverse graduated lex compare.
  102. % The exponent vectors e1 and e2 are in reverse graduated lex
  103. % ordering. evRevGradLexcomp(e1,e2) returns the digit 0 if exponent
  104. % vector e1 is equal exponent vector e2, the digit 1 if e1 is
  105. % greater than e2, else the digit -1. */
  106. if null e1 then 0
  107. else if null e2 then evrevgradlexcomp(e1,'(0))
  108. else if car e1 #= car e2 then evrevgradlexcomp(cdr e1, cdr e2)
  109. else (if te1 #= te2 then evinvlexcomp(e1,e2)
  110. else if te1 #> te2 then 1 else -1)
  111. where te1 = evtdeg e1, te2 = evtdeg e2;
  112. symbolic procedure evtdeg e1;
  113. % /* Exponent vector total degree. e1 is an exponent vector.
  114. % evtdeg(e1) calculates the total degree of the exponent
  115. % e1 and returns an integer. */
  116. (<<while e1 do <<x := car e1 #+ x; e1 := cdr e1>>; x>>) where x = 0;
  117. % The following section contains additional term order modes.
  118. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  119. %
  120. % gradlexgradlex
  121. %
  122. % this order can have several steps
  123. % torder gradlexgradlex,3,2,4;
  124. %
  125. flag ('(gradlexgradlex),'dipsortmode);
  126. flag ('(gradlexgradlex),'dipsortextension);
  127. put('gradlexgradlex,'evcomp,'evgradgradcomp);
  128. symbolic procedure evgradgradcomp (e1,e2);
  129. evgradgradcomp1 (e1,e2,car vdpsortextension!*,
  130. cdr vdpsortextension!*);
  131. symbolic procedure evgradgradcomp1 (e1,e2,n,nl);
  132. if null e1 then 0
  133. else if null e2 then evgradgradcomp1(e1,'(0),n,nl)
  134. else if n#=0 then if null nl then evgradlexcomp(e1,e2)
  135. else evgradgradcomp1 (e1,e2,car nl,cdr nl)
  136. else if car e1 #= car e2 then
  137. evgradgradcomp1(cdr e1,cdr e2,n#-1,nl)
  138. else (if te1 #= te2 then if car e1 #> car e2 then 1 else -1
  139. else if te1 #> te2 then 1 else -1)
  140. where te1 = evpartdeg(e1,n), te2 = evpartdeg(e2,n);
  141. symbolic procedure evpartdeg(e1,n); evpartdeg1(e1,n,0);
  142. symbolic procedure evpartdeg1(e1,n,sum);
  143. if n #= 0 or null e1 then sum
  144. else evpartdeg1(cdr e1,n #-1, car e1 #+ sum);
  145. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  146. %
  147. % gradlexrevgradlex
  148. %
  149. %
  150. flag ('(gradlexrevgradlex),'dipsortmode);
  151. flag ('(gradlexrevgradlex),'dipsortextension);
  152. put('gradlexrevgradlex,'evcomp,'evgradrevgradcomp);
  153. symbolic procedure evgradrevgradcomp (e1,e2);
  154. evgradrevgradcomp1 (e1,e2,car vdpsortextension!*);
  155. symbolic procedure evgradrevgradcomp1 (e1,e2,n);
  156. if null e1 then 0
  157. else if null e2 then evgradrevgradcomp1(e1,'(0),n)
  158. else if n#=0 then evrevgradlexcomp(e1,e2)
  159. else if car e1 #= car e2 then evgradrevgradcomp1(cdr e1,cdr e2,n#-1)
  160. else (if te1 #= te2 then if car e1 #< car e2 then 1 else -1
  161. else if te1 #> te2 then 1 else -1)
  162. where te1 = evpartdeg(e1,n), te2 = evpartdeg(e2,n);
  163. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  164. %
  165. % LEXGRADLEX
  166. %
  167. %
  168. flag ('(lexgradlex),'dipsortmode);
  169. flag ('(lexgradlex),'dipsortextension);
  170. put('lexgradlex,'evcomp,'evlexgradlexcomp);
  171. symbolic procedure evlexgradlexcomp (e1,e2);
  172. evlexgradlexcomp1 (e1,e2,car vdpsortextension!*);
  173. symbolic procedure evlexgradlexcomp1 (e1,e2,n);
  174. if null e1 then (if evzero!? e2 then 0 else -1)
  175. else if null e2 then evlexgradlexcomp1(e1,'(0),n)
  176. else if n#=0 then evgradlexcomp(e1,e2)
  177. else if car e1 #= car e2 then evlexgradlexcomp1(cdr e1,cdr e2,n#-1)
  178. else if car e1 #> car e2 then 1 else -1;
  179. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  180. %
  181. % LEXREVGRADLEX
  182. %
  183. %
  184. flag ('(lexrevgradlex),'dipsortmode);
  185. flag ('(lexrevgradlex),'dipsortextension);
  186. put('lexrevgradlex,'evcomp,'evlexrevgradlexcomp);
  187. symbolic procedure evlexrevgradlexcomp (e1,e2);
  188. evlexrevgradlexcomp1 (e1,e2,car vdpsortextension!*);
  189. symbolic procedure evlexrevgradlexcomp1 (e1,e2,n);
  190. if null e1 then (if evzero!? e2 then 0 else -1)
  191. else if null e2 then evlexrevgradlexcomp1(e1,'(0),n)
  192. else if n#=0 then evrevgradlexcomp(e1,e2)
  193. else if car e1 #= car e2 then
  194. evlexrevgradlexcomp1(cdr e1,cdr e2,n#-1)
  195. else if car e1 #> car e2 then 1 else -1;
  196. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  197. %
  198. % WEIGHTED
  199. %
  200. %
  201. flag ('(weighted),'dipsortmode);
  202. flag ('(weighted),'dipsortextension);
  203. put('weighted,'evcomp,'evweightedcomp);
  204. symbolic procedure evweightedcomp (e1,e2);
  205. (if dg1 #= dg2 then evlexcomp(e1,e2) else
  206. if dg1 #> dg2 then 1 else -1
  207. ) where dg1=evweightedcomp2(0,e1,vdpsortextension!*),
  208. dg2=evweightedcomp2(0,e2,vdpsortextension!*);
  209. symbolic procedure evweightedcomp1 (e,w); evweightedcomp2(0, e, w);
  210. symbolic procedure evweightedcomp2 (n,e,w);
  211. % scalar product of exponent and weight vector
  212. if null e then n else
  213. if null w then evweightedcomp2(n, e, '(1 1 1 1 1)) else
  214. if car w = 0 then evweightedcomp2(n, cdr e, cdr w) else
  215. if car w = 1 then evweightedcomp2(n #+ car e, cdr e, cdr w) else
  216. evweightedcomp2(car e #* car w #+ n, cdr e, cdr w);
  217. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  218. %
  219. % GRADED term order
  220. % cascading a graded sorting with another term order.
  221. %
  222. % The grade of a term is defined as a scalar product of the exponent
  223. % vector and a grade vector which contains non-negative integers.
  224. % In contrast to a weight vector the grade vector may contain also
  225. % zeros. A vector of ones is used if no vector is given explicitly.
  226. %
  227. fluid '(gradedrec!*);
  228. flag ('(graded),'dipsortmode);
  229. flag ('(graded),'dipsortextension);
  230. put('graded,'evcomp,'evgradedcomp);
  231. put('graded,'evcompinit,'evgradedinit);
  232. symbolic procedure evgradedinit();
  233. begin scalar w,gvect,vse;
  234. vse:=vdpsortextension!*;
  235. while pairp vdpsortextension!* and numberp car vdpsortextension!*
  236. do <<gvect:=car vdpsortextension!* . gvect;
  237. vdpsortextension!* := cdr vdpsortextension!*>>;
  238. if vdpsortextension!* then
  239. <<w:=car vdpsortextension!*;
  240. vdpsortextension!* := cdr vdpsortextension!*>>
  241. else w:='lex;
  242. dipsortingmode w;
  243. gradedrec!*:={reversip gvect,dipsortevcomp!*,vdpsortextension!*};
  244. dipsortevcomp!* := 'evgradedcomp;
  245. dipsortmode!* := 'graded;
  246. vdpsortextension!* := vse;
  247. end;
  248. symbolic procedure evgradedcomp (e1,e2);
  249. (if dg1 #= dg2 then
  250. apply(cadr gradedrec!*,{e1,e2})
  251. where vdpsortextension!*=caddr gradedrec!*
  252. else
  253. if dg1 #> dg2 then 1 else -1
  254. ) where dg1=ev!-gamma e1, dg2=ev!-gamma e2;
  255. symbolic procedure ev!-gamma(ev);
  256. % compute the grade of an exponent vector;
  257. evweightedcomp1 (ev,
  258. if dipsortmode!* = 'graded then car gradedrec!* else
  259. if dipsortmode!* = 'weighted then vdpsortextension!* else
  260. nil);
  261. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  262. %
  263. % MATRIX
  264. %
  265. %
  266. % In the following routines I assume that 99 percent of the matrix
  267. % entries will be 0 or 1 such that the special branches for these
  268. % numbers makes sense. We save lots of memory read and
  269. % multiplication is needed only entries other than 0 and 1.
  270. %
  271. % I could do the same optimization step for -1, but I don't
  272. % expect that many people will use term orders with negative
  273. % numbers.
  274. %
  275. % This package includes a compilation mode for matrix term orders
  276. % for fixed length variable lists. Compilation is done implicilty
  277. % when *comp is on, or explicitly by callint torder_compile.
  278. flag ('(matrix),'dipsortmode);
  279. flag ('(matrix),'dipsortextension);
  280. put('matrix,'evcomp,'evmatrixcomp);
  281. put('matrix,'evcompinit,'evmatrixinit);
  282. symbolic procedure evmatrixcomp(e1,e2);
  283. evmatrixcomp1(e1,e2,vdpmatrix!*);
  284. symbolic procedure evmatrixcomp1(e1,e2,m);
  285. if null m then 0 else
  286. (if w1 #= w2 then evmatrixcomp1(e1,e2,cdr m) else % #=
  287. if w1 #> w2 then 1 else -1)
  288. where
  289. w1= evmatrixcomp2 (e1,car m,0),
  290. w2= evmatrixcomp2 (e2,car m,0);
  291. symbolic procedure evmatrixcomp2(e,l,w);
  292. if null e or null l then w else
  293. (if l1 #= 0 then
  294. evmatrixcomp2(cdr e,cdr l,w) else
  295. if l1 #= 1 then
  296. evmatrixcomp2(cdr e,cdr l,w #+ car e)
  297. else evmatrixcomp3(e,l1,l,w)) where l1=car l;
  298. symbolic procedure evmatrixcomp3(e,l1,l,w);
  299. evmatrixcomp2(cdr e,cdr l,w #+ car e #* l1);
  300. symbolic procedure evmatrixinit1(w,mode);
  301. begin scalar m,mm;
  302. if not eqcar(w,'mat) or
  303. mode and length cadr w neq length dipvars!* then
  304. typerr(w,"term order matrix for". dipvars!*);
  305. for each row in cdr w do
  306. <<row:=for each c in row collect ieval c;
  307. mm:=row . mm;
  308. row:=reverse row;
  309. while eqcar(row,0) do row := cdr row;
  310. m:=reversip row . m>>;
  311. m:=reversip m; mm:=reversip mm;
  312. if m neq vdpmatrix!* then
  313. <<if length cadr w > length cdr w then
  314. lprim "Warning: non-square matrix used in torder"
  315. else if 0=reval{'det,w} then
  316. typerr(w,"term order (singular matrix)");
  317. if not evmatrixcheck mm then
  318. typerr(w,"term order (non admissible)")
  319. >>;
  320. return m
  321. end;
  322. symbolic procedure evmatrixinit();
  323. begin scalar c,m,w;
  324. w:=reval car vdpsortextension!*;
  325. m:=evmatrixinit1(w,t);
  326. if (c:=assoc(m,compiled!-orders!*)) then
  327. dipsortevcomp!* := cdr c else
  328. if !*comp then dipsortevcomp!* := evmatrixcompile m;
  329. vdpmatrix!*:=m;
  330. end;
  331. symbolic procedure evmatrixcheck m;
  332. % Check the usability of the term order matrix: the
  333. % top elements of each column must be positive. This
  334. % approach goes back to a recommendation of J. Apel.
  335. begin scalar bad,c,w;
  336. integer i,j,r;
  337. r:=length m;
  338. for i:=1:length car m do
  339. <<c:=nil;
  340. for j:=1:r do
  341. if (w:=nth(nth(m,j),i)) neq 0 and null c then
  342. <<c:=t; bad:=w < 0>>
  343. >>;
  344. return not bad;
  345. end;
  346. symbolic procedure evmatrixcompile m;
  347. begin scalar w;
  348. w:= evmatrixcompile1 m;
  349. putd(car w,'expr,caddr w);
  350. compiled!-orders!* := (m.car w).compiled!-orders!*;
  351. return car w;
  352. end;
  353. symbolic procedure evmatrixcompile1 m;
  354. begin scalar c,n,x,w,lvars,code;
  355. integer ld,p,k;
  356. for each row in m do k:=max(k,length row);
  357. lvars := for i:=1:k collect gensym();
  358. code := {{'setq,car lvars,
  359. '(idifference (car e1) (car e2))}};
  360. ld:=1;
  361. for each row in m do
  362. <<p:=0; w:=nil;
  363. while row do
  364. <<c:=car row; row := cdr row; p:=p+1;
  365. if c neq 0 then
  366. << % load the differences up to the current point.
  367. for i:=ld+1:p do
  368. << code:= append(code,'((setq e1(cdr e1))(setq e2(cdr e2))));
  369. code := append(code,
  370. {{'setq,nth(lvars,i),
  371. '(idifference (car e1) (car e2))}});
  372. ld:=i; >>;
  373. % collect the terms of the row sum
  374. x:=nth(lvars,p);
  375. if c = -1 then x := {'iminus,x} else
  376. if c neq 1 then x:={'itimes2,c,x};
  377. w:=if w then {'iplus2,x,w} else x >>;
  378. >>;
  379. if not atom w then
  380. <<code:=append(code,{{'setq,'w,w}});w:='w>>;
  381. code:=append(code,
  382. {{'cond,{{'iequal,w,0},t},
  383. {{'igreaterp,w,0},'(return 1)},
  384. '(t (return -1))}}); >>;
  385. % common trailor
  386. code:=append(code,'((return 0)));
  387. n:=gensym();
  388. return {n,k,evform {'lambda,'(e1 e2), 'prog.('w.lvars). code}}
  389. end;
  390. symbolic procedure evform(u);
  391. % Let form play on the generated code;
  392. form1(u,nil,'symbolic);
  393. symbolic procedure torder_compile_form(w,c,m);
  394. begin scalar n;
  395. if length w < 3 then rederr "illegal arguments";
  396. m:=evmatrixinit1(eval form caddr w,nil);
  397. c:=evmatrixcompile1 m;
  398. n:=eval form cadr w;
  399. return
  400. {'progn,
  401. {'putd,mkquote n,mkquote 'expr,mkquote caddr c},
  402. {'setq,'compiled!-orders!*,
  403. {'cons,{'cons,mkquote m,mkquote n}, 'compiled!-orders!*}},
  404. {'put,mkquote n,''evcomp,mkquote n},
  405. {'put,mkquote n,''evlength,cadr c},
  406. {'flag,mkquote{n},''dipsortmode}, mkquote n}
  407. end;
  408. put('torder_compile,'formfn,'torder_compile_form);
  409. endmodule;
  410. end;