source: git/libpolys/coeffs/gnumpc.cc @ d50995

spielwiese
Last change on this file since d50995 was d50995, checked in by Hans Schoenemann <hannes@…>, 9 years ago
warnings: fixed finvar.lib, rModifyRing, wrong assume in gnumpc.cc
  • Property mode set to 100644
File size: 15.9 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/*
5* ABSTRACT: computations with GMP complex floating-point numbers
6*
7* ngc == number gnu complex
8*/
9
10
11
12
13
14#include <omalloc/omalloc.h>
15
16#include <misc/auxiliary.h>
17#include <misc/mylimits.h>
18
19#include <reporter/reporter.h>
20
21#include <coeffs/coeffs.h>
22#include <coeffs/numbers.h>
23
24#include <coeffs/longrat.h>
25#include <coeffs/modulop.h>
26
27#include <coeffs/gnumpc.h>
28#include <coeffs/gnumpfl.h>
29#include <coeffs/shortfl.h>
30
31#include <coeffs/mpr_complex.h>
32
33
34/// Get a mapping function from src into the domain of this type: long_C!
35nMapFunc  ngcSetMap(const coeffs src, const coeffs dst);
36
37number ngcMapQ(number from, const coeffs r, const coeffs aRing);
38
39void ngcSetChar(const coeffs r);
40
41// Private interface should be hidden!!!
42
43/// Note: MAY NOT WORK AS EXPECTED!
44BOOLEAN  ngcGreaterZero(number za, const coeffs r);
45BOOLEAN  ngcGreater(number a, number b, const coeffs r);
46BOOLEAN  ngcEqual(number a, number b, const coeffs r);
47BOOLEAN  ngcIsOne(number a, const coeffs r);
48BOOLEAN  ngcIsMOne(number a, const coeffs r);
49BOOLEAN  ngcIsZero(number za, const coeffs r);
50number   ngcInit(long i, const coeffs r);
51int      ngcInt(number &n, const coeffs r);
52number   ngcNeg(number za, const coeffs r);
53number   ngcInvers(number a, const coeffs r);
54number   ngcParameter(int i, const coeffs r);
55number   ngcAdd(number la, number li, const coeffs r);
56number   ngcSub(number la, number li, const coeffs r);
57number   ngcMult(number a, number b, const coeffs r);
58number   ngcDiv(number a, number b, const coeffs r);
59void     ngcPower(number x, int exp, number *lu, const coeffs r);
60number   ngcCopy(number a, const coeffs r);
61number   ngc_Copy(number a, coeffs r);
62const char * ngcRead (const char *s, number *a, const coeffs r);
63void     ngcWrite(number &a, const coeffs r);
64number   ngcRePart(number a, const coeffs r);
65number   ngcImPart(number a, const coeffs r);
66
67void     ngcDelete(number *a, const coeffs r);
68void     ngcCoeffWrite(const coeffs r, BOOLEAN details);
69
70#ifdef LDEBUG
71BOOLEAN  ngcDBTest(number a, const char *f, const int l, const coeffs r);
72#endif
73
74
75// Why is this here? who needs it?
76// number ngcMapQ(number from, const coeffs r, const coeffs aRing);
77
78/// Our Type!
79static const n_coeffType ID = n_long_C;
80
81
82#ifdef LDEBUG
83// not yet implemented
84BOOLEAN ngcDBTest(number, const char *, const int, const coeffs r)
85{
86  assume( getCoeffType(r) == ID );
87
88  return TRUE;
89}
90#endif
91
92number   ngcParameter(int i, const coeffs r)
93{
94  assume( getCoeffType(r) == ID );
95  assume(i==1);
96
97  if( i == 1 )
98    return (number)(new gmp_complex( (long)0, (long)1 ));
99
100  return NULL; // new gmp_complex( )  // 0?
101}
102
103/*2
104* n := i
105*/
106number ngcInit (long i, const coeffs r)
107{
108  assume( getCoeffType(r) == ID );
109
110  gmp_complex* n= new gmp_complex( (long)i, (long)0 );
111
112  return (number)n;
113}
114
115/*2
116* convert number to int
117*/
118int ngcInt(number &i, const coeffs r)
119{
120  assume( getCoeffType(r) == ID );
121
122  return (int)((gmp_complex*)i)->real();
123}
124
125int ngcSize(number n, const coeffs R)
126{
127  int r = (int)((gmp_complex*)n)->real();
128  if (r < 0) r = -r;
129  int i = (int)((gmp_complex*)n)->imag();
130  if (i < 0) i = -i;
131  int oneNorm = r + i;
132  /* basically return the 1-norm of n;
133     only if this happens to be zero although n != 0,
134     return 1;
135     (this code ensures that zero has the size zero) */
136  if ((oneNorm == 0.0) & (ngcIsZero(n,R) == FALSE)) oneNorm = 1;
137  return oneNorm;
138}
139
140/*2
141* delete a
142*/
143void ngcDelete (number * a, const coeffs r)
144{
145  assume( getCoeffType(r) == ID );
146
147  if ( *a != NULL )
148  {
149    delete *(gmp_complex**)a;
150    *a=NULL;
151  }
152}
153
154/*2
155 * copy a to b
156*/
157number ngcCopy(number a, const coeffs r)
158{
159  assume( getCoeffType(r) == ID );
160
161  gmp_complex* b= new gmp_complex( *(gmp_complex*)a );
162  return (number)b;
163}
164
165
166/*2
167* za:= - za
168*/
169number ngcNeg (number a, const coeffs R)
170{
171  assume( getCoeffType(R) == ID );
172
173  gmp_complex* r=(gmp_complex*)a;
174  (*r).neg();
175  return (number)a;
176}
177
178/*
179* 1/a
180*/
181number ngcInvers(number a, const coeffs R)
182{
183  assume( getCoeffType(R) == ID );
184
185  gmp_complex* r = NULL;
186  if (((gmp_complex*)a)->isZero())
187  {
188    WerrorS(nDivBy0);
189  }
190  else
191  {
192    r = new gmp_complex( (gmp_complex)1 / (*(gmp_complex*)a) );
193  }
194  return (number)r;
195}
196
197/*2
198* u:= a + b
199*/
200number ngcAdd (number a, number b, const coeffs R)
201{
202  assume( getCoeffType(R) == ID );
203
204  gmp_complex* r= new gmp_complex( (*(gmp_complex*)a) + (*(gmp_complex*)b) );
205  return (number)r;
206}
207
208/*2
209* u:= a - b
210*/
211number ngcSub (number a, number b, const coeffs R)
212{
213  assume( getCoeffType(R) == ID );
214
215  gmp_complex* r= new gmp_complex( (*(gmp_complex*)a) - (*(gmp_complex*)b) );
216  return (number)r;
217}
218
219/*2
220* u := a * b
221*/
222number ngcMult (number a, number b, const coeffs R)
223{
224  assume( getCoeffType(R) == ID );
225
226  gmp_complex* r= new gmp_complex( (*(gmp_complex*)a) * (*(gmp_complex*)b) );
227  return (number)r;
228}
229
230/*2
231* u := a / b
232*/
233number ngcDiv (number a, number b, const coeffs r)
234{
235  assume( getCoeffType(r) == ID );
236
237  if (((gmp_complex*)b)->isZero())
238  {
239    // a/0 = error
240    WerrorS(nDivBy0);
241    return NULL;
242  }
243  gmp_complex* res = new gmp_complex( (*(gmp_complex*)a) / (*(gmp_complex*)b) );
244  return (number)res;
245}
246
247/*2
248* u:= x ^ exp
249*/
250void ngcPower ( number x, int exp, number * u, const coeffs r)
251{
252  assume( getCoeffType(r) == ID );
253
254  if ( exp == 0 )
255  {
256    gmp_complex* n = new gmp_complex(1);
257    *u=(number)n;
258    return;
259  }
260  else if ( exp == 1 )
261  {
262    n_New(u, r);
263    gmp_complex* n = new gmp_complex();
264    *n= *(gmp_complex*)x;
265    *u=(number)n;
266    return;
267  }
268  else if (exp == 2)
269  {
270    n_New(u, r);
271    gmp_complex* n = new gmp_complex();
272    *n= *(gmp_complex*)x;
273    *u=(number)n;
274    *(gmp_complex*)(*u) *= *(gmp_complex*)n;
275    return;
276  }
277  if ( (exp & 1) == 1 )
278  {
279    ngcPower(x,exp-1,u, r);
280    gmp_complex *n = new gmp_complex();
281    *n=*(gmp_complex*)x;
282    *(gmp_complex*)(*u) *= *(gmp_complex*)n;
283    delete n;
284  }
285  else
286  {
287    number w;
288    n_New(&w, r);
289    ngcPower(x,exp/2,&w, r);
290    ngcPower(w,2,u, r);
291    n_Delete(&w, r);
292  }
293}
294
295BOOLEAN ngcIsZero (number a, const coeffs r)
296{
297  assume( getCoeffType(r) == ID );
298
299  return ( ((gmp_complex*)a)->real().isZero() && ((gmp_complex*)a)->imag().isZero());
300}
301
302number ngcRePart(number a, const coeffs r)
303{
304  assume( getCoeffType(r) == ID );
305
306  gmp_complex* n = new gmp_complex(((gmp_complex*)a)->real());
307  return (number)n;
308}
309
310number ngcImPart(number a, const coeffs r)
311{
312  assume( getCoeffType(r) == ID );
313
314  gmp_complex* n = new gmp_complex(((gmp_complex*)a)->imag());
315  return (number)n;
316}
317
318/*2
319* za >= 0 ?
320*/
321BOOLEAN ngcGreaterZero (number a, const coeffs r)
322{
323  assume( getCoeffType(r) == ID );
324
325  if ( ! ((gmp_complex*)a)->imag().isZero() )
326    return ( abs( *(gmp_complex*)a).sign() >= 0 );
327  else
328    return ( ((gmp_complex*)a)->real().sign() >= 0 );
329}
330
331/*2
332* a > b ?
333*/
334BOOLEAN ngcGreater (number a, number b, const coeffs r)
335{
336  assume( getCoeffType(r) == ID );
337
338  gmp_complex *aa=(gmp_complex*)a;
339  gmp_complex *bb=(gmp_complex*)b;
340  return (*aa) > (*bb);
341}
342
343/*2
344* a = b ?
345*/
346BOOLEAN ngcEqual (number a, number b, const coeffs r)
347{
348  assume( getCoeffType(r) == ID );
349
350  gmp_complex *aa=(gmp_complex*)a;
351  gmp_complex *bb=(gmp_complex*)b;
352  return (*aa) == (*bb);
353}
354
355/*2
356* a == 1 ?
357*/
358BOOLEAN ngcIsOne (number a, const coeffs r)
359{
360  assume( getCoeffType(r) == ID );
361
362  return (((gmp_complex*)a)->real().isOne() && ((gmp_complex*)a)->imag().isZero());
363  //return (((gmp_complex*)a)->real().isOne());
364}
365
366/*2
367* a == -1 ?
368*/
369BOOLEAN ngcIsMOne (number a, const coeffs r)
370{
371  assume( getCoeffType(r) == ID );
372
373  return (((gmp_complex*)a)->real().isMOne() && ((gmp_complex*)a)->imag().isZero());
374  //return (((gmp_complex*)a)->real().isMOne());
375}
376
377/*2
378* extracts the number a from s, returns the rest
379*/
380const char * ngcRead (const char * s, number * a, const coeffs r)
381{
382  assume( getCoeffType(r) == ID );
383  const char * const complex_parameter = n_ParameterNames(r)[0];
384  assume( complex_parameter != NULL );
385  const int N = strlen(complex_parameter);
386
387  if ((*s >= '0') && (*s <= '9'))
388  {
389    gmp_float *re=NULL;
390    s=ngfRead(s,(number *)&re, r);
391    gmp_complex *aa=new gmp_complex(*re);
392    *a=(number)aa;
393    delete re;
394  }
395  else if (strncmp(s, complex_parameter, N)==0)
396  {
397    s += N;
398    gmp_complex *aa=new gmp_complex((long)0,(long)1);
399    *a=(number)aa;
400  }
401  else
402  {
403    *a=(number) new gmp_complex((long)1);
404  }
405  return s;
406}
407
408
409
410/*2
411* write a floating point number
412*/
413void ngcWrite (number &a, const coeffs r)
414{
415  assume( getCoeffType(r) == ID );
416
417  if (a==NULL)
418    StringAppendS("0");
419  else
420  {
421    char *out;
422    out= complexToStr(*(gmp_complex*)a, r->float_len, r);
423    StringAppendS(out);
424    //    omFreeSize((void *)out, (strlen(out)+1)* sizeof(char) );
425    omFree( (void *)out );
426  }
427}
428
429BOOLEAN ngcCoeffIsEqual (const coeffs r, n_coeffType n, void * parameter)
430{
431  if (n==ID)
432  {
433    LongComplexInfo* p = (LongComplexInfo *)(parameter);
434
435    if ((p==NULL)
436      && (6==r->float_len)
437      && (6==r->float_len2)
438      && (strcmp("i",n_ParameterNames(r)[0]) == 0)
439      )
440        return TRUE;
441    if ((p!=NULL) &&
442        (p->float_len == r->float_len) &&
443        (p->float_len2 == r->float_len2)
444       )
445      if (strcmp(p->par_name, n_ParameterNames(r)[0]) == 0)
446        return (TRUE);
447  }
448  return (FALSE);
449}
450
451static void ngcKillChar(coeffs r)
452{
453  char** p = (char**)n_ParameterNames(r);
454
455  const int P = n_NumberOfParameters(r);
456
457  for( int i = 1; i <= P; i++ )
458    if (p[i-1] != NULL)
459      omFree( (ADDRESS)p[i-1] );
460
461  omFreeSize((ADDRESS)p, P * sizeof(char*));
462}
463
464static char* ngcCoeffString(const coeffs r)
465{
466  const char *p=n_ParameterNames(r)[0];
467  char *s=(char*)omAlloc(31+strlen(p));
468  sprintf(s,"complex,%d,%d,%s",r->float_len,r->float_len2,p);
469  return s;
470}
471
472BOOLEAN ngcInitChar(coeffs n, void* parameter)
473{
474  assume( getCoeffType(n) == ID );
475  n->is_field=TRUE;
476  n->is_domain=TRUE;
477  n->rep=n_rep_gmp_complex;
478
479  n->cfKillChar = ngcKillChar;
480  n->ch = 0;
481  n->cfCoeffString=ngcCoeffString;
482
483  n->cfDelete  = ngcDelete;
484  //n->cfNormalize=ndNormalize;
485  n->cfInit   = ngcInit;
486  n->cfInt    = ngcInt;
487  n->cfAdd     = ngcAdd;
488  n->cfSub     = ngcSub;
489  n->cfMult    = ngcMult;
490  n->cfDiv     = ngcDiv;
491  n->cfExactDiv= ngcDiv;
492  n->cfInpNeg     = ngcNeg;
493  n->cfInvers  = ngcInvers;
494  n->cfCopy   = ngcCopy;
495  n->cfGreater = ngcGreater;
496  n->cfEqual   = ngcEqual;
497  n->cfIsZero  = ngcIsZero;
498  n->cfIsOne   = ngcIsOne;
499  n->cfIsMOne  = ngcIsMOne;
500  n->cfGreaterZero = ngcGreaterZero;
501
502  n->cfWriteLong  = ngcWrite;
503  n->cfWriteShort = ngcWrite;
504
505  n->cfRead    = ngcRead;
506  n->cfPower   = ngcPower;
507  n->cfSetMap = ngcSetMap;
508  n->cfRePart  = ngcRePart;
509  n->cfImPart  = ngcImPart;
510  n->cfCoeffWrite = ngcCoeffWrite;
511    // cfSize  = ndSize;
512#ifdef LDEBUG
513  //n->cfDBTest  = ndDBTest; // not yet implemented: ngcDBTest
514#endif
515
516  n->nCoeffIsEqual = ngcCoeffIsEqual;
517
518  n->cfSetChar=ngcSetChar;
519
520// we need to initialize n->nNULL at least for minpoly printing
521  n->nNULL  = n->cfInit(0,n);
522
523/*
524  //r->cfInitChar=nlInitChar;
525  r->cfKillChar=NULL;
526
527  r->cfMult  = nlMult;
528  r->cfSub   = nlSub;
529  r->cfAdd   = nlAdd;
530  r->cfDiv   = nlDiv;
531  r->cfIntMod= nlIntMod;
532  r->cfExactDiv= nlExactDiv;
533  r->cfInit = nlInit;
534  r->cfSize  = nlSize;
535  r->cfInt  = nlInt;
536#ifdef HAVE_RINGS
537  r->cfDivComp = NULL; // only for ring stuff
538  r->cfIsUnit = NULL; // only for ring stuff
539  r->cfGetUnit = NULL; // only for ring stuff
540  r->cfExtGcd = NULL; // only for ring stuff
541#endif
542  r->cfInpNeg   = nlNeg;
543  r->cfInvers= nlInvers;
544  r->cfCopy  = nl_Copy;
545  r->cfRePart = nl_Copy;
546  r->cfImPart = ndReturn0;
547  r->cfWriteLong = nlWrite;
548  r->cfRead = nlRead;
549  r->cfNormalize=nlNormalize;
550  r->cfGreater = nlGreater;
551#ifdef HAVE_RINGS
552  r->cfDivBy = NULL; // only for ring stuff
553#endif
554  r->cfEqual = nlEqual;
555  r->cfIsZero = nlIsZero;
556  r->cfIsOne = nlIsOne;
557  r->cfIsMOne = nlIsMOne;
558  r->cfGreaterZero = nlGreaterZero;
559  r->cfPower = nlPower;
560  r->cfGetDenom = nlGetDenom;
561  r->cfGetNumerator = nlGetNumerator;
562  r->cfGcd  = nlGcd;
563  r->cfLcm  = nlLcm;
564  r->cfDelete= nlDelete;
565  r->cfSetMap = nlSetMap;
566  r->cfName = ndName;
567  r->cfInpMult=nlInpMult;
568  r->cfInit_bigint=nlCopyMap;
569#ifdef LDEBUG
570  // debug stuff
571  r->cfDBTest=nlDBTest;
572#endif
573
574  // the variables:
575  r->nNULL = INT_TO_SR(0);
576  r->type = n_Q;
577  r->ch = 0;
578  r->has_simple_Alloc=FALSE;
579  r->has_simple_Inverse=FALSE;
580*/
581
582  n->iNumberOfParameters = 1;
583  n->cfParameter = ngcParameter;
584
585  char ** pParameterNames = (char **) omAlloc0(sizeof(char *));
586
587  if( parameter != NULL)
588  {
589    LongComplexInfo* p = (LongComplexInfo*)parameter;
590    pParameterNames[0] = omStrDup(p->par_name);
591    // fix wrong parameters:
592    if (p->float_len<SHORT_REAL_LENGTH) p->float_len=SHORT_REAL_LENGTH;
593    n->float_len = p->float_len;
594    n->float_len2 = p->float_len2;
595
596  } else // default values, just for testing!
597  {
598    pParameterNames[0] = omStrDup("i");
599    n->float_len = SHORT_REAL_LENGTH;
600    n->float_len2 = SHORT_REAL_LENGTH;
601  }
602
603  assume( pParameterNames != NULL );
604  assume( pParameterNames[0] != NULL );
605
606  n->pParameterNames = (const char**)pParameterNames;
607
608  // NOTE: n->complex_parameter was replaced by n_ParameterNames(n)[0]
609  // TODO: nfKillChar MUST destroy n->pParameterNames[0] (0-term. string) && n->pParameterNames (array of size 1)
610
611  return FALSE;
612}
613
614void ngcSetChar(const coeffs r)
615{
616  setGMPFloatDigits(r->float_len, r->float_len2);
617}
618
619
620
621number ngcMapQ(number from, const coeffs aRing, const coeffs r)
622{
623  assume( getCoeffType(r) == ID );
624  assume( aRing->rep == n_rep_gap_rat);
625
626  if ( from != NULL )
627  {
628    gmp_complex *res=new gmp_complex(numberFieldToFloat(from,QTOF,aRing));
629    return (number)res;
630  }
631  else
632    return NULL;
633}
634
635number ngcMapZ(number from, const coeffs aRing, const coeffs r)
636{
637  assume( getCoeffType(r) == ID );
638  assume( aRing->rep == n_rep_gap_gmp);
639
640  if ( from != NULL )
641  {
642    if (SR_HDL(from) & SR_INT)
643    {
644      gmp_float f_i= gmp_float(SR_TO_INT(from));
645      gmp_complex *res=new gmp_complex(f_i);
646      return (number)res;
647    }
648    gmp_float f_i=(mpz_ptr)from;
649    gmp_complex *res=new gmp_complex(f_i);
650    return (number)res;
651  }
652  else
653    return NULL;
654}
655
656static number ngcMapLongR(number from, const coeffs aRing, const coeffs r)
657{
658  assume( getCoeffType(r) == ID );
659  assume( getCoeffType(aRing) == n_long_R );
660
661  if ( from != NULL )
662  {
663    gmp_complex *res=new gmp_complex(*((gmp_float *)from));
664    return (number)res;
665  }
666  else
667    return NULL;
668}
669
670static number ngcMapR(number from, const coeffs aRing, const coeffs r)
671{
672  assume( getCoeffType(r) == ID );
673  assume( getCoeffType(aRing) == n_R );
674
675  if ( from != NULL )
676  {
677    gmp_complex *res=new gmp_complex((double)nrFloat(from));
678    return (number)res;
679  }
680  else
681    return NULL;
682}
683
684static number ngcMapP(number from, const coeffs aRing, const coeffs r)
685{
686  assume( getCoeffType(r) == ID );
687  assume( getCoeffType(aRing) ==  n_Zp );
688
689  if ( from != NULL )
690    return ngcInit(npInt(from, aRing), r);
691  else
692    return NULL;
693}
694
695static number ngcCopyMap(number from, const coeffs aRing, const coeffs r)
696{
697  assume( getCoeffType(r) == ID );
698  assume( getCoeffType(aRing) ==  ID );
699
700  gmp_complex* b = NULL;
701
702  if ( from !=  NULL )
703  {
704    b = new gmp_complex( *(gmp_complex*)from );
705  }
706  return (number)b;
707}
708
709nMapFunc ngcSetMap(const coeffs src, const coeffs dst)
710{
711  assume( getCoeffType(dst) == ID );
712
713  if (src->rep==n_rep_gap_rat) /* Q, Z*/
714  {
715    return ngcMapQ;
716  }
717  if (src->rep==n_rep_gap_gmp) /* Z */
718  {
719    return ngcMapZ;
720  }
721  if ((src->rep==n_rep_gmp_float) && nCoeff_is_long_R(src))
722  {
723    return ngcMapLongR;
724  }
725  if ((src->rep==n_rep_gmp_complex) && nCoeff_is_long_C(src))
726  {
727    return ngcCopyMap;
728  }
729  if ((src->rep==n_rep_float) && nCoeff_is_R(src))
730  {
731    return ngcMapR;
732  }
733  if ((src->rep==n_rep_int) && nCoeff_is_Zp(src))
734  {
735    return ngcMapP;
736  }
737  return NULL;
738}
739
740void    ngcCoeffWrite  (const coeffs r, BOOLEAN /*details*/)
741{
742  Print("//   characteristic : 0 (complex:%d digits, additional %d digits)\n",
743        r->float_len, r->float_len2);  /* long C */
744  Print("//   1 parameter    : %s \n", n_ParameterNames(r)[0]); // this trailing space is for compatibility with the legacy Singular
745  Print("//   minpoly        : (%s^2+1)\n", n_ParameterNames(r)[0]);
746}
Note: See TracBrowser for help on using the repository browser.