digitalmars.D.bugs - [Issue 5811] New: [patch] std.conv.parse isFloatingPoint!Target doesn't parse "inf"/"-inf" with input ranges
- d-bugmail puremagic.com (302/302) Apr 03 2011 http://d.puremagic.com/issues/show_bug.cgi?id=5811
- d-bugmail puremagic.com (13/13) Aug 09 2011 http://d.puremagic.com/issues/show_bug.cgi?id=5811
http://d.puremagic.com/issues/show_bug.cgi?id=5811 Summary: [patch] std.conv.parse isFloatingPoint!Target doesn't parse "inf"/"-inf" with input ranges Product: D Version: D2 Platform: Other OS/Version: Windows Status: NEW Keywords: patch Severity: normal Priority: P2 Component: Phobos AssignedTo: nobody puremagic.com ReportedBy: sandford jhu.edu --- Comment #0 from Rob Jacques <sandford jhu.edu> 2011-04-03 17:58:52 PDT --- I ran into a problem with parse!real(r), when r was a strict input range, r contained "inf" or "-inf" and "inf" wasn't the only item parsed from the stream. The patch simply consists of moving inf detection from the sign detection switch to right after the nan detection section, which I copy/paste/modified to inf. [Patch] DMD 2.052 (line 1301 in Github at time of posting) Target parse(Target, Source)(ref Source p) if (isInputRange!Source && /*!isSomeString!Source && */isFloatingPoint!Target) { static immutable real negtab[14] = [ 1e-4096L,1e-2048L,1e-1024L,1e-512L,1e-256L,1e-128L,1e-64L,1e-32L, 1e-16L,1e-8L,1e-4L,1e-2L,1e-1L,1.0L ]; static immutable real postab[13] = [ 1e+4096L,1e+2048L,1e+1024L,1e+512L,1e+256L,1e+128L,1e+64L,1e+32L, 1e+16L,1e+8L,1e+4L,1e+2L,1e+1L ]; // static immutable string infinity = "infinity"; // static immutable string nans = "nans"; ConvException bailOut(string f = __FILE__, size_t n = __LINE__) (string msg = null) { if (!msg) msg = "Floating point conversion error"; return new ConvException(text(f, ":", n, ": ", msg, " for input \"", p, "\".")); } for (;;) { enforce(!p.empty, bailOut()); if (!isspace(p.front)) break; p.popFront(); } char sign = 0; /* indicating + */ switch (p.front) { case '-': sign++; p.popFront(); enforce(!p.empty, bailOut()); break; case '+': p.popFront(); enforce(!p.empty, bailOut()); break; default: {} } bool isHex = false; bool startsWithZero = p.front == '0'; if(startsWithZero) { p.popFront(); if(p.empty) { return (sign) ? -0 : 0; } isHex = p.front == 'x' || p.front == 'X'; } real ldval = 0.0; char dot = 0; /* if decimal point has been seen */ int exp = 0; long msdec = 0, lsdec = 0; ulong msscale = 1; if (isHex) { int guard = 0; int anydigits = 0; uint ndigits = 0; p.popFront(); while (!p.empty) { int i = p.front; while (isxdigit(i)) { anydigits = 1; i = isalpha(i) ? ((i & ~0x20) - ('A' - 10)) : i - '0'; if (ndigits < 16) { msdec = msdec * 16 + i; if (msdec) ndigits++; } else if (ndigits == 16) { while (msdec >= 0) { exp--; msdec <<= 1; i <<= 1; if (i & 0x10) msdec |= 1; } guard = i << 4; ndigits++; exp += 4; } else { guard |= i; exp += 4; } exp -= dot; p.popFront(); if (p.empty) break; i = p.front; } if (i == '.' && !dot) { p.popFront(); dot = 4; } else break; } // Round up if (guard && (sticky || odd)) if (guard & 0x80 && (guard & 0x7F || msdec & 1)) { msdec++; if (msdec == 0) // overflow { msdec = 0x8000000000000000L; exp++; } } enforce(anydigits, bailOut()); enforce(!p.empty && (p.front == 'p' || p.front == 'P'), bailOut("Floating point parsing: exponent is required")); char sexp; int e; sexp = 0; p.popFront(); if (!p.empty) { switch (p.front) { case '-': sexp++; case '+': p.popFront(); enforce(!p.empty, new ConvException("Error converting input" " to floating point")); default: {} } } ndigits = 0; e = 0; while (!p.empty && isdigit(p.front)) { if (e < 0x7FFFFFFF / 10 - 10) // prevent integer overflow { e = e * 10 + p.front - '0'; } p.popFront(); ndigits = 1; } exp += (sexp) ? -e : e; enforce(ndigits, new ConvException("Error converting input" " to floating point")); if (msdec) { int e2 = 0x3FFF + 63; // left justify mantissa while (msdec >= 0) { msdec <<= 1; e2--; } // Stuff mantissa directly into real *cast(long *)&ldval = msdec; (cast(ushort *)&ldval)[4] = cast(ushort) e2; // Exponent is power of 2, not power of 10 ldval = ldexpl(ldval,exp); } goto L6; } else // not hex { if (toupper(p.front) == 'N' && !startsWithZero) { // nan enforce((p.popFront(), !p.empty && toupper(p.front) == 'A') && (p.popFront(), !p.empty && toupper(p.front) == 'N'), new ConvException("error converting input to floating point")); // skip past the last 'n' p.popFront(); return typeof(return).nan; } if (toupper(p.front) == 'I' && !startsWithZero) { // inf enforce((p.popFront(), !p.empty && toupper(p.front) == 'N') && (p.popFront(), !p.empty && toupper(p.front) == 'F'), new ConvException("error converting input to floating point")); // skip past the last 'n' p.popFront(); return sign ? -Target.infinity : Target.infinity; } bool sawDigits = startsWithZero; while (!p.empty) { int i = p.front; while (isdigit(i)) { sawDigits = true; /* must have at least 1 digit */ if (msdec < (0x7FFFFFFFFFFFL-10)/10) msdec = msdec * 10 + (i - '0'); else if (msscale < (0xFFFFFFFF-10)/10) { lsdec = lsdec * 10 + (i - '0'); msscale *= 10; } else { exp++; } exp -= dot; p.popFront(); if (p.empty) break; i = p.front; } if (i == '.' && !dot) { p.popFront(); dot++; } else { break; } } enforce(sawDigits, new ConvException("no digits seen")); } if (!p.empty && (p.front == 'e' || p.front == 'E')) { char sexp; int e; sexp = 0; p.popFront(); enforce(!p.empty, new ConvException("Unexpected end of input")); switch (p.front) { case '-': sexp++; case '+': p.popFront(); default: {} } bool sawDigits = 0; e = 0; while (!p.empty && isdigit(p.front)) { if (e < 0x7FFFFFFF / 10 - 10) // prevent integer overflow { e = e * 10 + p.front - '0'; } p.popFront(); sawDigits = 1; } exp += (sexp) ? -e : e; enforce(sawDigits, new ConvException("No digits seen.")); } ldval = msdec; if (msscale != 1) /* if stuff was accumulated in lsdec */ ldval = ldval * msscale + lsdec; if (ldval) { uint u = 0; int pow = 4096; while (exp > 0) { while (exp >= pow) { ldval *= postab[u]; exp -= pow; } pow >>= 1; u++; } while (exp < 0) { while (exp <= -pow) { ldval *= negtab[u]; enforce(ldval != 0, new ConvException("Range error")); exp += pow; } pow >>= 1; u++; } } L6: // if overflow occurred enforce(ldval != core.stdc.math.HUGE_VAL, new ConvException("Range error")); L1: return (sign) ? -ldval : ldval; } -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 03 2011
http://d.puremagic.com/issues/show_bug.cgi?id=5811 Kenji Hara <k.hara.pg gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |RESOLVED CC| |k.hara.pg gmail.com Resolution| |DUPLICATE --- Comment #1 from Kenji Hara <k.hara.pg gmail.com> 2011-08-09 19:07:34 PDT --- This problem was already fixed. *** This issue has been marked as a duplicate of issue 3369 *** -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Aug 09 2011