source: git/libpolys/polys/shiftop.cc @ f006a1

spielwiese
Last change on this file since f006a1 was f006a1, checked in by Karim Abou Zeid <karim23697@…>, 4 years ago
Syzygies via LPncGenCount ring variable
  • Property mode set to 100644
File size: 23.7 KB
Line 
1#include "shiftop.h"
2
3#ifdef HAVE_SHIFTBBA
4
5#include "templates/p_MemCopy.h"
6#include "monomials/p_polys.h"
7#include "polys/simpleideals.h"
8
9/* #define SHIFT_MULT_DEBUG */
10
11/* enable compat mode until the user interface is updated to support xy instead of x(1)*y(2)
12 * NOTE: it already works, but all tests and the libraries need to be updated first
13 * -> wait until the new interface is released
14*/
15#define SHIFT_MULT_COMPAT_MODE
16
17#ifdef SHIFT_MULT_DEBUG
18#include "../kernel/polys.h"
19#endif
20
21poly shift_pp_Mult_mm(poly p, const poly m, const ring ri)
22{
23#ifdef SHIFT_MULT_DEBUG
24  PrintLn(); PrintS("shift_pp_Mult_mm: ("); p_wrp(p, ri, ri); PrintS(") * "); p_wrp(m, ri, ri);
25#endif
26
27  p_Test(p, ri);
28  p_LmTest(m, ri);
29  if (p == NULL)
30  {
31    return NULL;
32  }
33
34  int lV = ri->isLPring;
35  poly _m = m; // temp hack because m is const
36#ifdef SHIFT_MULT_COMPAT_MODE
37  _m = p_Copy(_m, ri);
38  p_mLPunshift(_m, ri);
39  p = p_Copy(p, ri);
40  poly pCopyHead = p; // used to delete p later
41  p_LPunshift(p, ri);
42#else
43  assume(p_mFirstVblock(_m, ri) <= 1);
44  assume(p_FirstVblock(p, ri) <= 1); // TODO check that each block is <=1
45#endif
46  // at this point _m and p are shifted to 1
47
48  spolyrec rp;
49  poly q = &rp; // we use p for iterating and q for the result
50  number mCoeff = pGetCoeff(_m);
51  omBin bin = ri->PolyBin;
52  pAssume(!n_IsZero(mCoeff, ri->cf));
53  pAssume1(p_GetComp(m, ri) == 0 || p_MaxComp(p, ri) == 0);
54
55  int *mExpV = (int *) omAlloc((ri->N+1)*sizeof(int));
56  p_GetExpV(_m,mExpV,ri);
57  int mLength = p_mLastVblock(_m, mExpV, ri) * lV;
58  int *pExpV = (int *) omAlloc((ri->N+1)*sizeof(int));
59  do
60  {
61    p_AllocBin(pNext(q), bin, ri);
62    pIter(q);
63    pNext(q)=NULL;
64    pSetCoeff0(q, n_Mult(mCoeff, pGetCoeff(p), ri->cf));
65
66    p_GetExpV(p, pExpV, ri);
67    p_LPExpVappend(pExpV, mExpV, p_mLastVblock(p, pExpV, ri) * lV, mLength, ri);
68    p_MemCopy_LengthGeneral(q->exp, p->exp, ri->ExpL_Size); // otherwise q is not initialized correctly
69    p_SetExpV(q, pExpV, ri);
70
71    pIter(p);
72  }
73  while (p != NULL);
74  omFreeSize((ADDRESS) pExpV, (ri->N+1)*sizeof(int));
75  omFreeSize((ADDRESS) mExpV, (ri->N+1)*sizeof(int));
76  pNext(q) = NULL;
77#ifdef SHIFT_MULT_COMPAT_MODE
78  p_Delete(&_m, ri); // in this case we copied _m before
79  p_Delete(&pCopyHead, ri); // in this case we copied p before
80#endif
81#ifdef SHIFT_MULT_DEBUG
82  PrintLn(); PrintS("shift_pp_Mult_mm result: "); p_wrp(pNext(&rp), ri, ri); PrintLn();
83#endif
84  p_Test(pNext(&rp), ri);
85  return pNext(&rp);
86}
87
88// destroys p
89poly shift_p_Mult_mm(poly p, const poly m, const ring ri)
90{
91#ifdef SHIFT_MULT_DEBUG
92  PrintLn(); PrintS("shift_p_Mult_mm: ("); p_wrp(p, ri, ri); PrintS(") * "); p_wrp(m, ri, ri);
93#endif
94
95  p_Test(p, ri);
96  p_LmTest(m, ri);
97  pAssume(m != NULL);
98  assume(p!=NULL);
99
100  int lV = ri->isLPring;
101  poly _m = m; // temp hack because m is const
102#ifdef SHIFT_MULT_COMPAT_MODE
103  _m = p_Copy(_m, ri);
104  p_mLPunshift(_m, ri);
105  p_LPunshift(p, ri);
106#else
107  assume(p_mFirstVblock(_m, ri) <= 1);
108  assume(p_FirstVblock(p, ri) <= 1); // TODO check that each block is <=1
109#endif
110  // at this point _m and p are shifted to 1
111
112  poly q = p; // we use p for iterating and q for the result
113  number mCoeff = pGetCoeff(_m);
114  number pCoeff;
115  pAssume(!n_IsZero(mCoeff, ri->cf));
116
117  int *mExpV = (int *) omAlloc((ri->N+1)*sizeof(int));
118  p_GetExpV(_m,mExpV,ri);
119  int mLength = p_mLastVblock(_m, mExpV, ri) * lV;
120  int *pExpV = (int *) omAlloc((ri->N+1)*sizeof(int));
121  while (p != NULL)
122  {
123    pCoeff = pGetCoeff(p);
124    pSetCoeff0(p, n_Mult(mCoeff, pCoeff, ri->cf));
125    n_Delete(&pCoeff, ri->cf); // delete the old coeff
126
127    p_GetExpV(p,pExpV,ri);
128    p_LPExpVappend(pExpV, mExpV, p_mLastVblock(p, pExpV, ri) * lV, mLength, ri);
129    p_SetExpV(p, pExpV, ri);
130
131    pIter(p);
132  }
133  omFreeSize((ADDRESS) pExpV, (ri->N+1)*sizeof(int));
134  omFreeSize((ADDRESS) mExpV, (ri->N+1)*sizeof(int));
135#ifdef SHIFT_MULT_COMPAT_MODE
136  p_Delete(&_m, ri); // in this case we copied _m before
137#endif
138#ifdef SHIFT_MULT_DEBUG
139  PrintLn(); PrintS("shift_p_Mult_mm result: "); p_wrp(q, ri, ri); PrintLn();
140#endif
141  p_Test(q, ri);
142  return q;
143}
144
145poly shift_pp_mm_Mult(poly p, const poly m, const ring ri)
146{
147#ifdef SHIFT_MULT_DEBUG
148  PrintLn(); PrintS("shift_pp_mm_Mult: "); p_wrp(m, ri, ri); PrintS(" * ("); p_wrp(p, ri, ri); PrintS(")");
149#endif
150
151  p_Test(p, ri);
152  p_LmTest(m, ri);
153  if (p == NULL)
154  {
155    return NULL;
156  }
157
158  int lV = ri->isLPring;
159  poly _m = m; // temp hack because m is const
160#ifdef SHIFT_MULT_COMPAT_MODE
161  _m = p_Copy(_m, ri);
162  p_mLPunshift(_m, ri);
163  p = p_Copy(p, ri);
164  poly pCopyHead = p; // used to delete p later
165  p_LPunshift(p, ri);
166#else
167  assume(p_mFirstVblock(_m, ri) <= 1);
168  assume(p_FirstVblock(p, ri) <= 1); // TODO check that each block is <=1
169#endif
170  // at this point _m and p are shifted to 1
171
172  spolyrec rp;
173  poly q = &rp; // we use p for iterating and q for the result
174  number mCoeff = pGetCoeff(_m);
175  omBin bin = ri->PolyBin;
176  pAssume(!n_IsZero(mCoeff, ri->cf));
177  pAssume1(p_GetComp(m, ri) == 0 || p_MaxComp(p, ri) == 0);
178
179  int *mExpV = (int *) omAlloc((ri->N+1)*sizeof(int));
180  p_GetExpV(_m,mExpV,ri);
181  int mLength = p_mLastVblock(_m, mExpV, ri) * lV;
182  int *pExpV = (int *) omAlloc((ri->N+1)*sizeof(int));
183  do
184  {
185    p_AllocBin(pNext(q), bin, ri);
186    pIter(q);
187    pNext(q)=NULL;
188    pSetCoeff0(q, n_Mult(mCoeff, pGetCoeff(p), ri->cf));
189
190    p_GetExpV(p, pExpV, ri);
191    p_LPExpVprepend(pExpV, mExpV, p_mLastVblock(p, pExpV, ri) * lV, mLength, ri);
192    p_MemCopy_LengthGeneral(q->exp, p->exp, ri->ExpL_Size); // otherwise q is not initialized correctly
193    p_SetExpV(q, pExpV, ri);
194
195    pIter(p);
196  }
197  while (p != NULL);
198  omFreeSize((ADDRESS) pExpV, (ri->N+1)*sizeof(int));
199  omFreeSize((ADDRESS) mExpV, (ri->N+1)*sizeof(int));
200  pNext(q) = NULL;
201#ifdef SHIFT_MULT_COMPAT_MODE
202  p_Delete(&_m, ri); // in this case we copied _m before
203  p_Delete(&pCopyHead, ri); // in this case we copied p before
204#endif
205#ifdef SHIFT_MULT_DEBUG
206  PrintLn(); PrintS("shift_pp_mm_Mult result: "); p_wrp(pNext(&rp), ri, ri); PrintLn();
207#endif
208  p_Test(pNext(&rp), ri);
209  return pNext(&rp);
210}
211
212// destroys p
213poly shift_p_mm_Mult(poly p, const poly m, const ring ri)
214{
215#ifdef SHIFT_MULT_DEBUG
216  PrintLn(); PrintS("shift_p_mm_Mult: "); p_wrp(m, ri, ri); PrintS(" * ("); p_wrp(p, ri, ri); PrintS(")");
217#endif
218
219  p_Test(p, ri);
220  p_LmTest(m, ri);
221  pAssume(m != NULL);
222  assume(p!=NULL);
223
224  int lV = ri->isLPring;
225  poly _m = m; // temp hack because m is const
226#ifdef SHIFT_MULT_COMPAT_MODE
227  _m = p_Copy(_m, ri);
228  p_mLPunshift(_m, ri);
229  p_LPunshift(p, ri);
230#else
231  assume(p_mFirstVblock(_m, ri) <= 1);
232  assume(p_FirstVblock(p, ri) <= 1); // TODO check that each block is <=1
233#endif
234  // at this point _m and p are shifted to 1
235
236  poly q = p; // we use p for iterating and q for the result
237  number mCoeff = pGetCoeff(_m);
238  number pCoeff;
239  pAssume(!n_IsZero(mCoeff, ri->cf));
240
241  int *mExpV = (int *) omAlloc((ri->N+1)*sizeof(int));
242  p_GetExpV(_m,mExpV,ri);
243  int mLength = p_mLastVblock(_m, mExpV, ri) * lV;
244  int *pExpV = (int *) omAlloc((ri->N+1)*sizeof(int));
245  while (p != NULL)
246  {
247    pCoeff = pGetCoeff(p);
248    pSetCoeff0(p, n_Mult(mCoeff, pCoeff, ri->cf));
249    n_Delete(&pCoeff, ri->cf); // delete the old coeff
250
251    p_GetExpV(p,pExpV,ri);
252    p_LPExpVprepend(pExpV, mExpV, p_mLastVblock(p, pExpV, ri) * lV, mLength, ri);
253    p_SetExpV(p, pExpV, ri);
254
255    pIter(p);
256  }
257  omFreeSize((ADDRESS) pExpV, (ri->N+1)*sizeof(int));
258  omFreeSize((ADDRESS) mExpV, (ri->N+1)*sizeof(int));
259#ifdef SHIFT_MULT_COMPAT_MODE
260  p_Delete(&_m, ri); // in this case we copied _m before
261#endif
262#ifdef SHIFT_MULT_DEBUG
263  PrintLn(); PrintS("shift_p_mm_Mult result: "); p_wrp(q, ri, ri); PrintLn();
264#endif
265  p_Test(q, ri);
266  return q;
267}
268
269// p - m*q destroys p
270poly shift_p_Minus_mm_Mult_qq(poly p, poly m, poly q, int& Shorter, const poly spNoether, const ring ri) {
271#ifdef SHIFT_MULT_DEBUG
272  PrintLn(); PrintS("shift_p_Minus_mm_Mult_qq: "); p_wrp(p, ri, ri); PrintS(" - "); p_wrp(m, ri, ri); PrintS(" * "); p_wrp(q, ri, ri);
273#endif
274
275  Shorter = pLength(p) + pLength(q);
276
277  poly qq = p_Add_q(p, shift_pp_mm_Mult(q, p_Neg(p_Copy(m, ri), ri), ri), ri);
278
279#ifdef SHIFT_MULT_DEBUG
280  PrintLn(); PrintS("shift_p_Minus_mm_Mult_qq result: "); p_wrp(qq, ri, ri); PrintLn();
281#endif
282  Shorter -= pLength(qq);
283  return qq;
284}
285
286// Unsupported Operation STUBs
287poly shift_pp_Mult_mm_Noether_STUB(poly p, const poly m, const poly spNoether, int &ll, const ring ri) {
288  PrintLn(); WarnS("pp_Mult_mm_Noether is not supported yet by Letterplace. Ignoring spNoether and using pp_Mult_mm. This might lead to unexpected behavior.");
289
290  int pLen = 0;
291  if (ll >= 0)
292  {
293    pLen = pLength(p);
294  }
295
296  p = shift_pp_Mult_mm(p, m, ri);
297
298  if (ll >= 0)
299  {
300    ll = pLen - pLength(p);
301  }
302  else
303  {
304    ll = pLength(p);
305  }
306
307  return p;
308}
309
310
311poly shift_pp_Mult_Coeff_mm_DivSelectMult_STUB(poly p,const poly m, const poly a, const poly b, int &shorter,const ring r) {
312  PrintLn(); WarnS("pp_Mult_Coeff_mm_DivSelectMult is not supported yet by Letterplace. This might lead to unexpected behavior.");
313  return NULL;
314}
315
316poly shift_pp_Mult_Coeff_mm_DivSelect_STUB(poly p, const poly m, int &shorter, const ring r) {
317  PrintLn(); WarnS("pp_Mult_Coeff_mm_DivSelect is not supported yet by Letterplace. This might lead to unexpected behavior.");
318  return NULL;
319}
320
321// auxiliary
322
323// unshifts the monomial m
324void p_mLPunshift(poly m, const ring ri)
325{
326  if (m == NULL || p_LmIsConstantComp(m,ri)) return;
327
328  int lV = ri->isLPring;
329
330  int shift = p_mFirstVblock(m, ri) - 1;
331
332  if (shift == 0) return;
333
334  int *e=(int *)omAlloc((ri->N+1)*sizeof(int));
335  int *s=(int *)omAlloc0((ri->N+1)*sizeof(int));
336  p_GetExpV(m, e, ri);
337
338  int expVoffset = shift*lV;
339  for (int i = 1 + expVoffset; i <= ri->N; i++)
340  {
341    assume(e[i] <= 1);
342    s[i - expVoffset] = e[i];
343  }
344  p_SetExpV(m,s,ri);
345  omFreeSize((ADDRESS) e, (ri->N+1)*sizeof(int));
346  omFreeSize((ADDRESS) s, (ri->N+1)*sizeof(int));
347}
348
349// unshifts the polynomial p, note: the ordering can be destroyed if the shifts for the monomials are not equal
350void p_LPunshift(poly p, const ring ri)
351{
352  while (p!=NULL)
353  {
354    p_mLPunshift(p, ri);
355    pIter(p);
356  }
357}
358
359void p_mLPshift(poly m, int sh, const ring ri)
360{
361  if (sh == 0 || m == NULL || p_LmIsConstantComp(m,ri)) return;
362
363  int lV = ri->isLPring;
364
365  assume(p_mFirstVblock(m,ri) + sh >= 1);
366  assume(p_mLastVblock(m,ri) + sh <= ri->N/lV);
367
368  int *e=(int *)omAlloc((ri->N+1)*sizeof(int));
369  int *s=(int *)omAlloc0((ri->N+1)*sizeof(int));
370  p_GetExpV(m,e,ri);
371
372  if (p_mLastVblock(m, e, ri) + sh > ri->N/lV)
373  {
374    Werror("degree bound of Letterplace ring is %d, but at least %d is needed for this shift", ri->N/lV, p_mLastVblock(m, e, ri) + sh);
375  }
376  for (int i = ri->N - sh*lV; i > 0; i--)
377  {
378    assume(e[i]<=1);
379    if (e[i]==1)
380    {
381      s[i + (sh*lV)] = e[i]; /* actually 1 */
382    }
383  }
384  p_SetExpV(m,s,ri);
385  omFreeSize((ADDRESS) e, (ri->N+1)*sizeof(int));
386  omFreeSize((ADDRESS) s, (ri->N+1)*sizeof(int));
387}
388
389void p_LPshift(poly p, int sh, const ring ri)
390{
391  if (sh == 0) return;
392
393  while (p!=NULL)
394  {
395    p_mLPshift(p, sh, ri);
396    pIter(p);
397  }
398}
399
400/* returns the number of maximal block */
401/* appearing among the monomials of p */
402/* the 0th block is the 1st one */
403int p_LastVblock(poly p, const ring r)
404{
405  poly q = p;
406  int ans = 0;
407  while (q!=NULL)
408  {
409    int ansnew = p_mLastVblock(q, r);
410    ans    = si_max(ans,ansnew);
411    pIter(q);
412  }
413  return(ans);
414}
415
416/* for a monomial p, returns the number of the last block */
417/* where a nonzero exponent is sitting */
418int p_mLastVblock(poly p, const ring ri)
419{
420  if (p == NULL || p_LmIsConstantComp(p,ri))
421  {
422    return(0);
423  }
424
425  int *e=(int *)omAlloc((ri->N+1)*sizeof(int));
426  p_GetExpV(p,e,ri);
427  int b = p_mLastVblock(p, e, ri);
428  omFreeSize((ADDRESS) e, (ri->N+1)*sizeof(int));
429  return b;
430}
431
432/* for a monomial p with exponent vector expV, returns the number of the last block */
433/* where a nonzero exponent is sitting */
434int p_mLastVblock(poly p, int *expV, const ring ri)
435{
436  if (p == NULL || p_LmIsConstantComp(p,ri))
437  {
438    return(0);
439  }
440
441  int lV = ri->isLPring;
442  int j,b;
443  j = ri->N;
444  while ( (!expV[j]) && (j>=1) ) j--;
445  assume(j>0);
446  b = (int)((j+lV-1)/lV); /* the number of the block, >=1 */
447  return b;
448}
449
450/* returns the number of maximal block */
451/* appearing among the monomials of p */
452/* the 0th block is the 1st one */
453int p_FirstVblock(poly p, const ring r)
454{
455  if (p == NULL) {
456    return 0;
457  }
458
459  poly q = p;
460  int ans = p_mFirstVblock(q, r);
461  while (q!=NULL)
462  {
463    int ansnew = p_mFirstVblock(q, r);
464    if (ansnew > 0) { // don't count constants
465      ans = si_min(ans,ansnew);
466    }
467    pIter(q);
468  }
469  /* do not need to delete q */
470  return(ans);
471}
472
473/* for a monomial p, returns the number of the first block */
474/* where a nonzero exponent is sitting */
475int p_mFirstVblock(poly p, const ring ri)
476{
477  if (p == NULL || p_LmIsConstantComp(p,ri))
478  {
479    return(0);
480  }
481
482  int *e=(int *)omAlloc((ri->N+1)*sizeof(int));
483  p_GetExpV(p,e,ri);
484  int b = p_mFirstVblock(p, e, ri);
485  omFreeSize((ADDRESS) e, (ri->N+1)*sizeof(int));
486  return b;
487}
488
489/* for a monomial p with exponent vector expV, returns the number of the first block */
490/* where a nonzero exponent is sitting */
491int p_mFirstVblock(poly p, int *expV, const ring ri)
492{
493  if (p == NULL || p_LmIsConstantComp(p,ri))
494  {
495    return(0);
496  }
497
498  int lV = ri->isLPring;
499  int j,b;
500  j = 1;
501  while ( (!expV[j]) && (j<=ri->N-1) ) j++;
502  assume(j <= ri->N);
503  b = (int)(j+lV-1)/lV; /* the number of the block, 1<= b <= r->N  */
504  return b;
505}
506
507// appends m2ExpV to m1ExpV, also adds their components (one of them is always zero)
508void p_LPExpVappend(int *m1ExpV, int *m2ExpV, int m1Length, int m2Length, const ring ri) {
509#ifdef SHIFT_MULT_DEBUG
510  PrintLn(); PrintS("Append");
511  PrintLn(); WriteLPExpV(m1ExpV, ri);
512  PrintLn(); WriteLPExpV(m2ExpV, ri);
513#endif
514  int last = m1Length + m2Length;
515  if (last > ri->N)
516  {
517    Werror("degree bound of Letterplace ring is %d, but at least %d is needed for this multiplication", ri->N/ri->isLPring, last/ri->isLPring);
518    last = ri->N;
519  }
520  for (int i = 1 + m1Length; i < 1 + last; ++i)
521  {
522    assume(m2ExpV[i - m1Length] <= 1);
523    m1ExpV[i] = m2ExpV[i - m1Length];
524  }
525
526  assume(m1ExpV[0] == 0 || m2ExpV[0] == 0); // one component should be zero (otherwise this doesn't make any sense)
527  m1ExpV[0] += m2ExpV[0]; // as in the commutative variant (they use MemAdd)
528#ifdef SHIFT_MULT_DEBUG
529  PrintLn(); WriteLPExpV(m1ExpV, ri);
530#endif
531  assume(_p_mLPNCGenValid(m1ExpV, ri));
532}
533
534// prepends m2ExpV to m1ExpV, also adds their components (one of them is always zero)
535void p_LPExpVprepend(int *m1ExpV, int *m2ExpV, int m1Length, int m2Length, const ring ri)
536{
537#ifdef SHIFT_MULT_DEBUG
538  PrintLn(); PrintS("Prepend");
539  PrintLn(); WriteLPExpV(m1ExpV, ri);
540  PrintLn(); WriteLPExpV(m2ExpV, ri);
541#endif
542  int last = m1Length + m2Length;
543  if (last > ri->N)
544  {
545    Werror("degree bound of Letterplace ring is %d, but at least %d is needed for this multiplication", ri->N/ri->isLPring, last/ri->isLPring);
546    last = ri->N;
547  }
548
549  // shift m1 by m2Length
550  for (int i = last; i >= 1 + m2Length; --i)
551  {
552    m1ExpV[i] = m1ExpV[i - m2Length];
553  }
554
555  // write m2 to m1
556  for (int i = 1; i < 1 + m2Length; ++i)
557  {
558    assume(m2ExpV[i] <= 1);
559    m1ExpV[i] = m2ExpV[i];
560  }
561
562  assume(m1ExpV[0] == 0 || m2ExpV[0] == 0); // one component should be zero (otherwise this doesn't make any sense)
563  m1ExpV[0] += m2ExpV[0]; // as in the commutative variant (they use MemAdd)
564#ifdef SHIFT_MULT_DEBUG
565  PrintLn(); WriteLPExpV(m1ExpV, ri);
566#endif
567  assume(_p_mLPNCGenValid(m1ExpV, ri));
568}
569
570void WriteLPExpV(int *expV, ring ri)
571{
572  char *s = LPExpVString(expV, ri);
573  PrintS(s);
574  omFree(s);
575}
576
577char* LPExpVString(int *expV, ring ri)
578{
579  StringSetS("");
580  for (int i = 0; i <= ri->N; ++i)
581  {
582    StringAppend("%d", expV[i]);
583    if (i == 0)
584    {
585      StringAppendS("| ");
586    }
587    if (i % ri->isLPring == 0 && i != ri->N)
588    {
589      StringAppendS(" ");
590    }
591  }
592  return StringEndS();
593}
594
595// splits a frame (e.g. x(1)*y(5)) m1 into m1 and m2 (e.g. m1=x(1) and m2=y(1))
596// according to p which is inside the frame
597void k_SplitFrame(poly &m1, poly &m2, int at, const ring r)
598{
599  int lV = r->isLPring;
600
601  number m1Coeff = pGetCoeff(m1);
602
603  int hole = lV * at;
604  m2 = p_GetExp_k_n(m1, 1, hole, r);
605  m1 = p_GetExp_k_n(m1, hole, r->N, r);
606
607  p_mLPunshift(m2, r);
608  p_SetCoeff(m1, m1Coeff, r);
609
610  assume(p_FirstVblock(m1,r) <= 1);
611  assume(p_FirstVblock(m2,r) <= 1);
612}
613
614BOOLEAN _p_mLPNCGenValid(int *mExpV, const ring r)
615{
616  BOOLEAN hasNCGen = FALSE;
617  int lV = r->isLPring;
618  int degbound = r->N/lV;
619  int ncGenCount = r->LPncGenCount;
620  for (int i = 1; i <= degbound; i++)
621  {
622    for (int j = i*lV; j > (i*lV - ncGenCount); j--)
623    {
624      if (mExpV[j])
625      {
626        if (hasNCGen)
627        {
628          return FALSE;
629        }
630        hasNCGen = TRUE;
631      }
632    }
633  }
634  return TRUE;
635}
636
637/* tests whether each polynomial of an ideal I lies in in V */
638int id_IsInV(ideal I, const ring r)
639{
640  int i;
641  int s    = IDELEMS(I)-1;
642  for(i = 0; i <= s; i++)
643  {
644    if ( !p_IsInV(I->m[i], r) )
645    {
646      return(0);
647    }
648  }
649  return(1);
650}
651
652/* tests whether the whole polynomial p in in V */
653int p_IsInV(poly p, const ring r)
654{
655  poly q = p;
656  while (q!=NULL)
657  {
658    if ( !p_mIsInV(q, r) )
659    {
660      return(0);
661    }
662    q = pNext(q);
663  }
664  return(1);
665}
666
667/* there should be two routines: */
668/* 1. test place-squarefreeness: in homog this suffices: isInV */
669/* 2. test the presence of a hole -> in the tail??? */
670
671int p_mIsInV(poly p, const ring r)
672{
673  int lV = r->isLPring;
674  /* investigate only the leading monomial of p in currRing */
675  if ( p_Totaldegree(p, r)==0 ) return(1);
676  /* returns 1 iff p is in V */
677  /* that is in each block up to a certain one there is only one nonzero exponent */
678  /* lV = the length of V = the number of orig vars */
679  int *e = (int *)omAlloc((r->N+1)*sizeof(int));
680  int  b = (int)((r->N+lV-1)/lV); /* the number of blocks */
681  //int b  = (int)(currRing->N)/lV;
682  int *B = (int *)omAlloc0((b+1)*sizeof(int)); /* the num of elements in a block */
683  p_GetExpV(p,e,r);
684  int i,j;
685  for (j=1; j<=b; j++)
686  {
687    /* we go through all the vars */
688    /* by blocks in lV vars */
689    for (i=(j-1)*lV + 1; i<= j*lV; i++)
690    {
691      if (e[i]) B[j] = B[j]+1;
692    }
693  }
694  //  j = b;
695  //  while ( (!B[j]) && (j>=1)) j--;
696  for (j=b; j>=1; j--)
697  {
698    if (B[j]!=0) break;
699  }
700
701  if (j==0)
702  {
703    omFreeSize((ADDRESS) e, (r->N+1)*sizeof(int));
704    omFreeSize((ADDRESS) B, (b+1)*sizeof(int));
705    return 1;
706  }
707
708  if (!_p_mLPNCGenValid(e, r))
709  {
710    omFreeSize((ADDRESS) e, (r->N+1)*sizeof(int));
711    omFreeSize((ADDRESS) B, (b+1)*sizeof(int));
712    return 0;
713  }
714
715  omFreeSize((ADDRESS) e, (r->N+1)*sizeof(int));
716
717//   {
718//     /* it is a zero exp vector, which is in V */
719//     freeT(B, b);
720//     return(1);
721//   }
722  /* now B[j] != 0 and we test place-squarefreeness */
723  for (; j>=1; j--)
724  {
725    if (B[j]!=1)
726    {
727      omFreeSize((ADDRESS) B, (b+1)*sizeof(int));
728      return 0;
729    }
730  }
731
732  omFreeSize((ADDRESS) B, (b+1)*sizeof(int));
733  return 1;
734}
735
736BOOLEAN p_LPDivisibleBy(poly a, poly b, const ring r)
737{
738  pIfThen1(b!=NULL, p_LmCheckPolyRing1(b, r));
739  pIfThen1(a!=NULL, p_LmCheckPolyRing1(a, r));
740
741  if (b == NULL) return TRUE;
742  if (a != NULL && (p_GetComp(a, r) == 0 || p_GetComp(a,r) == p_GetComp(b,r)))
743      return _p_LPLmDivisibleByNoComp(a,b,r);
744  return FALSE;
745}
746
747BOOLEAN p_LPLmDivisibleBy(poly a, poly b, const ring r)
748{
749  p_LmCheckPolyRing1(b, r);
750  pIfThen1(a != NULL, p_LmCheckPolyRing1(b, r));
751  if (p_GetComp(a, r) == 0 || p_GetComp(a,r) == p_GetComp(b,r))
752    return _p_LPLmDivisibleByNoComp(a, b, r);
753  return FALSE;
754}
755
756BOOLEAN _p_LPLmDivisibleByNoComp(poly a, poly b, const ring r)
757{
758  if(p_LmIsConstantComp(a, r))
759    return TRUE;
760#ifdef SHIFT_MULT_COMPAT_MODE
761  a = p_Head(a, r);
762  p_mLPunshift(a, r);
763  b = p_Head(b, r);
764  p_mLPunshift(b, r);
765#endif
766  int i = (r->N / r->isLPring) - p_LastVblock(a, r);
767  do {
768    int j = r->N - (i * r->isLPring);
769    bool divisible = true;
770    do
771    {
772      if (p_GetExp(a, j, r) > p_GetExp(b, j + (i * r->isLPring), r))
773      {
774        divisible = false;
775        break;
776      }
777      j--;
778    }
779    while (j);
780    if (divisible) return TRUE;
781    i--;
782  }
783  while (i > -1);
784#ifdef SHIFT_MULT_COMPAT_MODE
785  p_Delete(&a, r);
786  p_Delete(&b, r);
787#endif
788  return FALSE;
789}
790
791poly p_LPVarAt(poly p, int pos, const ring r)
792{
793  if (p == NULL || pos < 1 || pos > (r->N / r->isLPring)) return NULL;
794  poly v = p_One(r);
795  for (int i = (pos-1) * r->isLPring + 1; i <= pos * r->isLPring; i++) {
796    if (p_GetExp(p, i, r)) {
797      p_SetExp(v, i - (pos-1) * r->isLPring, 1, r);
798      return v;
799    }
800  }
801  return v;
802}
803
804/// substitute weights from orderings a,wp,Wp
805/// by d copies of it at position p
806static BOOLEAN freeAlgebra_weights(const ring old_ring, ring new_ring, int p, int d)
807{
808  omFree(new_ring->wvhdl[p]);
809  int *w=(int*)omAlloc(new_ring->N*sizeof(int));
810  for(int b=0;b<d;b++)
811  {
812    for(int i=old_ring->N-1;i>=0;i--)
813    {
814      if (old_ring->wvhdl[p][i]<-0) return TRUE;
815      w[b*old_ring->N+i]=old_ring->wvhdl[p][i];
816    }
817  }
818  new_ring->wvhdl[p]=w;
819  new_ring->block1[p]=new_ring->N;
820  return FALSE;
821}
822
823ring freeAlgebra(ring r, int d, int ncGenCount)
824{
825  if (ncGenCount) r = rCopy0(r);
826  for (int i = 1; i <= ncGenCount; i++)
827  {
828    char *varname=(char *)omAlloc(256);
829    sprintf(varname, "ncgen(%d)", i);
830    ring save = r;
831    r = rPlusVar(r, varname, 0);
832    omFreeSize(varname, 256);
833    rDelete(save);
834  }
835  ring R=rCopy0(r);
836  int p;
837  if((r->order[0]==ringorder_C)
838  ||(r->order[0]==ringorder_c))
839    p=1;
840  else
841    p=0;
842  // create R->N
843  R->N=r->N*d;
844  R->isLPring=r->N;
845  R->LPncGenCount=ncGenCount;
846  // create R->order
847  BOOLEAN has_order_a=FALSE;
848  while (r->order[p]==ringorder_a)
849  {
850    if (freeAlgebra_weights(r,R,p,d))
851    {
852      WerrorS("weights must be positive");
853      return NULL;
854    }
855    has_order_a=TRUE;
856    p++;
857  }
858  R->block1[p]=R->N; /* only dp,Dp,wp,Wp; will be discarded for lp*/
859  switch(r->order[p])
860  {
861    case ringorder_dp:
862    case ringorder_Dp:
863      break;
864    case ringorder_wp:
865    case ringorder_Wp:
866      if (freeAlgebra_weights(r,R,p,d))
867      {
868        WerrorS("weights must be positive");
869        return NULL;
870      }
871      break;
872    case ringorder_lp:
873    case ringorder_rp:
874    {
875      if(has_order_a)
876      {
877        WerrorS("ordering (a(..),lp/rp not implemented for Letterplace rings");
878        return NULL;
879      }
880      int ** wvhdl=(int**)omAlloc0((r->N+3)*sizeof(int*));
881      rRingOrder_t* ord=(rRingOrder_t*)omAlloc0((r->N+3)*sizeof(rRingOrder_t));
882      int* blk0=(int*)omAlloc0((r->N+3)*sizeof(int));
883      int* blk1=(int*)omAlloc0((r->N+3)*sizeof(int));
884      omFree(R->wvhdl);  R->wvhdl=wvhdl;
885      omFree(R->order);  R->order=ord;
886      omFree(R->block0); R->block0=blk0;
887      omFree(R->block1); R->block1=blk1;
888      for(int i=0;i<r->N;i++)
889      {
890        ord[i+p]=ringorder_a;
891        //Print("entry:%d->a\n",i+p);
892        blk0[i+p]=1;
893        blk1[i+p]=R->N;
894        wvhdl[i+p]=(int*)omAlloc0(R->N*sizeof(int));
895        for(int j=0;j<d;j++)
896        {
897          assume(j*r->N+i<R->N);
898          if (r->order[p]==ringorder_lp)
899            wvhdl[i+p][j*r->N+i]=1;
900         else
901            wvhdl[i+p][(j+1)*r->N-i-1]=1;
902        }
903      }
904      ord[r->N+p]=r->order[p]; /* lp or rp */
905      //Print("entry:%d->lp\n",r->N+p);
906      blk0[r->N+p]=1;
907      blk1[r->N+p]=R->N;
908      // copy component order
909      if (p==1) ord[0]=r->order[0];
910      else if (p==0) ord[r->N+1]=r->order[1];
911      else
912      { // should never happen:
913        WerrorS("ordering not implemented for Letterplace rings");
914        return NULL;
915      }
916      //if (p==1) PrintS("entry:0 ->c/C\n");
917      //else if (p==0) Print("entry:%d ->c/C\n",r->N+1);
918      break;
919    }
920    default: WerrorS("ordering not implemented for Letterplace rings");
921      return NULL;
922  }
923  // create R->names
924  char **names=(char**)omAlloc(R->N*sizeof(char*));
925  for(int b=0;b<d;b++)
926  {
927    for(int i=r->N-1;i>=0;i--)
928      names[b*r->N+i]=omStrDup(r->names[i]);
929  }
930  for(int i=r->N-1;i>=0;i--) omFree(R->names[i]);
931  omFree(R->names);
932  R->names=names;
933
934  if (ncGenCount) rDelete(r);
935  rComplete(R,TRUE);
936  return R;
937}
938#endif
Note: See TracBrowser for help on using the repository browser.