source: git/libpolys/polys/operations/p_Mult_q.cc @ 39f6c80

spielwiese
Last change on this file since 39f6c80 was 39f6c80, checked in by Hans Schoenemann <hannes@…>, 5 years ago
fix: _p_Mult_q for vector
  • Property mode set to 100644
File size: 7.6 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/***************************************************************
5 *  File:    p_Mult_q.cc
6 *  Purpose: multiplication of polynomials
7 *  Author:  obachman (Olaf Bachmann)
8 *  Created: 8/00
9 *******************************************************************/
10
11#include "misc/auxiliary.h"
12#include "factory/factory.h"
13
14#include "misc/options.h"
15
16#include "coeffs/numbers.h"
17#include "polys/monomials/p_polys.h"
18#include "polys/kbuckets.h"
19#include "polys/clapsing.h"
20
21#include "polys/templates/p_Procs.h"
22#include "polys/templates/p_MemCmp.h"
23#include "polys/templates/p_MemAdd.h"
24#include "polys/templates/p_MemCopy.h"
25#include "polys/flintconv.h"
26#include "polys/flint_mpoly.h"
27
28#include "p_Mult_q.h"
29
30
31BOOLEAN pqLength(poly p, poly q, int &lp, int &lq, const int min)
32{
33  int l = 0;
34
35  do
36  {
37    if (p == NULL)
38    {
39      lp = l;
40      if (l < min)
41      {
42        if (q != NULL)
43          lq = l+1;
44        else
45          lq = l;
46        return FALSE;
47      }
48      lq = l + pLength(q);
49      return TRUE;
50    }
51    pIter(p);
52    if (q == NULL)
53    {
54      lq = l;
55      if (l < min)
56      {
57        lp = l+1;
58        return FALSE;
59      }
60      lp = l + 1 + pLength(p);
61      return TRUE;
62    }
63    pIter(q);
64    l++;
65  }
66  while (1);
67}
68
69
70static poly _p_Mult_q_Bucket(poly p, const int lp,
71                             poly q, const int lq,
72                             const int copy, const ring r)
73{
74  assume(p != NULL && pNext(p) != NULL && q != NULL && pNext(q) != NULL);
75  pAssume1(! pHaveCommonMonoms(p, q));
76  assume(!rField_is_Ring(r) || rField_is_Domain(r));
77  assume(lp >= 1 && lq >= 1);
78  p_Test(p, r);
79  p_Test(q, r);
80
81  poly res = pp_Mult_mm(p,q,r);     // holds initially q1*p
82  poly qq = pNext(q);               // we iter of this
83  poly qn = pp_Mult_mm(qq, p,r);    // holds p1*qi
84  poly pp = pNext(p);               // used for Lm(qq)*pp
85  poly rr = res;                    // last monom which is surely not NULL
86  poly rn = pNext(res);             // pNext(rr)
87  number n, n1;
88
89  kBucket_pt bucket = kBucketCreate(r);
90
91  // initialize bucket
92  kBucketInit(bucket, pNext(rn), lp - 2);
93  pNext(rn) = NULL;
94
95  // now the main loop
96  Top:
97  if (rn == NULL) goto Smaller;
98  p_LmCmpAction(rn, qn, r, goto Equal, goto Greater, goto Smaller);
99
100  Greater:
101  // rn > qn, so iter
102  rr = rn;
103  pNext(rn) = kBucketExtractLm(bucket);
104  pIter(rn);
105  goto Top;
106
107  // rn < qn, append qn to rr, and compute next Lm(qq)*pp
108  Smaller:
109  pNext(rr) = qn;
110  rr = qn;
111  pIter(qn);
112  Work: // compute res + Lm(qq)*pp
113  if (rn == NULL)
114  {
115    pNext(rr) = pp_Mult_mm(pp, qq, r);
116    kBucketInit(bucket, pNext(pNext(rr)), lp - 2);
117    pNext(pNext(rr)) = NULL;
118  }
119  else
120  {
121    kBucketSetLm(bucket, rn);
122    kBucket_Plus_mm_Mult_pp(bucket, qq, pp, lp - 1);
123    pNext(rr) = kBucketExtractLm(bucket);
124  }
125
126  pIter(qq);
127  if (qq == NULL) goto Finish;
128  rn = pNext(rr);
129  goto Top;
130
131  Equal:
132  n1 = pGetCoeff(rn);
133  n = n_Add(n1, pGetCoeff(qn), r->cf);
134  n_Delete(&n1, r->cf);
135  if (n_IsZero(n, r->cf))
136  {
137    n_Delete(&n, r->cf);
138    p_LmFree(rn, r);
139  }
140  else
141  {
142    pSetCoeff0(rn, n);
143    rr = rn;
144  }
145  rn = kBucketExtractLm(bucket);
146  n_Delete(&pGetCoeff(qn),r->cf);
147  qn = p_LmFreeAndNext(qn, r);
148  goto Work;
149
150  Finish:
151  assume(rr != NULL && pNext(rr) != NULL);
152  pNext(pNext(rr)) = kBucketClear(bucket);
153  kBucketDestroy(&bucket);
154
155  if (!copy)
156  {
157    p_Delete(&p, r);
158    p_Delete(&q, r);
159  }
160  p_Test(res, r);
161  return res;
162}
163
164#ifdef HAVE_RINGS
165static poly _p_Mult_q_Normal_ZeroDiv(poly p, poly q, const int copy, const ring r)
166{
167  assume(p != NULL && pNext(p) != NULL && q != NULL && pNext(q) != NULL);
168  pAssume1(! pHaveCommonMonoms(p, q));
169  p_Test(p, r);
170  p_Test(q, r);
171
172  poly res = pp_Mult_mm(p,q,r);     // holds initially q1*p
173  poly qq = pNext(q);               // we iter of this
174
175  while (qq != NULL)
176  {
177    res = p_Plus_mm_Mult_qq(res, qq, p, r);
178    pIter(qq);
179  }
180
181  if (!copy)
182  {
183    p_Delete(&p, r);
184    p_Delete(&q, r);
185  }
186
187  p_Test(res, r);
188
189  return res;
190}
191#endif
192
193static poly _p_Mult_q_Normal(poly p, poly q, const int copy, const ring r)
194{
195  assume(r != NULL);
196  assume(p != NULL && pNext(p) != NULL && q != NULL && pNext(q) != NULL);
197#ifdef HAVE_RINGS
198  assume(nCoeff_is_Domain(r->cf));
199#endif
200  pAssume1(! p_HaveCommonMonoms(p, q, r));
201  p_Test(p, r);
202  p_Test(q, r);
203
204  poly res = pp_Mult_mm(p,q,r);     // holds initially q1*p
205  poly qq = pNext(q);               // we iter of this
206  poly qn = pp_Mult_mm(qq, p,r);    // holds p1*qi
207  poly pp = pNext(p);               // used for Lm(qq)*pp
208  poly rr = res;                    // last monom which is surely not NULL
209  poly rn = pNext(res);             // pNext(rr)
210  number n, n1;
211
212  // now the main loop
213  Top:
214  if (rn == NULL) goto Smaller;
215  p_LmCmpAction(rn, qn, r, goto Equal, goto Greater, goto Smaller);
216
217  Greater:
218  // rn > qn, so iter
219  rr = rn;
220  pIter(rn);
221  goto Top;
222
223  // rn < qn, append qn to rr, and compute next Lm(qq)*pp
224  Smaller:
225  pNext(rr) = qn;
226  rr = qn;
227  pIter(qn);
228
229  Work: // compute res + Lm(qq)*pp
230  if (rn == NULL)
231    pNext(rr) = pp_Mult_mm(pp, qq, r);
232  else
233  {
234    pNext(rr) = p_Plus_mm_Mult_qq(rn, qq, pp, r);
235  }
236
237  pIter(qq);
238  if (qq == NULL) goto Finish;
239  rn = pNext(rr);
240  goto Top;
241
242  Equal:
243  n1 = pGetCoeff(rn);
244  n = n_Add(n1, pGetCoeff(qn), r->cf);
245  n_Delete(&n1, r->cf);
246  if (n_IsZero(n, r->cf))
247  {
248    n_Delete(&n, r->cf);
249    rn = p_LmFreeAndNext(rn, r);
250  }
251  else
252  {
253    pSetCoeff0(rn, n);
254    rr = rn;
255    pIter(rn);
256  }
257  n_Delete(&pGetCoeff(qn),r->cf);
258  qn = p_LmFreeAndNext(qn, r);
259  goto Work;
260
261  Finish:
262  if (!copy)
263  {
264    p_Delete(&p, r);
265    p_Delete(&q, r);
266  }
267  p_Test(res, r);
268  return res;
269}
270
271
272// Use factory if min(pLength(p), pLength(q)) >= MIN_LENGTH_FACTORY (>MIN_LENGTH_BUCKET)
273// Not thoroughly tested what is best
274#define MIN_LENGTH_FACTORY 200
275#define MIN_LENGTH_FACTORY_QQ 60
276#define MIN_FLINT_QQ 10
277#define MIN_FLINT_Zp 20
278
279/// Returns:  p * q,
280/// Destroys: if !copy then p, q
281/// Assumes: pLength(p) >= 2 pLength(q) >=2, !rIsPluralRing(r)
282poly _p_Mult_q(poly p, poly q, const int copy, const ring r)
283{
284  assume(r != NULL);
285#ifdef HAVE_RINGS
286  if (!nCoeff_is_Domain(r->cf))
287    return _p_Mult_q_Normal_ZeroDiv(p, q, copy, r);
288#endif
289  int lp, lq, l;
290  poly pt;
291
292  pqLength(p, q, lp, lq, MIN_LENGTH_FACTORY);
293
294  if (lp < lq)
295  {
296    pt = p;
297    p =  q;
298    q = pt;
299    l = lp;
300    lp = lq;
301    lq = l;
302  }
303  BOOLEAN pure_polys=(p_GetComp(p,r)==0) && (p_GetComp(q,r)==0);
304  #ifdef HAVE_FLINT
305  #if __FLINT_RELEASE >= 20503
306  if (lq>MIN_FLINT_QQ)
307  {
308    fmpq_mpoly_ctx_t ctx;
309    if (pure_polys && rField_is_Q(r) && !convSingRFlintR(ctx,r))
310    {
311      lp=pLength(p);
312      //printf("mul in flint\n");
313      poly res=Flint_Mult_MP(p,lp,q,lq,ctx,r);
314      if (!copy)
315      {
316        p_Delete(&p,r);
317        p_Delete(&q,r);
318      }
319      return res;
320    }
321  }
322  if (lq>MIN_FLINT_Zp)
323  {
324    nmod_mpoly_ctx_t ctx;
325    if (pure_polys && rField_is_Zp(r) && !convSingRFlintR(ctx,r))
326    {
327      lp=pLength(p);
328      //printf("mul in flint\n");
329      poly res=Flint_Mult_MP(p,lp,q,lq,ctx,r);
330      if (!copy)
331      {
332        p_Delete(&p,r);
333        p_Delete(&q,r);
334      }
335      return res;
336    }
337  }
338  #endif
339  #endif
340  if (lq < MIN_LENGTH_BUCKET || TEST_OPT_NOT_BUCKETS)
341    return _p_Mult_q_Normal(p, q, copy, r);
342  else if (pure_polys
343  && (((lq >= MIN_LENGTH_FACTORY)
344    && (r->cf->convSingNFactoryN!=ndConvSingNFactoryN))
345  || ((lq >= MIN_LENGTH_FACTORY_QQ)
346    && rField_is_Q(r))))
347  {
348    poly h=singclap_pmult(p,q,r);
349    if (!copy)
350    {
351      p_Delete(&p,r);
352      p_Delete(&q,r);
353    }
354    return h;
355  }
356  else
357  {
358    lp=pLength(p);
359    assume(lq == pLength(q));
360    return _p_Mult_q_Bucket(p, lp, q, lq, copy, r);
361  }
362}
Note: See TracBrowser for help on using the repository browser.