|
From: <wa...@us...> - 2003-03-26 04:51:04
|
Update of /cvsroot/pywebsvcs/SOAPpy/SOAPpy In directory sc8-pr-cvs1:/tmp/cvs-serv17473 Modified Files: SOAP.py Added Files: ieee754.py Log Message: - Added ieee754.py, which handles checking for IEEE 754 special values: Inf, -Inf, NaN, ... - Updated SOAP.py to use the new ieee754 module instead of the old (broken) windows hack. --- NEW FILE: ieee754.py --- """Utilities for handling IEEE 754 special values This class implements constants and functions for working with IEEE754 double-precision special values. It provides constants for NaN (Not a Number), NegInf (Negative Infinity), PosInf (Positive Infinity), and Inf (also Positive Infinity), as well as functions to test for these values. The code is implemented in pure python by taking advantage of the 'struck' standard module. Some efficiency could be gained by translating the core routines into C. See <http://babbage.cs.qc.edu/courses/cs341/IEEE-754references.html> for a description of the IEEE 754 floating point standard. Author: Gregory R. Warnes <gre...@gr...> Date:: 2003-03-25 Version 0.5.0 """ ident = "$Id: ieee754.py,v 1.1 2003/03/26 04:51:00 warnes Exp $" __version__ = "0.5.0" from struct import pack, unpack # check endianess _big_endian = pack('i',1)[0] != '\x01' # and define appropriate constants if(_big_endian): HW=0 LW=1 NaN = unpack('d', '\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF')[0] Inf = unpack('d', '\x7F\xF0\x00\x00\x00\x00\x00\x00')[0] PosInf = Inf NegInf = -Inf else: HW=1 LW=0 NaN = unpack('d', '\x00\x00\x00\x00\x00\x00\xf8\xff')[0] Inf = unpack('d', '\x00\x00\x00\x00\x00\x00\xf0\x7f')[0] PosInf = Inf NegInf = -Inf def _double_as_longs(dval): "Use unpack to decode a double precision float into two long integers" tmp = unpack('ll',pack('d', dval)) return (tmp[HW], tmp[LW] ) ## ## Functions to extract components of the IEEE 754 floating point format ## def sign(dval): "Extract the sign bit from a double-precision floating point value" ll = _double_as_longs(dval) return ll[0] >> 31 & 0x01 def exponent(dval): """Extract the exponentent bits from a double-precision floating point value. Note that for normalized values, the exponentdent bits have an offset of 1023. As a consequence, the actual exponentent is obtained by subtracting 1023 for the value returned by this function """ ll = _double_as_longs(dval) return ( ll[0] >> 20 ) & 0x7ff def mantissa(dval): ll = _double_as_longs(dval) mantissa1 = ( ll[0] & 0xfffffL ) << 32 mantissa2 = ll[1] return mantissa1 + mantissa2 ## ## Functions to test for IEEE 754 special values ## def is_NaN(value): "Determine if the argument is a IEEE 754 NaN (Not a Number) value." return ( exponent(value)==0x7ff and mantissa(value)!=0 ) def is_Infinite(value): """Determine if the argument is an infinite IEEE 754 value (positive or negative inifinity)""" return ( exponent(value)==0x7ff and mantissa(value)== 0 ) def is_Finite(value): """Determine if the argument is an finite IEEE 754 value (i.e., is not NaN, positive or negative inifinity)""" return ( exponent(value)!=0x7ff ) def is_Inf(value): "Determine if the argument is a IEEE 754 positive infinity value" return ( sign(value)==0 and exponent(value)==0x7ff \ and mantissa(value)== 0 ) is_PosInf = is_Inf def is_NegInf(value): "Determine if the argument is a IEEE 754 negative infinity value" return ( sign(value)==1 and exponent(value)==0x7ff and \ mantissa(value)== 0 ) Index: SOAP.py =================================================================== RCS file: /cvsroot/pywebsvcs/SOAPpy/SOAPpy/SOAP.py,v retrieving revision 1.21 retrieving revision 1.22 diff -u -d -r1.21 -r1.22 --- SOAP.py 25 Mar 2003 20:53:38 -0000 1.21 +++ SOAP.py 26 Mar 2003 04:51:00 -0000 1.22 @@ -94,6 +94,7 @@ import SocketServer from XMLname import toXMLname, fromXMLname from types import * +import ieee754 try: from M2Crypto import SSL except: pass @@ -102,16 +103,6 @@ __version__ = "0.9.9-pre1" -# Platform hackery - -# Check float support -try: - float("NaN") - float("INF") - float("-INF") - good_float = 1 -except: - good_float = 0 ################################################################################ # Exceptions @@ -1975,7 +1966,7 @@ if self._next == "E": if name[1] != 'Envelope': - raise Error, "expected `SOAP-ENV:Envelope', got `%s:%s'" % \ + raise Error, "expected `SOAP-ENV:Envelope', gto `%s:%s'" % \ (self._prem_r[name[0]], name[1]) if name[0] != NS.ENV: raise faultType, ("%s:VersionMismatch" % NS.ENV_T, @@ -2681,27 +2672,23 @@ if self.floatlimits.has_key (t[1]): l = self.floatlimits[t[1]] s = d.strip().lower() - try: - d = float(s) - except: - # Some platforms don't implement the float stuff. This - # is close, but NaN won't be > "INF" as required by the - # standard. - if s in ("nan", "inf"): - return 1e300**2 - if s == "-inf": - return -1e300**2 + if s == "nan": + return ieee754.NaN + elif s == "inf": + return ieee754.PosInf + elif s == "-inf": + return ieee754.NegInf - raise + d = float(s) - if str (d) == 'nan': + if str(d).lower() == 'nan': if s != 'nan': raise ValueError, "invalid %s" % t[1] - elif str (d) == '-inf': + elif str(d).lower() == '-inf': if s != '-inf': raise UnderflowError, "%s too small" % t[1] - elif str (d) == 'inf': + elif str(d).lower() == 'inf': if s != 'inf': raise OverflowError, "%s too large" % t[1] elif d < 0: @@ -3124,18 +3111,14 @@ "id": id, "attrs": a} def dump_float(self, obj, tag, typed = 1, ns_map = {}): - # Terrible windows hack - if not good_float: - if obj == float(1e300**2): - obj = "INF" - elif obj == float(-1e300**2): - obj = "-INF" - - obj = str(obj) - if obj in ('inf', '-inf'): - obj = str(obj).upper() - elif obj == 'nan': - obj = 'NaN' + if ieee754.is_PosInf(obj): + obj = "INF" + elif ieee754.is_NegInf(obj): + obj = "-INF" + elif ieee754.is_NaN(obj): + obj = "NaN" + else: + obj = str(obj) # Note: python 'float' is actually a SOAP 'double'. self.out.append(self.dumper(None, "double", obj, tag, typed, ns_map, |