mailRe: r2801 - /branches/test_suite/float.py


Others Months | Index by Date | Thread Index
>>   [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Header


Content

Posted by Gary S. Thompson on November 13, 2006 - 16:55:
edward.dauvergne@xxxxxxxxx wrote:

Author: bugman
Date: Sat Nov 11 10:57:35 2006
New Revision: 2801

URL: http://svn.gna.org/viewcvs/relax?rev=2801&view=rev
Log:
Two functions for converting a string bit pattern to a float and a number of 
IEEE-754 constants.

The fucntions 'bitpatternToFloat()' and 'bitpatternToInt()' have been added to 'float.py'. The
first converts a 64 bit IEEE-754 bit pattern in the form of a string into a 64 bit Python float.
The second converts an arbitrary bit pattern into its integer representation. By looping over each
8 characters of the string (1 byte), 'bitpatternToFloat()' calls 'bitpatternToInt()' to create an
array of integers. Then 'packBytesAsPyFloat()' is called to convert the byte array into the float.
These two functions convert between big and little endian when necessary.


Nice functions! However, I would suggest that these should go in utility
functions or  the test suite.... I am trying to keep float.py as the
bare minimum file for testing floating point numbers and floating point
constants

A couple of other matters as well

1. the constants are not much use at the end of the file as if anything
else in the file wants to refer to them they won't be able to
2. I was thinking of a test case with random numbers in the exponent of
the nan and then reporting what the bit pattern that failed was....
3. I was also thinking of having test caseswith minimum and maximum bit
patterns e.g. max denorm min denorm nan with highest mantissa bit set
nan with smallest mantissa bit set etc

By passing big-endian 64 bit patterns to the 'bitpatternToFloat()' function, 
the following IEEE-754
constants are defined:
   PosZero:            
0000000000000000000000000000000000000000000000000000000000000000
   NegZero:            
1000000000000000000000000000000000000000000000000000000000000000
   PosEpsilonDenorm:   
0000000000000000000000000000000000000000000000000000000000000001
   NegEpsilonDenorm:   
1000000000000000000000000000000000000000000000000000000000000001
   PosEpsilonNorm:     
0000000000010000000000000000000000000000000000000000000000000001
   NegEpsilonNorm:     
1000000000010000000000000000000000000000000000000000000000000001
   PosMax:             
0111111111101111111111111111111111111111111111111111111111111111
   NegMin:             
1111111111101111111111111111111111111111111111111111111111111111
   PosInf:             
0111111111110000000000000000000000000000000000000000000000000000
   NegInf:             
1111111111110000000000000000000000000000000000000000000000000000
   PosNaN_A:           
0111111111110000000000000000000000000000001000000000000000000000
   NegNaN_A:           
1111111111110000000000000000000000000000001000000000000000000000
   PosNaN_B:           
0111111111110000000000000000011111111111111111111110000000000000
   NegNaN_B:           
1111111111110000000000000000011111111111111111111110000000000000
   PosNaN_C:           
0111111111110101010101010101010101010101010101010101010101010101
   NegNaN_C:           
1111111111110101010101010101010101010101010101010101010101010101
   PosNaN = PosNaN_C
   NegNaN = NegNaN_C



I have some code that reads and displays these as octes which makes life
easier...

11111111 11110101 01010101 01010101 01010101 01010101 01010101 01010101

Modified:
   branches/test_suite/float.py

Modified: branches/test_suite/float.py
URL: http://svn.gna.org/viewcvs/relax/branches/test_suite/float.py?rev=2801&r1=2800&r2=2801&view=diff
==============================================================================
--- branches/test_suite/float.py (original)
+++ branches/test_suite/float.py Sat Nov 11 10:57:35 2006
@@ -637,6 +637,7 @@
''' return isInf(obj) and isPositive(obj)


+
def isNegInf(obj):
''' check to see if a python float is negative infinity @@ -647,11 +648,124 @@
throws -- throws a TypeError if obj isn't a python float '''
- - return isInf(obj) and not isPositive(obj) - -
- -
-
-
+
+ return isInf(obj) and not isPositive(obj)
+
+
+def bitpatternToFloat(string, endian='big'):
+ """Convert a 64 bit IEEE-754 ascii bit pattern into a 64 bit Python float.
+
+ @param string: The ascii bit pattern repesenting the IEEE-754 float.
+ @type string: str
+ @param endian: The endianness of the bit pattern (can be 'big' or 'little').
+ @type endian: str
+ @return: The 64 bit float corresponding to the IEEE-754 bit pattern.
+ @returntype: float
+ @raise: TypeError if 'string' is not a string, the length of the 'string' is not 64, or
+ if 'string' does not consist solely of the characters '0' and '1'.
+ """
+
+ # Test that the bit pattern is a string.
+ if type(string) != str:
+ raise TypeError, "The string argument '%s' is not a string." % string



I think this is to restrictive opther things can act as sequences...


+
+ # Test the length of the bit pattern.
+ if len(string) != 64:
+ raise TypeError, "The string '%s' is not 64 characters long." % string
+
+ # Test that the string consists solely of zeros and ones.
+ for char in string:
+ if char not in ['0', '1']:
+ raise TypeError, "The string '%s' should be composed solely of the characters '0' and '1'." % string
+
+ # Reverse the byte order as neccessary.
+ if endian == 'big' and sys.byteorder == 'little':
+ string = string[::-1]
+ elif endian == 'little' and sys.byteorder == 'big':
+ string = string[::-1]
+



this could be better written as

# Reverse the byte order as neccessary.
if endian != sys.byteorder:
   string = string[::-1]


and then add an assert effectivley of the form endian..tolower() in ('little','big')

+    # Convert the bit pattern into a byte array (of integers).
+    bytes = []
+    for i in xrange(8):
+        bytes.append(bitpatternToInt(string[i*8:i*8+8], 
endian=sys.byteorder))
+
+    # Pack the byte array into a float and return it.
+    return packBytesAsPyFloat(bytes)
+
+
+def bitpatternToInt(string, endian='big'):
+    """Convert a bit pattern into its integer representation.
+
+    @param string:  The ascii string repesenting binary data.
+    @type string:   str
+    @param endian:  The endianness of the bit pattern (can be 'big' or 
'little').
+    @type endian:   str
+    @return:        The integer value.
+    @returntype:    int
+    """
+
+    # Test that the bit pattern is a string.
+    if type(string) != str:
+        raise TypeError, "The string argument '%s' is not a string." % string
+
+    # Test that the string consists solely of zeros and ones.
+    for char in string:
+        if char not in ['0', '1']:
+            raise TypeError, "The string '%s' should be composed solely of the 
characters '0' and '1'." % string
+
+    # Reverse the byte order as neccessary.
+    if endian == 'big' and sys.byteorder == 'little':
+        string = string[::-1]
+    elif endian == 'little' and sys.byteorder == 'big':
+        string = string[::-1]
+
+    # Calculate the integer corresponding to the string.
+    int_val = 0
+    for i in xrange(len(string)):
+        if int(string[i]):
+            int_val = int_val + 2**i
+
+    # Return the integer value.
+    return int_val
+
+
+# IEEE-754 Constants.
+#####################
+
+# The following bit patterns are to be read from right to left (big-endian).
+# Hence bit positions 0 and 63 are to the far right and far left 
respectively.
+PosZero             = 
bitpatternToFloat('0000000000000000000000000000000000000000000000000000000000000000',
 endian='big')
+NegZero             = 
bitpatternToFloat('1000000000000000000000000000000000000000000000000000000000000000',
 endian='big')
+PosEpsilonDenorm    = 
bitpatternToFloat('0000000000000000000000000000000000000000000000000000000000000001',
 endian='big')
+NegEpsilonDenorm    = 
bitpatternToFloat('1000000000000000000000000000000000000000000000000000000000000001',
 endian='big')
+PosEpsilonNorm      = 
bitpatternToFloat('0000000000010000000000000000000000000000000000000000000000000001',
 endian='big')
+NegEpsilonNorm      = 
bitpatternToFloat('1000000000010000000000000000000000000000000000000000000000000001',
 endian='big')
+PosMax              = 
bitpatternToFloat('0111111111101111111111111111111111111111111111111111111111111111',
 endian='big')
+NegMin              = 
bitpatternToFloat('1111111111101111111111111111111111111111111111111111111111111111',
 endian='big')
+PosInf              = 
bitpatternToFloat('0111111111110000000000000000000000000000000000000000000000000000',
 endian='big')
+NegInf              = 
bitpatternToFloat('1111111111110000000000000000000000000000000000000000000000000000',
 endian='big')
+PosNaN_A            = 
bitpatternToFloat('0111111111110000000000000000000000000000001000000000000000000000',
 endian='big')
+NegNaN_A            = 
bitpatternToFloat('1111111111110000000000000000000000000000001000000000000000000000',
 endian='big')
+PosNaN_B            = 
bitpatternToFloat('0111111111110000000000000000011111111111111111111110000000000000',
 endian='big')
+NegNaN_B            = 
bitpatternToFloat('1111111111110000000000000000011111111111111111111110000000000000',
 endian='big')
+PosNaN_C            = 
bitpatternToFloat('0111111111110101010101010101010101010101010101010101010101010101',
 endian='big')
+NegNaN_C            = 
bitpatternToFloat('1111111111110101010101010101010101010101010101010101010101010101',
 endian='big')
+PosNaN = PosNaN_C
+NegNaN = NegNaN_C
+
+#print "%-30s%-20.40g" % ("Pos zero: ", PosZero)
+#print "%-30s%-20.40g" % ("Neg zero: ", NegZero)
+#print "%-30s%-20.40g" % ("Pos epsilon denorm: ", PosEpsilonDenorm)
+#print "%-30s%-20.40g" % ("Neg epsilon denorm: ", NegEpsilonDenorm)
+#print "%-30s%-20.40g" % ("Pos epsilon norm: ", PosEpsilonNorm)
+#print "%-30s%-20.40g" % ("Neg epsilon norm: ", NegEpsilonNorm)
+#print "%-30s%-20.40g" % ("Max: ", PosMax)
+#print "%-30s%-20.40g" % ("Min: ", NegMin)
+#print "%-30s%-20.40g" % ("Pos inf: ", PosInf)
+#print "%-30s%-20.40g" % ("Neg inf: ", NegInf)
+#print "%-30s%-20.40g" % ("Pos NaN (A): ", PosNaN_A)
+#print "%-30s%-20.40g" % ("Neg NaN (A): ", NegNaN_A)
+#print "%-30s%-20.40g" % ("Pos NaN (B): ", PosNaN_B)
+#print "%-30s%-20.40g" % ("Neg NaN (B): ", NegNaN_B)
+#print "%-30s%-20.40g" % ("Pos NaN (C): ", PosNaN_C)
+#print "%-30s%-20.40g" % ("Neg NaN (C): ", NegNaN_C)


_______________________________________________ relax (http://nmr-relax.com)

This is the relax-commits mailing list
relax-commits@xxxxxxx

To unsubscribe from this list, get a password
reminder, or change your subscription options,
visit the list information page at
https://mail.gna.org/listinfo/relax-commits

.



regards
gary

--
-------------------------------------------------------------------
Dr Gary Thompson
Astbury Centre for Structural Molecular Biology,
University of Leeds, Astbury Building,
Leeds, LS2 9JT, West-Yorkshire, UK             Tel. +44-113-3433024
email: garyt@xxxxxxxxxxxxxxx                   Fax  +44-113-2331407
-------------------------------------------------------------------






Related Messages


Powered by MHonArc, Updated Wed Nov 15 10:00:30 2006