source: git/Singular/mpr_complex.cc @ 3a143d

spielwiese
Last change on this file since 3a143d was 3a143d, checked in by Hans Schönemann <hannes@…>, 25 years ago
*hannes/wenk: nPower for complex git-svn-id: file:///usr/local/Singular/svn/trunk@3222 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 12.3 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: mpr_complex.cc,v 1.9 1999-07-02 14:28:53 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 "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)+10;
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)+5+eexponent) * sizeof(char) + 10;
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+2)*sizeof(char)+10;
314      out= (char*)AllocL(*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      sprintf(out,"%s%s",csign,in+sign);
323    }
324  }
325  else
326  {
327//      if ( exponent > 0 )
328//      {
329      int c=1,d=10;
330      while ( exponent / d > 0 )
331      { // count digits
332        d*=10;
333        c++;
334      }
335      *size= (strlen(in)+12+c) * sizeof(char) + 10;
336      out= (char*)AllocL(*size);
337      sprintf(out,"%s0.%se%d",csign,in+sign,(unsigned int)exponent);
338//      }
339//      else
340//      {
341//        *size=2;
342//        out= (char*)AllocL(*size);
343//        strcpy(out,"0");
344//      }
345  }
346  return out;
347}
348
349char *floatToStr( const gmp_float & r, const unsigned int oprec )
350{
351#if 1
352  mp_exp_t exponent;
353  int size,insize;
354  char *nout,*out,*in;
355
356  insize= (oprec+2) * sizeof(char) + 10;
357  in= (char*)AllocL( insize );
358
359  mpf_get_str(in,&exponent,10,oprec,*(r.mpfp()));
360
361  if ( (exponent > 0)
362  && (exponent < (int)oprec)
363  && (strlen(in)-(in[0]=='-'?1:0) == oprec) )
364  {
365    FreeL( (ADDRESS) in );
366    insize= (exponent+oprec+2) * sizeof(char) + 10;
367    in= (char*)AllocL( insize );
368    int newprec= exponent+oprec;
369    mpf_get_str(in,&exponent,10,newprec,*(r.mpfp()));
370  }
371  nout= nicifyFloatStr( in, exponent, oprec, &size, SIGN_EMPTY );
372  FreeL( (ADDRESS) in );
373  out= (char*)AllocL( (strlen(nout)+1) * sizeof(char) );
374  strcpy( out, nout );
375  FreeL( (ADDRESS) nout );
376
377  return out;
378#else
379  // for testing purpose...
380  char *out= (char*)AllocL( (1024) * sizeof(char) );
381  sprintf(out,"% .10f",(double)r);
382  return out;
383#endif
384}
385//<-
386
387//-> gmp_complex::*
388// <gmp_complex> = <gmp_complex> operator <gmp_complex>
389//
390gmp_complex operator + ( const gmp_complex & a, const gmp_complex & b )
391{
392  return gmp_complex( a.r + b.r, a.i + b.i );
393}
394gmp_complex operator - ( const gmp_complex & a, const gmp_complex & b )
395{
396  return gmp_complex( a.r - b.r, a.i - b.i );
397}
398gmp_complex operator * ( const gmp_complex & a, const gmp_complex & b )
399{
400  return gmp_complex( a.real() * b.real() - a.imag() * b.imag(),
401                  a.real() * b.imag() + a.imag() * b.real());
402}
403gmp_complex operator / ( const gmp_complex & a, const gmp_complex & b )
404{
405  gmp_float ar = abs(b.real());
406  gmp_float ai = abs(b.imag());
407  gmp_float nr, ni, t, d;
408  if (ar <= ai)
409  {
410    t = b.real() / b.imag();
411    d = b.imag() * ((gmp_float)1 + t*t);
412    nr = (a.real() * t + a.imag()) / d;
413    ni = (a.imag() * t - a.real()) / d;
414  }
415  else
416  {
417    t = b.imag() / b.real();
418    d = b.real() * ((gmp_float)1 + t*t);
419    nr = (a.real() + a.imag() * t) / d;
420    ni = (a.imag() - a.real() * t) / d;
421  }
422  return gmp_complex( nr, ni );
423}
424
425// <gmp_complex> operator <gmp_complex>
426//
427gmp_complex & gmp_complex::operator += ( const gmp_complex & b )
428{
429  r+=b.r;
430  i+=b.i;
431  return *this;
432}
433gmp_complex & gmp_complex::operator -= ( const gmp_complex & b )
434{
435  r-=b.r;
436  i-=b.i;
437  return *this;
438}
439gmp_complex & gmp_complex::operator *= ( const gmp_complex & b )
440{
441  gmp_float f = r * b.r - i * b.i;
442  i = r * b.i + i * b.r;
443  r = f;
444  return *this;
445}
446gmp_complex & gmp_complex::operator /= ( const gmp_complex & b )
447{
448  gmp_float ar = abs(b.r);
449  gmp_float ai = abs(b.i);
450  gmp_float nr, ni, t, d;
451  if (ar <= ai)
452  {
453    t = b.r / b.i;
454    d = b.i * ((gmp_float)1 + t*t);
455    nr = (r * t + i) / d;
456    ni = (i * t - r) / d;
457  }
458  else
459  {
460    t = b.i / b.r;
461    d = b.r * ((gmp_float)1 + t*t);
462    nr = (r + i * t) / d;
463    ni = (i - r * t) / d;
464  }
465  r = nr;
466  i = ni;
467  return *this;
468}
469
470// Returns square root of gmp_complex number
471//
472gmp_complex sqrt( const gmp_complex & x )
473{
474  gmp_float r = abs(x);
475  gmp_float nr, ni;
476  if (r == (gmp_float) 0.0)
477  {
478    nr = ni = r;
479  }
480  else if ( x.real() > (gmp_float)0)
481  {
482    nr = sqrt((gmp_float)0.5 * (r + x.real()));
483    ni = x.imag() / nr / (gmp_float)2;
484  }
485  else
486  {
487    ni = sqrt((gmp_float)0.5 * (r - x.real()));
488    if (x.imag() < (gmp_float)0)
489    {
490      ni = - ni;
491    }
492    nr = x.imag() / ni / (gmp_float)2;
493  }
494  gmp_complex *tmp= new gmp_complex(nr, ni);
495  return *tmp;
496}
497
498// converts a gmp_complex to a string ( <real part> + I * <imaginary part> )
499//
500char *complexToStr( const gmp_complex & c, const unsigned int oprec )
501{
502  char *out,*in_imag,*in_real;
503
504  if ( !c.imag().isZero() )
505  {
506    in_real=floatToStr( c.real(), oprec );         // get real part
507    in_imag=floatToStr( abs(c.imag()), oprec );    // get imaginary part
508
509    if (rField_is_long_C())
510    {
511      int len=(strlen(in_real)+strlen(in_imag)+5+strlen(currRing->parameter[0]))*sizeof(char);
512      out=(char*)AllocL(len);
513      memset(out,0,len);
514      sprintf(out,"%s%s%s*%s",in_real,c.imag().sign()>=0?"+":"-",currRing->parameter[0],in_imag);
515    }
516    else
517    {
518      int len=(strlen(in_real)+strlen(in_imag)+8) * sizeof(char);
519      out=(char*)AllocL( len );
520      memset(out,0,len);
521      sprintf(out,"%s%s%s",in_real,c.imag().sign()>=0?" + I ":" - I ",in_imag);
522    }
523    FreeL( (ADDRESS) in_real );
524    FreeL( (ADDRESS) in_imag );
525  }
526  else
527  {
528    out= floatToStr( c.real(), oprec );
529  }
530  return out;
531}
532//<-
533//%e
534
535//#endif // HAVE_MPR
536
537// local Variables: ***
538// folded-file: t ***
539// compile-command-1: "make installg" ***
540// compile-command-2: "make install" ***
541// End: ***
Note: See TracBrowser for help on using the repository browser.