source: git/factory/FLINTconvert.cc @ 6e12a45

fieker-DuValspielwiese
Last change on this file since 6e12a45 was 6e12a45, checked in by Hans Schoenemann <hannes@…>, 4 years ago
univariate factorization over Z via FLINT
  • Property mode set to 100644
File size: 21.3 KB
Line 
1/*****************************************************************************\
2 * Computer Algebra System SINGULAR
3\*****************************************************************************/
4/** @file FLINTconvert.cc
5 *
6 * This file implements functions for conversion to FLINT (www.flintlib.org)
7 * and back.
8 *
9 * @author Martin Lee
10 *
11 **/
12/*****************************************************************************/
13
14
15
16#include <config.h>
17
18
19#include "canonicalform.h"
20#include "fac_util.h"
21#include "cf_iter.h"
22#include "cf_factory.h"
23#include "gmpext.h"
24#include "singext.h"
25#include "cf_algorithm.h"
26
27#ifdef HAVE_OMALLOC
28#define Alloc(L) omAlloc(L)
29#define Free(A,L) omFreeSize(A,L)
30#else
31#define Alloc(L) malloc(L)
32#define Free(A,L) free(A)
33#endif
34
35#ifdef HAVE_FLINT
36#ifdef HAVE_CSTDIO
37#include <cstdio>
38#else
39#include <stdio.h>
40#endif
41#ifdef __cplusplus
42extern "C"
43{
44#endif
45#ifndef __GMP_BITS_PER_MP_LIMB
46#define __GMP_BITS_PER_MP_LIMB GMP_LIMB_BITS
47#endif
48#include <flint/fmpz.h>
49#include <flint/fmpq.h>
50#include <flint/fmpz_poly.h>
51#include <flint/fmpz_mod_poly.h>
52#include <flint/nmod_poly.h>
53#include <flint/fmpq_poly.h>
54#include <flint/nmod_mat.h>
55#include <flint/fmpz_mat.h>
56#if ( __FLINT_RELEASE >= 20400)
57#include <flint/fq.h>
58#include <flint/fq_poly.h>
59#include <flint/fq_nmod.h>
60#include <flint/fq_nmod_poly.h>
61#include <flint/fq_nmod_mat.h>
62#endif
63#if ( __FLINT_RELEASE >= 20503)
64#include <flint/fmpq_mpoly.h>
65#endif
66#ifdef __cplusplus
67}
68#endif
69
70#include "FLINTconvert.h"
71
72void convertCF2Fmpz (fmpz_t result, const CanonicalForm& f)
73{
74  if (f.isImm())
75    fmpz_set_si (result, f.intval());
76  else
77  {
78    mpz_t gmp_val;
79    f.mpzval(gmp_val);
80    fmpz_set_mpz (result, gmp_val);
81    mpz_clear (gmp_val);
82  }
83}
84
85void convertFacCF2Fmpz_poly_t (fmpz_poly_t result, const CanonicalForm& f)
86{
87  fmpz_poly_init2 (result, degree (f)+1);
88  _fmpz_poly_set_length(result, degree(f)+1);
89  for (CFIterator i= f; i.hasTerms(); i++)
90    convertCF2Fmpz (fmpz_poly_get_coeff_ptr(result, i.exp()), i.coeff());
91}
92
93CanonicalForm convertFmpz2CF (const fmpz_t coefficient)
94{
95  if (fmpz_cmp_si (coefficient, MINIMMEDIATE) >= 0 &&
96      fmpz_cmp_si (coefficient, MAXIMMEDIATE) <= 0)
97  {
98    long coeff= fmpz_get_si (coefficient);
99    return CanonicalForm (coeff);
100  }
101  else
102  {
103    mpz_t gmp_val;
104    mpz_init (gmp_val);
105    fmpz_get_mpz (gmp_val, coefficient);
106    CanonicalForm result= CanonicalForm (CFFactory::basic (gmp_val));
107    return result;
108  }
109}
110
111CanonicalForm
112convertFmpz_poly_t2FacCF (const fmpz_poly_t poly, const Variable& x)
113{
114  CanonicalForm result= 0;
115  fmpz* coeff;
116  for (int i= 0; i < fmpz_poly_length (poly); i++)
117  {
118    coeff= fmpz_poly_get_coeff_ptr (poly, i);
119    if (!fmpz_is_zero (coeff))
120      result += convertFmpz2CF (coeff)*power (x,i);
121  }
122  return result;
123}
124
125void
126convertFacCF2nmod_poly_t (nmod_poly_t result, const CanonicalForm& f)
127{
128  bool save_sym_ff= isOn (SW_SYMMETRIC_FF);
129  if (save_sym_ff) Off (SW_SYMMETRIC_FF);
130  nmod_poly_init2 (result, getCharacteristic(), degree (f)+1);
131  for (CFIterator i= f; i.hasTerms(); i++)
132  {
133    CanonicalForm c= i.coeff();
134    if (!c.isImm()) c=c.mapinto(); //c%= getCharacteristic();
135    if (!c.isImm())
136    {  //This case will never happen if the characteristic is in fact a prime
137       // number, since all coefficients are represented as immediates
138       printf("convertCF2nmod_poly_t: coefficient not immediate!, char=%d\n",
139              getCharacteristic());
140    }
141    else
142      nmod_poly_set_coeff_ui (result, i.exp(), c.intval());
143  }
144  if (save_sym_ff) On (SW_SYMMETRIC_FF);
145}
146
147CanonicalForm
148convertnmod_poly_t2FacCF (const nmod_poly_t poly, const Variable& x)
149{
150  CanonicalForm result= 0;
151  for (int i= 0; i < nmod_poly_length (poly); i++)
152  {
153    ulong coeff= nmod_poly_get_coeff_ui (poly, i);
154    if (coeff != 0)
155      result += CanonicalForm ((long)coeff)*power (x,i);
156  }
157  return result;
158}
159
160void convertCF2Fmpq (fmpq_t result, const CanonicalForm& f)
161{
162  //ASSERT (isOn (SW_RATIONAL), "expected rational");
163  if (f.isImm ())
164  {
165    fmpq_set_si (result, f.intval(), 1);
166  }
167  else if(f.inQ())
168  {
169    mpz_t gmp_val;
170    gmp_numerator (f, gmp_val);
171    fmpz_set_mpz (fmpq_numref (result), gmp_val);
172    mpz_clear (gmp_val);
173    gmp_denominator (f, gmp_val);
174    fmpz_set_mpz (fmpq_denref (result), gmp_val);
175    mpz_clear (gmp_val);
176  }
177  else if(f.inZ())
178  {
179    mpz_t gmp_val;
180    f.mpzval(gmp_val);
181    fmpz_set_mpz (fmpq_numref (result), gmp_val);
182    mpz_clear (gmp_val);
183    fmpz_one(fmpq_denref(result));
184  }
185  else
186  {
187    printf("wrong type\n");
188  }
189}
190
191CanonicalForm convertFmpq_t2CF (const fmpq_t q)
192{
193  bool isRat= isOn (SW_RATIONAL);
194  if (!isRat)
195    On (SW_RATIONAL);
196
197  CanonicalForm num, den;
198  mpz_t nnum, nden;
199  mpz_init (nnum);
200  mpz_init (nden);
201  fmpz_get_mpz (nnum, fmpq_numref (q));
202  fmpz_get_mpz (nden, fmpq_denref (q));
203
204  CanonicalForm result;
205  if (mpz_is_imm (nden))
206  {
207    if (mpz_is_imm(nnum))
208    {
209      num= CanonicalForm (mpz_get_si(nnum));
210      den= CanonicalForm (mpz_get_si(nden));
211      mpz_clear (nnum);
212      mpz_clear (nden);
213      result= num/den;
214    }
215    else if (mpz_cmp_si(nden,1)==0)
216    {
217      result= CanonicalForm( CFFactory::basic(nnum));
218      mpz_clear (nden);
219    }
220    else
221      result= CanonicalForm( CFFactory::rational( nnum, nden, false));
222  }
223  else
224  {
225    result= CanonicalForm( CFFactory::rational( nnum, nden, false));
226  }
227  if (!isRat)
228    Off (SW_RATIONAL);
229  return result;
230}
231
232CanonicalForm
233convertFmpq_poly_t2FacCF (const fmpq_poly_t p, const Variable& x)
234{
235  CanonicalForm result= 0;
236  fmpq_t coeff;
237  long n= p->length;
238  for (long i= 0; i < n; i++)
239  {
240    fmpq_init (coeff);
241    fmpq_poly_get_coeff_fmpq (coeff, p, i);
242    if (fmpq_is_zero (coeff))
243    {
244      fmpq_clear (coeff);
245      continue;
246    }
247    result += convertFmpq_t2CF (coeff)*power (x, i);
248    fmpq_clear (coeff);
249  }
250  return result;
251}
252
253void convertFacCF2Fmpz_array (fmpz* result, const CanonicalForm& f)
254{
255  for (CFIterator i= f; i.hasTerms(); i++)
256    convertCF2Fmpz (&result[i.exp()], i.coeff());
257}
258
259void convertFacCF2Fmpq_poly_t (fmpq_poly_t result, const CanonicalForm& f)
260{
261  bool isRat= isOn (SW_RATIONAL);
262  if (!isRat)
263    On (SW_RATIONAL);
264
265  fmpq_poly_init2 (result, degree (f)+1);
266  _fmpq_poly_set_length (result, degree (f) + 1);
267  CanonicalForm den= bCommonDen (f);
268  convertFacCF2Fmpz_array (fmpq_poly_numref (result), f*den);
269  convertCF2Fmpz (fmpq_poly_denref (result), den);
270
271  if (!isRat)
272    Off (SW_RATIONAL);
273}
274
275CFFList
276convertFLINTnmod_poly_factor2FacCFFList (const nmod_poly_factor_t fac,
277                                          const mp_limb_t leadingCoeff,
278                                          const Variable& x
279                                         )
280{
281  CFFList result;
282  if (leadingCoeff != 1)
283    result.insert (CFFactor (CanonicalForm ((long) leadingCoeff), 1));
284
285  long i;
286
287  for (i = 0; i < fac->num; i++)
288    result.append (CFFactor (convertnmod_poly_t2FacCF (
289                             (nmod_poly_t &)fac->p[i],x),
290                             fac->exp[i]));
291  return result;
292}
293
294#if __FLINT_RELEASE >= 20503
295CFFList
296convertFLINTfmpz_poly_factor2FacCFFList (
297                   const fmpz_poly_factor_t fac, ///< [in] a nmod_poly_factor_t
298                   const Variable& x       ///< [in] variable the result should
299                                           ///< have
300                                        )
301
302{
303  CFFList result;
304  long i;
305
306  for (i = 0; i < fac->num; i++)
307    result.append (CFFactor (convertFmpz_poly_t2FacCF (
308                             (fmpz_poly_t &)fac->p[i],x),
309                             fac->exp[i]));
310  return result;
311}
312#endif
313
314#if __FLINT_RELEASE >= 20400
315CFFList
316convertFLINTFq_nmod_poly_factor2FacCFFList (const fq_nmod_poly_factor_t fac,
317                                       const Variable& x, const Variable& alpha,
318                                       const fq_nmod_ctx_t fq_con
319                                         )
320{
321  CFFList result;
322
323  long i;
324
325  for (i = 0; i < fac->num; i++)
326    result.append (CFFactor (convertFq_nmod_poly_t2FacCF (
327                             (fq_nmod_poly_t &)fac->poly[i], x, alpha, fq_con),
328                             fac->exp[i]));
329  return result;
330}
331#endif
332
333void
334convertFacCF2Fmpz_mod_poly_t (fmpz_mod_poly_t result, const CanonicalForm& f,
335                              const fmpz_t p)
336{
337  fmpz_mod_poly_init2 (result, p, degree (f) + 1);
338  fmpz_poly_t buf;
339  convertFacCF2Fmpz_poly_t (buf, f);
340  fmpz_mod_poly_set_fmpz_poly (result, buf);
341  fmpz_poly_clear (buf);
342}
343
344CanonicalForm
345convertFmpz_mod_poly_t2FacCF (const fmpz_mod_poly_t poly, const Variable& x,
346                              const modpk& b)
347{
348  fmpz_poly_t buf;
349  fmpz_poly_init (buf);
350  fmpz_mod_poly_get_fmpz_poly (buf, poly);
351  CanonicalForm result= convertFmpz_poly_t2FacCF (buf, x);
352  fmpz_poly_clear (buf);
353  return b (result);
354}
355
356#if __FLINT_RELEASE >= 20400
357void
358convertFacCF2Fq_nmod_t (fq_nmod_t result, const CanonicalForm& f,
359                        const fq_nmod_ctx_t ctx)
360{
361  bool save_sym_ff= isOn (SW_SYMMETRIC_FF);
362  if (save_sym_ff) Off (SW_SYMMETRIC_FF);
363  for (CFIterator i= f; i.hasTerms(); i++)
364  {
365    CanonicalForm c= i.coeff();
366    if (!c.isImm()) c=c.mapinto(); //c%= getCharacteristic();
367    if (!c.isImm())
368    {  //This case will never happen if the characteristic is in fact a prime
369       // number, since all coefficients are represented as immediates
370       printf("convertFacCF2Fq_nmod_t: coefficient not immediate!, char=%d\n",
371              getCharacteristic());
372    }
373    else
374    {
375      STICKYASSERT (i.exp() <= fq_nmod_ctx_degree(ctx), "convertFacCF2Fq_nmod_t: element is not reduced");
376      nmod_poly_set_coeff_ui (result, i.exp(), c.intval());
377    }
378  }
379  if (save_sym_ff) On (SW_SYMMETRIC_FF);
380}
381
382CanonicalForm
383convertFq_nmod_t2FacCF (const fq_nmod_t poly, const Variable& alpha)
384{
385  return convertnmod_poly_t2FacCF (poly, alpha);
386}
387
388void
389convertFacCF2Fq_t (fq_t result, const CanonicalForm& f, const fq_ctx_t ctx)
390{
391  fmpz_poly_init2 (result, fq_ctx_degree(ctx));
392  ASSERT (degree (f) < fq_ctx_degree (ctx), "input is not reduced");
393  _fmpz_poly_set_length(result, degree(f)+1);
394  for (CFIterator i= f; i.hasTerms(); i++)
395    convertCF2Fmpz (fmpz_poly_get_coeff_ptr(result, i.exp()), i.coeff());
396  _fmpz_vec_scalar_mod_fmpz (result->coeffs, result->coeffs, degree (f) + 1,
397                             &ctx->p);
398  _fmpz_poly_normalise (result);
399}
400
401CanonicalForm
402convertFq_t2FacCF (const fq_t poly, const Variable& alpha)
403{
404  return convertFmpz_poly_t2FacCF (poly, alpha);
405}
406
407void
408convertFacCF2Fq_poly_t (fq_poly_t result, const CanonicalForm& f,
409                        const fq_ctx_t ctx)
410{
411  fq_poly_init2 (result, degree (f)+1, ctx);
412  _fq_poly_set_length (result, degree (f) + 1, ctx);
413  fmpz_poly_t buf;
414  for (CFIterator i= f; i.hasTerms(); i++)
415  {
416    convertFacCF2Fmpz_poly_t (buf, i.coeff());
417    _fmpz_vec_scalar_mod_fmpz (buf->coeffs, buf->coeffs, degree (i.coeff()) + 1,
418                               &ctx->p);
419    _fmpz_poly_normalise (buf);
420    fq_poly_set_coeff (result, i.exp(), buf, ctx);
421    fmpz_poly_clear (buf);
422  }
423}
424
425void
426convertFacCF2Fq_nmod_poly_t (fq_nmod_poly_t result, const CanonicalForm& f,
427                             const fq_nmod_ctx_t ctx)
428{
429  fq_nmod_poly_init2 (result, degree (f)+1, ctx);
430  _fq_nmod_poly_set_length (result, degree (f) + 1, ctx);
431  fq_nmod_t buf;
432  fq_nmod_init2 (buf, ctx);
433  for (CFIterator i= f; i.hasTerms(); i++)
434  {
435    convertFacCF2Fq_nmod_t (buf, i.coeff(), ctx);
436    fq_nmod_poly_set_coeff (result, i.exp(), buf, ctx);
437    fq_nmod_zero (buf, ctx);
438  }
439  fq_nmod_clear (buf, ctx);
440}
441
442CanonicalForm
443convertFq_poly_t2FacCF (const fq_poly_t p, const Variable& x,
444                        const Variable& alpha, const fq_ctx_t ctx)
445{
446  CanonicalForm result= 0;
447  fq_t coeff;
448  long n= fq_poly_length (p, ctx);
449  fq_init2 (coeff, ctx);
450  for (long i= 0; i < n; i++)
451  {
452    fq_poly_get_coeff (coeff, p, i, ctx);
453    if (fq_is_zero (coeff, ctx))
454      continue;
455    result += convertFq_t2FacCF (coeff, alpha)*power (x, i);
456    fq_zero (coeff, ctx);
457  }
458  fq_clear (coeff, ctx);
459
460  return result;
461}
462
463CanonicalForm
464convertFq_nmod_poly_t2FacCF (const fq_nmod_poly_t p, const Variable& x,
465                             const Variable& alpha, const fq_nmod_ctx_t ctx)
466{
467  CanonicalForm result= 0;
468  fq_nmod_t coeff;
469  long n= fq_nmod_poly_length (p, ctx);
470  fq_nmod_init2 (coeff, ctx);
471  for (long i= 0; i < n; i++)
472  {
473    fq_nmod_poly_get_coeff (coeff, p, i, ctx);
474    if (fq_nmod_is_zero (coeff, ctx))
475      continue;
476    result += convertFq_nmod_t2FacCF (coeff, alpha)*power (x, i);
477    fq_nmod_zero (coeff, ctx);
478  }
479  fq_nmod_clear (coeff, ctx);
480
481  return result;
482}
483#endif
484
485void convertFacCFMatrix2Fmpz_mat_t (fmpz_mat_t M, const CFMatrix &m)
486{
487  fmpz_mat_init (M, (long) m.rows(), (long) m.columns());
488
489  int i,j;
490  for(i=m.rows();i>0;i--)
491  {
492    for(j=m.columns();j>0;j--)
493    {
494      convertCF2Fmpz (fmpz_mat_entry (M,i-1,j-1), m(i,j));
495    }
496  }
497}
498CFMatrix* convertFmpz_mat_t2FacCFMatrix(const fmpz_mat_t m)
499{
500  CFMatrix *res=new CFMatrix(fmpz_mat_nrows (m),fmpz_mat_ncols (m));
501  int i,j;
502  for(i=res->rows();i>0;i--)
503  {
504    for(j=res->columns();j>0;j--)
505    {
506      (*res)(i,j)=convertFmpz2CF(fmpz_mat_entry (m,i-1,j-1));
507    }
508  }
509  return res;
510}
511
512void convertFacCFMatrix2nmod_mat_t (nmod_mat_t M, const CFMatrix &m)
513{
514  nmod_mat_init (M, (long) m.rows(), (long) m.columns(), getCharacteristic());
515
516  bool save_sym_ff= isOn (SW_SYMMETRIC_FF);
517  if (save_sym_ff) Off (SW_SYMMETRIC_FF);
518  int i,j;
519  for(i=m.rows();i>0;i--)
520  {
521    for(j=m.columns();j>0;j--)
522    {
523      if(!(m(i,j)).isImm()) printf("convertFacCFMatrix2FLINTmat_zz_p: not imm.\n");
524      nmod_mat_entry (M,i-1,j-1)= (m(i,j)).intval();
525    }
526  }
527  if (save_sym_ff) On (SW_SYMMETRIC_FF);
528}
529
530CFMatrix* convertNmod_mat_t2FacCFMatrix(const nmod_mat_t m)
531{
532  CFMatrix *res=new CFMatrix(nmod_mat_nrows (m), nmod_mat_ncols (m));
533  int i,j;
534  for(i=res->rows();i>0;i--)
535  {
536    for(j=res->columns();j>0;j--)
537    {
538      (*res)(i,j)=CanonicalForm((long) nmod_mat_entry (m, i-1, j-1));
539    }
540  }
541  return res;
542}
543
544#if __FLINT_RELEASE >= 20400
545void
546convertFacCFMatrix2Fq_nmod_mat_t (fq_nmod_mat_t M,
547                                  const fq_nmod_ctx_t fq_con, const CFMatrix &m)
548{
549  fq_nmod_mat_init (M, (long) m.rows(), (long) m.columns(), fq_con);
550  int i,j;
551  for(i=m.rows();i>0;i--)
552  {
553    for(j=m.columns();j>0;j--)
554    {
555      convertFacCF2nmod_poly_t (M->rows[i-1]+j-1, m (i,j));
556    }
557  }
558}
559
560CFMatrix*
561convertFq_nmod_mat_t2FacCFMatrix(const fq_nmod_mat_t m,
562                                 const fq_nmod_ctx_t& fq_con,
563                                 const Variable& alpha)
564{
565  CFMatrix *res=new CFMatrix(fq_nmod_mat_nrows (m, fq_con),
566                             fq_nmod_mat_ncols (m, fq_con));
567  int i,j;
568  for(i=res->rows();i>0;i--)
569  {
570    for(j=res->columns();j>0;j--)
571    {
572      (*res)(i,j)=convertFq_nmod_t2FacCF (fq_nmod_mat_entry (m, i-1, j-1),
573                                          alpha);
574    }
575  }
576  return res;
577}
578#endif
579#if __FLINT_RELEASE >= 20503
580static void convFlint_RecPP ( const CanonicalForm & f, ulong * exp, nmod_mpoly_t result, nmod_mpoly_ctx_t ctx, int N )
581{
582  // assume f!=0
583  if ( ! f.inCoeffDomain() )
584  {
585    int l = f.level();
586    for ( CFIterator i = f; i.hasTerms(); i++ )
587    {
588      exp[N-l] = i.exp();
589      convFlint_RecPP( i.coeff(), exp, result, ctx, N );
590    }
591    exp[N-l] = 0;
592  }
593  else
594  {
595    int c=f.intval(); // with Off(SW_SYMMETRIC_FF): 0<=c<p
596    nmod_mpoly_push_term_ui_ui(result,c,exp,ctx);
597  }
598}
599
600static void convFlint_RecPP ( const CanonicalForm & f, ulong * exp, fmpq_mpoly_t result, fmpq_mpoly_ctx_t ctx, int N )
601{
602  // assume f!=0
603  if ( ! f.inBaseDomain() )
604  {
605    int l = f.level();
606    for ( CFIterator i = f; i.hasTerms(); i++ )
607    {
608      exp[N-l] = i.exp();
609      convFlint_RecPP( i.coeff(), exp, result, ctx, N );
610    }
611    exp[N-l] = 0;
612  }
613  else
614  {
615    fmpq_t c;
616    fmpq_init(c);
617    convertCF2Fmpq(c,f);
618    fmpq_mpoly_push_term_fmpq_ui(result,c,exp,ctx);
619    fmpq_clear(c);
620  }
621}
622
623void convFactoryPFlintMP ( const CanonicalForm & f, nmod_mpoly_t res, nmod_mpoly_ctx_t ctx, int N )
624{
625  if (f.isZero()) return;
626  ulong * exp = (ulong*)Alloc(N*sizeof(ulong));
627  memset(exp,0,N*sizeof(ulong));
628  bool save_sym_ff= isOn (SW_SYMMETRIC_FF);
629  if (save_sym_ff) Off (SW_SYMMETRIC_FF);
630  convFlint_RecPP( f, exp, res, ctx, N );
631  if (save_sym_ff) On(SW_SYMMETRIC_FF);
632  Free(exp,N*sizeof(ulong));
633}
634
635void convFactoryPFlintMP ( const CanonicalForm & f, fmpq_mpoly_t res, fmpq_mpoly_ctx_t ctx, int N )
636{
637  if (f.isZero()) return;
638  ulong * exp = (ulong*)Alloc(N*sizeof(ulong));
639  memset(exp,0,N*sizeof(ulong));
640  convFlint_RecPP( f, exp, res, ctx, N );
641  fmpq_mpoly_reduce(res,ctx);
642  Free(exp,N*sizeof(ulong));
643}
644
645CanonicalForm convFlintMPFactoryP(nmod_mpoly_t f, nmod_mpoly_ctx_t ctx, int N)
646{
647  CanonicalForm result;
648  int d=nmod_mpoly_length(f,ctx)-1;
649  ulong* exp=(ulong*)Alloc(N*sizeof(ulong));
650  for(int i=d; i>=0; i--)
651  {
652    ulong c=nmod_mpoly_get_term_coeff_ui(f,i,ctx);
653    nmod_mpoly_get_term_exp_ui(exp,f,i,ctx);
654    CanonicalForm term=(int)c;
655    for ( int i = 0; i <N; i++ )
656    {
657      if (exp[i]!=0) term*=CanonicalForm( Variable( N-i ), exp[i] );
658    }
659    result+=term;
660  }
661  Free(exp,N*sizeof(ulong));
662  return result;
663}
664
665CanonicalForm convFlintMPFactoryP(fmpq_mpoly_t f, fmpq_mpoly_ctx_t ctx, int N)
666{
667  CanonicalForm result;
668  int d=fmpq_mpoly_length(f,ctx)-1;
669  ulong* exp=(ulong*)Alloc(N*sizeof(ulong));
670  fmpq_t c;
671  fmpq_init(c);
672  for(int i=d; i>=0; i--)
673  {
674    fmpq_mpoly_get_term_coeff_fmpq(c,f,i,ctx);
675    fmpq_mpoly_get_term_exp_ui(exp,f,i,ctx);
676    CanonicalForm term=convertFmpq_t2CF(c);
677    for ( int i = 0; i <N; i++ )
678    {
679      if (exp[i]!=0) term*=CanonicalForm( Variable( N-i ), exp[i] );
680    }
681    result+=term;
682  }
683  fmpq_clear(c);
684  Free(exp,N*sizeof(ulong));
685  return result;
686}
687
688// stolen from:
689// https://graphics.stanford.edu/~seander/bithacks.html#IntegerLog
690static inline int SI_LOG2(int v)
691{
692  const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
693  const unsigned int S[] = {1, 2, 4, 8, 16};
694
695  unsigned int r = 0; // result of log2(v) will go here
696  if (v & b[4]) { v >>= S[4]; r |= S[4]; }
697  if (v & b[3]) { v >>= S[3]; r |= S[3]; }
698  if (v & b[2]) { v >>= S[2]; r |= S[2]; }
699  if (v & b[1]) { v >>= S[1]; r |= S[1]; }
700  if (v & b[0]) { v >>= S[0]; r |= S[0]; }
701  return (int)r;
702}
703
704CanonicalForm mulFlintMP_Zp(const CanonicalForm& F,int lF, const CanonicalForm& G, int lG,int m)
705{
706  int bits=SI_LOG2(m)+1;
707  int N=F.level();
708  nmod_mpoly_ctx_t ctx;
709  nmod_mpoly_ctx_init(ctx,N,ORD_LEX,getCharacteristic());
710  nmod_mpoly_t f,g,res;
711  nmod_mpoly_init3(f,lF,bits,ctx);
712  nmod_mpoly_init3(g,lG,bits,ctx);
713  convFactoryPFlintMP(F,f,ctx,N);
714  convFactoryPFlintMP(G,g,ctx,N);
715  nmod_mpoly_init(res,ctx);
716  nmod_mpoly_mul(res,f,g,ctx);
717  nmod_mpoly_clear(g,ctx);
718  nmod_mpoly_clear(f,ctx);
719  CanonicalForm RES=convFlintMPFactoryP(res,ctx,N);
720  nmod_mpoly_clear(res,ctx);
721  nmod_mpoly_ctx_clear(ctx);
722  return RES;
723}
724
725CanonicalForm mulFlintMP_QQ(const CanonicalForm& F,int lF, const CanonicalForm& G, int lG, int m)
726{
727  int bits=SI_LOG2(m)+1;
728  int N=F.level();
729  fmpq_mpoly_ctx_t ctx;
730  fmpq_mpoly_ctx_init(ctx,N,ORD_LEX);
731  fmpq_mpoly_t f,g,res;
732  fmpq_mpoly_init3(f,lF,bits,ctx);
733  fmpq_mpoly_init3(g,lG,bits,ctx);
734  convFactoryPFlintMP(F,f,ctx,N);
735  convFactoryPFlintMP(G,g,ctx,N);
736  fmpq_mpoly_init(res,ctx);
737  fmpq_mpoly_mul(res,f,g,ctx);
738  fmpq_mpoly_clear(g,ctx);
739  fmpq_mpoly_clear(f,ctx);
740  CanonicalForm RES=convFlintMPFactoryP(res,ctx,N);
741  fmpq_mpoly_clear(res,ctx);
742  fmpq_mpoly_ctx_clear(ctx);
743  return RES;
744}
745
746CanonicalForm gcdFlintMP_Zp(const CanonicalForm& F, const CanonicalForm& G)
747{
748  int N=F.level();
749  int lf,lg,m=1<<MPOLY_MIN_BITS;
750  lf=size_maxexp(F,m);
751  lg=size_maxexp(G,m);
752  int bits=SI_LOG2(m)+1;
753  nmod_mpoly_ctx_t ctx;
754  nmod_mpoly_ctx_init(ctx,N,ORD_LEX,getCharacteristic());
755  nmod_mpoly_t f,g,res;
756  nmod_mpoly_init3(f,lf,bits,ctx);
757  nmod_mpoly_init3(g,lg,bits,ctx);
758  convFactoryPFlintMP(F,f,ctx,N);
759  convFactoryPFlintMP(G,g,ctx,N);
760  nmod_mpoly_init(res,ctx);
761  int ok=nmod_mpoly_gcd(res,f,g,ctx);
762  nmod_mpoly_clear(g,ctx);
763  nmod_mpoly_clear(f,ctx);
764  CanonicalForm RES=1;
765  if (ok)
766  {
767    RES=convFlintMPFactoryP(res,ctx,N);
768  }
769  nmod_mpoly_clear(res,ctx);
770  nmod_mpoly_ctx_clear(ctx);
771  return RES;
772}
773
774static CanonicalForm b_content ( const CanonicalForm & f )
775{
776    if ( f.inCoeffDomain() )
777        return f;
778    else
779    {
780        CanonicalForm result = 0;
781        CFIterator i;
782        for ( i = f; i.hasTerms() && (!result.isOne()); i++ )
783            result=bgcd( b_content(i.coeff()) , result );
784        return result;
785    }
786}
787
788
789CanonicalForm gcdFlintMP_QQ(const CanonicalForm& F, const CanonicalForm& G)
790{
791  int N=F.level();
792  fmpq_mpoly_ctx_t ctx;
793  fmpq_mpoly_ctx_init(ctx,N,ORD_LEX);
794  fmpq_mpoly_t f,g,res;
795  fmpq_mpoly_init(f,ctx);
796  fmpq_mpoly_init(g,ctx);
797  convFactoryPFlintMP(F,f,ctx,N);
798  convFactoryPFlintMP(G,g,ctx,N);
799  fmpq_mpoly_init(res,ctx);
800  int ok=fmpq_mpoly_gcd(res,f,g,ctx);
801  fmpq_mpoly_clear(g,ctx);
802  fmpq_mpoly_clear(f,ctx);
803  CanonicalForm RES=1;
804  if (ok)
805  {
806    // Flint normalizes the gcd to be monic.
807    // Singular wants a gcd defined over ZZ that is primitive and has a positive leading coeff.
808    if (!fmpq_mpoly_is_zero(res, ctx))
809    {
810      fmpq_t content;
811      fmpq_init(content);
812      fmpq_mpoly_content(content, res, ctx);
813      fmpq_mpoly_scalar_div_fmpq(res, res, content, ctx);
814      fmpq_clear(content);
815    }
816    RES=convFlintMPFactoryP(res,ctx,N);
817    // gcd(2x,4x) should be 2x, so RES should also have the gcd(lc(F),lc(G))
818    RES*=bgcd(b_content(F),b_content(G));
819  }
820  fmpq_mpoly_clear(res,ctx);
821  fmpq_mpoly_ctx_clear(ctx);
822  return RES;
823}
824
825#endif
826
827#endif
828
829
Note: See TracBrowser for help on using the repository browser.