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

spielwiese
Last change on this file since a0f2b6 was a0f2b6, checked in by Karim Abou Zeid <karim23697@…>, 6 years ago
Make prepend more efficient in letterplace kernel multiplication
  • Property mode set to 100644
File size: 11.4 KB
Line 
1#include "shiftop.h"
2#include "templates/p_MemCopy.h"
3
4/* #define SHIFT_MULT_DEBUG */
5/* #define SHIFT_MULT_COMPAT_MODE */
6
7#ifdef SHIFT_MULT_DEBUG
8#include "../kernel/polys.h"
9#endif
10
11poly shift_pp_Mult_mm(poly p, const poly m, const ring ri)
12{
13#ifdef SHIFT_MULT_DEBUG
14  PrintLn(); PrintS("shift_pp_Mult_mm: ("); p_wrp(p, ri, ri); PrintS(") * "); p_wrp(m, ri, ri);
15#endif
16
17  p_Test(p, ri);
18  p_LmTest(m, ri);
19  if (p == NULL)
20  {
21    return NULL;
22  }
23
24  int lV = ri->isLPring;
25  poly _m = m; // temp hack because m is const
26#ifdef SHIFT_MULT_COMPAT_MODE
27  _m = p_Copy(_m, ri);
28  p_mLPUnShift(_m, ri);
29  p = p_Copy(p, ri);
30  poly pCopyHead = p; // used to delete p later
31  p_LPUnShift(p, ri);
32#else
33  assume(p_mFirstVblock(_m, ri) <= 1);
34  assume(p_FirstVblock(p, ri) <= 1); // TODO check that each block is <=1
35#endif
36  // at this point _m and p are shifted to 1
37
38  spolyrec rp;
39  poly q = &rp; // we use p for iterating and q for the result
40  number mCoeff = pGetCoeff(_m);
41  omBin bin = ri->PolyBin;
42  pAssume(!n_IsZero(mCoeff, ri->cf));
43  pAssume1(p_GetComp(m, ri) == 0 || p_MaxComp(p, ri) == 0);
44
45  int mLength = p_mLastVblock(_m, ri) * lV;
46  int *mExpV = (int *) omAlloc0((ri->N+1)*sizeof(int));
47  p_GetExpV(_m,mExpV,ri);
48  do
49  {
50    p_AllocBin(pNext(q), bin, ri);
51    pIter(q);
52    pSetCoeff0(q, n_Mult(mCoeff, pGetCoeff(p), ri->cf));
53
54    int *pExpV = (int *) omAlloc0((ri->N+1)*sizeof(int));
55    p_GetExpV(p, pExpV, ri);
56    p_LPExpVappend(pExpV, mExpV, p_mLastVblock(p, ri) * lV, mLength, ri);
57    p_MemCopy_LengthGeneral(q->exp, p->exp, ri->ExpL_Size); // otherwise q is not initialized correctly
58    p_SetExpV(q, pExpV, ri);
59    omFreeSize((ADDRESS) pExpV, (ri->N+1)*sizeof(int));
60
61    pIter(p);
62  }
63  while (p != NULL);
64  omFreeSize((ADDRESS) mExpV, (ri->N+1)*sizeof(int));
65  pNext(q) = NULL;
66#ifdef SHIFT_MULT_COMPAT_MODE
67  p_Delete(&_m, ri); // in this case we copied _m before
68  p_Delete(&pCopyHead, ri); // in this case we copied p before
69#endif
70#ifdef SHIFT_MULT_DEBUG
71  PrintLn(); PrintS("shift_pp_Mult_mm result: "); p_wrp(pNext(&rp), ri, ri); PrintLn();
72#endif
73  p_Test(pNext(&rp), ri);
74  return pNext(&rp);
75}
76
77// destroys p
78poly shift_p_Mult_mm(poly p, const poly m, const ring ri)
79{
80#ifdef SHIFT_MULT_DEBUG
81  PrintLn(); PrintS("shift_p_Mult_mm: ("); p_wrp(p, ri, ri); PrintS(") * "); p_wrp(m, ri, ri);
82#endif
83
84  p_Test(p, ri);
85  p_LmTest(m, ri);
86  pAssume(m != NULL);
87  assume(p!=NULL);
88
89  int lV = ri->isLPring;
90  poly _m = m; // temp hack because m is const
91#ifdef SHIFT_MULT_COMPAT_MODE
92  _m = p_Copy(_m, ri);
93  p_mLPUnShift(_m, ri);
94  p_LPUnShift(p, ri);
95#else
96  assume(p_mFirstVblock(_m, ri) <= 1);
97  assume(p_FirstVblock(p, ri) <= 1); // TODO check that each block is <=1
98#endif
99  // at this point _m and p are shifted to 1
100
101  poly q = p; // we use p for iterating and q for the result
102  number mCoeff = pGetCoeff(_m);
103  number pCoeff;
104  pAssume(!n_IsZero(mCoeff, ri->cf));
105
106  int mLength = p_mLastVblock(_m, ri) * lV;
107  int *mExpV = (int *) omAlloc0((ri->N+1)*sizeof(int));
108  p_GetExpV(_m,mExpV,ri);
109  while (p != NULL)
110  {
111    pCoeff = pGetCoeff(p);
112    pSetCoeff0(p, n_Mult(mCoeff, pCoeff, ri->cf));
113    n_Delete(&pCoeff, ri->cf); // delete the old coeff
114
115    int *pExpV = (int *) omAlloc0((ri->N+1)*sizeof(int));
116    p_GetExpV(p,pExpV,ri);
117    p_LPExpVappend(pExpV, mExpV, p_mLastVblock(p, ri) * lV, mLength, ri);
118    p_SetExpV(p, pExpV, ri);
119    omFreeSize((ADDRESS) pExpV, (ri->N+1)*sizeof(int));
120
121    pIter(p);
122  }
123  omFreeSize((ADDRESS) mExpV, (ri->N+1)*sizeof(int));
124#ifdef SHIFT_MULT_COMPAT_MODE
125  p_Delete(&_m, ri); // in this case we copied _m before
126#endif
127#ifdef SHIFT_MULT_DEBUG
128  PrintLn(); PrintS("shift_p_Mult_mm result: "); p_wrp(q, ri, ri); PrintLn();
129#endif
130  p_Test(q, ri);
131  return q;
132}
133
134poly shift_pp_mm_Mult(poly p, const poly m, const ring ri)
135{
136#ifdef SHIFT_MULT_DEBUG
137  PrintLn(); PrintS("shift_pp_mm_Mult: "); p_wrp(m, ri, ri); PrintS(" * ("); p_wrp(p, ri, ri); PrintS(")");
138#endif
139
140  p_Test(p, ri);
141  p_LmTest(m, ri);
142  if (p == NULL)
143  {
144    return NULL;
145  }
146
147  int lV = ri->isLPring;
148  poly _m = m; // temp hack because m is const
149#ifdef SHIFT_MULT_COMPAT_MODE
150  _m = p_Copy(_m, ri);
151  p_mLPUnShift(_m, ri);
152  p = p_Copy(p, ri);
153  poly pCopyHead = p; // used to delete p later
154  p_LPUnShift(p, ri);
155#else
156  assume(p_mFirstVblock(_m, ri) <= 1);
157  assume(p_FirstVblock(p, ri) <= 1); // TODO check that each block is <=1
158#endif
159  // at this point _m and p are shifted to 1
160
161  spolyrec rp;
162  poly q = &rp; // we use p for iterating and q for the result
163  number mCoeff = pGetCoeff(_m);
164  omBin bin = ri->PolyBin;
165  pAssume(!n_IsZero(mCoeff, ri->cf));
166  pAssume1(p_GetComp(m, ri) == 0 || p_MaxComp(p, ri) == 0);
167
168  int mLength = p_mLastVblock(_m, ri) * lV;
169  int *mExpV = (int *) omAlloc0((ri->N+1)*sizeof(int));
170  p_GetExpV(_m,mExpV,ri);
171  do
172  {
173    p_AllocBin(pNext(q), bin, ri);
174    pIter(q);
175    pSetCoeff0(q, n_Mult(mCoeff, pGetCoeff(p), ri->cf));
176
177    int *pExpV = (int *) omAlloc0((ri->N+1)*sizeof(int));
178    p_GetExpV(p, pExpV, ri);
179    p_LPExpVprepend(pExpV, mExpV, p_mLastVblock(p, ri) * lV, mLength, ri);
180    p_MemCopy_LengthGeneral(q->exp, p->exp, ri->ExpL_Size); // otherwise q is not initialized correctly
181    p_SetExpV(q, pExpV, ri);
182    omFreeSize((ADDRESS) pExpV, (ri->N+1)*sizeof(int));
183
184    pIter(p);
185  }
186  while (p != NULL);
187  omFreeSize((ADDRESS) mExpV, (ri->N+1)*sizeof(int));
188  pNext(q) = NULL;
189#ifdef SHIFT_MULT_COMPAT_MODE
190  p_Delete(&_m, ri); // in this case we copied _m before
191  p_Delete(&pCopyHead, ri); // in this case we copied p before
192#endif
193#ifdef SHIFT_MULT_DEBUG
194  PrintLn(); PrintS("shift_pp_mm_Mult result: "); p_wrp(pNext(&rp), ri, ri); PrintLn();
195#endif
196  p_Test(pNext(&rp), ri);
197  return pNext(&rp);
198}
199
200// destroys p
201poly shift_p_mm_Mult(poly p, const poly m, const ring ri)
202{
203#ifdef SHIFT_MULT_DEBUG
204  PrintLn(); PrintS("shift_p_mm_Mult: "); p_wrp(m, ri, ri); PrintS(" * ("); p_wrp(p, ri, ri); PrintS(")");
205#endif
206
207  p_Test(p, ri);
208  p_LmTest(m, ri);
209  pAssume(m != NULL);
210  assume(p!=NULL);
211
212  int lV = ri->isLPring;
213  poly _m = m; // temp hack because m is const
214#ifdef SHIFT_MULT_COMPAT_MODE
215  _m = p_Copy(_m, ri);
216  p_mLPUnShift(_m, ri);
217  p_LPUnShift(p, ri);
218#else
219  assume(p_mFirstVblock(_m, ri) <= 1);
220  assume(p_FirstVblock(p, ri) <= 1); // TODO check that each block is <=1
221#endif
222  // at this point _m and p are shifted to 1
223
224  poly q = p; // we use p for iterating and q for the result
225  number mCoeff = pGetCoeff(_m);
226  number pCoeff;
227  pAssume(!n_IsZero(mCoeff, ri->cf));
228
229  int mLength = p_mLastVblock(_m, ri) * lV;
230  int *mExpV = (int *) omAlloc0((ri->N+1)*sizeof(int));
231  p_GetExpV(_m,mExpV,ri);
232  while (p != NULL)
233  {
234    pCoeff = pGetCoeff(p);
235    pSetCoeff0(p, n_Mult(mCoeff, pCoeff, ri->cf));
236    n_Delete(&pCoeff, ri->cf); // delete the old coeff
237
238    int *pExpV = (int *) omAlloc0((ri->N+1)*sizeof(int));
239    p_GetExpV(p,pExpV,ri);
240    p_LPExpVprepend(pExpV, mExpV, p_mLastVblock(p, ri) * lV, mLength, ri);
241    p_SetExpV(p, pExpV, ri);
242    omFreeSize((ADDRESS) pExpV, (ri->N+1)*sizeof(int));
243
244    pIter(p);
245  }
246  omFreeSize((ADDRESS) mExpV, (ri->N+1)*sizeof(int));
247#ifdef SHIFT_MULT_COMPAT_MODE
248  p_Delete(&_m, ri); // in this case we copied _m before
249#endif
250#ifdef SHIFT_MULT_DEBUG
251  PrintLn(); PrintS("shift_p_mm_Mult result: "); p_wrp(q, ri, ri); PrintLn();
252#endif
253  p_Test(q, ri);
254  return q;
255}
256
257// p - m*q destroys p
258poly shift_p_Minus_mm_Mult_qq(poly p, poly m, poly q, int& Shorter, const poly spNoether, const ring ri) {
259#ifdef SHIFT_MULT_DEBUG
260  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);
261#endif
262
263  Shorter = pLength(p) + pLength(q);
264
265  poly qq = p_Add_q(p, shift_pp_mm_Mult(q, p_Neg(p_Copy(m, ri), ri), ri), ri);
266
267#ifdef SHIFT_MULT_DEBUG
268  PrintLn(); PrintS("shift_p_Minus_mm_Mult_qq result: "); p_wrp(qq, ri, ri); PrintLn();
269#endif
270  Shorter -= pLength(qq);
271  return qq;
272}
273
274// Unsupported Operation STUBs
275poly shift_pp_Mult_mm_Noether_STUB(poly p, const poly m, const poly spNoether, int &ll, const ring ri) {
276  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.");
277
278  int pLen = 0;
279  if (ll >= 0) {
280    pLen = pLength(p);
281  }
282
283  p = shift_pp_Mult_mm(p, m, ri);
284
285  if (ll >= 0) {
286    ll = pLen - pLength(p);
287  } else {
288    ll = pLength(p);
289  }
290
291  return p;
292}
293
294
295poly shift_pp_Mult_Coeff_mm_DivSelectMult_STUB(poly p,const poly m, const poly a, const poly b, int &shorter,const ring r) {
296  PrintLn(); WarnS("pp_Mult_Coeff_mm_DivSelectMult is not supported yet by Letterplace. This might lead to unexpected behavior.");
297  return NULL;
298}
299
300poly shift_pp_Mult_Coeff_mm_DivSelect_STUB(poly p, const poly m, int &shorter, const ring r) {
301  PrintLn(); WarnS("pp_Mult_Coeff_mm_DivSelect is not supported yet by Letterplace. This might lead to unexpected behavior.");
302  return NULL;
303}
304
305// auxiliary
306
307// unshifts the monomial m
308void p_mLPUnShift(poly m, const ring ri)
309{
310  if (m == NULL || p_LmIsConstantComp(m,ri)) return;
311
312  int lV = ri->isLPring;
313
314  int shift = p_mFirstVblock(m, ri) - 1;
315
316  if (shift == 0) return;
317
318  int L = p_mLastVblock(m, ri);
319
320  int *e=(int *)omAlloc0((ri->N+1)*sizeof(int));
321  int *s=(int *)omAlloc0((ri->N+1)*sizeof(int));
322  p_GetExpV(m, e, ri);
323
324  int expVoffset = shift*lV;
325  for (int i = 1 + expVoffset; i <= L*lV; ++i)
326  {
327    assume(e[i] <= 1);
328    s[i - expVoffset] = e[i];
329  }
330  p_SetExpV(m,s,ri);
331  omFreeSize((ADDRESS) e, (ri->N+1)*sizeof(int));
332  omFreeSize((ADDRESS) s, (ri->N+1)*sizeof(int));
333}
334
335// unshifts the polynomial p, note: the ordering can be destroyed if the shifts for the monomials are not equal
336void p_LPUnShift(poly p, const ring ri)
337{
338  while (p!=NULL)
339  {
340    p_mLPUnShift(p, ri);
341    pIter(p);
342  }
343  p_Test(p, ri); // check if ordering was destroyed
344}
345
346// appends m2ExpV to m1ExpV, also adds their components (one of them is always zero)
347void p_LPExpVappend(int *m1ExpV, int *m2ExpV, int m1Length, int m2Length, const ring ri) {
348#ifdef SHIFT_MULT_DEBUG
349  PrintLn(); PrintS("Append");
350  PrintLn(); WriteLPExpV(m1ExpV, ri);
351  PrintLn(); WriteLPExpV(m2ExpV, ri);
352#endif
353  assume(m1Length + m2Length <= ri->N);
354  for (int i = 1 + m1Length; i < 1 + m1Length + m2Length; ++i)
355  {
356    assume(m2ExpV[i - m1Length] <= 1);
357    m1ExpV[i] = m2ExpV[i - m1Length];
358  }
359
360  assume(m1ExpV[0] == 0 || m2ExpV[0] == 0); // one component should be zero (otherwise this doesn't make any sense)
361  m1ExpV[0] += m2ExpV[0]; // as in the commutative variant (they use MemAdd)
362#ifdef SHIFT_MULT_DEBUG
363  PrintLn(); WriteLPExpV(m1ExpV, ri);
364#endif
365}
366
367// prepends m2ExpV to m1ExpV, also adds their components (one of them is always zero)
368void p_LPExpVprepend(int *m1ExpV, int *m2ExpV, int m1Length, int m2Length, const ring ri) {
369#ifdef SHIFT_MULT_DEBUG
370  PrintLn(); PrintS("Prepend");
371  PrintLn(); WriteLPExpV(m1ExpV, ri);
372  PrintLn(); WriteLPExpV(m2ExpV, ri);
373#endif
374  assume(m1Length + m2Length <= ri->N);
375
376  // shift m1 by m2Length
377  for (int i = m2Length + m1Length; i >= 1 + m2Length; --i)
378  {
379    m1ExpV[i] = m1ExpV[i - m2Length];
380  }
381
382  // write m2 to m1
383  for (int i = 1; i < 1 + m2Length; ++i)
384  {
385    assume(m2ExpV[i] <= 1);
386    m1ExpV[i] = m2ExpV[i];
387  }
388
389  assume(m1ExpV[0] == 0 || m2ExpV[0] == 0); // one component should be zero (otherwise this doesn't make any sense)
390  m1ExpV[0] += m2ExpV[0]; // as in the commutative variant (they use MemAdd)
391#ifdef SHIFT_MULT_DEBUG
392  PrintLn(); WriteLPExpV(m1ExpV, ri);
393#endif
394}
395
396void WriteLPExpV(int *expV, ring ri) {
397  for (int i = 0; i <= ri->N; ++i) {
398    Print("%d", expV[i]);
399    if (i == 0) {
400      Print("| ");
401    }
402    if (i % ri->isLPring == 0) {
403      Print(" ");
404    }
405  }
406}
Note: See TracBrowser for help on using the repository browser.