vdp2dip.red 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982
  1. module vdp2dip;
  2. imports dipoly;
  3. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  4. %
  5. % interface for Virtual Distributive Polynomials (VDP)
  6. %
  7. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  8. % "Distributive representation" with respect to a given set of
  9. % variables ("vdpvars") means for a polynomial, that the polynomial
  10. % is regarded as a sequence of monomials, each of which is a
  11. % product of a "coefficient" and of some powers of the variables.
  12. % This internal representation is very closely connected to the
  13. % standard external (printed) representation of a polynomial in
  14. % REDUCE if nothing is factored out. The monomials are logically
  15. % ordered by a term order mode based on the ordering which is
  16. % given bye the sequence "vdpvars"; with respect to this ordering
  17. % the representation of a polynomial is unique. The "highest" term
  18. % is the car one. Monomials are represented by their coefficient
  19. % ("vbc") and by a vector of the exponents("vev") (in the order
  20. % corresponding to the vector vars). The distributive representation
  21. % is good for those algorithms, which base their decisions on the
  22. % complete ledading monomial: this representation guarantees a
  23. % fast and uniform access to the car monomial and to the reductum
  24. % (the cdr of the polynomial beginning with the cadr monomial).
  25. % The algorithms of the Groebner package are of this type. The
  26. % interface defines the distributive polynomials as abstract data
  27. % objects via their acess functions. These functions map the
  28. % distributive operations to an arbitrary real data structure
  29. % ("virtual"). The mapping of the access functions to an actual
  30. % data structure is cdrricted only by the demand, that the typical
  31. % "distributive operations" be efficient. Additionally to the
  32. % algebraic value a VDP object has a property list. So the algorithms
  33. % using the VDP interface can assign name-value-pairs to individual
  34. % polynomials. The interface is defined by a set of routines which
  35. % create and handle the distributive polynomials. In general the
  36. % first letters of the routine name classifies the data its works on:
  37. % vdp... complete virt. polynomial objects
  38. % vbc... virt. base coefficients
  39. % vev... virt. exponent vectors
  40. % 0. general control
  41. %
  42. % vdpinit(dv) initialises the vdp package for the variables
  43. % given in the list "dv". vdpinit modifies the
  44. % torder and returns the prvevious torder as its
  45. % result. vdpinit sets the global variable
  46. % vdpvars!*;
  47. % 1. conversion
  48. %
  49. % a2vdp algebraic (prefix) to vdp
  50. % f2vdp standard form to vdp
  51. % a2vbc algebraic (prefix) to vbc
  52. % vdp2a vdp to algebraic (prefix)
  53. % vdp2f vdp to standard form
  54. % vbc2a vbc to algebraic (prefix)
  55. % 2. composing/decomposing
  56. %
  57. % vdpfmon make a vdp from a vbc and an vev
  58. % vdpMonComp add a monomial (vbc and vev) to the front of a vdp
  59. % vdpAppendMon add a monomial (vbc and vev) to the bottom of a vdp
  60. % vdpMonAdd add a monomial (vbc and vev) to a vdp, not yet
  61. % knowing the place of the insertion
  62. % vdpAppendVdp concat two vdps
  63. %
  64. % vdpLbc extract leading vbc
  65. % vdpevlmon extract leading vev
  66. % vdpred reductum of vdp
  67. % vdplastmon last monomial of polynomial
  68. % vevnth nth element from exponent vector
  69. % 3. testing
  70. %
  71. % vdpZero? test vdp = 0
  72. % vdpredZero!? test rductum of vdp = 0
  73. % vdpOne? test vdp = 1
  74. % vevZero? test vev = (0 0 ... 0)
  75. % vbczero? test vbc = 0
  76. % vbcminus? test vbc <= 0 (not decidable for algebraic vbcs)
  77. % vbcplus? test vbc >= 0 (not decidable for algebraic vbcs)
  78. % vbcone!? test vbc = 1
  79. % vbcnumberp test vbc is a numeric value
  80. % vevdivides? test if vev1 < vev2 elementwise
  81. % vevlcompless? test ordering vev1 < vev2
  82. % vdpvevlcomp calculate ordering vev1 / vev1: -1, 0 or +1
  83. % vdpEqual test vdp1 = vdp2
  84. % vdpMember member based on "vdpEqual"
  85. % vevequal test vev1 = vev2
  86. % 4. arithmetic
  87. %
  88. % 4.1 vdp arithmetic
  89. %
  90. % vdpsum vdp + vdp
  91. % special routines for monomials: see above (2.)
  92. % vdpdif vdp - vdp
  93. % vdpprod vdp * vdp
  94. % vdpvbcprod vbc * vdp
  95. % vdpDivMon vdp / (vbc,vev) divisability presumed
  96. % vdpCancelvev substitute all multiples of monomial (1,vev) in vdp by 0
  97. % vdpLcomb1 vdp1*(vbc1,vev1) + vdp2*(vbc2,vev2)
  98. % vdpContent calculate gcd over all vbcs
  99. % 4.2 vbc arithmetic
  100. %
  101. % vbcsum vbc1 + vbc2
  102. % vbcdif vbc1 - vbc2
  103. % vbcneg - vbc
  104. % vbcprod vbc1 * vbc2
  105. % vbcquot vbc1 / vbc2 divisability assumed if domain = ring
  106. % vbcinv 1 / vbc only usable in field
  107. % vbcgcd gcd(vbc1,vbc2) only usable in Euclidean field
  108. % 4.2 vev arithmetic
  109. %
  110. % vevsum vev1 + vev2 elementwise
  111. % vevdif vev1 - vev2 elementwise
  112. % vevtdeg sum over all exponents
  113. % vevzero generate a zero vev
  114. % 5. auxiliary
  115. %
  116. % vdpPutProp assign indicator-value-pair to vdp
  117. % the property "number" is used for printing.
  118. % vdpGetProp read value of indicator from vdp
  119. % vdplSort sort list of polynomials with respect to ordering
  120. % vdplSortIn sort a vdp into a sorted list of vdps
  121. % vdpprint print a vdp together with its number
  122. % vdpprin2t print a vdp "naked"
  123. % vdpprin3t print a vdp with closing ";"
  124. % vdpcondense replace exponent vectors by equal objects from
  125. % global list dipevlist!* in order to save memory
  126. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  127. %
  128. % RECORD STRUCTURE
  129. %
  130. % a virtual polynomial here is a record (list) with the entries
  131. % ('vdp <vdpevlmon> <vdplbc> <form> <plist>)
  132. %
  133. % 'vdp a type tag
  134. % <vdpevlmon> the exponents of the variables in the leading
  135. % leading monomial; the positions correspond to
  136. % the positions in vdpvars!*. Trailing zeroes
  137. % can be omitted.
  138. %
  139. % <lcoeff> the "coefficient" of the leading monomial, which
  140. % in general is a standard form.
  141. %
  142. % <form> the complete polynomial, e.g. as REDUCE standard form.
  143. %
  144. % <plist> an asso list for the properties of the polynomial
  145. %
  146. % The components should not be manipulated only via the interface
  147. % functions and macros, so that application programs remain
  148. % independent from the internal representation.
  149. % The only general assumption made on <form> is, that the zero
  150. % polynomial is represented as NIL. That is the case e.g. for both,
  151. % REDUCE standard forms and DIPOLYs.
  152. % Conventions for the usage:
  153. % -------------------------
  154. %
  155. % vdpint has to be called prveviously to all vdp calls. The list of
  156. % vdp paraemters is passed to vdpinit. The value of vdpvars!*
  157. % and the current torder must remain unmodfied afterwards.
  158. % usual are simple id's, e.g.
  159. %
  160. %
  161. % Modifications to vdpvars!* during calculations
  162. % ----------------------------------------------
  163. %
  164. % This mapping of vdp operations to standard forms offers the
  165. % ability to enlarge vdpvars during the calculation in order
  166. % to add new (intermediate) variables. Basis is the convention,
  167. % that exponent vectors logically have an arbitrary number
  168. % of trailing zeros. All routines processing exponent vectors
  169. % are able to handle varying length of exponent vectors.
  170. % A new call to vdpinit is necessary.
  171. %
  172. % During calculation vdpvars may be enlarged (new variables
  173. % suffixed) without needs to modify existing polynomials; only
  174. % korder has to be set to the new variable sequence.
  175. % modifications to the sequence in vdpvars requires a
  176. % new call to vdpinit and a reordering of exisiting
  177. % polynomials, e.g. by
  178. % vdpint newvdpvars;
  179. % f2vdp vdp2f p1; f2vdp vdp2f p2; .....
  180. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  181. %
  182. % DECLARATION SECTION
  183. %
  184. % this module must be present during code generation for modules
  185. % using the vdp - sf interface
  186. fluid '(vdpvars!* intvdpvars!* secondvalue!* vdpsortmode!* !*groebrm
  187. !*vdpinteger !*trgroeb !*trgroebs !*groebdivide pcount!*
  188. !*gsugar dipevlist!* !*gcd);
  189. global '(vdpprintmax groebmonfac);
  190. flag('(vdpprintmax),'share);
  191. % basic internal constructor of vdp-record
  192. smacro procedure makevdp (vbc,vev,form); list('vdp,vev,vbc,form,nil);
  193. % basic selectors (conversions)
  194. smacro procedure vdppoly u; cadr cddr u;
  195. smacro procedure vdplbc u; caddr u;
  196. smacro procedure vdpevlmon u; cadr u;
  197. % basic tests
  198. smacro procedure vdpzero!? u;
  199. null u or null vdppoly u;
  200. smacro procedure vevzero!? u;
  201. null u or (car u = 0 and vevzero!?1 cdr u);
  202. smacro procedure vdpone!? p;
  203. not vdpzero!? p and vevzero!? vdpevlmon p;
  204. % base coefficients
  205. % manipulating of exponent vectors
  206. smacro procedure vevdivides!? (vev1,vev2);
  207. vevmtest!?(vev2,vev1);
  208. smacro procedure vevzero();
  209. vevmaptozero1(vdpvars!*,nil);
  210. smacro procedure vdpnumber f; vdpgetprop(f,'number) ;
  211. % the code for checkpointing is factored out
  212. % This version: NO CHECKPOINT FACILITY
  213. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  214. %
  215. % interface for DIPOLY polynomials as records (objects).
  216. %
  217. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  218. %
  219. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  220. %
  221. fluid '(intvdpvars!* vdpvars!* secondvalue!* vdpsfsortmode!* !*groebrm
  222. !*vdpinteger !*trgroeb !*trgroebs !*groebdivide pcount!*
  223. !*groebsubs);
  224. fluid '(vdpsortmode!*);
  225. global '(vdpprintmax groebmonfac);
  226. flag('(vdpprintmax),'share);
  227. fluid '(dipvars!* !*vdpinteger);
  228. symbolic procedure dip2vdp u;
  229. % Is used when u can be empty.
  230. (if dipzero!? uu then makevdp(a2bc 0,nil,nil)
  231. else makevdp(diplbc uu,dipevlmon uu,uu))
  232. where uu = if !*groebsubs then dipsubs2 u else u;
  233. % some simple mappings
  234. smacro procedure makedipzero(); nil;
  235. symbolic procedure vdpredzero!? u; dipzero!? dipmred vdppoly u;
  236. symbolic procedure vdplastmon u;
  237. % Return bc . ev of last monomial of u.
  238. begin
  239. u:=vdppoly u;
  240. if dipzero!? u then return nil;
  241. while not dipzero!? u and not dipzero!? dipmred u do
  242. u:=dipmred u;
  243. return diplbc u . dipevlmon u;
  244. end;
  245. symbolic procedure vbczero!? u; bczero!? u;
  246. symbolic procedure vbcnumber u;
  247. if pairp u and numberp car u and 1=cdr u then cdr u else nil;
  248. symbolic procedure vbcfi u; bcfd u;
  249. symbolic procedure a2vbc u; a2bc u;
  250. symbolic procedure vbcquot(u,v); bcquot(u,v);
  251. symbolic procedure vbcneg u; bcneg u;
  252. symbolic procedure vbcabs u; if vbcminus!? u then bcneg u else u;
  253. symbolic procedure vbcone!? u; bcone!? u;
  254. symbolic procedure vbcprod (u,v); bcprod(u,v);
  255. % initializing vdp-dip polynomial package
  256. symbolic procedure vdpinit2(vars);
  257. begin scalar oldorder;
  258. vdpcleanup();
  259. oldorder := kord!*;
  260. if null vars then rerror(dipoly,8,"Vdpinit: vdpvars not set");
  261. vdpvars!* := dipvars!* := vars;
  262. torder2 vdpsortmode!*;
  263. return oldorder;
  264. end;
  265. symbolic procedure vdpcleanup();
  266. dipevlist!*:={nil};
  267. symbolic procedure vdpred u;
  268. begin scalar r,s;
  269. r:=dipmred vdppoly u;
  270. if dipzero!? r then return makevdp(nil ./ nil,nil,makedipzero());
  271. r:=makevdp(diplbc r,dipevlmon r,r);
  272. if !*gsugar and (s:=vdpgetprop(u,'sugar)) then gsetsugar(r,s);
  273. return r;
  274. end;
  275. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  276. %
  277. % coefficient handling; here we assume that coefficients are
  278. % standard quotients;
  279. %
  280. symbolic procedure vbcgcd (u,v);
  281. begin scalar x;
  282. if not vbcsize(u, -100) or not vbcsize(v, -100)
  283. then return '(1 . 1);
  284. x := if denr u = 1 and denr v = 1 then
  285. if fixp numr u and fixp numr v then gcdn(numr u,numr v) ./ 1
  286. else gcdf!*(numr u,numr v) ./ 1
  287. else 1 ./ 1;
  288. return x
  289. end;
  290. symbolic procedure vbcsize(u, n);
  291. if n #> -1 then nil
  292. else if atom u then n
  293. else
  294. begin
  295. n := vbcsize(car u, n #+ 1);
  296. if null n then return nil;
  297. return vbcsize(cdr u, n);
  298. end;
  299. % Cofactors: compute (q,v) such that q*a=v*b.
  300. symbolic procedure vbc!-cofac(bc1,bc2);
  301. % Compute base coefficient cofactors.
  302. <<if vbcminus!? bc1 and vbcminus!? bc2 then gcd:=vbcneg gcd;
  303. vbcquot(bc2,gcd).vbcquot(bc1,gcd) >>
  304. where gcd=vbcgcd(bc1,bc2);
  305. symbolic procedure vev!-cofac(ev1,ev2);
  306. % Compute exponent vector cofactors.
  307. (vevdif(lcm,ev1) . vevdif(lcm,ev2)) where lcm =vevlcm(ev1,ev2);
  308. % the following functions must be redefinable
  309. symbolic procedure vbcplus!? u; (numberp v and v>0) where v = numr u;
  310. symbolic procedure bcplus!? u; (numberp v and v>0) where v = numr u;
  311. symbolic procedure vbcminus!? u;
  312. (numberp v and v<0) where v = numr u;
  313. symbolic procedure vbcinv u; bcinv u;
  314. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  315. %
  316. % conversion between forms, vdps and prefix expressions
  317. %
  318. % prefix to vdp
  319. symbolic procedure a2vdp u;
  320. if u=0 or null u then makevdp(nil ./ nil,nil,makedipzero())
  321. else (makevdp(diplbc r,dipevlmon r,r) where r = a2dip u);
  322. % vdp to prefix
  323. symbolic procedure vdp2a u; dip2a vdppoly u;
  324. symbolic procedure vbc2a u; bc2a u;
  325. % form to vdp
  326. symbolic procedure f2vdp(u);
  327. if u=0 or null u then makevdp(nil ./ nil,nil,makedipzero())
  328. else (makevdp(diplbc r,dipevlmon r,r) where r = f2dip u);
  329. % vdp to form
  330. symbolic procedure vdp2f u; dip2f vdppoly u;
  331. % vdp from monomial
  332. symbolic procedure vdpfmon (coef,vev);
  333. begin scalar r;
  334. r:= makevdp(coef,vev,dipfmon(coef,vev));
  335. if !*gsugar then gsetsugar(r,vevtdeg vev);
  336. return r;
  337. end;
  338. % add a monomial to a vdp in front (new vev and coeff)
  339. symbolic procedure vdpmoncomp(coef,vev,vdp);
  340. if vdpzero!? vdp then vdpfmon(coef,vev)
  341. else
  342. if vbczero!? coef then vdp
  343. else
  344. makevdp(coef,vev,dipmoncomp(coef,vev,vdppoly vdp));
  345. %add a monomial to the end of a vdp (vev remains unchanged)
  346. symbolic procedure vdpappendmon(vdp,coef,vev);
  347. if vdpzero!? vdp then vdpfmon(coef,vev)
  348. else
  349. if vbczero!? coef then vdp
  350. else
  351. makevdp(vdplbc vdp,vdpevlmon vdp,
  352. dipsum(vdppoly vdp,dipfmon(coef,vev)));
  353. % add monomial to vdp, place of new monomial still unknown
  354. symbolic procedure vdpmonadd(coef,vev,vdp);
  355. if vdpzero!? vdp then vdpfmon(coef,vev) else
  356. (if c = 1 then vdpmoncomp(coef,vev,vdp) else
  357. if c = -1 then makevdp (vdplbc vdp,vdpevlmon vdp,
  358. dipsum(vdppoly vdp,dipfmon(coef,vev)))
  359. else vdpsum(vdp,vdpfmon(coef,vev))
  360. ) where c = vevcomp(vev,vdpevlmon vdp);
  361. symbolic procedure vdpzero(); a2vdp 0;
  362. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  363. %
  364. % comparing of exponent vectors
  365. %
  366. %
  367. symbolic procedure vdpvevlcomp (p1,p2);
  368. dipevlcomp (vdppoly p1,vdppoly p2);
  369. symbolic procedure vevilcompless!?(e1,e2); 1 = evilcomp(e2,e1);
  370. symbolic procedure vevilcomp (e1,e2); evilcomp (e1,e2);
  371. symbolic procedure vevcompless!?(e1,e2); 1 = evcomp(e2,e1);
  372. symbolic procedure vevcomp (e1,e2); evcomp (e1,e2);
  373. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  374. %
  375. % routines traversing the "coefficients"
  376. %
  377. % CONTENT of a vdp
  378. % The content is the gcd of all coefficients.
  379. symbolic procedure vdpcontent d;
  380. if vdpzero!? d then a2bc 0 else
  381. <<d := vdppoly d;
  382. dipnumcontent(dipmred d,diplbc d)>>;
  383. symbolic procedure vdpcontent1(d,c); dipnumcontent(vdppoly d,c);
  384. symbolic procedure dipnumcontent(d,c);
  385. if bcone!? c or dipzero!? d then c
  386. else dipnumcontent(dipmred d,vbcgcd(c,diplbc d));
  387. symbolic procedure dipcontenti p;
  388. % the content is a pair of the lcm of the coefficients and the
  389. % exponent list of the common monomial factor.
  390. if dipzero!? p then 1 else
  391. (if dipzero!? rp then diplbc p .
  392. (if !*groebrm then dipevlmon p else nil)
  393. else
  394. dipcontenti1(diplbc p,
  395. if !*groebrm then dipevlmon p else nil,rp) )
  396. where rp=dipmred p;
  397. symbolic procedure dipcontenti1 (n,ev,p1);
  398. if dipzero!? p1 then n . ev
  399. else begin scalar nn;
  400. nn := vbcgcd (n,diplbc p1);
  401. if ev then ev := dipcontevmin(dipevlmon p1,ev);
  402. if bcone!? nn and null ev then return nn . nil
  403. else return dipcontenti1 (nn,ev,dipmred p1)
  404. end;
  405. % CONTENT and MONFAC (if groebrm on)
  406. symbolic procedure vdpcontenti d;
  407. vdpcontent d . if !*groebrm then vdpmonfac d else nil;
  408. symbolic procedure vdpmonfac d; dipmonfac vdppoly d;
  409. symbolic procedure dipmonfac p;
  410. % exponent list of the common monomial factor.
  411. if dipzero!? p or not !*groebrm then evzero()
  412. else (if dipzero!? rp then dipevlmon p
  413. else dipmonfac1(dipevlmon p,rp) ) where rp=dipmred p;
  414. symbolic procedure dipmonfac1(ev,p1);
  415. if dipzero!? p1 or evzero!? ev then ev
  416. else dipmonfac1(dipcontevmin(ev,dipevlmon p1),dipmred p1);
  417. % vdpCoeffcientsFromDomain!?
  418. symbolic procedure vdpcoeffcientsfromdomain!? w;
  419. dipcoeffcientsfromdomain!? vdppoly w;
  420. symbolic procedure dipcoeffcientsfromdomain!? w;
  421. if dipzero!? w then t else
  422. (if bcdomain!? v then dipcoeffcientsfromdomain!? dipmred w
  423. else nil) where v =diplbc w;
  424. symbolic procedure vdplength f; diplength vdppoly f;
  425. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  426. %
  427. % polynomial operations:
  428. % coefficient normalization and reduction of monomial
  429. % factors
  430. %
  431. symbolic procedure vdpequal(p1,p2);
  432. p1 eq p2
  433. or (n1 and n1 = n2 % number comparison is faster most times
  434. or dipequal(vdppoly p1,vdppoly p2)
  435. where n1 = vdpgetprop(p1,'number),
  436. n2 = vdpgetprop(p2,'number));
  437. symbolic procedure dipequal(p1,p2);
  438. if dipzero!? p1 then dipzero!? p2
  439. else if dipzero!? p2 then nil
  440. else diplbc p1 = diplbc p2
  441. and evequal(dipevlmon p1,dipevlmon p2)
  442. and dipequal(dipmred p1,dipmred p2);
  443. symbolic procedure evequal(e1,e2);
  444. % test equality with variable length exponent vectors
  445. if null e1 and null e2 then t
  446. else if null e1 then evequal('(0),e2)
  447. else if null e2 then evequal(e1,'(0))
  448. else 0=(car e1 #- car e2) and evequal(cdr e1,cdr e2);
  449. symbolic procedure vdplcm p; diplcm vdppoly p;
  450. symbolic procedure vdprectoint(p,q); dip2vdp diprectoint(vdppoly p,q);
  451. symbolic procedure vdpsimpcont(p);
  452. begin scalar r,q;
  453. q := vdppoly p;
  454. if dipzero!? q then return p;
  455. r := dipsimpcont q;
  456. p := dip2vdp cdr r; % the polynomial
  457. r := car r; % the monomial factor if any
  458. if not evzero!? r and (dipmred q or evtdeg r>1)
  459. then vdpputprop(p,'monfac,r);
  460. return p;
  461. end;
  462. symbolic procedure dipsimpcont (p);
  463. if !*vdpinteger or not !*groebdivide then dipsimpconti p
  464. else dipsimpcontr p;
  465. % routines for integer coefficient case:
  466. % calculation of contents and dividing all coefficients by it
  467. symbolic procedure dipsimpconti (p);
  468. % calculate the contents of p and divide all coefficients by it
  469. begin scalar co,lco,res,num;
  470. if dipzero!? p then return nil . p;
  471. co := bcfd 1;
  472. co := if !*groebdivide then dipcontenti p
  473. else if !*groebrm then co . dipmonfac p
  474. else co . nil;
  475. num := car co;
  476. if not bcplus!? num then num := bcneg num;
  477. if not bcplus!? diplbc p then num := bcneg num;
  478. if bcone!? num and cdr co = nil then return nil . p;
  479. lco := cdr co;
  480. if groebmonfac neq 0 then lco := dipcontlowerev cdr co;
  481. res := p;
  482. if not(bcone!? num and lco = nil) then
  483. res := dipreduceconti (p,num,lco);
  484. if null cdr co then return nil . res;
  485. lco := evdif(cdr co,lco);
  486. return(if lco and not evzero!? evdif(dipevlmon res,lco)
  487. then lco else nil).res;
  488. end;
  489. symbolic procedure vdpreduceconti (p,co,vev);
  490. % divide polynomial p by monomial from co and vev
  491. vdpdivmon(p,co,vev);
  492. % divide all coefficients of p by cont
  493. symbolic procedure dipreduceconti (p,co,ev);
  494. if dipzero!? p
  495. then makedipzero()
  496. else
  497. dipmoncomp ( bcquot (diplbc p,co),
  498. if ev then evdif(dipevlmon p,ev)
  499. else dipevlmon p,
  500. dipreduceconti (dipmred p,co,ev));
  501. % routines for rational coefficient case:
  502. % calculation of contents and dividing all coefficients by it
  503. symbolic procedure dipsimpcontr (p);
  504. % calculate the contents of p and divide all coefficients by it
  505. begin scalar co,lco,res;
  506. if dipzero!? p then return nil . p;
  507. co := dipcontentr p;
  508. if bcone!? diplbc p and co = nil then return nil . p;
  509. lco := dipcontlowerev co;
  510. res := p;
  511. if not(bcone!? diplbc p and lco = nil) then
  512. res := dipreducecontr (p,bcinv diplbc p,lco);
  513. return (if co then evdif(co,lco) else nil) . res;
  514. end;
  515. symbolic procedure dipcontentr p;
  516. % the content is the exponent list of the common monomial factor.
  517. (if dipzero!? rp then
  518. (if !*groebrm then dipevlmon p else nil)
  519. else
  520. dipcontentr1(if !*groebrm then dipevlmon p else nil,rp) )
  521. where rp=dipmred p;
  522. symbolic procedure dipcontentr1 (ev,p1);
  523. if dipzero!? p1 then ev
  524. else begin
  525. if ev then ev := dipcontevmin(dipevlmon p1,ev);
  526. if null ev then return nil
  527. else return dipcontentr1 (ev,dipmred p1)
  528. end;
  529. % divide all coefficients of p by cont
  530. symbolic procedure dipreducecontr (p,co,ev);
  531. if dipzero!? p
  532. then makedipzero()
  533. else
  534. dipmoncomp ( bcprod (diplbc p,co),
  535. if ev then evdif(dipevlmon p,ev)
  536. else dipevlmon p,
  537. dipreducecontr (dipmred p,co,ev));
  538. symbolic procedure dipcontevmin (e1,e2);
  539. % calculates the minimum of two exponents; if one is shorter, trailing
  540. % zeroes are assumed.
  541. % e1 is an exponent vector. e2 is a list of exponents
  542. begin scalar res;
  543. while e1 and e2 do
  544. <<res := (if ilessp(car e1,car e2) then car e1 else car e2)
  545. . res;
  546. e1 := cdr e1; e2 := cdr e2>>;
  547. while res and 0=car res do res := cdr res;
  548. return reversip res;
  549. end;
  550. symbolic procedure dipcontlowerev (e1);
  551. % subtract a 1 from those elements of an exponent vector which
  552. % are greater than 1.
  553. % e1 is a list of exponents, the result is an exponent vector.
  554. begin scalar res;
  555. while e1 do
  556. <<res := (if igreaterp(car e1,0) then car e1 - 1 else 0)
  557. . res;
  558. e1 := cdr e1>>;
  559. while res and 0 = car res do res := cdr res;
  560. if res and !*trgroebs then
  561. <<prin2 "***** exponent reduction:";
  562. prin2t reverse res>>;
  563. return reversip res;
  564. end;
  565. symbolic procedure dipappendmon(dip,bc,ev);
  566. append(dip,dipfmon(bc,ev));
  567. smacro procedure dipnconcmon(dip,bc,ev);
  568. nconc(dip,dipfmon(bc,ev));
  569. smacro procedure dipappenddip(dip1,dip2); append(dip1,dip2);
  570. smacro procedure dipnconcdip(dip1,dip2); nconc(dip1,dip2);
  571. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  572. %
  573. % basic polynomial arithmetic:
  574. %
  575. symbolic procedure vdpsum(d1,d2);
  576. begin scalar r;
  577. r:=dip2vdp dipsum(vdppoly d1,vdppoly d2);
  578. if !*gsugar then gsetsugar(r,max(gsugar d1,gsugar d2));
  579. return r;
  580. end;
  581. symbolic procedure vdpdif(d1,d2);
  582. begin scalar r;
  583. r:= dip2vdp dipdif(vdppoly d1,vdppoly d2);
  584. if !*gsugar then gsetsugar(r,max(gsugar d1,gsugar d2));
  585. return r;
  586. end;
  587. symbolic procedure vdpprod(d1,d2);
  588. begin scalar r;
  589. r:= dip2vdp dipprod(vdppoly d1,vdppoly d2);
  590. if !*gsugar then gsetsugar(r,gsugar d1 + gsugar d2);
  591. return r;
  592. end;
  593. % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
  594. %
  595. % linear combination: the Buchberger Workhorse
  596. %
  597. % LCOMB1: calculate mon1 * vdp1 + mon2 * vdp2
  598. symbolic procedure vdpilcomb1(d1,vbc1,vev1,d2,vbc2,vev2);
  599. begin scalar r;
  600. r:=
  601. dip2vdp dipilcomb1 (vdppoly d1,vbc1,vev1,vdppoly d2,vbc2,vev2);
  602. if !*gsugar then gsetsugar(r,max(gsugar d1+vevtdeg vev1,
  603. gsugar d2+vevtdeg vev2));
  604. return r;
  605. end;
  606. symbolic procedure dipilcomb1 (p1,bc1,ev1,p2,bc2,ev2);
  607. % same asl dipILcomb, exponent vectors multiplied in already
  608. begin scalar gcd;
  609. gcd := !*gcd;
  610. return
  611. begin scalar ep1,ep2,sl,res,sum,z1,z2,p1new,p2new,lptr,bptr,c,!*gcd;
  612. !*gcd := if vbcsize(bc1,-100) and vbcsize(bc2,-100)then gcd;
  613. z1 := not evzero!? ev1; z2 := not evzero!? ev2;
  614. p1new := p2new := t;
  615. lptr := bptr := res := makedipzero();
  616. loop:
  617. if p1new then
  618. << if dipzero!? p1 then
  619. return if dipzero!? p2 then res else
  620. dipnconcdip(res, dipprod(p2,dipfmon(bc2,ev2)));
  621. ep1 := dipevlmon p1;
  622. if z1 then ep1 := evsum(ep1,ev1);
  623. p1new := nil;>>;
  624. if p2new then
  625. << if dipzero!? p2 then
  626. return dipnconcdip(res, dipprod(p1,dipfmon(bc1,ev1)));
  627. ep2 := dipevlmon p2;
  628. if z2 then ep2 := evsum(ep2,ev2);
  629. p2new := nil; >>;
  630. sl := evcomp(ep1, ep2);
  631. if sl = 1 then
  632. << if !*gcd and not vbcsize(diplbc p1, -100)
  633. then !*gcd := nil;
  634. c := bcprod(diplbc p1,bc1);
  635. if not bczero!? c then
  636. <<lptr := dipnconcmon (bptr,c,ep1);
  637. bptr := dipmred lptr>>;
  638. p1 := dipmred p1; p1new := t;
  639. >>
  640. else if sl = -1 then
  641. << if !*gcd and not vbcsize(diplbc p2, -100)
  642. then !*gcd := nil;
  643. c := bcprod(diplbc p2,bc2);
  644. if not bczero!? c then
  645. <<lptr := dipnconcmon (bptr,c,ep2);
  646. bptr := dipmred lptr>>;
  647. p2 := dipmred p2; p2new := t;
  648. >>
  649. else
  650. << if !*gcd and (not vbcsize(diplbc p1,-100) or
  651. not vbcsize(diplbc p2,-100)) then !*gcd := nil;
  652. sum := bcsum (bcprod(diplbc p1,bc1),
  653. bcprod(diplbc p2,bc2));
  654. if not bczero!? sum then
  655. << lptr := dipnconcmon(bptr,sum,ep1);
  656. bptr := dipmred lptr>>;
  657. p1 := dipmred p1; p2 := dipmred p2;
  658. p1new := p2new := t;
  659. >>;
  660. if dipzero!? res then <<res := bptr := lptr>>; % initial
  661. goto loop;
  662. end;
  663. end;
  664. symbolic procedure vdpvbcprod(p,a);
  665. (if !*gsugar then gsetsugar(q,gsugar p) else q)
  666. where q=dip2vdp dipbcprod(vdppoly p,a);
  667. symbolic procedure vdpdivmon(p,c,vev);
  668. (if !*gsugar then gsetsugar(q,gsugar p) else q)
  669. where q=dip2vdp dipdivmon(vdppoly p,c,vev);
  670. symbolic procedure dipdivmon(p,bc,ev);
  671. % divides a polynomial by a monomial
  672. % we are sure that the monomial ev is a factor of p
  673. if dipzero!? p
  674. then makedipzero()
  675. else
  676. dipmoncomp ( bcquot(diplbc p,bc),
  677. evdif(dipevlmon p,ev),
  678. dipdivmon (dipmred p,bc,ev));
  679. symbolic procedure vdpcancelmvev(p,vev);
  680. (if !*gsugar then gsetsugar(q,gsugar p) else q)
  681. where q=dip2vdp dipcancelmev(vdppoly p,vev);
  682. symbolic procedure dipcancelmev(f,ev);
  683. % cancels all monomials in f which are multiples of ev
  684. dipcancelmev1(f,ev,makedipzero());
  685. symbolic procedure dipcancelmev1(f,ev,res);
  686. if dipzero!? f then res
  687. else if evmtest!?(dipevlmon f,ev) then
  688. dipcancelmev1(dipmred f,ev,res)
  689. else dipcancelmev1(dipmred f,ev,
  690. % dipAppendMon(res,diplbc f,dipevlmon f));
  691. dipnconcmon(res,diplbc f,dipevlmon f));
  692. % some prehistoric routines needed in resultant operation
  693. symbolic procedure vevsum0(n,p);
  694. % exponent vector sum version 0. n is the length of vdpvars!*.
  695. % p is a distributive polynomial.
  696. if vdpzero!? p then vevzero1 n else
  697. vevsum(vdpevlmon p, vevsum0(n,vdpred p));
  698. symbolic procedure vevzero1 n;
  699. % Returns the exponent vector power representation
  700. % of length n for a zero power.
  701. begin scalar x;
  702. for i:=1: n do << x := 0 . x >>;
  703. return x
  704. end;
  705. symbolic procedure vdpresimp u;
  706. % fi domain changes, the coefficients have to be resimped
  707. dip2vdp dipresimp vdppoly u;
  708. symbolic procedure dipresimp u;
  709. if null u then nil else
  710. (for each x in u collect
  711. <<toggle := not toggle;
  712. if toggle then simp prepsq x else x>>
  713. ) where toggle = t;
  714. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  715. %
  716. % printing of polynomials
  717. %
  718. symbolic procedure vdpprin2t u; << vdpprint1(u,nil,9999); terpri()>>;
  719. symbolic procedure vdpprin3t u;
  720. << vdpprint1(u,nil,9999); prin2t ";">>;
  721. symbolic procedure vdpprint u; <<vdpprin2 u; terpri()>>;
  722. symbolic procedure vdpprin2 u;
  723. <<(if x then <<prin2 "P("; prin2 x;
  724. if s then<<prin2 "/",prin2 s>>;
  725. prin2 "): ">>)
  726. where x=vdpgetprop(u,'number),
  727. s=vdpgetprop(u,'sugar);
  728. vdpprint1(u,nil,vdpprintmax)>>;
  729. symbolic procedure vdpprint1(u,v,max); vdpprint1x(vdppoly u,v,max);
  730. symbolic procedure vdpprint1x(u,v,max);
  731. % /* Prints a distributive polynomial in infix form.
  732. % U is a distributive form. V is a flag which is true if a term
  733. % has preceded current form
  734. % max limits the number of terms to be printed
  735. if dipzero!? u then if null v then dipprin2 0 else nil
  736. else if max = 0 then % maximum of terms reached
  737. << terpri();
  738. prin2 " ### etc (";
  739. prin2 diplength u;
  740. prin2 " terms) ###";
  741. terpri();>>
  742. else begin scalar bool,w;
  743. w := diplbc u;
  744. if bcminus!? w then <<bool := t; w := bcneg w>>;
  745. if bool then dipprin2 " - " else if v then dipprin2 " + ";
  746. (if not bcone!? w or evzero!? x then<<bcprin w; dipevlpri(x,t)>>
  747. else dipevlpri(x,nil))
  748. where x = dipevlmon u;
  749. vdpprint1x(dipmred u,t, max - 1)
  750. end;
  751. symbolic procedure dipprin2 u;
  752. <<if posn()>69 then terprit 2 ; prin2 u>>;
  753. symbolic procedure vdpsave u; u;
  754. % switching between term order modes
  755. symbolic procedure torder2 u; dipsortingmode u;
  756. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  757. %
  758. % additional conversion utilities
  759. % conversion dip to standard form / standard quotient
  760. symbolic procedure dip2f u;
  761. (if denr v neq 1 then
  762. <<print u;
  763. rerror(dipoly,9,
  764. "Distrib. poly. with rat coeff cannot be converted")>>
  765. else numr v) where v = dip2sq u;
  766. symbolic procedure dip2sq u;
  767. % convert a dip into a standard quotient.
  768. if dipzero!? u then nil ./ 1
  769. else addsq(diplmon2sq(diplbc u,dipevlmon u),dip2sq dipmred u);
  770. symbolic procedure diplmon2sq(bc,ev);
  771. %convert a monomial into a standard quotient.
  772. multsq(bc,dipev2f(ev,dipvars!*) ./ 1);
  773. symbolic procedure dipev2f(ev,vars);
  774. if null ev then 1
  775. else if car ev = 0 then dipev2f(cdr ev,cdr vars)
  776. else multf(car vars .** car ev .* 1 .+ nil,
  777. dipev2f(cdr ev,cdr vars));
  778. % evaluate SUBS2 for the coefficients of a dip
  779. symbolic procedure dipsubs2 u;
  780. begin scalar v,secondvalue!*;
  781. secondvalue!* := 1 ./ 1;
  782. v := dipsubs21 u;
  783. return diprectoint(v,secondvalue!*);
  784. end;
  785. symbolic procedure dipsubs21 u;
  786. begin scalar c;
  787. if dipzero!? u then return u;
  788. c := groebsubs2 diplbc u;
  789. if null numr c then return dipsubs21 dipmred u;
  790. if not(denr c = 1) then
  791. secondvalue!* := bclcmd(c,secondvalue!*);
  792. return dipmoncomp(c,dipevlmon u,dipsubs21 dipmred u);
  793. end;
  794. % conversion standard form to dip
  795. symbolic procedure f2dip u; f2dip1(u,evzero(),bcfd 1);
  796. symbolic procedure f2dip1 (u,ev,bc);
  797. % f to dip conversion: scan the standard form. ev
  798. % and bc are the exponent and coefficient parts collected
  799. % so far from higher parts.
  800. if null u then nil
  801. else if domainp u then dipfmon(bcprod(bc,bcfd u),ev)
  802. else dipsum(f2dip2(mvar u,ldeg u,lc u,ev,bc),
  803. f2dip1(red u,ev,bc));
  804. symbolic procedure f2dip2(var,dg,c,ev,bc);
  805. % f to dip conversion:
  806. % multiply leading power either into exponent vector
  807. % or into the base coefficient.
  808. <<if ev1 then ev := ev1
  809. else bc := multsq(bc,var.**dg.*1 .+nil./1);
  810. f2dip1(c,ev,bc)>>
  811. where ev1=if memq(var,dipvars!*) then
  812. evinsert(ev,var,dg,dipvars!*) else nil;
  813. symbolic procedure evinsert(ev,v,dg,vars);
  814. % f to dip conversion:
  815. % Insert the "dg" into the ev in the place of variable v.
  816. if null ev or null vars then nil
  817. else if car vars eq v then dg . cdr ev
  818. else car ev . evinsert(cdr ev,v,dg,cdr vars);
  819. symbolic procedure vdpcondense f;
  820. dipcondense car cdddr f;
  821. endmodule;
  822. end;