torder.red 16 KB

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