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
32namespace cxsc {
33
34int d_init_dm (void);
35void d_outp(char *buffer, Dotprecision c,
36 int FormatFlag, int FracDigits, int rnd,
37 int *length);
38
39#if _WIN32
40extern __declspec(thread) char *dm;
41#elif __APPLE__ && !CXSC_FORCE_TLS
42extern char *dm;
43#else
44extern __thread char *dm;
45#endif
46
47
48char* GetHexDigits (char* s, a_btyp& x, int count);
49
50int 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
58std::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
74std::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
185std::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
193std::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}
253void operator >>(const char *a,real &b) noexcept
254{
255 std::string c(a);
256 c>>b;
257}
258void operator >>(const string &a,real &b) noexcept
259{
260 std::string c(a);
261 c>>b;
262}
263std::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
318char* 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
373namespace 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
385int 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.