1 """Utilities for handling IEEE 754 floating point special values
3 This python module implements constants and functions for working with
4 IEEE754 double-precision special values. It provides constants for
5 Not-a-Number (NaN), Positive Infinity (PosInf), and Negative Infinity
6 (NegInf), as well as functions to test for these values.
8 The code is implemented in pure python by taking advantage of the
9 'struct' standard module. Care has been taken to generate proper
10 results on both big-endian and little-endian machines. Some efficiency
11 could be gained by translating the core routines into C.
13 See <http://babbage.cs.qc.edu/courses/cs341/IEEE-754references.html>
14 for reference material on the IEEE 754 floating point standard.
16 Further information on this package is available at
17 <http://www.analytics.washington.edu/statcomp/projects/rzope/fpconst/>.
19 ------------------------------------------------------------------
20 Author: Gregory R. Warnes <Gregory.R.Warnes@Pfizer.com>
23 Copyright: (c) 2003-2005 Pfizer, Licensed to PSF under a Contributor Agreement
24 License: Licensed under the Apache License, Version 2.0 (the"License");
25 you may not use this file except in compliance with the License.
26 You may obtain a copy of the License at
28 http://www.apache.org/licenses/LICENSE-2.0
30 Unless required by applicable law or agreed to in
31 writing, software distributed under the License is
32 distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
33 CONDITIONS OF ANY KIND, either express or implied. See
34 the License for the specific language governing
35 permissions and limitations under the License.
36 ------------------------------------------------------------------
40 ident = "$Id: fpconst.py,v 1.16 2005/02/24 17:42:03 warnes Exp $"
42 import struct, operator
45 _big_endian = struct.pack('i',1)[0] != '\x01'
47 # and define appropriate constants
49 NaN = struct.unpack('d', '\x7F\xF8\x00\x00\x00\x00\x00\x00')[0]
50 PosInf = struct.unpack('d', '\x7F\xF0\x00\x00\x00\x00\x00\x00')[0]
53 NaN = struct.unpack('d', '\x00\x00\x00\x00\x00\x00\xf8\xff')[0]
54 PosInf = struct.unpack('d', '\x00\x00\x00\x00\x00\x00\xf0\x7f')[0]
57 def _double_as_bytes(dval):
58 "Use struct.unpack to decode a double precision float into eight bytes"
59 tmp = list(struct.unpack('8B',struct.pack('d', dval)))
65 ## Functions to extract components of the IEEE 754 floating point format
69 "Extract the sign bit from a double-precision floating point value"
70 bb = _double_as_bytes(dval)
71 return bb[0] >> 7 & 0x01
74 """Extract the exponentent bits from a double-precision floating
77 Note that for normalized values, the exponent bits have an offset
78 of 1023. As a consequence, the actual exponentent is obtained
79 by subtracting 1023 from the value returned by this function
81 bb = _double_as_bytes(dval)
82 return (bb[0] << 4 | bb[1] >> 4) & 0x7ff
85 """Extract the _mantissa bits from a double-precision floating
88 bb = _double_as_bytes(dval)
89 mantissa = bb[1] & 0x0f << 48
90 mantissa += bb[2] << 40
91 mantissa += bb[3] << 32
95 def _zero_mantissa(dval):
96 """Determine whether the mantissa bits of the given double are all
98 bb = _double_as_bytes(dval)
99 return ((bb[1] & 0x0f) | reduce(operator.or_, bb[2:])) == 0
102 ## Functions to test for IEEE 754 special values
106 "Determine if the argument is a IEEE 754 NaN (Not a Number) value."
107 return (_exponent(value)==0x7ff and not _zero_mantissa(value))
110 """Determine if the argument is an infinite IEEE 754 value (positive
111 or negative inifinity)"""
112 return (_exponent(value)==0x7ff and _zero_mantissa(value))
115 """Determine if the argument is an finite IEEE 754 value (i.e., is
116 not NaN, positive or negative inifinity)"""
117 return (_exponent(value)!=0x7ff)
120 "Determine if the argument is a IEEE 754 positive infinity value"
121 return (_sign(value)==0 and _exponent(value)==0x7ff and \
122 _zero_mantissa(value))
125 "Determine if the argument is a IEEE 754 negative infinity value"
126 return (_sign(value)==1 and _exponent(value)==0x7ff and \
127 _zero_mantissa(value))
130 ## Functions to test public functions.
134 assert( not isNaN(PosInf) )
135 assert( not isNaN(NegInf) )
136 assert( isNaN(NaN ) )
137 assert( not isNaN( 1.0) )
138 assert( not isNaN( -1.0) )
141 assert( isInf(PosInf) )
142 assert( isInf(NegInf) )
143 assert( not isInf(NaN ) )
144 assert( not isInf( 1.0) )
145 assert( not isInf( -1.0) )
148 assert( not isFinite(PosInf) )
149 assert( not isFinite(NegInf) )
150 assert( not isFinite(NaN ) )
151 assert( isFinite( 1.0) )
152 assert( isFinite( -1.0) )
155 assert( isPosInf(PosInf) )
156 assert( not isPosInf(NegInf) )
157 assert( not isPosInf(NaN ) )
158 assert( not isPosInf( 1.0) )
159 assert( not isPosInf( -1.0) )
162 assert( not isNegInf(PosInf) )
163 assert( isNegInf(NegInf) )
164 assert( not isNegInf(NaN ) )
165 assert( not isNegInf( 1.0) )
166 assert( not isNegInf( -1.0) )
176 if __name__ == "__main__":