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 Edward d'Auvergne on November 15, 2006 - 03:14:
On 11/13/06, Gary S. Thompson <garyt@xxxxxxxxxxxxxxx> wrote:
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

I agree - these string to float conversions are auxiliary to intended purpose of the IEEE-754 module. Unfortunately as you hadn't committed the utility function code yet - I wasn't able to put the functions there :).

How would you like to design the ieee754 module?  Have you searched
for documentation describing how to create standard Python modules,
i.e. the format and structure of the modules?  Should the utility
functions be part of the module?  Or should the be their own module?
The 'bitpatternToFloat()' function I added is 100% specific to
IEEE-754 though.  Do you think it would be a good idea, for future
Python inclusion and to improve on 'fpconst', to create a module which
includes as many IEEE-754 related functions as possible?


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

I didn't expect anything in 'float.py' to use them. I just expanded the constants proposed in PEP-754 (http://www.python.org/dev/peps/pep-0754/) into a complete list of all the IEEE-754 special numbers. That was pretty simple to do. They can be imported into the unit tests as an accurate replacement for FLOAT_EPSILON, etc. Their main usage would be by the users of the module.


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....

You mean mantissa? The three NaN just give the users of the module a few different NaN numbers to play with. I can't stand the way I've named them though!


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

These can still be pre-defined constants within the ieee754 module for others to use. We may as well give the users of the module access to a complete series of ieee754 special numbers, including the limits. Essentially I have added all of the 64 bit special values discussed in the current Wikipedia article http://en.wikipedia.org/wiki/IEEE-754.


>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

I don't know if the spaces help much. As the mantissa is from 0-51, the exponent from 52-62, and the sign bit is at position 63, wouldn't the best place for spaces be to separate out the components of the IEEE-754 float, e.g.:

1 1111111111 10101010101010101010101010101010101010101010101010101

ieee754 doesn't seem to be an octet based system.


>+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...

Feel free to remove the test. I can see how it would be restrictive.


>+    # 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]

Good point. Again feel free to make the modification.


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

Is this necessary? If the user supplies dud arguments, I'm not sure what to do. There should be Python standards for standard Python modules somewhere which say how to properly handle incorrect user input.

Edward



Related Messages


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