source: git/libpolys/coeffs/flintcf_Q.cc @ f5e732

spielwiese
Last change on this file since f5e732 was 52e6ef, checked in by Hans Schoenemann <hannes@…>, 8 years ago
chg: use misc/auxiliary.h in libpolys and kernel/mod2.h in Singular for config
  • Property mode set to 100644
File size: 15.3 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/*
5* ABSTRACT: flint: fmpq_poly
6*/
7#include <ctype.h> /* isdigit*/
8
9#include <misc/auxiliary.h>
10
11#ifdef SINGULAR_4_1
12#ifdef HAVE_FLINT
13
14#include <flint/flint.h>
15#include <flint/fmpq_poly.h>
16#include <factory/factory.h>
17
18#include <omalloc/omalloc.h>
19#include <coeffs/coeffs.h>
20
21#include <coeffs/numbers.h>
22#include <coeffs/longrat.h>
23
24typedef fmpq_poly_struct *fmpq_poly_ptr;
25typedef fmpz *fmpz_ptr;
26/*2
27* extracts a long integer from s, returns the rest
28*/
29static char * nlEatLong(char *s, mpz_ptr i)
30{
31  const char * start=s;
32
33  while (*s >= '0' && *s <= '9') s++;
34  if (*s=='\0')
35  {
36    mpz_set_str(i,start,10);
37  }
38  else
39  {
40    char c=*s;
41    *s='\0';
42    mpz_set_str(i,start,10);
43    *s=c;
44  }
45  return s;
46}
47
48static const char* Eati(const char *s, int *i)
49{
50
51  if (((*s) >= '0') && ((*s) <= '9'))
52  {
53    unsigned long ii=0L;
54    do
55    {
56      ii *= 10;
57      ii += *s++ - '0';
58    }
59    while (((*s) >= '0') && ((*s) <= '9'));
60    *i=(int)ii;
61  }
62  else (*i) = 1;
63  return s;
64}
65
66
67
68static void CoeffWrite(const coeffs r, BOOLEAN details)
69{
70  PrintS("// coefficients: flint fmpq_poly\n");
71}
72static BOOLEAN CoeffIsEqual(const coeffs r, n_coeffType n, void * parameter)
73{
74  return (r->type==n);
75}
76static void KillChar(coeffs r)
77{
78  // not yet
79}
80static void SetChar(const coeffs r)
81{
82  // dummy
83}
84static number Mult(number a, number b, const coeffs c)
85{
86  fmpq_poly_ptr res=(fmpq_poly_ptr)omAlloc(sizeof(fmpq_poly_t));
87  fmpq_poly_init(res);
88  fmpq_poly_mul(res,(fmpq_poly_ptr)a,(fmpq_poly_ptr)b);
89  return (number)res;
90}
91static number Sub(number a, number b, const coeffs c)
92{
93  fmpq_poly_ptr res=(fmpq_poly_ptr)omAlloc(sizeof(fmpq_poly_t));
94  fmpq_poly_init(res);
95  fmpq_poly_sub(res,(fmpq_poly_ptr)a,(fmpq_poly_ptr)b);
96  return (number)res;
97}
98static number Add(number a, number b, const coeffs c)
99{
100  fmpq_poly_ptr res=(fmpq_poly_ptr)omAlloc(sizeof(fmpq_poly_t));
101  fmpq_poly_init(res);
102  fmpq_poly_add(res,(fmpq_poly_ptr)a,(fmpq_poly_ptr)b);
103  return (number)res;
104}
105static number Div(number a, number b, const coeffs c)
106{
107  fmpq_poly_ptr res=(fmpq_poly_ptr)omAlloc(sizeof(fmpq_poly_t));
108  fmpq_poly_init(res);
109  if(fmpq_poly_is_zero((fmpq_poly_ptr)b))
110  {
111     WerrorS(nDivBy0);
112  }
113  else
114  {
115    fmpq_poly_div(res,(fmpq_poly_ptr)a,(fmpq_poly_ptr)b);
116    fmpq_poly_t mod;
117    fmpq_poly_init(mod);
118    fmpq_poly_rem(mod,(fmpq_poly_ptr)a,(fmpq_poly_ptr)b);
119    if (!fmpq_poly_is_zero((fmpq_poly_ptr)mod))
120    {
121      WerrorS("cannot divide");
122    }
123    fmpq_poly_clear(mod);
124  }
125  return (number)res;
126}
127static number ExactDiv(number a, number b, const coeffs c)
128{
129  fmpq_poly_ptr res=(fmpq_poly_ptr)omAlloc(sizeof(fmpq_poly_t));
130  fmpq_poly_init(res);
131  if(fmpq_poly_is_zero((fmpq_poly_ptr)b))
132  {
133     WerrorS(nDivBy0);
134  }
135  else
136    fmpq_poly_div(res,(fmpq_poly_ptr)a,(fmpq_poly_ptr)b);
137  return (number)res;
138}
139static number IntMod(number a, number b, const coeffs c)
140{
141  fmpq_poly_ptr res=(fmpq_poly_ptr)omAlloc(sizeof(fmpq_poly_t));
142  fmpq_poly_init(res);
143  fmpq_poly_rem(res,(fmpq_poly_ptr)a,(fmpq_poly_ptr)b);
144  return (number)res;
145}
146static number Init (long i, const coeffs r)
147{
148  fmpq_poly_ptr res=(fmpq_poly_ptr)omAlloc(sizeof(fmpq_poly_t));
149  fmpq_poly_init(res);
150  fmpq_poly_set_si(res,i);
151  return (number)res;
152}
153static number InitMPZ (mpz_t i, const coeffs r)
154{
155  fmpq_poly_ptr res=(fmpq_poly_ptr)omAlloc(sizeof(fmpq_poly_t));
156  fmpq_poly_init(res);
157  fmpq_poly_set_mpz(res,i);
158  return (number)res;
159}
160static int Size (number n, const coeffs r)
161{
162  return fmpq_poly_degree((fmpq_poly_ptr)n);
163}
164static long Int (number &n, const coeffs r)
165{
166  if (fmpq_poly_degree((fmpq_poly_ptr)n)==0)
167  {
168    mpq_t m;
169    mpq_init(m);
170    fmpq_poly_get_coeff_mpq(m,(fmpq_poly_ptr)n,0);
171    mpz_t num,den;
172    mpz_init(num);
173    mpz_init(den);
174    mpq_get_num(num,m);
175    mpq_get_den(den,m);
176    long nl=mpz_get_si(num);
177    if (mpz_cmp_si(num,nl)!=0) nl=0;
178    long dl=mpz_get_si(den);
179    if ((dl!=1)||(mpz_cmp_si(den,dl)!=0)) nl=0;
180    mpz_clear(num);
181    mpz_clear(den);
182    mpq_clear(m);
183    return nl;
184  }
185  return 0;
186}
187static void MPZ(mpz_t result, number &n, const coeffs r)
188{
189  mpz_init(result);
190  if (fmpq_poly_degree((fmpq_poly_ptr)n)==0)
191  {
192    mpq_t m;
193    mpq_init(m);
194    fmpq_poly_get_coeff_mpq(m,(fmpq_poly_ptr)n,0);
195    mpz_t den;
196    mpz_init(den);
197    mpq_get_num(result,m);
198    mpq_get_den(den,m);
199    int dl=(int)mpz_get_si(den);
200    if ((dl!=1)||(mpz_cmp_si(den,(long)dl)!=0)) mpz_set_ui(result,0);
201    mpz_clear(den);
202    mpq_clear(m);
203  }
204}
205static number Neg(number a, const coeffs r)
206{
207  fmpq_poly_neg((fmpq_poly_ptr)a,(fmpq_poly_ptr)a);
208  return a;
209}
210static number Invers(number a, const coeffs r)
211{
212  if(fmpq_poly_is_zero((fmpq_poly_ptr)a))
213  {
214    WerrorS(nDivBy0);
215    return NULL;
216  }
217  if (fmpq_poly_degree((fmpq_poly_ptr)a)==0)
218  {
219    fmpq_poly_ptr res=(fmpq_poly_ptr)omAlloc(sizeof(fmpq_poly_t));
220    fmpq_poly_init(res);
221    fmpq_poly_inv(res,(fmpq_poly_ptr)a);
222    return (number)res;
223  }
224  else
225  {
226    WerrorS("not invertable");
227    return NULL;
228  }
229}
230static number Copy(number a, const coeffs r)
231{
232 fmpq_poly_ptr res=(fmpq_poly_ptr)omAlloc(sizeof(fmpq_poly_t));
233 fmpq_poly_init(res);
234 fmpq_poly_set(res,(fmpq_poly_ptr)a);
235 return (number)res;
236}
237//static number RePart(number a, const coeffs r)
238//{
239//}
240//static number ImPart(number a, const coeffs r)
241//{
242//}
243static BOOLEAN IsOne (number a, const coeffs r);
244static BOOLEAN IsZero (number a, const coeffs r);
245//static void WriteLong(number &a, const coeffs r)
246//{
247//}
248static void WriteShort(number a, const coeffs r)
249{
250  //fmpq_poly_print_pretty((fmpq_poly_ptr)a,r->pParameterNames[0]);
251  if (IsOne(a,r)) StringAppendS("1");
252  else if (IsZero(a,r)) StringAppendS("0");
253  else
254  {
255  StringAppendS("(");
256  mpq_t m;
257  mpq_init(m);
258  mpz_t num,den;
259  mpz_init(num);
260  mpz_init(den);
261  BOOLEAN need_plus=FALSE;
262  for(int i=fmpq_poly_length((fmpq_poly_ptr)a);i>=0;i--)
263  {
264    fmpq_poly_get_coeff_mpq(m,(fmpq_poly_ptr)a,i);
265    mpq_get_num(num,m);
266    mpq_get_den(den,m);
267    if (mpz_cmp_ui(num,0)!=0)
268    {
269      if (need_plus && (mpz_cmp_si(num,0)>0))
270        StringAppendS("+");
271      need_plus=TRUE;
272      int l=mpz_sizeinbase(num,10);
273      l=si_max(l,(int)mpz_sizeinbase(den,10));
274      l+=2;
275      char *s=(char*)omAlloc(l);
276      char *z=mpz_get_str(s,10,num);
277      if ((i==0)
278      ||(mpz_cmp_si(num,1)!=0)
279      ||(mpz_cmp_si(den,1)!=0))
280      {
281        StringAppendS(z);
282        if (mpz_cmp_si(den,1)!=0)
283        {
284          StringAppendS("/");
285          z=mpz_get_str(s,10,den);
286          StringAppendS(z);
287        }
288        if (i!=0) StringAppendS("*");
289      }
290      if (i>1)
291        StringAppend("%s^%d",r->pParameterNames[0],i);
292      else if (i==1)
293        StringAppend("%s",r->pParameterNames[0]);
294    }
295  }
296  mpz_clear(den);
297  mpz_clear(num);
298  mpq_clear(m);
299  StringAppendS(")");
300  }
301}
302static const char* Read(const char * st, number * a, const coeffs r)
303{
304// we only read "monomials" (i.e. [-][digits][parameter]),
305// everythings else (+,*,^,()) is left to the singular interpreter
306  const char *s=st;
307  *a=(number)omAlloc(sizeof(fmpq_poly_t));
308  fmpq_poly_init((fmpq_poly_ptr)(*a));
309  BOOLEAN neg=FALSE;
310  if (*s=='-') { neg=TRUE; s++;}
311  if (isdigit(*s))
312  {
313    mpz_t z;
314    mpz_init(z);
315    s=nlEatLong((char *)s, z);
316    fmpq_poly_set_mpz((fmpq_poly_ptr)(*a),z);
317    if (*s == '/')
318    {
319      s++;
320      s=nlEatLong((char *)s, z);
321      fmpq_poly_scalar_div_mpz((fmpq_poly_ptr)(*a),(fmpq_poly_ptr)(*a),z);
322    }
323    mpz_clear(z);
324  }
325  else if(strncmp(s,r->pParameterNames[0],strlen(r->pParameterNames[0]))==0)
326  {
327    fmpq_poly_set_coeff_si((fmpq_poly_ptr)(*a),1,1);
328    s+=strlen(r->pParameterNames[0]);
329    if(isdigit(*s))
330    {
331      int i=1;
332      s=Eati(s,&i);
333      if (i!=1)
334      {
335        fmpq_poly_set_coeff_si((fmpq_poly_ptr)(*a),1,0);
336        fmpq_poly_set_coeff_si((fmpq_poly_ptr)(*a),i,1);
337      }
338    }
339  }
340  if (neg)
341    fmpq_poly_neg((fmpq_poly_ptr)(*a),(fmpq_poly_ptr)(*a));
342  return s;
343}
344static void Normalize(number &a, const coeffs r)
345{
346  fmpq_poly_canonicalise((fmpq_poly_ptr)a);
347}
348static BOOLEAN Greater (number a, number b, const coeffs r)
349{
350  return (fmpq_poly_cmp((fmpq_poly_ptr)a,(fmpq_poly_ptr)b)>0);
351}
352static BOOLEAN Equal (number a, number b, const coeffs r)
353{
354  return (fmpq_poly_equal((fmpq_poly_ptr)a,(fmpq_poly_ptr)b));
355}
356static BOOLEAN IsZero (number a, const coeffs r)
357{
358  return fmpq_poly_is_zero((fmpq_poly_ptr)a);
359}
360static BOOLEAN IsOne (number a, const coeffs r)
361{
362  return fmpq_poly_is_one((fmpq_poly_ptr)a);
363}
364static BOOLEAN IsMOne (number k, const coeffs r)
365{
366  if (fmpq_poly_length((fmpq_poly_ptr)k)>0) return FALSE;
367  fmpq_poly_canonicalise((fmpq_poly_ptr)k);
368  mpq_t m;
369  mpq_init(m);
370  fmpq_poly_get_coeff_mpq(m,(fmpq_poly_ptr)k,0);
371  mpz_t num,den;
372  mpz_init(num);
373  mpq_get_num(num,m);
374  BOOLEAN result=TRUE;
375  if (mpz_cmp_si(num,(long)-1)!=0) result=FALSE;
376  else
377  {
378    mpz_init(den);
379    mpq_get_den(den,m);
380    int dl=(int)mpz_get_si(den);
381    if ((dl!=1)||(mpz_cmp_si(den,(long)dl)!=0)) result=FALSE;
382    mpz_clear(den);
383  }
384  mpz_clear(num);
385  mpq_clear(m);
386  return (result);
387}
388static BOOLEAN GreaterZero (number k, const coeffs r)
389{
390  // does it have a leading sign?
391  // no: 0 and 1 do not have, everything else is in (...)
392  return TRUE;
393}
394static void Power(number a, int i, number * result, const coeffs r)
395{
396  fmpq_poly_ptr res=(fmpq_poly_ptr)omAlloc(sizeof(fmpq_poly_t));
397  fmpq_poly_init(res);
398  *result=(number)res;
399  fmpq_poly_pow((fmpq_poly_ptr)(*result),(fmpq_poly_ptr)a,i);
400}
401static number GetDenom(number &n, const coeffs r)
402{
403 fmpq_poly_ptr res=(fmpq_poly_ptr)omAlloc(sizeof(fmpq_poly_t));
404 fmpq_poly_init(res);
405 fmpz_ptr den=fmpq_poly_denref(res);
406 fmpq_poly_set_fmpz(res,den);
407 return (number)res;
408}
409static number GetNumerator(number &n, const coeffs r)
410{
411 fmpq_poly_ptr res=(fmpq_poly_ptr)omAlloc(sizeof(fmpq_poly_t));
412 fmpq_poly_init(res);
413 fmpq_poly_set(res,(fmpq_poly_ptr)n);
414 fmpz_ptr den=fmpq_poly_denref(res);
415 fmpq_poly_scalar_mul_fmpz(res,res,den);
416 return (number)res;
417}
418static number Gcd(number a, number b, const coeffs r)
419{
420  fmpq_poly_ptr res=(fmpq_poly_ptr)omAlloc(sizeof(fmpq_poly_t));
421  fmpq_poly_init(res);
422  fmpq_poly_gcd(res,(fmpq_poly_ptr)a,(fmpq_poly_ptr)b);
423  return (number)res;
424}
425static number ExtGcd(number a, number b, number *s, number *t,const coeffs r)
426{
427  fmpq_poly_ptr res=(fmpq_poly_ptr)omAlloc(sizeof(fmpq_poly_t));
428  fmpq_poly_init(res);
429  fmpq_poly_init((fmpq_poly_ptr)*s);
430  fmpq_poly_init((fmpq_poly_ptr)*t);
431  fmpq_poly_xgcd(res,(fmpq_poly_ptr)*s,(fmpq_poly_ptr)*t,(fmpq_poly_ptr)a,(fmpq_poly_ptr)b);
432  return (number)res;
433}
434static number Lcm(number a, number b, const coeffs r)
435{
436  WerrorS("not yet: Lcm");
437}
438static void Delete(number * a, const coeffs r)
439{
440  if ((*a)!=NULL)
441  {
442    fmpq_poly_clear((fmpq_poly_ptr)*a);
443    omFree(*a);
444    *a=NULL;
445  }
446}
447static nMapFunc SetMap(const coeffs src, const coeffs dst)
448{
449  WerrorS("not yet: SetMap");
450  return NULL;
451}
452//static void InpMult(number &a, number b, const coeffs r)
453//{
454//}
455//static void InpAdd(number &a, number b, const coeffs r)
456//{
457//}
458static number Init_bigint(number i, const coeffs dummy, const coeffs dst)
459{
460  fmpq_poly_ptr res=(fmpq_poly_ptr)omAlloc(sizeof(fmpq_poly_t));
461  fmpq_poly_init(res);
462  if (SR_HDL(i) & SR_INT)
463  {
464    fmpq_poly_set_si(res,SR_TO_INT(i));
465  }
466  else
467    fmpq_poly_set_mpz(res,i->z);
468  return (number)res;
469}
470static number Farey(number p, number n, const coeffs)
471{
472  WerrorS("not yet: Farey");
473}
474static number ChineseRemainder(number *x, number *q,int rl, BOOLEAN sym,CFArray &inv_cache,const coeffs)
475{
476  WerrorS("not yet: ChineseRemainder");
477}
478static int ParDeg(number x,const coeffs r)
479{
480  return fmpq_poly_degree((fmpq_poly_ptr)x);
481}
482static number Parameter(const int i, const coeffs r)
483{
484  fmpq_poly_ptr res=(fmpq_poly_ptr)omAlloc(sizeof(fmpq_poly_t));
485  fmpq_poly_init(res);
486  fmpq_poly_set_coeff_si(res,1,1);
487  return (number)res;
488}
489static void WriteFd(number a, FILE *f, const coeffs)
490{
491  // format: len a_len(num den) .. a_0
492  fmpq_poly_ptr aa=(fmpq_poly_ptr)a;
493  int l=fmpq_poly_length(aa);
494  fprintf(f,"%d ",l);
495  mpq_t m;
496  mpq_init(m);
497  mpz_t num,den;
498  mpz_init(num);
499  mpz_init(den);
500  for(int i=l; i>=0; i--)
501  {
502    fmpq_poly_get_coeff_mpq(m,(fmpq_poly_ptr)a,i);
503    mpq_get_num(num,m);
504    mpq_get_den(den,m);
505    mpz_out_str (f,SSI_BASE, num);
506    fputc(' ',f);
507    mpz_out_str (f,SSI_BASE, den);
508    fputc(' ',f);
509  }
510  mpz_clear(den);
511  mpz_clear(num);
512  mpq_clear(m);
513}
514static number ReadFd(s_buff f, const coeffs)
515{
516  // format: len a_len .. a_0
517  fmpq_poly_ptr aa=(fmpq_poly_ptr)omAlloc(sizeof(fmpq_poly_t));
518  fmpq_poly_init(aa);
519  int l=s_readint(f);
520  mpz_t nm;
521  mpz_init(nm);
522  mpq_t m;
523  mpq_init(m);
524  for (int i=l;i>=0;i--)
525  {
526
527    s_readmpz_base (f,nm, SSI_BASE);
528    mpq_set_num(m,nm);
529    s_readmpz_base (f,nm, SSI_BASE);
530    mpq_set_den(m,nm);
531    fmpq_poly_set_coeff_mpq(aa,i,m);
532  }
533  mpz_clear(nm);
534  mpq_clear(m);
535  return (number)aa;
536}
537// cfClearContent
538// cfClearDenominators
539static number ConvFactoryNSingN( const CanonicalForm n, const coeffs r)
540{
541  WerrorS("not yet: ConvFactoryNSingN");
542}
543static CanonicalForm ConvSingNFactoryN( number n, BOOLEAN setChar, const coeffs r )
544{
545  WerrorS("not yet: ConvSingNFactoryN");
546}
547char * CoeffName(const coeffs r)
548{
549  return (char*)"flint:Q[a]";
550}
551static char* CoeffString(const coeffs r)
552{
553  return omStrDup(CoeffName(r));
554}
555#ifdef LDEBUG
556static BOOLEAN DBTest(number a, const char *f, const int l, const coeffs r)
557{
558  return TRUE;
559}
560#endif
561BOOLEAN flintQ_InitChar(coeffs cf, void * infoStruct)
562{
563  cf->cfCoeffString  = CoeffString;
564  cf->cfCoeffName    = CoeffName;
565  cf->cfCoeffWrite   = CoeffWrite;
566  cf->nCoeffIsEqual  = CoeffIsEqual;
567  cf->cfKillChar     = KillChar;
568  cf->cfSetChar      = SetChar;
569  cf->ch=0; //char 0
570  cf->cfMult         = Mult;
571  cf->cfSub          = Sub;
572  cf->cfAdd          = Add;
573  cf->cfDiv          = Div;
574  cf->cfExactDiv     = ExactDiv; // ???
575  cf->cfInit         =Init;
576  cf->cfInitMPZ      =InitMPZ;
577  cf->cfSize         = Size;
578  cf->cfInt          = Int;
579  cf->cfMPZ          = MPZ;
580  cf->cfInpNeg       = Neg;
581  cf->cfInvers       = Invers;
582  cf->cfCopy         = Copy;
583  cf->cfRePart       = Copy;
584  // default: cf->cfImPart       = ndReturn0;
585  cf->cfWriteLong    = WriteShort; //WriteLong;
586  cf->cfWriteShort = WriteShort;
587  cf->cfRead         = Read;
588  cf->cfNormalize    = Normalize;
589
590  //cf->cfDivComp=
591  //cf->cfIsUnit=
592  //cf->cfGetUnit=
593  //cf->cfDivBy=
594
595  cf->cfGreater=Greater;
596  cf->cfEqual  =Equal;
597  cf->cfIsZero =IsZero;
598  cf->cfIsOne  =IsOne;
599  cf->cfIsMOne =IsMOne;
600  cf->cfGreaterZero=GreaterZero;
601
602  cf->cfPower        = Power;
603  cf->cfGetDenom     = GetDenom;
604  cf->cfGetNumerator = GetNumerator;
605  cf->cfGcd          = Gcd;
606  cf->cfExtGcd         = ExtGcd;
607  cf->cfLcm          = Lcm;
608  cf->cfDelete       = Delete;
609  cf->cfSetMap       = SetMap;
610  // default: cf->cfInpMult
611  // default: cf->cfInpAdd
612  cf->cfFarey        =Farey;
613  cf->cfChineseRemainder=ChineseRemainder;
614  cf->cfParDeg = ParDeg;
615  cf->cfParameter = Parameter;
616  //  cf->cfClearContent = ClearContent;
617  //  cf->cfClearDenominators = ClearDenominators;
618  cf->convFactoryNSingN=ConvFactoryNSingN;
619  cf->convSingNFactoryN=ConvSingNFactoryN;
620  cf->cfWriteFd  = WriteFd;
621  cf->cfReadFd = ReadFd;
622#ifdef LDEBUG
623  cf->cfDBTest       = DBTest;
624#endif
625
626  cf->iNumberOfParameters = 1;
627  char **pn=(char**)omAlloc0(sizeof(char*));
628  pn[0]=(char*)omStrDup("a");
629  cf->pParameterNames = (const char **)pn;
630  cf->has_simple_Inverse= FALSE;
631  cf->has_simple_Alloc= FALSE;
632  cf->is_field=FALSE;
633
634  return FALSE;
635}
636#endif
637#endif
Note: See TracBrowser for help on using the repository browser.