source: git/Singular/mpr_complex.cc @ bad404

spielwiese
Last change on this file since bad404 was bad404, checked in by Moritz Wenk <wenk@…>, 25 years ago
* wenk: changed ngcGreaterZero git-svn-id: file:///usr/local/Singular/svn/trunk@3227 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 12.7 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: mpr_complex.cc,v 1.12 1999-07-02 16:43:19 wenk 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 "structs.h"
17#include "febase.h"
18#include "mmemory.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
38size_t gmp_output_digits= DEFPREC;
39
40//-> setGMPFloat*
41/** Set size of mantissa to <bytes> bytes and guess the number of
42 * output digits.
43 *
44 * Set internal gmp floating point precision to (bytes+EXTRABYTES)*8 bits and
45 * set external precision (i.e. any number smaller than this is treated as ZERO)
46 * to bytes*8 bits.
47 * The precision in bytes is the size of the mantissa!
48 * Guesses the number of digits <-> precision
49 */
50void setGMPFloatPrecBytes( unsigned long int bytes )
51{
52  unsigned long int bits= bytes * 8;
53  gmp_float::setPrecision( (bytes+EXTRABYTES)*8 );
54  gmp_float::setEqualBits( bits );
55  // guess the maximal number of digits for this precision
56  gmp_output_digits=  -10 + (size_t)
57    ( (((bits>64?bits:64)+2*mp_bits_per_limb-1)/mp_bits_per_limb)
58      * mp_bits_per_limb * (log(2)/log(10)));
59}
60
61unsigned long int getGMPFloatPrecBytes()
62{
63  return gmp_float::getEqualBits()/8;
64}
65
66// Sets the lenght of the mantissa to <digits> digits
67void setGMPFloatDigits( size_t digits )
68{
69  size_t bits= 1 + (size_t) (digits / (log(2)/log(10)));
70  bits= bits>64?bits:64;
71  //  gmp_float::setPrecision( bits+EXTRABYTES*8 );
72  gmp_float::setPrecision( bits+(bits/2) );
73  gmp_float::setEqualBits( bits );
74  gmp_output_digits= digits;
75}
76
77size_t getGMPFloatDigits()
78{
79  return gmp_output_digits;
80}
81//<-
82
83//-> gmp_float::*
84unsigned long int gmp_float::gmp_default_prec_bits= GMP_DEFAULT_PREC_BITS;
85unsigned long int gmp_float::gmp_needequal_bits= GMP_NEEDEQUAL_BITS;
86
87// <gmp_float> = <gmp_float> operator <gmp_float>
88gmp_float operator + ( const gmp_float & a, const gmp_float & b )
89{
90  gmp_float tmp( a );
91  tmp += b;
92  return tmp;
93}
94gmp_float operator - ( const gmp_float & a, const gmp_float & b )
95{
96  gmp_float tmp( a );
97  tmp -= b;
98  return tmp;
99}
100gmp_float operator * ( const gmp_float & a, const gmp_float & b )
101{
102  gmp_float tmp( a );
103  tmp *= b;
104  return tmp;
105}
106gmp_float operator / ( const gmp_float & a, const gmp_float & b )
107{
108  gmp_float tmp( a );
109  tmp /= b;
110  return tmp;
111}
112
113// <gmp_float> == <gmp_float> ?? up to the first gmp_float::gmp_needequal_bits bits
114bool operator == ( const gmp_float & a, const gmp_float & b )
115{
116  //return mpf_cmp( a.t, b.t ) == 0;
117  return mpf_eq( a.t , b.t , gmp_float::gmp_needequal_bits );
118}
119bool operator > ( const gmp_float & a, const gmp_float & b )
120{
121  return mpf_cmp( a.t, b.t ) > 0;
122}
123bool operator < ( const gmp_float & a, const gmp_float & b )
124{
125  return mpf_cmp( a.t, b.t ) < 0;
126}
127bool operator >= ( const gmp_float & a, const gmp_float & b )
128{
129  return mpf_cmp( a.t, b.t ) >= 0;
130}
131bool operator <= ( const gmp_float & a, const gmp_float & b )
132{
133  return mpf_cmp( a.t, b.t ) <= 0;
134}
135
136// unary -
137gmp_float operator - ( const gmp_float & a )
138{
139  gmp_float tmp;
140  mpf_neg( *(tmp.mpfp()), *(a.mpfp()) );
141  return tmp;
142}
143
144gmp_float abs( const gmp_float & a )
145{
146  gmp_float *tmp= new gmp_float();
147  mpf_abs( *tmp->mpfp(), *a.mpfp() );
148  return *tmp;
149}
150gmp_float sqrt( const gmp_float & a )
151{
152  gmp_float *tmp= new gmp_float();
153  mpf_sqrt( *tmp->mpfp(), *a.mpfp() );
154  return *tmp;
155}
156gmp_float sin( const gmp_float & a )
157{
158  gmp_float *tmp= new gmp_float( sin((double)a) );
159  return *tmp;
160}
161gmp_float cos( const gmp_float & a )
162{
163  gmp_float *tmp= new gmp_float( cos((double)a) );
164  return *tmp;
165}
166gmp_float log( const gmp_float & a )
167{
168  gmp_float *tmp= new gmp_float( log((double)a) );
169  return *tmp;
170}
171gmp_float hypot( const gmp_float & a, const gmp_float & b )
172{
173#if 1
174  gmp_float *tmp= new gmp_float();
175  *tmp= sqrt( (a*a) + (b*b) );
176  return *tmp;
177#else
178  gmp_float *tmp= new gmp_float( hypot( (double)a, (double)b ) );
179  return *tmp;
180#endif
181}
182gmp_float exp( const gmp_float & a )
183{
184  gmp_float *tmp= new gmp_float( exp((double)a) );
185  return *tmp;
186}
187gmp_float max( const gmp_float & a, const gmp_float & b )
188{
189  gmp_float *tmp= new gmp_float();
190  a > b ? *tmp= a : *tmp= b;
191  return *tmp;
192}
193//
194// number to float, number = Q, R, C
195// makes a COPY of num! (Ist das gut?)
196//
197gmp_float numberToFloat( number num )
198{
199  gmp_float r;
200
201  if ( rField_is_Q() )
202  {
203    if ( num != NULL )
204    {
205      if (SR_HDL(num) & SR_INT)
206      {
207        r= SR_TO_INT(num);
208      }
209      else
210      {
211        if ( num->s == 0 )
212        {
213          nlNormalize( num );
214        }
215        if (SR_HDL(num) & SR_INT)
216        {
217          r= SR_TO_INT(num);
218        }
219        else
220        {
221          if ( num->s != 3 )
222          {
223            r= &num->z;
224            r/= (gmp_float)&num->n;
225          }
226          else
227          {
228            r= &num->z;
229          }
230        }
231      }
232    }
233    else
234    {
235      r= 0.0;
236    }
237  }
238  else if (rField_is_long_R() || rField_is_long_C())
239  {
240    r= *(gmp_float*)num;
241  }
242  else if ( rField_is_R() )
243  {
244    // Add some code here :-)
245    WerrorS("Ground field not implemented!");
246  }
247  else
248  {
249    WerrorS("Ground field not implemented!");
250  }
251
252  return r;
253}
254
255// Do some strange things with the mantissa string and the exponent
256// to get some nice output string.
257char *nicifyFloatStr( char * in, mp_exp_t exponent, size_t oprec, int *size, int thesign )
258{
259  char *out;
260
261  int sign= (in[0] == '-') ? 1 : 0;
262  char csign[2];
263
264  switch (thesign)
265  {
266    case SIGN_PLUS:
267      sign ? strcpy(csign,"-") : strcpy(csign,"+");  //+123, -123
268      break;
269    case SIGN_SPACE:
270      sign ? strcpy(csign,"-") : strcpy(csign," ");  // 123, -123
271      break;
272    case SIGN_EMPTY:
273    default:
274      sign ? strcpy(csign,"-") : strcpy(csign,"");   //123, -123
275      break;
276  }
277
278  if ( strlen(in) == 0 )
279  {
280    *size= 2*sizeof(char);
281    out= (char*)AllocL( *size );
282    strcpy(out,"0");
283    return out;
284  }
285
286  if ( ((unsigned int)abs(exponent) <= oprec)
287       /*|| (exponent+sign >= (int)strlen(in))*/ )
288  {
289    if ( exponent+sign < (int)strlen(in) )
290    {
291      int eexponent= (exponent >= 0) ? 0 : -exponent;
292      int eeexponent= (exponent >= 0) ? exponent : 0;
293      *size= (strlen(in)+15+eexponent) * sizeof(char);
294      out= (char*)AllocL(*size);
295      memset(out,0,*size);
296
297      strcpy(out,csign);
298      strncat(out,in+sign,eeexponent);
299
300      if (exponent == 0)
301        strcat(out,"0.");
302      else if ( exponent > 0 )
303        strcat(out,".");
304      else
305      {
306        strcat(out,"0.");
307        memset(out+strlen(out),'0',eexponent);
308      }
309      strcat(out,in+sign+eeexponent);
310    }
311    else if ( exponent+sign > (int)strlen(in) )
312    {
313      *size= (strlen(in)+exponent+12)*sizeof(char);
314      out= (char*)AllocL(*size);
315      memset(out,0,*size);
316      sprintf(out,"%s%s",csign,in+sign);
317      memset(out+strlen(out),'0',exponent-strlen(in)+sign);
318    }
319    else
320    {
321      *size= (strlen(in)+2) * sizeof(char) + 10;
322      out= (char*)AllocL(*size);
323      memset(out,0,*size);
324      sprintf(out,"%s%s",csign,in+sign);
325    }
326  }
327  else
328  {
329//      if ( exponent > 0 )
330//      {
331      int c=1,d=10;
332      while ( exponent / d > 0 )
333      { // count digits
334        d*=10;
335        c++;
336      }
337      *size= (strlen(in)+12+c) * sizeof(char) + 10;
338      out= (char*)AllocL(*size);
339      memset(out,0,*size);
340      sprintf(out,"%s0.%se%d",csign,in+sign,(unsigned int)exponent);
341//      }
342//      else
343//      {
344//        *size=2;
345//        out= (char*)AllocL(*size);
346//        strcpy(out,"0");
347//      }
348  }
349  return out;
350}
351
352char *floatToStr( const gmp_float & r, const unsigned int oprec )
353{
354#if 1
355  mp_exp_t exponent;
356  int size,insize;
357  char *nout,*out,*in;
358
359  insize= (oprec+2) * sizeof(char) + 10;
360  in= (char*)AllocL( insize );
361
362  mpf_get_str(in,&exponent,10,oprec,*(r.mpfp()));
363
364  if ( (exponent > 0)
365  && (exponent < (int)oprec)
366  && (strlen(in)-(in[0]=='-'?1:0) == oprec) )
367  {
368    FreeL( (ADDRESS) in );
369    insize= (exponent+oprec+2) * sizeof(char) + 10;
370    in= (char*)AllocL( insize );
371    int newprec= exponent+oprec;
372    mpf_get_str(in,&exponent,10,newprec,*(r.mpfp()));
373  }
374  nout= nicifyFloatStr( in, exponent, oprec, &size, SIGN_EMPTY );
375  FreeL( (ADDRESS) in );
376  out= (char*)AllocL( (strlen(nout)+1) * sizeof(char) );
377  strcpy( out, nout );
378  FreeL( (ADDRESS) nout );
379
380  return out;
381#else
382  // for testing purpose...
383  char *out= (char*)AllocL( (1024) * sizeof(char) );
384  sprintf(out,"% .10f",(double)r);
385  return out;
386#endif
387}
388//<-
389
390//-> gmp_complex::*
391// <gmp_complex> = <gmp_complex> operator <gmp_complex>
392//
393gmp_complex operator + ( const gmp_complex & a, const gmp_complex & b )
394{
395  return gmp_complex( a.r + b.r, a.i + b.i );
396}
397gmp_complex operator - ( const gmp_complex & a, const gmp_complex & b )
398{
399  return gmp_complex( a.r - b.r, a.i - b.i );
400}
401gmp_complex operator * ( const gmp_complex & a, const gmp_complex & b )
402{
403  return gmp_complex( a.real() * b.real() - a.imag() * b.imag(),
404                  a.real() * b.imag() + a.imag() * b.real());
405}
406gmp_complex operator / ( const gmp_complex & a, const gmp_complex & b )
407{
408  gmp_float ar = abs(b.real());
409  gmp_float ai = abs(b.imag());
410  gmp_float nr, ni, t, d;
411  if (ar <= ai)
412  {
413    t = b.real() / b.imag();
414    d = b.imag() * ((gmp_float)1 + t*t);
415    nr = (a.real() * t + a.imag()) / d;
416    ni = (a.imag() * t - a.real()) / d;
417  }
418  else
419  {
420    t = b.imag() / b.real();
421    d = b.real() * ((gmp_float)1 + t*t);
422    nr = (a.real() + a.imag() * t) / d;
423    ni = (a.imag() - a.real() * t) / d;
424  }
425  return gmp_complex( nr, ni );
426}
427
428// <gmp_complex> operator <gmp_complex>
429//
430gmp_complex & gmp_complex::operator += ( const gmp_complex & b )
431{
432  r+=b.r;
433  i+=b.i;
434  return *this;
435}
436gmp_complex & gmp_complex::operator -= ( const gmp_complex & b )
437{
438  r-=b.r;
439  i-=b.i;
440  return *this;
441}
442gmp_complex & gmp_complex::operator *= ( const gmp_complex & b )
443{
444  gmp_float f = r * b.r - i * b.i;
445  i = r * b.i + i * b.r;
446  r = f;
447  return *this;
448}
449gmp_complex & gmp_complex::operator /= ( const gmp_complex & b )
450{
451  gmp_float ar = abs(b.r);
452  gmp_float ai = abs(b.i);
453  gmp_float nr, ni, t, d;
454  if (ar <= ai)
455  {
456    t = b.r / b.i;
457    d = b.i * ((gmp_float)1 + t*t);
458    nr = (r * t + i) / d;
459    ni = (i * t - r) / d;
460  }
461  else
462  {
463    t = b.i / b.r;
464    d = b.r * ((gmp_float)1 + t*t);
465    nr = (r + i * t) / d;
466    ni = (i - r * t) / d;
467  }
468  r = nr;
469  i = ni;
470  return *this;
471}
472
473// Returns square root of gmp_complex number
474//
475gmp_complex sqrt( const gmp_complex & x )
476{
477  gmp_float r = abs(x);
478  gmp_float nr, ni;
479  if (r == (gmp_float) 0.0)
480  {
481    nr = ni = r;
482  }
483  else if ( x.real() > (gmp_float)0)
484  {
485    nr = sqrt((gmp_float)0.5 * (r + x.real()));
486    ni = x.imag() / nr / (gmp_float)2;
487  }
488  else
489  {
490    ni = sqrt((gmp_float)0.5 * (r - x.real()));
491    if (x.imag() < (gmp_float)0)
492    {
493      ni = - ni;
494    }
495    nr = x.imag() / ni / (gmp_float)2;
496  }
497  gmp_complex *tmp= new gmp_complex(nr, ni);
498  return *tmp;
499}
500
501// converts a gmp_complex to a string ( <real part> + I * <imaginary part> )
502//
503char *complexToStr( const gmp_complex & c, const unsigned int oprec )
504{
505  char *out,*in_imag,*in_real;
506
507  if ( !c.imag().isZero() )
508  {
509
510    in_real=floatToStr( c.real(), oprec );         // get real part
511    in_imag=floatToStr( abs(c.imag()), oprec );    // get imaginary part
512
513    if (rField_is_long_C())
514    {
515      int len=(strlen(in_real)+strlen(in_imag)+7+strlen(currRing->parameter[0]))*sizeof(char);
516      out=(char*)AllocL(len);
517      memset(out,0,len);
518      if (  !c.real().isZero() )  // (-23-i*5.43) or (15.1+i*5.3)
519        sprintf(out,"(%s%s%s*%s)",in_real,c.imag().sign()>=0?"+":"-",currRing->parameter[0],in_imag);
520      else // (-i*43) or (i*34)
521        sprintf(out,"(%s%s*%s)",c.imag().sign()>=0?"":"-",currRing->parameter[0],in_imag);
522    }
523    else
524    {
525      int len=(strlen(in_real)+strlen(in_imag)+9) * sizeof(char);
526      out=(char*)AllocL( len );
527      memset(out,0,len);
528      if ( !c.real().isZero() ) 
529        sprintf(out,"(%s%s%s)",in_real,c.imag().sign()>=0?"+I*":"-I*",in_imag);
530      else
531        sprintf(out,"(%s%s)",c.imag().sign()>=0?"I*":"-I*",in_imag);
532    }
533    FreeL( (ADDRESS) in_real );
534    FreeL( (ADDRESS) in_imag );
535  }
536  else 
537  {
538    out= floatToStr( c.real(), oprec );
539  }
540
541  return out;
542}
543//<-
544//%e
545
546//#endif // HAVE_MPR
547
548// local Variables: ***
549// folded-file: t ***
550// compile-command-1: "make installg" ***
551// compile-command-2: "make install" ***
552// End: ***
Note: See TracBrowser for help on using the repository browser.