C-XSC - A C++ Class Library for Extended Scientific Computing  2.5.4
realio.cpp
1 /*
2 ** CXSC is a C++ library for eXtended Scientific Computing (V 2.5.4)
3 **
4 ** Copyright (C) 1990-2000 Institut fuer Angewandte Mathematik,
5 ** Universitaet Karlsruhe, Germany
6 ** (C) 2000-2014 Wiss. Rechnen/Softwaretechnologie
7 ** Universitaet Wuppertal, Germany
8 **
9 ** This library is free software; you can redistribute it and/or
10 ** modify it under the terms of the GNU Library General Public
11 ** License as published by the Free Software Foundation; either
12 ** version 2 of the License, or (at your option) any later version.
13 **
14 ** This library is distributed in the hope that it will be useful,
15 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 ** Library General Public License for more details.
18 **
19 ** You should have received a copy of the GNU Library General Public
20 ** License along with this library; if not, write to the Free
21 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23 
24 /* CVS $Id: realio.cpp,v 1.31 2014/01/30 17:23:48 cxsc Exp $ */
25 
26 #include <cstring>
27 #include "real.hpp"
28 #include "ioflags.hpp"
29 #include "RtsFunc.h"
30 #include "dot.hpp"
31 
32 namespace cxsc {
33 
34 int d_init_dm (void);
35 void d_outp(char *buffer, Dotprecision c,
36  int FormatFlag, int FracDigits, int rnd,
37  int *length);
38 
39 #if _WIN32
40 extern __declspec(thread) char *dm;
41 #elif __APPLE__ && !CXSC_FORCE_TLS
42 extern char *dm;
43 #else
44 extern __thread char *dm;
45 #endif
46 
47 
48 char* GetHexDigits (char* s, a_btyp& x, int count);
49 
50 int r_outpx (char *buffer, a_real s,a_intg FormatFlag, a_intg FracDigits, a_intg rnd, a_intg *length);
51 
52 #define WASGOOD 0
53 #define ISINFINITYPLUS -1
54 #define ISINFINITYMINUS -2
55 #define ISQUIETNAN -3
56 #define ISSIGNALINGNAN -4
57 
58 std::string realToHex(const real& a)
59 {
60  a_btyp* b = (a_btyp*) &a;
61  int i;
62  char cs[256];
63 
64  for (i=0; i < realwidth-19; i++) cs[i] = ' ';
65  cs[i] = 0;
66  sprintf (&cs[strlen(cs)], "%s", ((b[HIGHREAL] & 0x80000000L) ? "-" : "+"));
67  sprintf (&cs[strlen(cs)],"%c", '1');
68  sprintf (&cs[strlen(cs)],"%05lX", (b[HIGHREAL] & 0xFFFFFL));
69  sprintf (&cs[strlen(cs)],"%08lX",(long unsigned int)(b[LOWREAL]));
70  sprintf (&cs[strlen(cs)],"e%03X",(unsigned int)((b[HIGHREAL] >> 20) & 0x7FF));
71  return string(cs);
72 }
73 
74 std::string & operator<<(std::string &s, const real& a) noexcept
75 {
76 #if _WIN32
77  static __declspec(thread) char cs[256];
78 #elif __APPLE__ && !CXSC_FORCE_TLS
79  static char cs[256];
80 #else
81  static __thread char cs[256];
82 #endif
83 
84  if (ioflags.isset(IOFlags::hex))
85  {
86  a_btyp* b = (a_btyp*) &a;
87  int i;
88  char cs[256];
89 
90  for (i=0; i < realwidth-19; i++) cs[i] = ' ';
91  cs[i] = 0;
92  sprintf (&cs[strlen(cs)], "%s", ((b[HIGHREAL] & 0x80000000L) ? "-" : "+"));
93  sprintf (&cs[strlen(cs)],"%c", '1');
94  sprintf (&cs[strlen(cs)],"%05lX", (b[HIGHREAL] & 0xFFFFFL));
95  sprintf (&cs[strlen(cs)],"%08lX",(long unsigned int)(b[LOWREAL]));
96  sprintf (&cs[strlen(cs)],"e%03X",(unsigned int)((b[HIGHREAL] >> 20) & 0x7FF));
97  s+=cs;
98  } else if (ioflags.isset(IOFlags::rndnone))
99  {
100  if (IsSignalingNaN(a)) s+="<SignallingNaN>";
101  else if (IsQuietNaN(a)) s+="<QuietNaN>";
102  else if (IsInfinity(a)) s+="<Infinity>";
103  else
104  {
105  if (realdigits && realwidth)
106  sprintf (cs, "%*.*g", realwidth, realdigits, a.w); // no need for "lg"
107  else if (realwidth)
108  sprintf (cs, "%*g", realwidth, a.w);
109  else
110  sprintf (cs, "%g", a.w);
111  s+=cs;
112  }
113  } else
114  {
115  rndtype rnd;
116  a_intg length, formatflag, addblanks;
117  a_intg digits = realdigits;
118  char *str;
119 
120  if (d_init_dm () == -1)
121  {
122  // throw
123  // errmon (ERR_ALL(NOMOREMEMORY));
124  // errmon (ERR_ALL(NOCONTINUEPOSSIBLE));
125  }
126 
127  if (ioflags.isset(IOFlags::rndup))
128  rnd = RND_UP;
129  else if (ioflags.isset(IOFlags::rnddown))
130  rnd = RND_DOWN;
131  else
132  rnd = RND_NEXT;
133 
134  if (ioflags.isset(IOFlags::variable))
135  formatflag = realwidth;
136  else if (ioflags.isset(IOFlags::varfixwidth))
137  formatflag = realwidth, digits = -digits;
138  else
139  formatflag = (ioflags.isset(IOFlags::fixed)) ? 0 : -1;
140 
141  switch (r_outpx (dm, a.w, formatflag, digits, rnd, &length))
142  {
143  case WASGOOD:
144  dm[length] = 0;
145  str = dm;
146  if (*str == '+')
147  {
148  if (ioflags.isset(IOFlags::blank))
149  *str = ' ';
150  else if (ioflags.isset(IOFlags::noblank))
151  str++;
152  }
153  break;
154  case ISINFINITYPLUS:
155  str = (char*)"<+Infinity>";
156  break;
157  case ISINFINITYMINUS:
158  str = (char*)"<-Infinity>";
159  break;
160  case ISQUIETNAN:
161  str = (char*)"<QuietNaN>";
162  break;
163  case ISSIGNALINGNAN:
164  str = (char*)"<SignalingNaN>";
165  break;
166  default:
167  str = (char*)"<ERROR>";
168  break;
169  }
170  length = strlen(str);
171  addblanks = (length < realwidth) ? realwidth - length : 0;
172 
173  if (ioflags.isset(IOFlags::rightjust))
174  for (;addblanks; addblanks--)
175  s+= ' ';
176 
177  s+=str;
178 
179  for (;addblanks; addblanks--)
180  s+= ' ';
181  }
182  return s;
183 }
184 
185 std::ostream & operator <<(std::ostream &o,const real &a) noexcept
186 {
187  std::string s="";
188  s << a;
189  o << s;
190  return o;
191 }
192 
193 std::string & operator>> (std::string & str, real& a) noexcept
194 {
195  char *s=new char[str.size()+1];
196  char *orgs=s;
197  strcpy(s,str.c_str());
198 
199  if (ioflags.isset(IOFlags::hex))
200  {
201  a_btyp* b = (a_btyp*) &a;
202  a_btyp x;
203 
204  b[0] = b[1] = 0;
205  s = cskipwhitespaces (s);
206  if (*s == '-')
207  {
208  b[HIGHREAL] |= 0x80000000L;
209  s++;
210  } else if (*s == '+')
211  s++;
212 
213  // ----------------------------------------------------
214  // es wird ohne Pruefung folgendes Format vorausgestzt :
215  // 1xxxxxxxxxxxxxeXXX
216  // wobei x = HexDigits der Mantisse
217  // X = HexDigits des Exponents
218  // saemmtliche HexDigits muessen gross geschrieben sein !
219 
220  if (*s)
221  s++; // skip '1'
222  s = GetHexDigits (s, x, 5);
223  b[HIGHREAL] |= x; // get mantissa
224  s = GetHexDigits (s, x, 8);
225  b[LOWREAL] = x;
226  if (*s)
227  s++; // skip 'e'
228  s = GetHexDigits (s, x, 3);
229  b[HIGHREAL] |= x << 20; // get exponent
230  if (*s)
231  s++; // skip at least one more char
232  } else
233  {
234  rndtype rndfl;
235 
236  if (ioflags.isset(IOFlags::rndup))
237  rndfl = RND_UP;
238  else if (ioflags.isset(IOFlags::rnddown))
239  rndfl = RND_DOWN;
240  else
241  rndfl = RND_NEXT;
242 
243  str=s;
244  dotprecision dot;
245  str >> dot;
246  strcpy(s,str.c_str()); // Ooooooooohhhh... :((
247  a = rnd (dot, rndfl);
248  }
249  str=s;
250  delete [] orgs;
251  return str;
252 }
253 void operator >>(const char *a,real &b) noexcept
254 {
255  std::string c(a);
256  c>>b;
257 }
258 void operator >>(const string &a,real &b) noexcept
259 {
260  std::string c(a);
261  c>>b;
262 }
263 std::istream& operator>> (std::istream& s, real& a) noexcept
264 {
265  if (ioflags.isset(IOFlags::hex))
266  {
267  char inp[20];
268  int i;
269  char c;
270 
271  // !! There are no checks about the right input-format, it is assumed
272  // the fixed format : S1xxxxxxxxxxxxxeXXX
273  // whereby S means the sign
274  // '1' is the leading implicit binary one of the mantissa
275  // x are the mantissa hexdigits
276  // 'e' signals the beginning of the exponent
277  // X are the exponent hexdigits
278 
279  // skip white spaces and
280  // get the sign, the 14 Mantissadigits and the exponent
281  // (total 19 chars)
282 
283  c = skipwhitespaces (s);
284  for (i=0; i < 19; i++)
285  {
286  inp[i] = c;
287  if (s.good()) s.get(c); else c = '\0';
288  }
289  inp[i] = '\0';
290 
291  inp >> a;
292  } else
293  {
294  rndtype rndfl;
295 
296  if (ioflags.isset(IOFlags::rndup))
297  rndfl = RND_UP;
298  else if (ioflags.isset(IOFlags::rnddown))
299  rndfl = RND_DOWN;
300  else
301  rndfl = RND_NEXT;
302 
303  dotprecision dot;
304  s >> dot;
305  a = rnd (dot, rndfl);
306  }
307  return s;
308 }
309 
310 //----------------------------------------------------------------------------
311 // GetHexDigits
312 //
313 // Interpretiert die naechsten "count" Zeichen aus dem String "s"
314 // als HexDigits, der binaere Wert wird dann in "x" zurueckgegeben.
315 // Als Returnwert wird ein Zeiger auf die Stringposition nach den
316 // HexDigits zurueckgegeben.
317 
318 char* GetHexDigits (char* s, a_btyp& x, int count)
319 {
320  int i, c;
321 
322  for (x=0,i=0; i < count && *s; s++,i++) {
323  if ((c = *s) >= 'A') c -= 'A' - 10; else c -= '0';
324  if (c < 0 || c > 0xF) c = 0;
325  x = (x << 4) | c;
326  }
327  return s;
328 }
329 
330 } // namespace cxsc
331 
332 /****************************************************************/
333 /* */
334 /* Filename : r_outpx.c */
335 /* */
336 /* Entries : void r_outp */
337 /* (buffer,s,FormatFlag, */
338 /* FracDigits,rnd,length) */
339 /* char *buffer; */
340 /* a_real s; */
341 /* a_intg rnd,FormatFlag,FracDigits; */
342 /* a_intg *length; */
343 /* */
344 /* Arguments : buffer - output buffer holding string */
345 /* s - IEEE value */
346 /* FormatFlag - format selection */
347 /* -1 = scientific format */
348 /* 0 = fixed format */
349 /* > 0 = variable format */
350 /* value is the total field */
351 /* width */
352 /* FracDigits - number of fraction digits*/
353 /* rnd - rounding mode */
354 /* -1 = round downwards */
355 /* 0 = round to nearest */
356 /* 1 = round upwards */
357 /* length - size of buffer string */
358 /* */
359 /* Description : Convert an IEEE double format number */
360 /* to a character string. */
361 /* */
362 /****************************************************************/
363 
364 /*#ifndef ALL_IN_ONE
365 #ifdef AIX
366 #include "/u/p88c/runtime/o_defs.h"
367 #else
368 #include "o_defs.h"
369 #endif
370 #define local
371 #endif*/
372 
373 namespace cxsc {
374 
375 #define WASGOOD 0
376 #define ISINFINITYPLUS -1
377 #define ISINFINITYMINUS -2
378 #define ISQUIETNAN -3
379 #define ISSIGNALINGNAN -4
380 
381 #define MANT_INFINITY(a) ((a)[0]==HIDDEN_BIT && (a)[1]==ZERO)
382 #define SIGNALING(a) ((a) & SIGNAL_BIT)
383 #define SIGNAL_BIT ((a_btyp)0x00080000L)
384 
385 int r_outpx(char *buffer, a_real s, a_intg FormatFlag,
386  a_intg FracDigits, a_intg rnd, a_intg *length)
387 {
388  a_intg ActWidth,DecPlaces,expo,IntDigits,MinNumChars;
389  a_intg dexpo,digits,bdp,k,l,addpoint;
390  a_intg HoldWidth = (FracDigits < 0);
391  a_bool vz,zero;
392  a_btyp mant[BSIZE];
393 
394  if (HoldWidth)
395  FracDigits = -FracDigits;
396  *length = 0;
397 
398  zero = b_deko(s,&expo,mant,&vz);
399 
400 /* */
401 /* infinity or NaN */
402 /* */
403  if (expo>EXPO_MAX)
404  {
405  if (MANT_INFINITY(mant))
406  { /* Infinity */
407  k = (vz) ? ISINFINITYMINUS : ISINFINITYPLUS;
408  } else
409  { /* NaN */
410  k = (SIGNALING(mant[0])) ? ISSIGNALINGNAN : ISQUIETNAN;
411  }
412  return k;
413  }
414 
415  for (k=D_U_RATIO;k<BSIZE;k++)
416  mant[k] = ZERO;
417 
418  if (vz)
419  rnd = -rnd;
420 
421  if (FormatFlag > 0 && FormatFlag-FracDigits <= 2)
422  {
423  FormatFlag = FracDigits+3;
424  }
425  if (!zero && FormatFlag > 0)
426  {
427  dexpo = (a_intg) ((expo*30103L)/100000L);
428  if (dexpo < -((FracDigits+1)/2) ||
429  (dexpo > 0 && dexpo >= FormatFlag-FracDigits-2))
430  {
431  FormatFlag = -1;
432  if (HoldWidth)
433  {
434  FracDigits = (FracDigits < 5) ? 0 : FracDigits-5;
435  }
436  }
437  }
438 
439  if (expo>800)
440  bdp = (BUFFERSIZE-8)-(FormatFlag == -1 ? 0 : FracDigits);
441  else if (expo<-800)
442  bdp = 8;
443  else
444  bdp = B_D_P;
445 
446  addpoint = (FracDigits == 0) ? 0 : 1;
447 /* */
448 /* floating-point representation */
449 /* */
450  if (FormatFlag == -1)
451  {
452  DecPlaces = FracDigits;
453  ActWidth = DecPlaces+ExpDigits+4+addpoint;
454 /* */
455 /* number is zero */
456 /* */
457  if (zero)
458  {
459  *buffer++ = (vz) ? '-' : '+';
460  *buffer++ = '0';
461  if (FracDigits)
462  {
463  *buffer++ = XSC_DECIMAL_POINT;
464  for (k=0;k<DecPlaces;k++) *buffer++ = '0';
465  }
466  *buffer++ = EXPONENT_E;
467  *buffer++ = PLUS_SIGN;
468  for (k=0;k<ExpDigits;k++)
469  *buffer++ = '0';
470 
471  *length = ActWidth;
472 
473  return WASGOOD;
474  }
475 /* */
476 /* determine output string */
477 /* */
478  digits = DecPlaces+(1+2);
479  dexpo = -1;
480  b_out(mant,expo,digits,buffer,&bdp,&dexpo);
481 
482  if (dexpo>0 && dexpo>DecPlaces+2)
483  digits = dexpo+1;
484 
485  b_rnd(rnd,buffer,digits,DecPlaces+1,&bdp,&dexpo);
486 
487  if (FracDigits)
488  {
489  buffer[bdp-dexpo-1] = buffer[bdp-dexpo];
490  buffer[bdp-dexpo] = XSC_DECIMAL_POINT;
491  }
492  buffer[bdp-dexpo+DecPlaces+1] = EXPONENT_E;
493  buffer[bdp-dexpo+DecPlaces+2] = (dexpo<0) ? MINUS_SIGN : PLUS_SIGN;
494  expo = (dexpo<0) ? -dexpo : dexpo;
495  for (k=ExpDigits;k>0;k--)
496  {
497  buffer[bdp-dexpo+DecPlaces+2+k] = expo%10+'0';
498  expo /= 10;
499  }
500  *length = 2+addpoint+DecPlaces+2+ExpDigits;
501 
502  l = bdp - 1 - addpoint - dexpo;
503  buffer[l] = (vz) ? '-' : '+';
504  for (k=0;k<*length;k++,l++)
505  buffer[k] = buffer[l];
506  } else
507 /* */
508 /* fixed-point representation */
509 /* */
510  {
511 /* */
512 /* number is zero */
513 /* */
514  if (zero)
515  {
516  *length = FracDigits+2+addpoint;
517  *buffer++ = (vz) ? '-' : '+';
518  *buffer++ = '0';
519  if (FracDigits)
520  {
521  *buffer++ = XSC_DECIMAL_POINT;
522  for (k=0;k<FracDigits;k++)
523  *buffer++ = '0';
524  }
525  return WASGOOD;
526  }
527 
528  /* estimate number of decimal digits */
529  if (expo>=0)
530  {
531  IntDigits = ((expo+1)*61)/200+1;
532  } else
533  {
534  IntDigits = 0;
535  dexpo = 0;
536  }
537 
538  /* fill fractional part with zeros */
539  for (k=0;k<=FracDigits+2;k++)
540  buffer[bdp+k] = '0';
541 
542  digits = IntDigits+FracDigits+2;
543  b_out(mant,expo,digits,buffer,&bdp,&dexpo);
544 
545  /* correct setting of IntDigits */
546  if (expo>=0)
547  {
548  IntDigits = dexpo+1;
549  } else
550  {
551  IntDigits = 1;
552  digits++;
553  }
554 
555  b_rnd(rnd,buffer,digits,IntDigits+FracDigits,&bdp,&dexpo);
556 
557  /* correct setting of IntDigits after rounding */
558  IntDigits = dexpo+1;
559 
560  /* value is zero after rounding; */
561  if (vz)
562  {
563  for (k=(bdp+1)-IntDigits;k<(bdp+1)+FracDigits;k++)
564  {
565  if (buffer[k]!='0')
566  break;
567  }
568  if (k==(bdp+1)+FracDigits)
569  vz = FALSE;
570  }
571 
572  MinNumChars = IntDigits+FracDigits+1+addpoint;
573 
574  if (FracDigits)
575  {
576  /* generate decimal point */
577  for (k=bdp-IntDigits;k<bdp;k++)
578  buffer[k] = buffer[k+1];
579  buffer[bdp] = XSC_DECIMAL_POINT;
580  }
581 
582  *length = MinNumChars;
583 /* */
584 /* sign of number */
585 /* */
586  l = bdp - 1 - addpoint - dexpo;
587  buffer[l] = (vz) ? '-' : '+';
588  for (k=0;k<*length;k++,l++)
589  buffer[k] = buffer[l];
590  }
591 
592  return WASGOOD;
593 }
594 
595 } // namespace cxsc
596 
The Data Type dotprecision.
Definition: dot.hpp:112
The Scalar Type real.
Definition: real.hpp:114
The namespace cxsc, providing all functionality of the class library C-XSC.
Definition: cdot.cpp:29
bool IsQuietNaN(const real &a)
Returns if the given real value represents the value of a quiet NaN.
bool IsSignalingNaN(const real &a)
Returns if the given real value represents the value of a signaling NaN.
string realToHex(const real &a)
Returns a real number in hexadecimal format as string.
Definition: realio.cpp:58
bool IsInfinity(const real &a)
Returns if the given real value represents the value infinity.