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

fieker-DuValspielwiese
Last change on this file since f190196 was f190196, checked in by Hans Schoenemann <hannes@…>, 6 years ago
fix: avoid out-of-array in shift for LPring
  • Property mode set to 100644
File size: 14.8 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
8/* #define SHIFT_MULT_DEBUG */
9
10/* enable compat mode until the user interface is updated to support xy instead of x(1)*y(2)
11 * NOTE: it already works, but all tests and the libraries need to be updated first
12 * -> wait until the new interface is released
13*/
14#define SHIFT_MULT_COMPAT_MODE
15
16#ifdef SHIFT_MULT_DEBUG
17#include "../kernel/polys.h"
18#endif
19
20poly shift_pp_Mult_mm(poly p, const poly m, const ring ri)
21{
22#ifdef SHIFT_MULT_DEBUG
23  PrintLn(); PrintS("shift_pp_Mult_mm: ("); p_wrp(p, ri, ri); PrintS(") * "); p_wrp(m, ri, ri);
24#endif
25
26  p_Test(p, ri);
27  p_LmTest(m, ri);
28  if (p == NULL)
29  {
30    return NULL;
31  }
32
33  int lV = ri->isLPring;
34  poly _m = m; // temp hack because m is const
35#ifdef SHIFT_MULT_COMPAT_MODE
36  _m = p_Copy(_m, ri);
37  p_mLPunshift(_m, ri);
38  p = p_Copy(p, ri);
39  poly pCopyHead = p; // used to delete p later
40  p_LPunshift(p, ri);
41#else
42  assume(p_mFirstVblock(_m, ri) <= 1);
43  assume(p_FirstVblock(p, ri) <= 1); // TODO check that each block is <=1
44#endif
45  // at this point _m and p are shifted to 1
46
47  spolyrec rp;
48  poly q = &rp; // we use p for iterating and q for the result
49  number mCoeff = pGetCoeff(_m);
50  omBin bin = ri->PolyBin;
51  pAssume(!n_IsZero(mCoeff, ri->cf));
52  pAssume1(p_GetComp(m, ri) == 0 || p_MaxComp(p, ri) == 0);
53
54  int *mExpV = (int *) omAlloc0((ri->N+1)*sizeof(int));
55  p_GetExpV(_m,mExpV,ri);
56  int mLength = p_mLastVblock(_m, mExpV, ri) * lV;
57  do
58  {
59    p_AllocBin(pNext(q), bin, ri);
60    pIter(q);
61    pSetCoeff0(q, n_Mult(mCoeff, pGetCoeff(p), ri->cf));
62
63    int *pExpV = (int *) omAlloc0((ri->N+1)*sizeof(int));
64    p_GetExpV(p, pExpV, ri);
65    p_LPExpVappend(pExpV, mExpV, p_mLastVblock(p, pExpV, ri) * lV, mLength, ri);
66    p_MemCopy_LengthGeneral(q->exp, p->exp, ri->ExpL_Size); // otherwise q is not initialized correctly
67    p_SetExpV(q, pExpV, ri);
68    omFreeSize((ADDRESS) pExpV, (ri->N+1)*sizeof(int));
69
70    pIter(p);
71  }
72  while (p != NULL);
73  omFreeSize((ADDRESS) mExpV, (ri->N+1)*sizeof(int));
74  pNext(q) = NULL;
75#ifdef SHIFT_MULT_COMPAT_MODE
76  p_Delete(&_m, ri); // in this case we copied _m before
77  p_Delete(&pCopyHead, ri); // in this case we copied p before
78#endif
79#ifdef SHIFT_MULT_DEBUG
80  PrintLn(); PrintS("shift_pp_Mult_mm result: "); p_wrp(pNext(&rp), ri, ri); PrintLn();
81#endif
82  p_Test(pNext(&rp), ri);
83  return pNext(&rp);
84}
85
86// destroys p
87poly shift_p_Mult_mm(poly p, const poly m, const ring ri)
88{
89#ifdef SHIFT_MULT_DEBUG
90  PrintLn(); PrintS("shift_p_Mult_mm: ("); p_wrp(p, ri, ri); PrintS(") * "); p_wrp(m, ri, ri);
91#endif
92
93  p_Test(p, ri);
94  p_LmTest(m, ri);
95  pAssume(m != NULL);
96  assume(p!=NULL);
97
98  int lV = ri->isLPring;
99  poly _m = m; // temp hack because m is const
100#ifdef SHIFT_MULT_COMPAT_MODE
101  _m = p_Copy(_m, ri);
102  p_mLPunshift(_m, ri);
103  p_LPunshift(p, ri);
104#else
105  assume(p_mFirstVblock(_m, ri) <= 1);
106  assume(p_FirstVblock(p, ri) <= 1); // TODO check that each block is <=1
107#endif
108  // at this point _m and p are shifted to 1
109
110  poly q = p; // we use p for iterating and q for the result
111  number mCoeff = pGetCoeff(_m);
112  number pCoeff;
113  pAssume(!n_IsZero(mCoeff, ri->cf));
114
115  int *mExpV = (int *) omAlloc0((ri->N+1)*sizeof(int));
116  p_GetExpV(_m,mExpV,ri);
117  int mLength = p_mLastVblock(_m, mExpV, ri) * lV;
118  while (p != NULL)
119  {
120    pCoeff = pGetCoeff(p);
121    pSetCoeff0(p, n_Mult(mCoeff, pCoeff, ri->cf));
122    n_Delete(&pCoeff, ri->cf); // delete the old coeff
123
124    int *pExpV = (int *) omAlloc0((ri->N+1)*sizeof(int));
125    p_GetExpV(p,pExpV,ri);
126    p_LPExpVappend(pExpV, mExpV, p_mLastVblock(p, pExpV, ri) * lV, mLength, ri);
127    p_SetExpV(p, pExpV, ri);
128    omFreeSize((ADDRESS) pExpV, (ri->N+1)*sizeof(int));
129
130    pIter(p);
131  }
132  omFreeSize((ADDRESS) mExpV, (ri->N+1)*sizeof(int));
133#ifdef SHIFT_MULT_COMPAT_MODE
134  p_Delete(&_m, ri); // in this case we copied _m before
135#endif
136#ifdef SHIFT_MULT_DEBUG
137  PrintLn(); PrintS("shift_p_Mult_mm result: "); p_wrp(q, ri, ri); PrintLn();
138#endif
139  p_Test(q, ri);
140  return q;
141}
142
143poly shift_pp_mm_Mult(poly p, const poly m, const ring ri)
144{
145#ifdef SHIFT_MULT_DEBUG
146  PrintLn(); PrintS("shift_pp_mm_Mult: "); p_wrp(m, ri, ri); PrintS(" * ("); p_wrp(p, ri, ri); PrintS(")");
147#endif
148
149  p_Test(p, ri);
150  p_LmTest(m, ri);
151  if (p == NULL)
152  {
153    return NULL;
154  }
155
156  int lV = ri->isLPring;
157  poly _m = m; // temp hack because m is const
158#ifdef SHIFT_MULT_COMPAT_MODE
159  _m = p_Copy(_m, ri);
160  p_mLPunshift(_m, ri);
161  p = p_Copy(p, ri);
162  poly pCopyHead = p; // used to delete p later
163  p_LPunshift(p, ri);
164#else
165  assume(p_mFirstVblock(_m, ri) <= 1);
166  assume(p_FirstVblock(p, ri) <= 1); // TODO check that each block is <=1
167#endif
168  // at this point _m and p are shifted to 1
169
170  spolyrec rp;
171  poly q = &rp; // we use p for iterating and q for the result
172  number mCoeff = pGetCoeff(_m);
173  omBin bin = ri->PolyBin;
174  pAssume(!n_IsZero(mCoeff, ri->cf));
175  pAssume1(p_GetComp(m, ri) == 0 || p_MaxComp(p, ri) == 0);
176
177  int *mExpV = (int *) omAlloc0((ri->N+1)*sizeof(int));
178  p_GetExpV(_m,mExpV,ri);
179  int mLength = p_mLastVblock(_m, mExpV, ri) * lV;
180  do
181  {
182    p_AllocBin(pNext(q), bin, ri);
183    pIter(q);
184    pSetCoeff0(q, n_Mult(mCoeff, pGetCoeff(p), ri->cf));
185
186    int *pExpV = (int *) omAlloc0((ri->N+1)*sizeof(int));
187    p_GetExpV(p, pExpV, ri);
188    p_LPExpVprepend(pExpV, mExpV, p_mLastVblock(p, pExpV, ri) * lV, mLength, ri);
189    p_MemCopy_LengthGeneral(q->exp, p->exp, ri->ExpL_Size); // otherwise q is not initialized correctly
190    p_SetExpV(q, pExpV, ri);
191    omFreeSize((ADDRESS) pExpV, (ri->N+1)*sizeof(int));
192
193    pIter(p);
194  }
195  while (p != NULL);
196  omFreeSize((ADDRESS) mExpV, (ri->N+1)*sizeof(int));
197  pNext(q) = NULL;
198#ifdef SHIFT_MULT_COMPAT_MODE
199  p_Delete(&_m, ri); // in this case we copied _m before
200  p_Delete(&pCopyHead, ri); // in this case we copied p before
201#endif
202#ifdef SHIFT_MULT_DEBUG
203  PrintLn(); PrintS("shift_pp_mm_Mult result: "); p_wrp(pNext(&rp), ri, ri); PrintLn();
204#endif
205  p_Test(pNext(&rp), ri);
206  return pNext(&rp);
207}
208
209// destroys p
210poly shift_p_mm_Mult(poly p, const poly m, const ring ri)
211{
212#ifdef SHIFT_MULT_DEBUG
213  PrintLn(); PrintS("shift_p_mm_Mult: "); p_wrp(m, ri, ri); PrintS(" * ("); p_wrp(p, ri, ri); PrintS(")");
214#endif
215
216  p_Test(p, ri);
217  p_LmTest(m, ri);
218  pAssume(m != NULL);
219  assume(p!=NULL);
220
221  int lV = ri->isLPring;
222  poly _m = m; // temp hack because m is const
223#ifdef SHIFT_MULT_COMPAT_MODE
224  _m = p_Copy(_m, ri);
225  p_mLPunshift(_m, ri);
226  p_LPunshift(p, ri);
227#else
228  assume(p_mFirstVblock(_m, ri) <= 1);
229  assume(p_FirstVblock(p, ri) <= 1); // TODO check that each block is <=1
230#endif
231  // at this point _m and p are shifted to 1
232
233  poly q = p; // we use p for iterating and q for the result
234  number mCoeff = pGetCoeff(_m);
235  number pCoeff;
236  pAssume(!n_IsZero(mCoeff, ri->cf));
237
238  int *mExpV = (int *) omAlloc0((ri->N+1)*sizeof(int));
239  p_GetExpV(_m,mExpV,ri);
240  int mLength = p_mLastVblock(_m, mExpV, ri) * lV;
241  while (p != NULL)
242  {
243    pCoeff = pGetCoeff(p);
244    pSetCoeff0(p, n_Mult(mCoeff, pCoeff, ri->cf));
245    n_Delete(&pCoeff, ri->cf); // delete the old coeff
246
247    int *pExpV = (int *) omAlloc0((ri->N+1)*sizeof(int));
248    p_GetExpV(p,pExpV,ri);
249    p_LPExpVprepend(pExpV, mExpV, p_mLastVblock(p, pExpV, ri) * lV, mLength, ri);
250    p_SetExpV(p, pExpV, ri);
251    omFreeSize((ADDRESS) pExpV, (ri->N+1)*sizeof(int));
252
253    pIter(p);
254  }
255  omFreeSize((ADDRESS) mExpV, (ri->N+1)*sizeof(int));
256#ifdef SHIFT_MULT_COMPAT_MODE
257  p_Delete(&_m, ri); // in this case we copied _m before
258#endif
259#ifdef SHIFT_MULT_DEBUG
260  PrintLn(); PrintS("shift_p_mm_Mult result: "); p_wrp(q, ri, ri); PrintLn();
261#endif
262  p_Test(q, ri);
263  return q;
264}
265
266// p - m*q destroys p
267poly shift_p_Minus_mm_Mult_qq(poly p, poly m, poly q, int& Shorter, const poly spNoether, const ring ri) {
268#ifdef SHIFT_MULT_DEBUG
269  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);
270#endif
271
272  Shorter = pLength(p) + pLength(q);
273
274  poly qq = p_Add_q(p, shift_pp_mm_Mult(q, p_Neg(p_Copy(m, ri), ri), ri), ri);
275
276#ifdef SHIFT_MULT_DEBUG
277  PrintLn(); PrintS("shift_p_Minus_mm_Mult_qq result: "); p_wrp(qq, ri, ri); PrintLn();
278#endif
279  Shorter -= pLength(qq);
280  return qq;
281}
282
283// Unsupported Operation STUBs
284poly shift_pp_Mult_mm_Noether_STUB(poly p, const poly m, const poly spNoether, int &ll, const ring ri) {
285  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.");
286
287  int pLen = 0;
288  if (ll >= 0) {
289    pLen = pLength(p);
290  }
291
292  p = shift_pp_Mult_mm(p, m, ri);
293
294  if (ll >= 0) {
295    ll = pLen - pLength(p);
296  } else {
297    ll = pLength(p);
298  }
299
300  return p;
301}
302
303
304poly shift_pp_Mult_Coeff_mm_DivSelectMult_STUB(poly p,const poly m, const poly a, const poly b, int &shorter,const ring r) {
305  PrintLn(); WarnS("pp_Mult_Coeff_mm_DivSelectMult is not supported yet by Letterplace. This might lead to unexpected behavior.");
306  return NULL;
307}
308
309poly shift_pp_Mult_Coeff_mm_DivSelect_STUB(poly p, const poly m, int &shorter, const ring r) {
310  PrintLn(); WarnS("pp_Mult_Coeff_mm_DivSelect is not supported yet by Letterplace. This might lead to unexpected behavior.");
311  return NULL;
312}
313
314// auxiliary
315
316// unshifts the monomial m
317void p_mLPunshift(poly m, const ring ri)
318{
319  if (m == NULL || p_LmIsConstantComp(m,ri)) return;
320
321  int lV = ri->isLPring;
322
323  int shift = p_mFirstVblock(m, ri) - 1;
324
325  if (shift == 0) return;
326
327  int *e=(int *)omAlloc0((ri->N+1)*sizeof(int));
328  int *s=(int *)omAlloc0((ri->N+1)*sizeof(int));
329  p_GetExpV(m, e, ri);
330
331  int expVoffset = shift*lV;
332  for (int i = 1 + expVoffset; i <= ri->N; i++)
333  {
334    assume(e[i] <= 1);
335    s[i - expVoffset] = e[i];
336  }
337  p_SetExpV(m,s,ri);
338  omFreeSize((ADDRESS) e, (ri->N+1)*sizeof(int));
339  omFreeSize((ADDRESS) s, (ri->N+1)*sizeof(int));
340}
341
342// unshifts the polynomial p, note: the ordering can be destroyed if the shifts for the monomials are not equal
343void p_LPunshift(poly p, const ring ri)
344{
345  while (p!=NULL)
346  {
347    p_mLPunshift(p, ri);
348    pIter(p);
349  }
350}
351
352void p_mLPshift(poly m, int sh, const ring ri)
353{
354  if (sh == 0 || m == NULL || p_LmIsConstantComp(m,ri)) return;
355
356  int lV = ri->isLPring;
357
358  assume(p_mFirstVblock(m,ri) + sh >= 1);
359  assume(p_mLastVblock(m,ri) + sh <= ri->N/lV);
360
361  int *e=(int *)omAlloc0((ri->N+1)*sizeof(int));
362  int *s=(int *)omAlloc0((ri->N+1)*sizeof(int));
363  p_GetExpV(m,e,ri);
364
365  for (int i = ri->N - sh*lV; i > 0; i--)
366  {
367    assume(e[i]<=1);
368    if (e[i]==1)
369    {
370      s[i + (sh*lV)] = e[i]; /* actually 1 */
371    }
372  }
373  p_SetExpV(m,s,ri);
374  omFreeSize((ADDRESS) e, (ri->N+1)*sizeof(int));
375  omFreeSize((ADDRESS) s, (ri->N+1)*sizeof(int));
376}
377
378void p_LPshift(poly p, int sh, const ring ri)
379{
380  if (sh == 0) return;
381
382  while (p!=NULL)
383  {
384    p_mLPshift(p, sh, ri);
385    pIter(p);
386  }
387}
388
389/* returns the number of maximal block */
390/* appearing among the monomials of p */
391/* the 0th block is the 1st one */
392int p_LastVblock(poly p, const ring r)
393{
394  poly q = p;
395  int ans = 0;
396  while (q!=NULL)
397  {
398    int ansnew = p_mLastVblock(q, r);
399    ans    = si_max(ans,ansnew);
400    pIter(q);
401  }
402  return(ans);
403}
404
405/* for a monomial p, returns the number of the last block */
406/* where a nonzero exponent is sitting */
407int p_mLastVblock(poly p, const ring ri)
408{
409  if (p == NULL || p_LmIsConstantComp(p,ri))
410  {
411    return(0);
412  }
413
414  int *e=(int *)omAlloc0((ri->N+1)*sizeof(int));
415  p_GetExpV(p,e,ri);
416  int b = p_mLastVblock(p, e, ri);
417  omFreeSize((ADDRESS) e, (ri->N+1)*sizeof(int));
418  return b;
419}
420
421/* for a monomial p with exponent vector expV, returns the number of the last block */
422/* where a nonzero exponent is sitting */
423int p_mLastVblock(poly p, int *expV, const ring ri)
424{
425  if (p == NULL || p_LmIsConstantComp(p,ri))
426  {
427    return(0);
428  }
429
430  int lV = ri->isLPring;
431  int j,b;
432  j = ri->N;
433  while ( (!expV[j]) && (j>=1) ) j--;
434  assume(j>0);
435  b = (int)((j+lV-1)/lV); /* the number of the block, >=1 */
436  return b;
437}
438
439/* returns the number of maximal block */
440/* appearing among the monomials of p */
441/* the 0th block is the 1st one */
442int p_FirstVblock(poly p, const ring r)
443{
444  if (p == NULL) {
445    return 0;
446  }
447
448  poly q = p;
449  int ans = p_mFirstVblock(q, r);
450  while (q!=NULL)
451  {
452    int ansnew = p_mFirstVblock(q, r);
453    if (ansnew > 0) { // don't count constants
454      ans = si_min(ans,ansnew);
455    }
456    pIter(q);
457  }
458  /* do not need to delete q */
459  return(ans);
460}
461
462/* for a monomial p, returns the number of the first block */
463/* where a nonzero exponent is sitting */
464int p_mFirstVblock(poly p, const ring ri)
465{
466  if (p == NULL || p_LmIsConstantComp(p,ri))
467  {
468    return(0);
469  }
470
471  int *e=(int *)omAlloc0((ri->N+1)*sizeof(int));
472  p_GetExpV(p,e,ri);
473  int b = p_mFirstVblock(p, e, ri);
474  omFreeSize((ADDRESS) e, (ri->N+1)*sizeof(int));
475  return b;
476}
477
478/* for a monomial p with exponent vector expV, returns the number of the first block */
479/* where a nonzero exponent is sitting */
480int p_mFirstVblock(poly p, int *expV, const ring ri)
481{
482  if (p == NULL || p_LmIsConstantComp(p,ri))
483  {
484    return(0);
485  }
486
487  int lV = ri->isLPring;
488  int j,b;
489  j = 1;
490  while ( (!expV[j]) && (j<=ri->N-1) ) j++;
491  assume(j <= ri->N);
492  b = (int)(j+lV-1)/lV; /* the number of the block, 1<= b <= r->N  */
493  return b;
494}
495
496// appends m2ExpV to m1ExpV, also adds their components (one of them is always zero)
497void p_LPExpVappend(int *m1ExpV, int *m2ExpV, int m1Length, int m2Length, const ring ri) {
498#ifdef SHIFT_MULT_DEBUG
499  PrintLn(); PrintS("Append");
500  PrintLn(); WriteLPExpV(m1ExpV, ri);
501  PrintLn(); WriteLPExpV(m2ExpV, ri);
502#endif
503  assume(m1Length + m2Length <= ri->N); // always throw an error?
504  for (int i = 1 + m1Length; i < 1 + m1Length + m2Length; ++i)
505  {
506    assume(m2ExpV[i - m1Length] <= 1);
507    m1ExpV[i] = m2ExpV[i - m1Length];
508  }
509
510  assume(m1ExpV[0] == 0 || m2ExpV[0] == 0); // one component should be zero (otherwise this doesn't make any sense)
511  m1ExpV[0] += m2ExpV[0]; // as in the commutative variant (they use MemAdd)
512#ifdef SHIFT_MULT_DEBUG
513  PrintLn(); WriteLPExpV(m1ExpV, ri);
514#endif
515}
516
517// prepends m2ExpV to m1ExpV, also adds their components (one of them is always zero)
518void p_LPExpVprepend(int *m1ExpV, int *m2ExpV, int m1Length, int m2Length, const ring ri) {
519#ifdef SHIFT_MULT_DEBUG
520  PrintLn(); PrintS("Prepend");
521  PrintLn(); WriteLPExpV(m1ExpV, ri);
522  PrintLn(); WriteLPExpV(m2ExpV, ri);
523#endif
524  assume(m1Length + m2Length <= ri->N); // always throw an error?
525
526  // shift m1 by m2Length
527  for (int i = m2Length + m1Length; i >= 1 + m2Length; --i)
528  {
529    m1ExpV[i] = m1ExpV[i - m2Length];
530  }
531
532  // write m2 to m1
533  for (int i = 1; i < 1 + m2Length; ++i)
534  {
535    assume(m2ExpV[i] <= 1);
536    m1ExpV[i] = m2ExpV[i];
537  }
538
539  assume(m1ExpV[0] == 0 || m2ExpV[0] == 0); // one component should be zero (otherwise this doesn't make any sense)
540  m1ExpV[0] += m2ExpV[0]; // as in the commutative variant (they use MemAdd)
541#ifdef SHIFT_MULT_DEBUG
542  PrintLn(); WriteLPExpV(m1ExpV, ri);
543#endif
544}
545
546void WriteLPExpV(int *expV, ring ri) {
547  for (int i = 0; i <= ri->N; ++i) {
548    Print("%d", expV[i]);
549    if (i == 0) {
550      Print("| ");
551    }
552    if (i % ri->isLPring == 0) {
553      Print(" ");
554    }
555  }
556}
557
558#endif
Note: See TracBrowser for help on using the repository browser.