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

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