source: git/Singular/mpr_complex.cc @ 97a7b44

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