source: git/libpolys/polys/operations/p_Mult_q.cc @ 4e654a2

spielwiese
Last change on this file since 4e654a2 was a3d94c, checked in by Oleksandr Motsak <motsak@…>, 13 years ago
FIX: finxing a circular dependency due to kbuckets.h and pShallowCopyDelete.h
  • Property mode set to 100644
File size: 6.3 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 *  Version: $Id$
10 *******************************************************************/
11#include "config.h"
12#include <misc/auxiliary.h>
13
14#ifdef HAVE_FACTORY
15#include <factory/factory.h>
16#endif
17
18#include <misc/options.h>
19
20#include <polys/monomials/p_polys.h>
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/templates/p_Numbers.h>
26#include <polys/kbuckets.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#ifdef HAVE_RINGS
77  assume(!rField_is_Ring(r));
78#endif
79  assume(lp >= 1 && lq >= 1);
80  p_Test(p, r);
81  p_Test(q, r);
82
83  poly res = pp_Mult_mm(p,q,r);     // holds initially q1*p
84  poly qq = pNext(q);               // we iter of this
85  poly qn = pp_Mult_mm(qq, p,r);    // holds p1*qi
86  poly pp = pNext(p);               // used for Lm(qq)*pp
87  poly rr = res;                    // last monom which is surely not NULL
88  poly rn = pNext(res);             // pNext(rr)
89  number n, n1;
90
91  kBucket_pt bucket = kBucketCreate(r);
92
93  // initialize bucket
94  kBucketInit(bucket, pNext(rn), lp - 2);
95  pNext(rn) = NULL;
96
97  // now the main loop
98  Top:
99  if (rn == NULL) goto Smaller;
100  p_LmCmpAction(rn, qn, r, goto Equal, goto Greater, goto Smaller);
101
102  Greater:
103  // rn > qn, so iter
104  rr = rn;
105  pNext(rn) = kBucketExtractLm(bucket);
106  pIter(rn);
107  goto Top;
108
109  // rn < qn, append qn to rr, and compute next Lm(qq)*pp
110  Smaller:
111  pNext(rr) = qn;
112  rr = qn;
113  pIter(qn);
114  Work: // compute res + Lm(qq)*pp
115  if (rn == NULL)
116  {
117    pNext(rr) = pp_Mult_mm(pp, qq, r);
118    kBucketInit(bucket, pNext(pNext(rr)), lp - 2);
119    pNext(pNext(rr)) = NULL;
120  }
121  else
122  {
123    kBucketSetLm(bucket, rn);
124    kBucket_Plus_mm_Mult_pp(bucket, qq, pp, lp - 1);
125    pNext(rr) = kBucketExtractLm(bucket);
126  }
127
128  pIter(qq);
129  if (qq == NULL) goto Finish;
130  rn = pNext(rr);
131  goto Top;
132
133  Equal:
134  n1 = pGetCoeff(rn);
135  n = n_Add(n1, pGetCoeff(qn), r->cf);
136  n_Delete(&n1, r->cf);
137  if (n_IsZero(n, r->cf))
138  {
139    n_Delete(&n, r->cf);
140    p_LmFree(rn, r);
141  }
142  else
143  {
144    pSetCoeff0(rn, n);
145    rr = rn;
146  }
147  rn = kBucketExtractLm(bucket);
148  n_Delete(&pGetCoeff(qn),r->cf);
149  qn = p_LmFreeAndNext(qn, r);
150  goto Work;
151
152  Finish:
153  assume(rr != NULL && pNext(rr) != NULL);
154  pNext(pNext(rr)) = kBucketClear(bucket);
155  kBucketDestroy(&bucket);
156
157  if (!copy)
158  {
159    p_Delete(&p, r);
160    p_Delete(&q, r);
161  }
162  p_Test(res, r);
163  return res;
164}
165
166#ifdef HAVE_RINGS
167static poly _p_Mult_q_Normal_ZeroDiv(poly p, poly q, const int copy, const ring r)
168{
169  assume(p != NULL && pNext(p) != NULL && q != NULL && pNext(q) != NULL);
170  pAssume1(! pHaveCommonMonoms(p, q));
171  p_Test(p, r);
172  p_Test(q, r);
173
174  poly res = pp_Mult_mm(p,q,r);     // holds initially q1*p
175  poly qq = pNext(q);               // we iter of this
176
177  while (qq != NULL)
178  {
179    res = p_Plus_mm_Mult_qq(res, qq, p, r);
180    pIter(qq);
181  }
182
183  if (!copy)
184  {
185    p_Delete(&p, r);
186    p_Delete(&q, r);
187  }
188
189  p_Test(res, r);
190
191  return res;
192}
193#endif
194
195static poly _p_Mult_q_Normal(poly p, poly q, const int copy, const ring r)
196{
197  assume(r != NULL);
198  assume(p != NULL && pNext(p) != NULL && q != NULL && pNext(q) != NULL);
199#ifdef HAVE_RINGS
200  assume(nCoeff_is_Domain(r->cf));
201#endif
202  pAssume1(! p_HaveCommonMonoms(p, q, r));
203  p_Test(p, r);
204  p_Test(q, r);
205
206  poly res = pp_Mult_mm(p,q,r);     // holds initially q1*p
207  poly qq = pNext(q);               // we iter of this
208  poly qn = pp_Mult_mm(qq, p,r);    // holds p1*qi
209  poly pp = pNext(p);               // used for Lm(qq)*pp
210  poly rr = res;                    // last monom which is surely not NULL
211  poly rn = pNext(res);             // pNext(rr)
212  number n, n1;
213
214  // now the main loop
215  Top:
216  if (rn == NULL) goto Smaller;
217  p_LmCmpAction(rn, qn, r, goto Equal, goto Greater, goto Smaller);
218
219  Greater:
220  // rn > qn, so iter
221  rr = rn;
222  pIter(rn);
223  goto Top;
224
225  // rn < qn, append qn to rr, and compute next Lm(qq)*pp
226  Smaller:
227  pNext(rr) = qn;
228  rr = qn;
229  pIter(qn);
230
231  Work: // compute res + Lm(qq)*pp
232  if (rn == NULL)
233    pNext(rr) = pp_Mult_mm(pp, qq, r);
234  else
235  {
236    pNext(rr) = p_Plus_mm_Mult_qq(rn, qq, pp, r);
237  }
238
239  pIter(qq);
240  if (qq == NULL) goto Finish;
241  rn = pNext(rr);
242  goto Top;
243
244  Equal:
245  n1 = pGetCoeff(rn);
246  n = n_Add(n1, pGetCoeff(qn), r->cf);
247  n_Delete(&n1, r->cf);
248  if (n_IsZero(n, r->cf))
249  {
250    n_Delete(&n, r->cf);
251    rn = p_LmFreeAndNext(rn, r);
252  }
253  else
254  {
255    pSetCoeff0(rn, n);
256    rr = rn;
257    pIter(rn);
258  }
259  n_Delete(&pGetCoeff(qn),r->cf);
260  qn = p_LmFreeAndNext(qn, r);
261  goto Work;
262
263  Finish:
264  if (!copy)
265  {
266    p_Delete(&p, r);
267    p_Delete(&q, r);
268  }
269  p_Test(res, r);
270  return res;
271}
272
273
274/// Returns:  p * q,
275/// Destroys: if !copy then p, q
276/// Assumes: pLength(p) >= 2 pLength(q) >=2
277poly _p_Mult_q(poly p, poly q, const int copy, const ring r)
278{
279  assume(r != NULL);
280#ifdef HAVE_RINGS
281  if (!nCoeff_is_Domain(r->cf))
282    return _p_Mult_q_Normal_ZeroDiv(p, q, copy, r);
283#endif
284  int lp, lq, l;
285  poly pt;
286
287  pqLength(p, q, lp, lq, MIN_LENGTH_BUCKET);
288
289  if (lp < lq)
290  {
291    pt = p;
292    p =  q;
293    q = pt;
294    l = lp;
295    lp = lq;
296    lq = l;
297  }
298  if (lq < MIN_LENGTH_BUCKET || TEST_OPT_NOT_BUCKETS)
299    return _p_Mult_q_Normal(p, q, copy, r);
300  else
301  {
302    assume(lp == pLength(p));
303    assume(lq == pLength(q));
304    return _p_Mult_q_Bucket(p, lp, q, lq, copy, r);
305  }
306}
Note: See TracBrowser for help on using the repository browser.