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

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