source: git/libpolys/coeffs/gnumpfl.cc @ ce1f78

spielwiese
Last change on this file since ce1f78 was ce1f78, checked in by Oleksandr Motsak <motsak@…>, 12 years ago
fixed short/long output of coeffs depending on ShortOut/CanShortOut options of rings Note: the ugly ShortOut correction p_String0Short/p_String0Long is due to Hans
  • Property mode set to 100644
File size: 10.2 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 "config.h"
12#include <coeffs/coeffs.h>
13#include <omalloc/omalloc.h>
14#include <reporter/reporter.h>
15#include <coeffs/numbers.h>
16#include <coeffs/modulop.h>
17#include <coeffs/longrat.h>
18#include <coeffs/shortfl.h>
19
20#include <coeffs/gnumpfl.h>
21#include <coeffs/mpr_complex.h>
22
23extern size_t gmp_output_digits;
24//ring ngfMapRing; // to be used also in gnumpc.cc
25
26/// Our Type!
27static const n_coeffType ID = n_long_R;
28
29union nf
30{
31  float _f;
32  number _n;
33  nf(float f) {_f = f;}
34  nf(number n) {_n = n;}
35  float F() const {return _f;}
36  number N() const {return _n;}
37};
38
39/*2
40* n := i
41*/
42number ngfInit (long i, const coeffs r)
43{
44  assume( getCoeffType(r) == ID );
45 
46  gmp_float* n= new gmp_float( (double)i );
47  return (number)n;
48}
49
50/*2
51* convert number to int
52*/
53int ngfInt(number &i, const coeffs r)
54{
55  assume( getCoeffType(r) == ID );
56 
57  double d=(double)*(gmp_float*)i;
58  if (d<0.0)
59    return (int)(d-0.5);
60  else
61    return (int)(d+0.5);
62}
63
64int ngfSize(number n, const coeffs r)
65{
66  int i = ngfInt(n, r);
67  /* basically return the largest integer in n;
68     only if this happens to be zero although n != 0,
69     return 1;
70     (this code ensures that zero has the size zero) */
71  if ((i == 0) && (ngfIsZero(n,r) == FALSE)) i = 1;
72  return i;
73}
74
75/*2
76* delete a
77*/
78void ngfDelete (number * a, const coeffs r)
79{
80  assume( getCoeffType(r) == ID );
81 
82  if ( *a != NULL )
83  {
84    delete *(gmp_float**)a;
85    *a=NULL;
86  }
87}
88
89/*2
90* copy a to b
91*/
92number ngfCopy(number a, const coeffs r)
93{
94  assume( getCoeffType(r) == ID );
95 
96  gmp_float* b= new gmp_float( *(gmp_float*)a );
97  return (number)b;
98}
99
100#if 0
101static number ngfCopyMap(number a, const coeffs r1, const coeffs r2)
102{
103  assume( getCoeffType(r1) == ID );
104  assume( getCoeffType(r2) == ID );
105 
106  gmp_float* b= NULL;
107  if ( a !=  NULL )
108  {
109    b= new gmp_float( *(gmp_float*)a );
110  }
111  return (number)b;
112}
113#endif
114
115/*2
116* za:= - za
117*/
118number ngfNeg (number a, const coeffs r)
119{
120  assume( getCoeffType(r) == ID );
121 
122  *(gmp_float*)a= -(*(gmp_float*)a);
123  return (number)a;
124}
125
126/*
127* 1/a
128*/
129number ngfInvers(number a, const coeffs r)
130{
131  assume( getCoeffType(r) == ID );
132 
133  gmp_float* f= NULL;
134  if (((gmp_float*)a)->isZero() )
135  {
136    WerrorS(nDivBy0);
137  }
138  else
139  {
140    f= new gmp_float( gmp_float(1) / (*(gmp_float*)a) );
141  }
142  return (number)f;
143}
144
145/*2
146* u:= a + b
147*/
148number ngfAdd (number a, number b, const coeffs R)
149{
150  assume( getCoeffType(R) == ID );
151 
152  gmp_float* r= new gmp_float( (*(gmp_float*)a) + (*(gmp_float*)b) );
153  return (number)r;
154}
155
156/*2
157* u:= a - b
158*/
159number ngfSub (number a, number b, const coeffs R)
160{
161  assume( getCoeffType(R) == ID );
162 
163  gmp_float* r= new gmp_float( (*(gmp_float*)a) - (*(gmp_float*)b) );
164  return (number)r;
165}
166
167/*2
168* u := a * b
169*/
170number ngfMult (number a, number b, const coeffs R)
171{
172  assume( getCoeffType(R) == ID );
173 
174  gmp_float* r= new gmp_float( (*(gmp_float*)a) * (*(gmp_float*)b) );
175  return (number)r;
176}
177
178/*2
179* u := a / b
180*/
181number ngfDiv (number a, number b, const coeffs r)
182{
183  assume( getCoeffType(r) == ID );
184 
185  if ( ((gmp_float*)b)->isZero() )
186  {
187    // a/0 = error
188    WerrorS(nDivBy0);
189    return NULL;
190  }
191  gmp_float* f= new gmp_float( (*(gmp_float*)a) / (*(gmp_float*)b) );
192  return (number)f;
193}
194
195/*2
196* u:= x ^ exp
197*/
198number ngfPower (number x, int exp, const coeffs r)
199{
200  assume( getCoeffType(r) == ID );
201 
202  if ( exp == 0 )
203  {
204    gmp_float* n = new gmp_float(1);
205    return (number)n;
206  }
207  else if ( ngfIsZero(x, r) ) // 0^e, e>0
208  {
209    return ngfInit(0, r);
210  }
211  else if ( exp == 1 )
212  {
213    return ngfCopy(x,r);
214  }
215  return (number) ( new gmp_float( (*(gmp_float*)x)^exp ) );
216}
217
218/* kept for compatibility reasons, to be deleted */
219void ngfPower ( number x, int exp, number * u, const coeffs r )
220{
221  *u = ngfPower(x, exp, r);
222} 
223
224BOOLEAN ngfIsZero (number a, const coeffs r)
225{
226  assume( getCoeffType(r) == ID );
227 
228  return ( ((gmp_float*)a)->isZero() );
229}
230
231/*2
232* za > 0 ?
233*/
234BOOLEAN ngfGreaterZero (number a, const coeffs r)
235{
236  assume( getCoeffType(r) == ID );
237 
238  return (((gmp_float*)a)->sign() > 0);
239}
240
241/*2
242* a > b ?
243*/
244BOOLEAN ngfGreater (number a, number b, const coeffs r)
245{
246  assume( getCoeffType(r) == ID );
247 
248  return ( (*(gmp_float*)a) > (*(gmp_float*)b) );
249}
250
251/*2
252* a = b ?
253*/
254BOOLEAN ngfEqual (number a, number b, const coeffs r)
255{
256  assume( getCoeffType(r) == ID );
257 
258  return ( (*(gmp_float*)a) == (*(gmp_float*)b) );
259}
260
261/*2
262* a == 1 ?
263*/
264BOOLEAN ngfIsOne (number a, const coeffs r)
265{
266  assume( getCoeffType(r) == ID );
267 
268  return ((gmp_float*)a)->isOne();
269}
270
271/*2
272* a == -1 ?
273*/
274BOOLEAN ngfIsMOne (number a, const coeffs r)
275{
276  assume( getCoeffType(r) == ID );
277 
278  return ((gmp_float*)a)->isMOne();
279}
280
281static char * ngfEatFloatNExp(char * s )
282{
283  char *start= s;
284
285  // eat floats (mantissa) like:
286  //   0.394394993, 102.203003008,  .300303032, pssibly starting with -
287  if (*s == '-') s++;
288  while ((*s >= '0' && *s <= '9')||(*s == '.')) s++;
289
290  // eat the exponent, starts with 'e' followed by '+', '-'
291  // and digits, like:
292  //   e-202, e+393, accept also E7
293  if ( (s != start) && ((*s == 'e')||(*s=='E')))
294  {
295    if (*s=='E') *s='e';
296    s++; // skip 'e'/'E'
297    if ((*s == '+') || (*s == '-')) s++;
298    while ((*s >= '0' && *s <= '9')) s++;
299  }
300
301  return s;
302}
303
304/*2
305* extracts the number a from s, returns the rest
306*
307* This is also called to print components of complex coefficients.
308* Handle with care!
309*/
310const char * ngfRead (const char * start, number * a, const coeffs r)
311{
312  assume( getCoeffType(r) == ID or getCoeffType(r) == n_long_C);
313 
314  char *s= (char *)start;
315
316  //Print("%s\n",s);
317
318  s= ngfEatFloatNExp( s );
319
320  if (*s=='\0')  // 0
321  {
322    if ( *(gmp_float**)a == NULL ) (*(gmp_float**)a)= new gmp_float();
323    (*(gmp_float**)a)->setFromStr(start);
324  }
325  else if (s==start)  // 1
326  {
327    if ( *(gmp_float**)a != NULL )  delete (*(gmp_float**)a);
328    (*(gmp_float**)a)= new gmp_float(1);
329  }
330  else
331  {
332    gmp_float divisor(1.0);
333    char *start2=s;
334    if ( *s == '/' )
335    {
336      s++;
337      s= ngfEatFloatNExp( (char *)s );
338      if (s!= start2+1)
339      {
340        char tmp_c=*s;
341        *s='\0';
342        divisor.setFromStr(start2+1);
343        *s=tmp_c;
344      }
345      else
346      {
347        Werror("wrong long real format: %s",start2);
348      }
349    }
350    char c=*start2;
351    *start2='\0';
352    if ( *(gmp_float**)a == NULL ) (*(gmp_float**)a)= new gmp_float();
353    (*(gmp_float**)a)->setFromStr(start);
354    *start2=c;
355    if (divisor.isZero())
356    {
357      WerrorS(nDivBy0);
358    }
359    else
360      (**(gmp_float**)a) /= divisor;
361  }
362
363  return s;
364}
365
366/*2
367* write a floating point number
368*/
369void ngfWrite (number &a, const coeffs r)
370{
371  assume( getCoeffType(r) == ID );
372 
373  extern size_t gmp_output_digits;
374  char *out;
375  if ( a != NULL )
376  {
377    out= floatToStr(*(gmp_float*)a, gmp_output_digits);
378    StringAppendS(out);
379    //omFreeSize((void *)out, (strlen(out)+1)* sizeof(char) );
380    omFree( (void *)out );
381  }
382  else
383  {
384    StringAppendS("0");
385  }
386}
387
388BOOLEAN ngfCoeffIsEqual (const coeffs r, n_coeffType n, void * parameter)
389{
390  if (n==ID) {
391    LongComplexInfo* p = (LongComplexInfo *)(parameter);
392    if (p->float_len == r->float_len && p->float_len2 == r->float_len2)
393      return TRUE;
394  }
395  return FALSE;
396}
397
398void ngfSetChar(const coeffs r)
399{
400  setGMPFloatDigits(r->float_len, r->float_len2);
401}
402
403BOOLEAN ngfInitChar(coeffs n, void *parameter)
404{
405  assume( getCoeffType(n) == ID );
406
407  n->cfKillChar = ndKillChar; /* dummy */
408
409  n->cfSetChar = ngfSetChar;
410  n->ch = 0;
411 
412  n->cfDelete  = ngfDelete;
413  n->cfNormalize=ndNormalize;
414  n->cfInit   = ngfInit;
415  n->cfInt    = ngfInt;
416  n->cfAdd     = ngfAdd;
417  n->cfSub     = ngfSub;
418  n->cfMult    = ngfMult;
419  n->cfDiv     = ngfDiv;
420  n->cfExactDiv= ngfDiv;
421  n->cfNeg     = ngfNeg;
422  n->cfInvers  = ngfInvers;
423  n->cfCopy   = ngfCopy;
424  n->cfGreater = ngfGreater;
425  n->cfEqual   = ngfEqual;
426  n->cfIsZero  = ngfIsZero;
427  n->cfIsOne   = ngfIsOne;
428  n->cfIsMOne  = ngfIsMOne;
429  n->cfGreaterZero = ngfGreaterZero;
430  n->cfWriteLong  = ngfWrite;
431  n->cfRead    = ngfRead;
432  n->cfPower   = ngfPower;
433  n->cfSetMap = ngfSetMap;
434  n->cfCoeffWrite = ngfCoeffWrite;
435  n->cfInit_bigint = ngfMapQ;
436#ifdef LDEBUG
437  n->cfDBTest  = ndDBTest; // not yet implemented: ngfDBTest
438#endif
439
440  n->nCoeffIsEqual = ngfCoeffIsEqual;
441
442  if( parameter != NULL)
443  {
444    LongComplexInfo* p = (LongComplexInfo*)parameter;
445     
446    n->float_len = p->float_len;
447    n->float_len2 = p->float_len2;
448  } else // default values, just for testing!
449  {
450    n->float_len = SHORT_REAL_LENGTH;
451    n->float_len2 = SHORT_REAL_LENGTH;
452  }
453   
454  assume( n->float_len <= n->float_len2 );
455  assume( n->float_len2 >= SHORT_REAL_LENGTH );
456  assume( n->complex_parameter == NULL );
457
458  return FALSE;
459}
460
461number ngfMapQ(number from, const coeffs src, const coeffs dst)
462{
463  assume( getCoeffType(dst) == ID );
464  assume( getCoeffType(src) == n_Q );
465 
466  gmp_float *res=new gmp_float(numberFieldToFloat(from,QTOF,dst));
467  return (number)res;
468}
469
470static number ngfMapR(number from, const coeffs src, const coeffs dst)
471{
472  assume( getCoeffType(dst) == ID );
473  assume( getCoeffType(src) == n_R );
474 
475  gmp_float *res=new gmp_float((double)nf(from).F());
476  return (number)res;
477}
478
479static number ngfMapP(number from, const coeffs src, const coeffs dst)
480{
481  assume( getCoeffType(dst) == ID );
482  assume( getCoeffType(src) ==  n_Zp );
483 
484  return ngfInit(npInt(from,src), dst);
485}
486
487static number ngfMapC(number from, const coeffs src, const coeffs dst)
488{
489  assume( getCoeffType(dst) == ID );
490  assume( getCoeffType(src) ==  n_long_C );
491 
492  gmp_float *res=new gmp_float(((gmp_complex*)from)->real());
493  return (number)res;
494}
495
496nMapFunc ngfSetMap(const coeffs src, const coeffs dst)
497{
498  assume( getCoeffType(dst) == ID );
499 
500  if (nCoeff_is_Q(src))
501  {
502    return ngfMapQ;
503  }
504  if (nCoeff_is_long_R(src))
505  {
506    return ndCopyMap; //ngfCopyMap;
507  }
508  if (nCoeff_is_R(src))
509  {
510    return ngfMapR;
511  }
512  if (nCoeff_is_long_C(src))
513  {
514    return ngfMapC;
515  }
516  if (nCoeff_is_Zp(src))
517  {
518    return ngfMapP;
519  }
520  return NULL;
521}
522
523
524void    ngfCoeffWrite  (const coeffs r, BOOLEAN /*details*/)
525{
526  Print("//   characteristic : 0 (real:%d digits, additional %d digits)\n",
527               r->float_len,r->float_len2);  /* long R */
528}
Note: See TracBrowser for help on using the repository browser.