source: git/libpolys/polys/operations/p_Mult_q.cc @ ba5e9e

spielwiese
Last change on this file since ba5e9e was ba5e9e, checked in by Oleksandr Motsak <motsak@…>, 11 years ago
Changed configure-scripts to generate individual public config files for each package: resources, libpolys, singular (main) fix: sources should include correct corresponding config headers.
  • 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 *******************************************************************/
10#ifdef HAVE_CONFIG_H
11#include "libpolysconfig.h"
12#endif /* HAVE_CONFIG_H */
13#include <misc/auxiliary.h>
14
15#ifdef HAVE_FACTORY
16#include <factory/factory.h>
17#endif
18
19#include <misc/options.h>
20
21#include <polys/monomials/p_polys.h>
22#include <polys/templates/p_Procs.h>
23#include <polys/templates/p_MemCmp.h>
24#include <polys/templates/p_MemAdd.h>
25#include <polys/templates/p_MemCopy.h>
26#include <polys/templates/p_Numbers.h>
27#include <polys/kbuckets.h>
28
29#include "p_Mult_q.h"
30
31
32BOOLEAN pqLength(poly p, poly q, int &lp, int &lq, const int min)
33{
34  int l = 0;
35
36  do
37  {
38    if (p == NULL)
39    {
40      lp = l;
41      if (l < min)
42      {
43        if (q != NULL)
44          lq = l+1;
45        else
46          lq = l;
47        return FALSE;
48      }
49      lq = l + pLength(q);
50      return TRUE;
51    }
52    pIter(p);
53    if (q == NULL)
54    {
55      lq = l;
56      if (l < min)
57      {
58        lp = l+1;
59        return FALSE;
60      }
61      lp = l + 1 + pLength(p);
62      return TRUE;
63    }
64    pIter(q);
65    l++;
66  }
67  while (1);
68}
69
70
71static poly _p_Mult_q_Bucket(poly p, const int lp,
72                             poly q, const int lq,
73                             const int copy, const ring r)
74{
75  assume(p != NULL && pNext(p) != NULL && q != NULL && pNext(q) != NULL);
76  pAssume1(! pHaveCommonMonoms(p, q));
77#ifdef HAVE_RINGS
78  assume(!rField_is_Ring(r));
79#endif
80  assume(lp >= 1 && lq >= 1);
81  p_Test(p, r);
82  p_Test(q, r);
83
84  poly res = pp_Mult_mm(p,q,r);     // holds initially q1*p
85  poly qq = pNext(q);               // we iter of this
86  poly qn = pp_Mult_mm(qq, p,r);    // holds p1*qi
87  poly pp = pNext(p);               // used for Lm(qq)*pp
88  poly rr = res;                    // last monom which is surely not NULL
89  poly rn = pNext(res);             // pNext(rr)
90  number n, n1;
91
92  kBucket_pt bucket = kBucketCreate(r);
93
94  // initialize bucket
95  kBucketInit(bucket, pNext(rn), lp - 2);
96  pNext(rn) = NULL;
97
98  // now the main loop
99  Top:
100  if (rn == NULL) goto Smaller;
101  p_LmCmpAction(rn, qn, r, goto Equal, goto Greater, goto Smaller);
102
103  Greater:
104  // rn > qn, so iter
105  rr = rn;
106  pNext(rn) = kBucketExtractLm(bucket);
107  pIter(rn);
108  goto Top;
109
110  // rn < qn, append qn to rr, and compute next Lm(qq)*pp
111  Smaller:
112  pNext(rr) = qn;
113  rr = qn;
114  pIter(qn);
115  Work: // compute res + Lm(qq)*pp
116  if (rn == NULL)
117  {
118    pNext(rr) = pp_Mult_mm(pp, qq, r);
119    kBucketInit(bucket, pNext(pNext(rr)), lp - 2);
120    pNext(pNext(rr)) = NULL;
121  }
122  else
123  {
124    kBucketSetLm(bucket, rn);
125    kBucket_Plus_mm_Mult_pp(bucket, qq, pp, lp - 1);
126    pNext(rr) = kBucketExtractLm(bucket);
127  }
128
129  pIter(qq);
130  if (qq == NULL) goto Finish;
131  rn = pNext(rr);
132  goto Top;
133
134  Equal:
135  n1 = pGetCoeff(rn);
136  n = n_Add(n1, pGetCoeff(qn), r->cf);
137  n_Delete(&n1, r->cf);
138  if (n_IsZero(n, r->cf))
139  {
140    n_Delete(&n, r->cf);
141    p_LmFree(rn, r);
142  }
143  else
144  {
145    pSetCoeff0(rn, n);
146    rr = rn;
147  }
148  rn = kBucketExtractLm(bucket);
149  n_Delete(&pGetCoeff(qn),r->cf);
150  qn = p_LmFreeAndNext(qn, r);
151  goto Work;
152
153  Finish:
154  assume(rr != NULL && pNext(rr) != NULL);
155  pNext(pNext(rr)) = kBucketClear(bucket);
156  kBucketDestroy(&bucket);
157
158  if (!copy)
159  {
160    p_Delete(&p, r);
161    p_Delete(&q, r);
162  }
163  p_Test(res, r);
164  return res;
165}
166
167#ifdef HAVE_RINGS
168static poly _p_Mult_q_Normal_ZeroDiv(poly p, poly q, const int copy, const ring r)
169{
170  assume(p != NULL && pNext(p) != NULL && q != NULL && pNext(q) != NULL);
171  pAssume1(! pHaveCommonMonoms(p, q));
172  p_Test(p, r);
173  p_Test(q, r);
174
175  poly res = pp_Mult_mm(p,q,r);     // holds initially q1*p
176  poly qq = pNext(q);               // we iter of this
177
178  while (qq != NULL)
179  {
180    res = p_Plus_mm_Mult_qq(res, qq, p, r);
181    pIter(qq);
182  }
183
184  if (!copy)
185  {
186    p_Delete(&p, r);
187    p_Delete(&q, r);
188  }
189
190  p_Test(res, r);
191
192  return res;
193}
194#endif
195
196static poly _p_Mult_q_Normal(poly p, poly q, const int copy, const ring r)
197{
198  assume(r != NULL);
199  assume(p != NULL && pNext(p) != NULL && q != NULL && pNext(q) != NULL);
200#ifdef HAVE_RINGS
201  assume(nCoeff_is_Domain(r->cf));
202#endif
203  pAssume1(! p_HaveCommonMonoms(p, q, r));
204  p_Test(p, r);
205  p_Test(q, r);
206
207  poly res = pp_Mult_mm(p,q,r);     // holds initially q1*p
208  poly qq = pNext(q);               // we iter of this
209  poly qn = pp_Mult_mm(qq, p,r);    // holds p1*qi
210  poly pp = pNext(p);               // used for Lm(qq)*pp
211  poly rr = res;                    // last monom which is surely not NULL
212  poly rn = pNext(res);             // pNext(rr)
213  number n, n1;
214
215  // now the main loop
216  Top:
217  if (rn == NULL) goto Smaller;
218  p_LmCmpAction(rn, qn, r, goto Equal, goto Greater, goto Smaller);
219
220  Greater:
221  // rn > qn, so iter
222  rr = rn;
223  pIter(rn);
224  goto Top;
225
226  // rn < qn, append qn to rr, and compute next Lm(qq)*pp
227  Smaller:
228  pNext(rr) = qn;
229  rr = qn;
230  pIter(qn);
231
232  Work: // compute res + Lm(qq)*pp
233  if (rn == NULL)
234    pNext(rr) = pp_Mult_mm(pp, qq, r);
235  else
236  {
237    pNext(rr) = p_Plus_mm_Mult_qq(rn, qq, pp, r);
238  }
239
240  pIter(qq);
241  if (qq == NULL) goto Finish;
242  rn = pNext(rr);
243  goto Top;
244
245  Equal:
246  n1 = pGetCoeff(rn);
247  n = n_Add(n1, pGetCoeff(qn), r->cf);
248  n_Delete(&n1, r->cf);
249  if (n_IsZero(n, r->cf))
250  {
251    n_Delete(&n, r->cf);
252    rn = p_LmFreeAndNext(rn, r);
253  }
254  else
255  {
256    pSetCoeff0(rn, n);
257    rr = rn;
258    pIter(rn);
259  }
260  n_Delete(&pGetCoeff(qn),r->cf);
261  qn = p_LmFreeAndNext(qn, r);
262  goto Work;
263
264  Finish:
265  if (!copy)
266  {
267    p_Delete(&p, r);
268    p_Delete(&q, r);
269  }
270  p_Test(res, r);
271  return res;
272}
273
274
275/// Returns:  p * q,
276/// Destroys: if !copy then p, q
277/// Assumes: pLength(p) >= 2 pLength(q) >=2
278poly _p_Mult_q(poly p, poly q, const int copy, const ring r)
279{
280  assume(r != NULL);
281#ifdef HAVE_RINGS
282  if (!nCoeff_is_Domain(r->cf))
283    return _p_Mult_q_Normal_ZeroDiv(p, q, copy, r);
284#endif
285  int lp, lq, l;
286  poly pt;
287
288  pqLength(p, q, lp, lq, MIN_LENGTH_BUCKET);
289
290  if (lp < lq)
291  {
292    pt = p;
293    p =  q;
294    q = pt;
295    l = lp;
296    lp = lq;
297    lq = l;
298  }
299  if (lq < MIN_LENGTH_BUCKET || TEST_OPT_NOT_BUCKETS)
300    return _p_Mult_q_Normal(p, q, copy, r);
301  else
302  {
303    assume(lp == pLength(p));
304    assume(lq == pLength(q));
305    return _p_Mult_q_Bucket(p, lp, q, lq, copy, r);
306  }
307}
Note: See TracBrowser for help on using the repository browser.