source: git/kernel/mpr_complex.cc @ 8c5988

spielwiese
Last change on this file since 8c5988 was 88d2e5, checked in by Hans Schönemann <hannes@…>, 19 years ago
*hannes: memeory leak... git-svn-id: file:///usr/local/Singular/svn/trunk@7699 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 15.7 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: mpr_complex.cc,v 1.2 2005-02-03 16:43:37 Singular Exp $ */
5
6/*
7* ABSTRACT - multipolynomial resultants - real floating-point numbers using gmp
8*            and complex numbers based on pairs of real floating-point numbers
9*
10*/
11
12// WARNING! ALWAYS use omAlloc and FreeL when alloc. memory for some char* !!
13
14#include "mod2.h"
15//#ifdef HAVE_MPR
16#include "structs.h"
17#include "febase.h"
18#include "omalloc.h"
19#include "numbers.h"
20#include "longrat.h"
21#include <math.h>
22#include "mpr_complex.h"
23
24//%s
25// this was copied form longrat0.cc
26// and will be used in numberToFloat.
27// Make sure that it is up to date!!
28#define SR_HDL(A) ((long)(A))
29#define SR_INT    1
30#define SR_TO_INT(SR) (((long)SR) >> 2)
31
32#define SIGN_PLUS  1
33#define SIGN_SPACE 2
34#define SIGN_EMPTY 4
35
36#define EXTRABYTES 4
37
38#define DEFPREC        20         // minimum number of digits (output operations)
39size_t gmp_output_digits= DEFPREC;
40
41extern int mmInit(void);
42int dummy=mmInit();
43static gmp_float gmpRel(0.0);
44static gmp_float diff(0.0);
45
46
47/** Set size of mantissa
48 *  digits - the number of output digits (basis 10)
49 *  the size of mantissa consists of two parts:
50 *    the "output" part a and the "rest" part b.
51 *  According to the GMP-precision digits is
52 *  recomputed to bits (basis 2).
53 *  Two numbers a, b are equal if
54 *    | a - b | < | a | * 0.1^digits .
55 *  In this case we have a - b = 0 .
56 *  The epsilon e is e=0.1^(digits+rest) with
57 *  1+e != 1, but 1+0.1*e = 1.
58 */
59void setGMPFloatDigits( size_t digits, size_t rest )
60{
61  size_t bits = 1 + (size_t) ((float)digits * 3.5);
62  size_t rb = 1 + (size_t) ((float)rest * 3.5);
63  size_t db = bits+rb;
64  gmp_output_digits= digits;
65  mpf_set_default_prec( db );
66  mpf_set_prec(*diff._mpfp(),32);
67  mpf_set_prec(*gmpRel._mpfp(),32);
68  mpf_set_d(*gmpRel._mpfp(),0.1);
69  mpf_pow_ui(*gmpRel._mpfp(),*gmpRel._mpfp(),digits);
70}
71
72size_t getGMPFloatDigits()
73{
74  return gmp_output_digits;
75}
76
77void gmp_float::setFromStr( char * in )
78{
79  // gmp doesn't understand number which begin with "." -- it needs 0.
80  // so, insert the zero
81  if (*in == '.')
82  {
83    int len = strlen(in)+2;
84    char* c_in = (char*) omAlloc(len);
85    *c_in = '0';
86    strcpy(&(c_in[1]), in);
87
88    mpf_set_str( t, c_in, 10 );
89    omFreeSize((void*)c_in, len);
90  }
91  else
92  {
93    mpf_set_str( t, in, 10 );
94  }
95}
96
97
98// <gmp_float> = <gmp_float> operator <gmp_float>
99gmp_float operator + ( const gmp_float & a, const gmp_float & b )
100{
101  gmp_float tmp( a );
102  tmp += b;
103  return tmp;
104}
105gmp_float operator - ( const gmp_float & a, const gmp_float & b )
106{
107  gmp_float tmp( a );
108  tmp -= b;
109  return tmp;
110}
111gmp_float operator * ( const gmp_float & a, const gmp_float & b )
112{
113  gmp_float tmp( a );
114  tmp *= b;
115  return tmp;
116}
117gmp_float operator / ( const gmp_float & a, const gmp_float & b )
118{
119  gmp_float tmp( a );
120  tmp /= b;
121  return tmp;
122}
123
124// <gmp_float> operator <gmp_float>
125gmp_float & gmp_float::operator += ( const gmp_float & a )
126{
127  if (mpf_sgn(t) != -(mpf_sgn(a.t)))
128  {
129    mpf_add( t, t, a.t);
130    return *this;
131  }
132  if((mpf_sgn(a.t)==0) && (mpf_sgn(t)==0))
133  {
134    mpf_set_d( t, 0.0);
135    return *this;
136  }
137  mpf_add( t, t, a.t );
138  mpf_set(diff.t, t);
139  mpf_set_prec(diff.t, 32);
140  mpf_div(diff.t, diff.t, a.t);
141  mpf_abs(diff.t, diff.t);
142  if(mpf_cmp(diff.t, gmpRel.t) < 0)
143    mpf_set_d( t, 0.0);
144  return *this;
145}
146gmp_float & gmp_float::operator -= ( const gmp_float & a )
147{
148  if (mpf_sgn(t) != mpf_sgn(a.t))
149  {
150    mpf_sub( t, t, a.t);
151    return *this;
152  }
153  if((mpf_sgn(a.t)==0) && (mpf_sgn(t)==0))
154  {
155    mpf_set_d( t, 0.0);
156    return *this;
157  }
158  mpf_sub( t, t, a.t );
159  mpf_set(diff.t, t);
160  mpf_set_prec(diff.t, 32);
161  mpf_div(diff.t, diff.t, a.t);
162  mpf_abs(diff.t, diff.t);
163  if(mpf_cmp(diff.t, gmpRel.t) < 0)
164    mpf_set_d( t, 0.0);
165  return *this;
166}
167
168// <gmp_float> == <gmp_float> ??
169bool operator == ( const gmp_float & a, const gmp_float & b )
170{
171  if(mpf_sgn(a.t) != mpf_sgn(b.t))
172    return false;
173  if((mpf_sgn(a.t)==0) && (mpf_sgn(b.t)==0))
174    return true;
175  mpf_sub(diff.t, a.t, b.t);
176  mpf_div(diff.t, diff.t, a.t);
177  mpf_abs(diff.t, diff.t);
178  if(mpf_cmp(diff.t, gmpRel.t) < 0)
179    return true;
180  else
181    return false;
182}
183// t == 0 ?
184bool gmp_float::isZero()
185{
186  return (mpf_sgn( t ) == 0);
187}
188// t == 1 ?
189bool gmp_float::isOne()
190{
191#ifdef  VARIANTE_1
192  return (mpf_cmp_ui( t , 1 ) == 0);
193#else
194  if (mpf_sgn(t) <= 0)
195    return false;
196  mpf_sub_ui(diff.t, t, 1);
197  mpf_abs(diff.t, diff.t);
198  if(mpf_cmp(diff.t, gmpRel.t) < 0)
199    return true;
200  else
201    return false;
202#endif
203}
204// t == -1 ?
205bool gmp_float::isMOne()
206{
207#ifdef VARIANTE_1
208  return (mpf_cmp_si( t , -1 ) == 0);
209#else
210  if (mpf_sgn(t) >= 0)
211    return false;
212  mpf_add_ui(diff.t, t, 1);
213  mpf_abs(diff.t, diff.t);
214  if(mpf_cmp(diff.t, gmpRel.t) < 0)
215    return true;
216  else
217    return false;
218#endif
219}
220bool operator > ( const gmp_float & a, const gmp_float & b )
221{
222  if (a.t == b.t)
223    return false;
224  return mpf_cmp( a.t, b.t ) > 0;
225}
226bool operator < ( const gmp_float & a, const gmp_float & b )
227{
228  if (a.t == b.t)
229    return false;
230  return mpf_cmp( a.t, b.t ) < 0;
231}
232bool operator >= ( const gmp_float & a, const gmp_float & b )
233{
234  if (a.t == b.t)
235    return true;
236  return mpf_cmp( a.t, b.t ) >= 0;
237}
238bool operator <= ( const gmp_float & a, const gmp_float & b )
239{
240  if (a.t == b.t)
241    return true;
242  return mpf_cmp( a.t, b.t ) <= 0;
243}
244
245// unary -
246gmp_float operator - ( const gmp_float & a )
247{
248  gmp_float tmp;
249  mpf_neg( *(tmp._mpfp()), *(a.mpfp()) );
250  return tmp;
251}
252
253gmp_float abs( const gmp_float & a )
254{
255  gmp_float tmp;
256  mpf_abs( *(tmp._mpfp()), *a.mpfp() );
257  return tmp;
258}
259gmp_float sqrt( const gmp_float & a )
260{
261  gmp_float tmp;
262  mpf_sqrt( *(tmp._mpfp()), *a.mpfp() );
263  return tmp;
264}
265gmp_float sin( const gmp_float & a )
266{
267  gmp_float tmp( sin((double)a) );
268  return tmp;
269}
270gmp_float cos( const gmp_float & a )
271{
272  gmp_float tmp( cos((double)a) );
273  return tmp;
274}
275gmp_float log( const gmp_float & a )
276{
277  gmp_float tmp( log((double)a) );
278  return tmp;
279}
280gmp_float hypot( const gmp_float & a, const gmp_float & b )
281{
282#if 1
283  return ( sqrt( (a*a) + (b*b) ) );
284#else
285  gmp_float tmp( hypot( (double)a, (double)b ) );
286  return tmp;
287#endif
288}
289gmp_float exp( const gmp_float & a )
290{
291  gmp_float tmp( exp((double)a) );
292  return tmp;
293}
294gmp_float max( const gmp_float & a, const gmp_float & b )
295{
296  gmp_float tmp;
297  a > b ? tmp= a : tmp= b;
298  return tmp;
299}
300//
301// number to float, number = Q, R, C
302// makes a COPY of num! (Ist das gut?)
303//
304gmp_float numberToFloat( number num )
305{
306  gmp_float r;
307
308  if ( rField_is_Q() )
309  {
310    if ( num != NULL )
311    {
312      if (SR_HDL(num) & SR_INT)
313      {
314        r= SR_TO_INT(num);
315      }
316      else
317      {
318        if ( num->s == 0 )
319        {
320          nlNormalize( num );
321        }
322        if (SR_HDL(num) & SR_INT)
323        {
324          r= SR_TO_INT(num);
325        }
326        else
327        {
328          if ( num->s != 3 )
329          {
330            r= &num->z;
331            r/= (gmp_float)&num->n;
332          }
333          else
334          {
335            r= &num->z;
336          }
337        }
338      }
339    }
340    else
341    {
342      r= 0.0;
343    }
344  }
345  else if (rField_is_long_R() || rField_is_long_C())
346  {
347    r= *(gmp_float*)num;
348  }
349  else if ( rField_is_R() )
350  {
351    // Add some code here :-)
352    WerrorS("Ground field not implemented!");
353  }
354  else
355  {
356    WerrorS("Ground field not implemented!");
357  }
358
359  return r;
360}
361
362gmp_float numberFieldToFloat( number num, int k )
363{
364  gmp_float r;
365
366  switch (k)
367  {
368  case QTOF:
369    if ( num != NULL )
370    {
371      if (SR_HDL(num) & SR_INT)
372      {
373        r= SR_TO_INT(num);
374      }
375      else
376      {
377        if ( num->s == 0 )
378        {
379          nlNormalize( num );
380        }
381        if (SR_HDL(num) & SR_INT)
382        {
383          r= SR_TO_INT(num);
384        }
385        else
386        {
387          if ( num->s != 3 )
388          {
389            r= &num->z;
390            r/= (gmp_float)&num->n;
391          }
392          else
393          {
394            r= &num->z;
395          }
396        }
397      }
398    }
399    else
400    {
401      r= 0.0;
402    }
403    break;
404  case RTOF:
405    r= *(gmp_float*)num;
406    break;
407  case CTOF:
408    WerrorS("Can not map from field C to field R!");
409    break;
410  case ZTOF:
411  default:
412    WerrorS("Ground field not implemented!");
413  } // switch
414
415  return r;
416}
417
418// Do some strange things with the mantissa string and the exponent
419// to get some nice output string.
420char *nicifyFloatStr( char * in, mp_exp_t exponent, size_t oprec, int *size, int thesign )
421{
422  char *out;
423
424  int sign= (in[0] == '-') ? 1 : 0;
425  char csign[2];
426
427  switch (thesign)
428  {
429    case SIGN_PLUS:
430      sign ? strcpy(csign,"-") : strcpy(csign,"+");  //+123, -123
431      break;
432    case SIGN_SPACE:
433      sign ? strcpy(csign,"-") : strcpy(csign," ");  // 123, -123
434      break;
435    case SIGN_EMPTY:
436    default:
437      sign ? strcpy(csign,"-") : strcpy(csign,"");   //123, -123
438      break;
439  }
440
441  if ( strlen(in) == 0 )
442  {
443    *size= 2*sizeof(char);
444    return omStrDup("0");
445  }
446
447  if ( ((unsigned int)ABS(exponent) <= oprec)
448       /*|| (exponent+sign >= (int)strlen(in))*/ )
449  {
450    if ( exponent+sign < (int)strlen(in) )
451    {
452      int eexponent= (exponent >= 0) ? 0 : -exponent;
453      int eeexponent= (exponent >= 0) ? exponent : 0;
454      *size= (strlen(in)+15+eexponent) * sizeof(char);
455      out= (char*)omAlloc(*size);
456      memset(out,0,*size);
457
458      strcpy(out,csign);
459      strncat(out,in+sign,eeexponent);
460
461      if (exponent == 0)
462        strcat(out,"0.");
463      else if ( exponent > 0 )
464        strcat(out,".");
465      else
466      {
467        strcat(out,"0.");
468        memset(out+strlen(out),'0',eexponent);
469      }
470      strcat(out,in+sign+eeexponent);
471    }
472    else if ( exponent+sign > (int)strlen(in) )
473    {
474      *size= (strlen(in)+exponent+12)*sizeof(char);
475      out= (char*)omAlloc(*size);
476      memset(out,0,*size);
477      sprintf(out,"%s%s",csign,in+sign);
478      memset(out+strlen(out),'0',exponent-strlen(in)+sign);
479    }
480    else
481    {
482      *size= (strlen(in)+2) * sizeof(char) + 10;
483      out= (char*)omAlloc(*size);
484      memset(out,0,*size);
485      sprintf(out,"%s%s",csign,in+sign);
486    }
487  }
488  else
489  {
490//      if ( exponent > 0 )
491//      {
492      int c=1,d=10;
493      while ( exponent / d > 0 )
494      { // count digits
495        d*=10;
496        c++;
497      }
498      *size= (strlen(in)+12+c) * sizeof(char) + 10;
499      out= (char*)omAlloc(*size);
500      memset(out,0,*size);
501      sprintf(out,"%s0.%se%s%d",csign,in+sign,exponent>=0?"+":"",(int)exponent);
502//      }
503//      else
504//      {
505//        *size=2;
506//        out= (char*)omAlloc(*size);
507//        strcpy(out,"0");
508//      }
509  }
510  return out;
511}
512
513char *floatToStr( const gmp_float & r, const unsigned int oprec )
514{
515#if 1
516  mp_exp_t exponent;
517  int size,insize;
518  char *nout,*out,*in;
519
520  insize= (oprec+2) * sizeof(char) + 10;
521  in= (char*)omAlloc( insize );
522
523  mpf_get_str(in,&exponent,10,oprec,*(r.mpfp()));
524
525  if ( (exponent > 0)
526  && (exponent < (int)oprec)
527  && (strlen(in)-(in[0]=='-'?1:0) == oprec) )
528  {
529    omFree( (ADDRESS) in );
530    insize= (exponent+oprec+2) * sizeof(char) + 10;
531    in= (char*)omAlloc( insize );
532    int newprec= exponent+oprec;
533    mpf_get_str(in,&exponent,10,newprec,*(r.mpfp()));
534  }
535  nout= nicifyFloatStr( in, exponent, oprec, &size, SIGN_EMPTY );
536  omFree( (ADDRESS) in );
537  out= (char*)omAlloc( (strlen(nout)+1) * sizeof(char) );
538  strcpy( out, nout );
539  omFree( (ADDRESS) nout );
540
541  return out;
542#else
543  // for testing purpose...
544  char *out= (char*)omAlloc( (1024) * sizeof(char) );
545  sprintf(out,"% .10f",(double)r);
546  return out;
547#endif
548}
549//<-
550
551//-> gmp_complex::*
552// <gmp_complex> = <gmp_complex> operator <gmp_complex>
553//
554gmp_complex operator + ( const gmp_complex & a, const gmp_complex & b )
555{
556  return gmp_complex( a.r + b.r, a.i + b.i );
557}
558gmp_complex operator - ( const gmp_complex & a, const gmp_complex & b )
559{
560  return gmp_complex( a.r - b.r, a.i - b.i );
561}
562gmp_complex operator * ( const gmp_complex & a, const gmp_complex & b )
563{
564  return gmp_complex( a.r * b.r - a.i * b.i,
565                  a.r * b.i + a.i * b.r);
566}
567gmp_complex operator / ( const gmp_complex & a, const gmp_complex & b )
568{
569  gmp_float d = b.r*b.r + b.i*b.i;
570  return gmp_complex( (a.r * b.r + a.i * b.i) / d,
571                (a.i * b.r - a.r * b.i) / d);
572}
573
574// <gmp_complex> operator <gmp_complex>
575//
576gmp_complex & gmp_complex::operator += ( const gmp_complex & b )
577{
578  r+=b.r;
579  i+=b.i;
580  return *this;
581}
582gmp_complex & gmp_complex::operator -= ( const gmp_complex & b )
583{
584  r-=b.r;
585  i-=b.i;
586  return *this;
587}
588gmp_complex & gmp_complex::operator *= ( const gmp_complex & b )
589{
590  gmp_float f = r * b.r - i * b.i;
591  i = r * b.i + i * b.r;
592  r = f;
593  return *this;
594}
595gmp_complex & gmp_complex::operator /= ( const gmp_complex & b )
596{
597  gmp_float d = b.r*b.r + b.i*b.i;
598  r = (r * b.r + i * b.i) / d;
599  i = (i * b.r - r * b.i) / d;
600  return *this;
601}
602
603// Returns square root of gmp_complex number
604//
605gmp_complex sqrt( const gmp_complex & x )
606{
607  gmp_float r = abs(x);
608  gmp_float nr, ni;
609  if (r == (gmp_float) 0.0)
610  {
611    nr = ni = r;
612  }
613  else if ( x.real() > (gmp_float)0)
614  {
615    nr = sqrt((gmp_float)0.5 * (r + x.real()));
616    ni = x.imag() / nr / (gmp_float)2;
617  }
618  else
619  {
620    ni = sqrt((gmp_float)0.5 * (r - x.real()));
621    if (x.imag() < (gmp_float)0)
622    {
623      ni = - ni;
624    }
625    nr = x.imag() / ni / (gmp_float)2;
626  }
627  gmp_complex tmp(nr, ni);
628  return tmp;
629}
630
631// converts a gmp_complex to a string ( <real part> + I * <imaginary part> )
632//
633char *complexToStr( gmp_complex & c, const unsigned int oprec )
634{
635  char *out,*in_imag,*in_real;
636
637  c.SmallToZero();
638  if ( !c.imag().isZero() )
639  {
640
641    in_real=floatToStr( c.real(), oprec );         // get real part
642    in_imag=floatToStr( abs(c.imag()), oprec );    // get imaginary part
643
644    if (rField_is_long_C())
645    {
646      int len=(strlen(in_real)+strlen(in_imag)+7+strlen(currRing->parameter[0]))*sizeof(char);
647      out=(char*)omAlloc(len);
648      memset(out,0,len);
649      if (  !c.real().isZero() )  // (-23-i*5.43) or (15.1+i*5.3)
650        sprintf(out,"(%s%s%s*%s)",in_real,c.imag().sign()>=0?"+":"-",currRing->parameter[0],in_imag);
651      else // (-i*43) or (i*34)
652      {
653        if (c.imag().isOne())
654          sprintf(out,currRing->parameter[0]);
655        else if (c.imag().isMOne())
656          sprintf(out,"-%s",currRing->parameter[0]);
657        else
658          sprintf(out,"(%s%s*%s)",c.imag().sign()>=0?"":"-",currRing->parameter[0],in_imag);
659      }
660    }
661    else
662    {
663      int len=(strlen(in_real)+strlen(in_imag)+9) * sizeof(char);
664      out=(char*)omAlloc( len );
665      memset(out,0,len);
666      if ( !c.real().isZero() )
667        sprintf(out,"(%s%s%s)",in_real,c.imag().sign()>=0?"+I*":"-I*",in_imag);
668      else
669        sprintf(out,"(%s%s)",c.imag().sign()>=0?"I*":"-I*",in_imag);
670    }
671    omFree( (ADDRESS) in_real );
672    omFree( (ADDRESS) in_imag );
673  }
674  else
675  {
676    out= floatToStr( c.real(), oprec );
677  }
678
679  return out;
680}
681//<-
682
683bool complexNearZero( gmp_complex * c, int digits )
684{
685  gmp_float eps,epsm;
686
687  if ( digits < 1 ) return true;
688
689  eps=pow(10.0,(int)digits);
690  //Print("eps: %s\n",floatToStr(eps,gmp_output_digits));
691  eps=(gmp_float)1.0/eps;
692  epsm=-eps;
693
694  //Print("eps: %s\n",floatToStr(eps,gmp_output_digits));
695
696  if ( c->real().sign() > 0 ) // +
697    return (c->real() < eps && (c->imag() < eps && c->imag() > epsm));
698  else // -
699    return (c->real() > epsm && (c->imag() < eps && c->imag() > epsm));
700}
701
702void gmp_complex::SmallToZero()
703{
704  gmp_float ar=this->real();
705  gmp_float ai=this->imag();
706  if (ar.isZero() || ai.isZero()) return;
707  mpf_abs(*ar._mpfp(), *ar._mpfp());
708  mpf_abs(*ai._mpfp(), *ai._mpfp());
709  mpf_set_prec(*ar._mpfp(), 32);
710  mpf_set_prec(*ai._mpfp(), 32);
711  if (ar > ai)
712  {
713    mpf_div(*ai._mpfp(), *ai._mpfp(), *ar._mpfp());
714    if (ai < gmpRel) this->imag(0.0);
715  }
716  else
717  {
718    mpf_div(*ar._mpfp(), *ar._mpfp(), *ai._mpfp());
719    if (ar < gmpRel) this->real(0.0);
720  }
721}
722
723//%e
724
725//#endif // HAVE_MPR
726
727// local Variables: ***
728// folded-file: t ***
729// compile-command-1: "make installg" ***
730// compile-command-2: "make install" ***
731// End: ***
Note: See TracBrowser for help on using the repository browser.