This is the mail archive of the libstdc++@sourceware.cygnus.com mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Patch: `>>' can't read what `<<' produced: NaNs and Inf


Hi,

I enclose a diff against a clean egcs-1.1.2/libio/iovfscanf.c and a test
file to show the patch effect. The patch applies also cleanly to
libstdc++-2.90.4, but I have not tested it with that distribution.

Implementing the changes at this level will affect all derived classes.
I have relinked some C++ applications with the newly created lib and
they work OK.

The decision to implement the changes only at iovfscanf.c and not also
at floatconv.c, _IO_strtod(), was due to a conditional compilation at
iovfscanf.c that could imply that in some platforms the system atof()
would be used, with no warranty that it would be able to read inf/nan's.
This makes the patch a bit ugly.

The test case, teste2.cc, should produce the following output:

1. -INF +INF    INF
   -Infinity    Infinity        Infinity
2. -Inf +Inf    Inf
   -Infinity    Infinity        Infinity
3. -inf +inf    inf
   -Infinity    Infinity        Infinity
4. -infI        +iNfiN  iNfInity
   -Infinity    Infinity        Infinity
5. -nan +nan    nan
   -NaN -NaN    -NaN
6. -NaN +NaN    NaN
   -NaN -NaN    -NaN
7. -NAN +NAN    NAN
   -NaN -NaN    -NaN
8. -NAN(0x123123)       +NaN(0x5464)    nan(0x34)
   -NaN -NaN    -NaN
9. -121.12      NaN     +3123.4 Inf     0.232
   -121.12      -NaN    3123.4  Infinity        0.232


If you have any problem with the patch, please contact me or
<ajc@inescn.pt>, the real code writer.

Hopping that this will be accepted,

Joao

-- 
Joao Cardoso, INESC  |  e-mail: jcardoso@inescn.pt
R. Jose Falcao 110   |  tel:    + 351 2 2094345
4050 Porto, Portugal |  fax:    + 351 2 2008487

#include <strstream.h>
#include <ieeefp.h>

main(){
	
    double x=1./0., y=0./0.;
	double  a=0.1, b=0.1, d=0.1, e=0.1, f=0.1, g=0.1, h=0.1, j=0.1;
    char c, buf[100];

    ostrstream os(buf,100);
    istrstream is(buf,100);

    os << "-INF\t" << "+INF\t" << "INF" << '\0';
	is >> a >> c  >> b >> c  >> d >> c;
	if (finite(a) || finite(b) || finite(d))
		cout << "1- Error\n";
	cout << "1. " << buf << "\n   " << a << "\t" << b << "\t" << d << '\n';

	os.seekp(ios::beg);
	is.seekg(0L,ios::beg);
	
    os << "-Inf\t" << "+Inf\t" << "Inf" << '\0';
	is >> a >> c  >> b >> c  >> d >> c;
	if (finite(a) || finite(b) || finite(d))
		cout << "2- Error\n";
	cout << "2. " << buf << "\n   " << a << "\t" << b << "\t" << d << '\n';

	os.seekp(ios::beg);
	is.seekg(0L,ios::beg);
	
    os << "-inf\t" << "+inf\t" << "inf" << '\0';
	is >> a >> c  >> b >> c  >> d >> c;
	if (finite(a) || finite(b) || finite(d))
		cout << "3- Error\n";
	cout << "3. " << buf << "\n   " << a << "\t" << b << "\t" << d << '\n';


	os.seekp(ios::beg);
	is.seekg(0L,ios::beg);
	
    os << "-infI\t" << "+iNfiN\t" << "iNfInity" << '\0';
	is >> a >> c  >> b >> c  >> d >> c;
	if (finite(a) || finite(b) || finite(d))
		cout << "4- Error\n";	
	cout << "4. " << buf << "\n   " << a << "\t" << b << "\t" << d << '\n';

	os.seekp(ios::beg);
	is.seekg(0L,ios::beg);
	
    os << "-nan\t" << "+nan\t" << "nan" << '\0';
	is >> a >> c  >> b >> c  >> d >> c;
	if (!isnand(a) || !isnand(b) || !isnand(d))
		cout << "5- Error\n";	
	cout << "5. " << buf << "\n   " << a << "\t" << b << "\t" << d << '\n';

	os.seekp(ios::beg);
	is.seekg(0L,ios::beg);

    os << "-NaN\t" << "+NaN\t" << "NaN" << '\0';
	is >> a >> c  >> b >> c  >> d >> c;
	if (!isnand(a) || !isnand(b) || !isnand(d))
		cout << "6- Error\n";		    	
	cout << "6. " << buf << "\n   " << a << "\t" << b << "\t" << d << '\n';

	os.seekp(ios::beg);
	is.seekg(0L,ios::beg);
	
    os << "-NAN\t" << "+NAN\t" << "NAN" << '\0';
	is >> a >> c  >> b >> c  >> d >> c;
	if (!isnand(a) || !isnand(b) || !isnand(d))
		cout << "7- Error\n";		    		
	cout << "7. " << buf << "\n   " << a << "\t" << b << "\t" << d << '\n';

	os.seekp(ios::beg);
	is.seekg(0L,ios::beg);

    os << "-NAN(0x123123)\t" << "+NaN(0x5464)\t" << "nan(0x34)" << '\0';
	is >> a >> c  >> b >> c  >> d >> c;
	if (!isnand(a) || !isnand(b) || !isnand(d))
		cout << "8- Error\n";		    			
	cout << "8. " << buf << "\n   " << a << "\t" << b << "\t" << d << '\n';

	os.seekp(ios::beg);
	is.seekg(0L,ios::beg);
	
    os << "-121.12\t" << "NaN\t" << "+3123.4\t" << "Inf\t" << "0.232" << '\0';
	is >> a >> c  >> b >> c  >> d >> c >> e >> c >> f;
	if (a != -121.12 || !isnand(b) || d != 3123.4 || finite(e) || f != 0.232)
		cout << "9- Error\n";		    				
	cout << "9. " << buf << "\n   " << a << "\t" << b << "\t" << d << "\t" << e << "\t" << f <<'\n';
}

*** iovfscanf.c.org	Sat Apr 10 04:10:34 1999
--- iovfscanf.c	Sat Apr 10 05:03:34 1999
***************
*** 81,86 ****
--- 81,88 ----
   * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point;
   * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral.
   */
+ #define	NNAN		0x02
+ #define	NINF		0x04
  #define	SIGNOK		0x40	/* +/- is (still) legal */
  #define	NDIGITS		0x80	/* no digits detected */
  
***************
*** 627,632 ****
--- 629,641 ----
  						goto fok;
  					}
  					break;
+ 				case 'n': case 'N': case 'i': case 'I':
+ 					flags|=NNAN;
+ 				case 'f': case 't': case 'y': case 'a':
+ 				case 'F': case 'T': case 'Y': case 'A':
+ 				case 'x': case 'X': case '(': case ')':
+ 					if(flags&NNAN)
+                                         	goto fok;
  				}
  				break;
  		fok:
***************
*** 637,642 ****
--- 646,659 ----
  				    break;	/* EOF */
  				}
  			}
+ 
+ 			if (flags & NNAN) {
+ 				flags|=NDIGITS|EXPOK;
+ 				if((flags & SIGNOK)==0)
+ 					if ((*buf!='+')&&(*buf!='-'))
+ 						flags|=SIGNOK;
+ 			}
+ 
  			/*
  			 * If no digits, might be missing exponent digits
  			 * (just give back the exponent) or might be missing
***************
*** 644,654 ****
  			 */
  			if (flags & NDIGITS) {
  				if (flags & EXPOK) {
! 					/* no digits at all */
! 					while (p > buf)
  					    _IO_ungetc (*(u_char *)--p, fp);
! 					goto match_failure;
! 				}
  				/* just a bad exponent (e and maybe sign) */
  				c = *(u_char *)--p;
  				if (c != 'e' && c != 'E') {
--- 661,706 ----
  			 */
  			if (flags & NDIGITS) {
  				if (flags & EXPOK) {
! 					    int sign;
! 					    double res;
! 					    char *s;
! 
! 					    sign=1;
! 					    s=buf;
! 					    flags&=~(NINF|NNAN);
! 					    if((flags & SIGNOK)==0)
!   					        sign= (*s++=='-')? -1: 1;
! 
! 					    if(*s=='I'||*s=='i') {
! 						++s;
! 						if(*s=='N'||*s=='n') {
! 						    ++s;
! 						    if(*s=='F'||*s=='f')
! 							flags|=NINF;
! 						}
! 					    }
! 					    else if(*s=='N'||*s=='n') {
! 						++s;
! 						if(*s=='A'||*s=='a') {
! 						       ++s;
! 						       if(*s=='N'||*s=='n')
! 							   flags|=NNAN;
! 						}
! 					   }
! 					   if (flags&(NINF|NNAN)) {
! 						nassigned++;
!                                            	res= (double)sign*(((flags & NINF))?1.0/0.:0./0.);
! 				           	if (flags & LONG)
!                                                 	*va_arg(ap, double *) = res;
!                                             	else
!                                                 	*va_arg(ap, float *) = res;
! 					    	break;
! 					  }
! 					  /* no digits at all */
! 					  while (p > buf)
  					    _IO_ungetc (*(u_char *)--p, fp);
! 					  goto match_failure;
! 					}
  				/* just a bad exponent (e and maybe sign) */
  				c = *(u_char *)--p;
  				if (c != 'e' && c != 'E') {

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]