source: git/Singular/mpr_complex.cc @ fdc537

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