source: git/Singular/mpr_complex.cc @ b2bae5

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