source: git/libpolys/coeffs/gnumpc.cc @ 131ab78

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