source: git/kernel/gnumpfl.cc @ 208e0c

spielwiese
Last change on this file since 208e0c was 208e0c, checked in by Hans Schönemann <hannes@…>, 14 years ago
const in *SetMap git-svn-id: file:///usr/local/Singular/svn/trunk@12374 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 8.0 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id$ */
5/*
6* ABSTRACT: computations with GMP floating-point numbers
7*
8* ngf == number gnu floats
9*/
10
11#include "mod2.h"
12#include "structs.h"
13#include "febase.h"
14#include "omalloc.h"
15#include "numbers.h"
16#include "modulop.h"
17#include "longrat.h"
18
19#include "gnumpfl.h"
20#include "mpr_complex.h"
21
22extern size_t gmp_output_digits;
23ring ngfMapRing; // to be used also in gnumpc.cc
24
25static number ngfMapP(number from)
26{
27  if ( from != NULL)
28    return ngfInit(npInt(from,ngfMapRing), currRing);
29  else
30    return NULL;
31}
32number ngfMapQ(number from)
33{
34  if ( from != NULL )
35  {
36    gmp_float *res=new gmp_float(numberFieldToFloat(from,QTOF));
37    return (number)res;
38  }
39  else
40    return NULL;
41}
42union nf
43{
44  float _f;
45  number _n;
46  nf(float f) {_f = f;}
47  nf(number n) {_n = n;}
48  float F() const {return _f;}
49  number N() const {return _n;}
50};
51static number ngfMapR(number from)
52{
53  if ( from != NULL )
54  {
55    gmp_float *res=new gmp_float((double)nf(from).F());
56    return (number)res;
57  }
58  else
59    return NULL;
60}
61static number ngfMapC(number from)
62{
63  if ( (from != NULL) || ((gmp_complex*)from)->real().isZero() )
64  {
65    gmp_float *res=new gmp_float(((gmp_complex*)from)->real());
66    return (number)res;
67  }
68  else
69    return NULL;
70}
71
72nMapFunc ngfSetMap(const ring src, const ring dst)
73{
74  if (rField_is_Q(src))
75  {
76    return ngfMapQ;
77  }
78  if (rField_is_long_R(src))
79  {
80    return ngfCopy;
81  }
82  if (rField_is_R(src))
83  {
84    return ngfMapR;
85  }
86  if (rField_is_Zp(src))
87  {
88    ngfMapRing=src;
89    return ngfMapP;
90  }
91  if (rField_is_long_C(src))
92  {
93    return ngfMapC;
94  }
95  return NULL;
96}
97
98/*2
99* n := i
100*/
101number ngfInit (int i, const ring r)
102{
103  gmp_float* n= NULL;
104  if ( i != 0 )
105  {
106    n= new gmp_float( (double)i );
107  }
108  return (number)n;
109}
110
111/*2
112* convert number to int
113*/
114int ngfInt(number &i, const ring r)
115{
116  if ( i == NULL ) return 0;
117  double d=(double)*(gmp_float*)i;
118  if (d<0.0)
119    return (int)(d-0.5);
120  else
121    return (int)(d+0.5);
122}
123
124/*2
125* delete a
126*/
127void ngfDelete (number * a, const ring r)
128{
129  if ( *a != NULL )
130  {
131    delete *(gmp_float**)a;
132    *a=NULL;
133  }
134}
135
136/*2
137* copy a to b
138*/
139number ngfCopy(number a)
140{
141  gmp_float* b= NULL;
142  if ( a !=  NULL )
143  {
144    b= new gmp_float( *(gmp_float*)a );
145  }
146  return (number)b;
147}
148
149number ngf_Copy(number a, ring r)
150{
151  gmp_float* b= NULL;
152  if ( a !=  NULL )
153  {
154    b= new gmp_float( *(gmp_float*)a );
155  }
156  return (number)b;
157}
158
159/*2
160* za:= - za
161*/
162number ngfNeg (number a)
163{
164  if ( a == NULL ) return NULL;
165  *(gmp_float*)a= -(*(gmp_float*)a);
166  return (number)a;
167}
168
169/*
170* 1/a
171*/
172number ngfInvers(number a)
173{
174  gmp_float* r= NULL;
175  if ( (a==NULL) || ((gmp_float*)a)->isZero() )
176  {
177    WerrorS(nDivBy0);
178  }
179  else
180  {
181    r= new gmp_float( (gmp_float)1 / (*(gmp_float*)a) );
182  }
183  return (number)r;
184}
185
186/*2
187* u:= a + b
188*/
189number ngfAdd (number a, number b)
190{
191  gmp_float* r= NULL;
192  if ( a==NULL && b==NULL )
193  {
194    return NULL;
195  }
196  else if ( a == NULL )
197  {
198    r= new gmp_float( *(gmp_float*)b );
199  }
200  else if ( b == NULL )
201  {
202    r= new gmp_float( *(gmp_float*)a );
203  }
204  else
205  {
206    r= new gmp_float( (*(gmp_float*)a) + (*(gmp_float*)b) );
207  }
208  return (number)r;
209}
210
211/*2
212* u:= a - b
213*/
214number ngfSub (number a, number b)
215{
216  gmp_float* r= NULL;
217  if ( a==NULL && b==NULL )
218  {
219    return NULL;
220  }
221  else if ( a == NULL )
222  {
223    r= new gmp_float( -(*(gmp_float*)b) );
224  }
225  else if ( b == NULL )
226  {
227    r= new gmp_float( *(gmp_float*)a );
228  }
229  else
230  {
231    r= new gmp_float( (*(gmp_float*)a) - (*(gmp_float*)b) );
232  }
233  return (number)r;
234}
235
236/*2
237* u := a * b
238*/
239number ngfMult (number a, number b)
240{
241  gmp_float* r= NULL;
242  if ( a==NULL || b==NULL )
243  {
244    return NULL;
245  }
246  else
247  {
248    r= new gmp_float( (*(gmp_float*)a) * (*(gmp_float*)b) );
249  }
250  return (number)r;
251}
252
253/*2
254* u := a / b
255*/
256number ngfDiv (number a, number b)
257{
258  if ( a==NULL )
259  {
260    // 0/b = 0
261    return NULL;
262  }
263  else if ( b==NULL || ((gmp_float*)b)->isZero() )
264  {
265    // a/0 = error
266    WerrorS(nDivBy0);
267    return NULL;
268  }
269  gmp_float* r= new gmp_float( (*(gmp_float*)a) / (*(gmp_float*)b) );
270  return (number)r;
271}
272
273/*2
274* u:= x ^ exp
275*/
276void ngfPower ( number x, int exp, number * u )
277{
278  if ( exp == 0 )
279  {
280    gmp_float* n = new gmp_float(1);
281    *u=(number)n;
282    return;
283  }
284  else if ( ngfIsZero(x) ) // 0^e, e>0
285  {
286    gmp_float* n = NULL;
287    *u=(number)n;
288    return;
289  }
290  else if ( exp == 1 )
291  {
292    nNew(u);
293    if ( x == NULL )
294    {
295      gmp_float* n = new gmp_float();
296      *u=(number)n;
297    }
298    else
299    {
300      gmp_float* n = new gmp_float();
301      *n= *(gmp_float*)x;
302      *u=(number)n;
303    }
304    return;
305  }
306  ngfPower(x,exp-1,u);
307
308  gmp_float *n=new gmp_float();
309  *n=*(gmp_float*)x;
310  *(gmp_float*)(*u) *= *(gmp_float*)n;
311  delete (gmp_float*)n;
312}
313
314BOOLEAN ngfIsZero (number a)
315{
316  if ( a == NULL ) return TRUE;
317  return ( ((gmp_float*)a)->isZero() );
318}
319
320/*2
321* za >= 0 ?
322*/
323BOOLEAN ngfGreaterZero (number a)
324{
325  if ( a == NULL ) return TRUE;
326  return ( (*(gmp_float*)a) >= (gmp_float)0.0 );
327}
328
329/*2
330* a > b ?
331*/
332BOOLEAN ngfGreater (number a, number b)
333{
334  if ( a==NULL )
335  {
336    return (((gmp_float*)b)->sign() < 0);
337  }
338  if ( b==NULL )
339  {
340    return (((gmp_float*)a)->sign() > 0);
341  }
342  return ( (*(gmp_float*)a) > (*(gmp_float*)b) );
343}
344
345/*2
346* a = b ?
347*/
348BOOLEAN ngfEqual (number a, number b)
349{
350  if ( a == NULL && b == NULL )
351  {
352    return TRUE;
353  }
354  else if ( a == NULL || b == NULL )
355  {
356    return FALSE;
357  }
358  return ( (*(gmp_float*)a) == (*(gmp_float*)b) );
359}
360
361/*2
362* a == 1 ?
363*/
364BOOLEAN ngfIsOne (number a)
365{
366  if ( a == NULL ) return FALSE;
367  return ((gmp_float*)a)->isOne();
368}
369
370/*2
371* a == -1 ?
372*/
373BOOLEAN ngfIsMOne (number a)
374{
375  if ( a == NULL ) return FALSE;
376  return ((gmp_float*)a)->isMOne();
377}
378
379/*2
380* result =gcd(a,b)
381* dummy, returns 1
382*/
383number ngfGcd(number a, number b)
384{
385  gmp_float *result= new gmp_float( 1 );
386  return (number)result;
387}
388
389static char * ngfEatFloatNExp(char * s )
390{
391  char *start= s;
392
393  // eat floats (mantissa) like:
394  //   0.394394993, 102.203003008,  .300303032, pssibly starting with -
395  if (*s == '-') s++;
396  while ((*s >= '0' && *s <= '9')||(*s == '.')) s++;
397
398  // eat the exponent, starts with 'e' followed by '+', '-'
399  // and digits, like:
400  //   e-202, e+393, accept also E7
401  if ( (s != start) && ((*s == 'e')||(*s=='E')))
402  {
403    if (*s=='E') *s='e';
404    s++; // skip 'e'/'E'
405    if ((*s == '+') || (*s == '-')) s++;
406    while ((*s >= '0' && *s <= '9')) s++;
407  }
408
409  return s;
410}
411
412/*2
413* extracts the number a from s, returns the rest
414*/
415const char * ngfRead (const char * start, number * a)
416{
417  char *s= (char *)start;
418
419  //Print("%s\n",s);
420
421  s= ngfEatFloatNExp( s );
422
423  if (*s=='\0')  // 0
424  {
425    if ( *(gmp_float**)a == NULL ) (*(gmp_float**)a)= new gmp_float();
426    (*(gmp_float**)a)->setFromStr(start);
427  }
428  else if (s==start)  // 1
429  {
430    if ( *(gmp_float**)a != NULL )  delete (*(gmp_float**)a);
431    (*(gmp_float**)a)= new gmp_float(1);
432  }
433  else
434  {
435    gmp_float divisor(1.0);
436    char *start2=s;
437    if ( *s == '/' )
438    {
439      s++;
440      s= ngfEatFloatNExp( (char *)s );
441      if (s!= start2+1)
442      {
443        char tmp_c=*s;
444        *s='\0';
445        divisor.setFromStr(start2+1);
446        *s=tmp_c;
447      }
448      else
449      {
450        Werror("wrong long real format: %s",start2);
451      }
452    }
453    char c=*start2;
454    *start2='\0';
455    if ( *(gmp_float**)a == NULL ) (*(gmp_float**)a)= new gmp_float();
456    (*(gmp_float**)a)->setFromStr(start);
457    *start2=c;
458    if (divisor.isZero())
459    {
460      WerrorS(nDivBy0);
461    }
462    else
463      (**(gmp_float**)a) /= divisor;
464  }
465
466  return s;
467}
468
469/*2
470* write a floating point number
471*/
472void ngfWrite (number &a)
473{
474  char *out;
475  if ( a != NULL )
476  {
477    out= floatToStr(*(gmp_float*)a,gmp_output_digits);
478    StringAppendS(out);
479    //omFreeSize((ADDRESS)out, (strlen(out)+1)* sizeof(char) );
480    omFree( (ADDRESS)out );
481  }
482  else
483  {
484    StringAppendS("0");
485  }
486}
487
488#ifdef LDEBUG
489//BOOLEAN ngfDBTest(number a, const char *f, const int l)
490//{
491//  return TRUE;
492//}
493#endif
494
495// local Variables: ***
496// folded-file: t ***
497// compile-command: "make installg" ***
498// End: ***
Note: See TracBrowser for help on using the repository browser.