source: git/libpolys/coeffs/gnumpc.cc @ 19ee5eb

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