source: git/Singular/mpr_complex.cc @ b7b08c

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