source: git/libpolys/polys/shiftop.cc @ 6b15a76

spielwiese
Last change on this file since 6b15a76 was 6b15a76, checked in by Hans Schoenemann <hannes@…>, 5 years ago
extend freeAlagebra to ordering a (+wp/Wp/dp/Dp) OR lp
  • Property mode set to 100644
File size: 21.6 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  for (int i = ri->N - sh*lV; i > 0; i--)
371  {
372    assume(e[i]<=1);
373    if (e[i]==1)
374    {
375      s[i + (sh*lV)] = e[i]; /* actually 1 */
376    }
377  }
378  p_SetExpV(m,s,ri);
379  omFreeSize((ADDRESS) e, (ri->N+1)*sizeof(int));
380  omFreeSize((ADDRESS) s, (ri->N+1)*sizeof(int));
381}
382
383void p_LPshift(poly p, int sh, const ring ri)
384{
385  if (sh == 0) return;
386
387  while (p!=NULL)
388  {
389    p_mLPshift(p, sh, ri);
390    pIter(p);
391  }
392}
393
394/* returns the number of maximal block */
395/* appearing among the monomials of p */
396/* the 0th block is the 1st one */
397int p_LastVblock(poly p, const ring r)
398{
399  poly q = p;
400  int ans = 0;
401  while (q!=NULL)
402  {
403    int ansnew = p_mLastVblock(q, r);
404    ans    = si_max(ans,ansnew);
405    pIter(q);
406  }
407  return(ans);
408}
409
410/* for a monomial p, returns the number of the last block */
411/* where a nonzero exponent is sitting */
412int p_mLastVblock(poly p, const ring ri)
413{
414  if (p == NULL || p_LmIsConstantComp(p,ri))
415  {
416    return(0);
417  }
418
419  int *e=(int *)omAlloc((ri->N+1)*sizeof(int));
420  p_GetExpV(p,e,ri);
421  int b = p_mLastVblock(p, e, ri);
422  omFreeSize((ADDRESS) e, (ri->N+1)*sizeof(int));
423  return b;
424}
425
426/* for a monomial p with exponent vector expV, returns the number of the last block */
427/* where a nonzero exponent is sitting */
428int p_mLastVblock(poly p, int *expV, const ring ri)
429{
430  if (p == NULL || p_LmIsConstantComp(p,ri))
431  {
432    return(0);
433  }
434
435  int lV = ri->isLPring;
436  int j,b;
437  j = ri->N;
438  while ( (!expV[j]) && (j>=1) ) j--;
439  assume(j>0);
440  b = (int)((j+lV-1)/lV); /* the number of the block, >=1 */
441  return b;
442}
443
444/* returns the number of maximal block */
445/* appearing among the monomials of p */
446/* the 0th block is the 1st one */
447int p_FirstVblock(poly p, const ring r)
448{
449  if (p == NULL) {
450    return 0;
451  }
452
453  poly q = p;
454  int ans = p_mFirstVblock(q, r);
455  while (q!=NULL)
456  {
457    int ansnew = p_mFirstVblock(q, r);
458    if (ansnew > 0) { // don't count constants
459      ans = si_min(ans,ansnew);
460    }
461    pIter(q);
462  }
463  /* do not need to delete q */
464  return(ans);
465}
466
467/* for a monomial p, returns the number of the first block */
468/* where a nonzero exponent is sitting */
469int p_mFirstVblock(poly p, const ring ri)
470{
471  if (p == NULL || p_LmIsConstantComp(p,ri))
472  {
473    return(0);
474  }
475
476  int *e=(int *)omAlloc((ri->N+1)*sizeof(int));
477  p_GetExpV(p,e,ri);
478  int b = p_mFirstVblock(p, e, ri);
479  omFreeSize((ADDRESS) e, (ri->N+1)*sizeof(int));
480  return b;
481}
482
483/* for a monomial p with exponent vector expV, returns the number of the first block */
484/* where a nonzero exponent is sitting */
485int p_mFirstVblock(poly p, int *expV, const ring ri)
486{
487  if (p == NULL || p_LmIsConstantComp(p,ri))
488  {
489    return(0);
490  }
491
492  int lV = ri->isLPring;
493  int j,b;
494  j = 1;
495  while ( (!expV[j]) && (j<=ri->N-1) ) j++;
496  assume(j <= ri->N);
497  b = (int)(j+lV-1)/lV; /* the number of the block, 1<= b <= r->N  */
498  return b;
499}
500
501// appends m2ExpV to m1ExpV, also adds their components (one of them is always zero)
502void p_LPExpVappend(int *m1ExpV, int *m2ExpV, int m1Length, int m2Length, const ring ri) {
503#ifdef SHIFT_MULT_DEBUG
504  PrintLn(); PrintS("Append");
505  PrintLn(); WriteLPExpV(m1ExpV, ri);
506  PrintLn(); WriteLPExpV(m2ExpV, ri);
507#endif
508  if (m1Length + m2Length > ri->N)
509  {
510    WarnS("letterplace degree bound too low for this multiplication");
511  }
512  for (int i = 1 + m1Length; i < 1 + m1Length + m2Length; ++i)
513  {
514    assume(m2ExpV[i - m1Length] <= 1);
515    m1ExpV[i] = m2ExpV[i - m1Length];
516  }
517
518  assume(m1ExpV[0] == 0 || m2ExpV[0] == 0); // one component should be zero (otherwise this doesn't make any sense)
519  m1ExpV[0] += m2ExpV[0]; // as in the commutative variant (they use MemAdd)
520#ifdef SHIFT_MULT_DEBUG
521  PrintLn(); WriteLPExpV(m1ExpV, ri);
522#endif
523}
524
525// prepends m2ExpV to m1ExpV, also adds their components (one of them is always zero)
526void p_LPExpVprepend(int *m1ExpV, int *m2ExpV, int m1Length, int m2Length, const ring ri)
527{
528#ifdef SHIFT_MULT_DEBUG
529  PrintLn(); PrintS("Prepend");
530  PrintLn(); WriteLPExpV(m1ExpV, ri);
531  PrintLn(); WriteLPExpV(m2ExpV, ri);
532#endif
533  if (m1Length + m2Length > ri->N)
534  {
535    WarnS("letterplace degree bound too low for this multiplication");
536  }
537
538  // shift m1 by m2Length
539  for (int i = m2Length + m1Length; i >= 1 + m2Length; --i)
540  {
541    m1ExpV[i] = m1ExpV[i - m2Length];
542  }
543
544  // write m2 to m1
545  for (int i = 1; i < 1 + m2Length; ++i)
546  {
547    assume(m2ExpV[i] <= 1);
548    m1ExpV[i] = m2ExpV[i];
549  }
550
551  assume(m1ExpV[0] == 0 || m2ExpV[0] == 0); // one component should be zero (otherwise this doesn't make any sense)
552  m1ExpV[0] += m2ExpV[0]; // as in the commutative variant (they use MemAdd)
553#ifdef SHIFT_MULT_DEBUG
554  PrintLn(); WriteLPExpV(m1ExpV, ri);
555#endif
556}
557
558void WriteLPExpV(int *expV, ring ri)
559{
560  char *s = LPExpVString(expV, ri);
561  PrintS(s);
562  omFree(s);
563}
564
565char* LPExpVString(int *expV, ring ri)
566{
567  StringSetS("");
568  for (int i = 0; i <= ri->N; ++i)
569  {
570    StringAppend("%d", expV[i]);
571    if (i == 0)
572    {
573      StringAppendS("| ");
574    }
575    if (i % ri->isLPring == 0 && i != ri->N)
576    {
577      StringAppendS(" ");
578    }
579  }
580  return StringEndS();
581}
582
583/* tests whether each polynomial of an ideal I lies in in V */
584int id_IsInV(ideal I, const ring r)
585{
586  int i;
587  int s    = IDELEMS(I)-1;
588  for(i = 0; i <= s; i++)
589  {
590    if ( !p_IsInV(I->m[i], r) )
591    {
592      return(0);
593    }
594  }
595  return(1);
596}
597
598/* tests whether the whole polynomial p in in V */
599int p_IsInV(poly p, const ring r)
600{
601  poly q = p;
602  while (q!=NULL)
603  {
604    if ( !p_mIsInV(q, r) )
605    {
606      return(0);
607    }
608    q = pNext(q);
609  }
610  return(1);
611}
612
613/* there should be two routines: */
614/* 1. test place-squarefreeness: in homog this suffices: isInV */
615/* 2. test the presence of a hole -> in the tail??? */
616
617int p_mIsInV(poly p, const ring r)
618{
619  int lV = r->isLPring;
620  /* investigate only the leading monomial of p in currRing */
621  if ( p_Totaldegree(p, r)==0 ) return(1);
622  /* returns 1 iff p is in V */
623  /* that is in each block up to a certain one there is only one nonzero exponent */
624  /* lV = the length of V = the number of orig vars */
625  int *e = (int *)omAlloc((r->N+1)*sizeof(int));
626  int  b = (int)((r->N+lV-1)/lV); /* the number of blocks */
627  //int b  = (int)(currRing->N)/lV;
628  int *B = (int *)omAlloc0((b+1)*sizeof(int)); /* the num of elements in a block */
629  p_GetExpV(p,e,r);
630  int i,j;
631  for (j=1; j<=b; j++)
632  {
633    /* we go through all the vars */
634    /* by blocks in lV vars */
635    for (i=(j-1)*lV + 1; i<= j*lV; i++)
636    {
637      if (e[i]) B[j] = B[j]+1;
638    }
639  }
640  //  j = b;
641  //  while ( (!B[j]) && (j>=1)) j--;
642  for (j=b; j>=1; j--)
643  {
644    if (B[j]!=0) break;
645  }
646  /* do not need e anymore */
647  omFreeSize((ADDRESS) e, (r->N+1)*sizeof(int));
648
649  if (j==0) goto ret_true;
650//   {
651//     /* it is a zero exp vector, which is in V */
652//     freeT(B, b);
653//     return(1);
654//   }
655  /* now B[j] != 0 and we test place-squarefreeness */
656  for (; j>=1; j--)
657  {
658    if (B[j]!=1)
659    {
660      omFreeSize((ADDRESS) B, (b+1)*sizeof(int));
661      return(0);
662    }
663  }
664 ret_true:
665  omFreeSize((ADDRESS) B, (b+1)*sizeof(int));
666  return(1);
667}
668
669BOOLEAN p_LPDivisibleBy(poly a, poly b, const ring r)
670{
671  pIfThen1(b!=NULL, p_LmCheckPolyRing1(b, r));
672  pIfThen1(a!=NULL, p_LmCheckPolyRing1(a, r));
673
674  if (b == NULL) return TRUE;
675  if (a != NULL && (p_GetComp(a, r) == 0 || p_GetComp(a,r) == p_GetComp(b,r)))
676      return _p_LPLmDivisibleByNoComp(a,b,r);
677  return FALSE;
678}
679
680BOOLEAN p_LPLmDivisibleBy(poly a, poly b, const ring r)
681{
682  p_LmCheckPolyRing1(b, r);
683  pIfThen1(a != NULL, p_LmCheckPolyRing1(b, r));
684  if (p_GetComp(a, r) == 0 || p_GetComp(a,r) == p_GetComp(b,r))
685    return _p_LPLmDivisibleByNoComp(a, b, r);
686  return FALSE;
687}
688
689BOOLEAN _p_LPLmDivisibleByNoComp(poly a, poly b, const ring r)
690{
691  if(p_LmIsConstantComp(a, r))
692    return TRUE;
693#ifdef SHIFT_MULT_COMPAT_MODE
694  a = p_Head(a, r);
695  p_mLPunshift(a, r);
696  b = p_Head(b, r);
697  p_mLPunshift(b, r);
698#endif
699  int i = (r->N / r->isLPring) - p_LastVblock(a, r);
700  do {
701    int j = r->N - (i * r->isLPring);
702    bool divisible = true;
703    do
704    {
705      if (p_GetExp(a, j, r) > p_GetExp(b, j + (i * r->isLPring), r))
706      {
707        divisible = false;
708        break;
709      }
710      j--;
711    }
712    while (j);
713    if (divisible) return TRUE;
714    i--;
715  }
716  while (i > -1);
717#ifdef SHIFT_MULT_COMPAT_MODE
718  p_Delete(&a, r);
719  p_Delete(&b, r);
720#endif
721  return FALSE;
722}
723
724poly p_LPVarAt(poly p, int pos, const ring r)
725{
726  if (p == NULL || pos < 1 || pos > (r->N / r->isLPring)) return NULL;
727  poly v = p_One(r);
728  for (int i = (pos-1) * r->isLPring + 1; i <= pos * r->isLPring; i++) {
729    if (p_GetExp(p, i, r)) {
730      p_SetExp(v, i - (pos-1) * r->isLPring, 1, r);
731      return v;
732    }
733  }
734  return v;
735}
736
737/// substitute weights from orderings a,wp,Wp
738/// by d copies of it at position p
739static BOOLEAN freeAlgebra_weights(const ring old_ring, ring new_ring, int p, int d)
740{
741  omFree(new_ring->wvhdl[p]);
742  int *w=(int*)omAlloc(new_ring->N*sizeof(int));
743  for(int b=0;b<d;b++)
744  {
745    for(int i=old_ring->N-1;i>=0;i--)
746    {
747      if (old_ring->wvhdl[p][i]<-0) return TRUE;
748      w[b*old_ring->N+i]=old_ring->wvhdl[p][i];
749    }
750  }
751  new_ring->wvhdl[p]=w;
752  new_ring->block1[p]=new_ring->N;
753  return FALSE;
754}
755
756ring freeAlgebra(ring r, int d)
757{
758  ring R=rCopy0(r);
759  int p;
760  if((r->order[0]==ringorder_C)
761  ||(r->order[0]==ringorder_c))
762    p=1;
763  else
764    p=0;
765  // create R->N
766  R->N=r->N*d;
767  R->isLPring=r->N;
768  // create R->order
769  BOOLEAN has_order_a=FALSE;
770  while (r->order[p]==ringorder_a)
771  {
772    if (freeAlgebra_weights(r,R,p,d))
773    {
774      WerrorS("weights must be positive");
775      return NULL;
776    }
777    has_order_a=TRUE;
778    p++;
779  }
780  R->block1[p]=R->N; /* only dp,Dp,wp,Wp; will be discarded for lp*/
781  switch(r->order[p])
782  {
783    case ringorder_dp:
784    case ringorder_Dp:
785      break;
786    case ringorder_wp:
787    case ringorder_Wp:
788      if (freeAlgebra_weights(r,R,p,d))
789      {
790        WerrorS("weights must be positive");
791        return NULL;
792      }
793      break;
794    case ringorder_lp:
795    case ringorder_rp:
796    {
797      if(has_order_a)
798      {
799        WerrorS("ordering (a(..),lp/rp not implemented for LP-rings");
800        return NULL;
801      }
802      int ** wvhdl=(int**)omAlloc0((r->N+2)*sizeof(int*));
803      rRingOrder_t* ord=(rRingOrder_t*)omAlloc0((r->N+2)*sizeof(rRingOrder_t));
804      int* blk0=(int*)omAlloc0((r->N+2)*sizeof(int));
805      int* blk1=(int*)omAlloc0((r->N+2)*sizeof(int));
806      omFree(R->wvhdl);  R->wvhdl=wvhdl;
807      omFree(R->order);  R->order=ord;
808      omFree(R->block0); R->block0=blk0;
809      omFree(R->block1); R->block1=blk1;
810      for(int i=0;i<r->N;i++)
811      {
812        ord[i+p]=ringorder_a;
813        blk0[i+p]=1;
814        blk1[i+p]=R->N;
815        wvhdl[i+p]=(int*)omAlloc0(R->N*sizeof(int));
816        for(int j=0;j<d;j++)
817        {
818          assume(j*r->N+i<R->N);
819          if (r->order[p]==ringorder_lp)
820            wvhdl[i+p][j*r->N+i]=1;
821         else
822            wvhdl[i+p][(j+1)*r->N-i-1]=1;
823        }
824      }
825      ord[r->N+p]=r->order[p]; /* lp or rp */
826      blk0[r->N+p]=1;
827      blk1[r->N+p]=R->N;
828      // copy component order
829      if (p==1) ord[0]=r->order[0];
830      else if (p==0) ord[r->N+1]=r->order[1];
831      else
832      { // should never happen:
833        WerrorS("ordering not implemented for LP-rings");
834        return NULL;
835      }
836      break;
837    }
838    default: WerrorS("ordering not implemented for LP-rings");
839      return NULL;
840  }
841  // create R->names
842  char **names=(char**)omAlloc(R->N*sizeof(char*));
843  for(int b=0;b<d;b++)
844  {
845    for(int i=r->N-1;i>=0;i--)
846      names[b*r->N+i]=omStrDup(r->names[i]);
847  }
848  for(int i=r->N-1;i>=0;i--) omFree(R->names[i]);
849  omFree(R->names);
850  R->names=names;
851
852  rComplete(R,TRUE);
853  return R;
854}
855#endif
Note: See TracBrowser for help on using the repository browser.