mailRe(2): 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 thompson on November 15, 2006 - 12:14:
In advance sorry for the slightly strange format but I am replying to this by
gmail at home having cut and pasted the message from the archive
(this is my second attempt it lost all the first set of edits) n.b. I will 
only
send this to the list now as i don't have eds e-mail address at home

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

This is true but certainly at this stage the product is just too half cut for
anyone else and I wanted to concentrate on the primary problem (i.e. float.py)
and complete that first unit, test it etc before I did some work on
the capabilities

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?

Something I have to thing about and read python in a nutshell. basically if the utility functions are private they shouldn't be part of the public interface. Otherwise it is just a question of keeping the utility of the module focused...

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?


I would try to keep the number of functions to the minimum and maintain 
fpconst
compatabilty. all other functions can go in separate modules if needed.



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.


fair enough still the top is the place to put them (this is also where users would expect to search for constants...)

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?

sorry mental typo

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!


I would suggest that we don't want to have multiple nans. decide on one good bit pattern that is easy to identify and then use it everywhere. This will make debugging a lost easier. One suggestion is to have a memorable hex pattern e.g. 'deadara' or something similar

as an aside from my (limited) reading of the ieee spec it seems that
the extra patterns
are just there to give the designers of fpus some flexibility

now when we come round to unit testing thats a different matter here we want
lots of nans and if the names are ugly who cares as long as they don't change!


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.

see my comments on nans

ehen >By passing big-endian 64 bit patterns to the 'bitpatternToFloat()' function, the following IEEE-754 >constants are defined: > PosZero: 0000000000000000000000000000000000000000000000000000000000000000 > NegZero: 1000000000000000000000000000000000000000000000000000000000000000 > PosEpsilonDenorm: ehen 0000000000000000000000000000000000000000000000000000000000000001 > NegEpsilonDenorm: 1000000000000000000000000000000000000000000000000000000000000001 > PosEpsilonNorm: 0000000000010000000000000000000000000000000000000000000000000001 > NegEpsilonNorm: 1000000000010000000000000000000000000000000000000000000000000001 > PosMax: 01111111111011111111111111111111111111111111111111ehen11111111111111 > NegMin: 1111111111101111111111111111111111111111111111111111111111111111 > PosInf: 01111111111100000000000000000000000000000000000000ehen00000000000000 > NegInf: 1111111111110000000000000000000000000000000000000000000000000000 > PosNaN_A: 0111111111110000000000000000000000000000001000000000000000000000 > NegNaN_A: 1111111111110000000000000000000000000000001000000000000000000000 > PosNaN_B: 0111111111110000000000000000011111111111111111111110000000000000 > NegNaN_B: 1111111111110000000000000000011111111111111111111110000000000000 > PosNaN_C: 01111111111101010101010101010101010101010101010101ehen01010101010101 > NegNaN_C: 1111111111110101010101010101010101010101010101010101010101010101 > PosNaN = PosNaN_C > NegNaN = NegNaN_C > > > I have some code that reads and displays these as ehenoctes which makes life easier...

  11111111 11110101 01010101 01010101 01010101 01010101 01010101 01010101
I don't know if the spaces help much.  As the mantehenissa 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.


this is true ieee754 breaks the mantissa and exponent  at a  nibble boundary

however it is good to have an easily read structure that is less 
monolithic....
and  the underlying structure of
numbers on computers is octet based, most computer programmers think
in octets/bytes at
the basic level  and when you manipulate the contents of nans you will tend to
split in to octets for bit manipulation. so octets seem a good idea...


one (ugly) suggestion would be

0bs1 e111111 1111 m1010 10101010 10101010 10101010 10101010 10101010 101010101

and then strip all leading 0b's all spaces and all letters. the addition of 0b
would allow you to use hex as well if you wanted (i would add that most system
programmers much prefer hex to bit patterns. if you look at many programs they
don't have binary constants but hex constants, and languages such as
python and c
support hex constants but not binary ones [most programmers find them
too wordy]

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


will do


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


will do


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


I think you need to assert that big and little are passed in endian if this is
a public function. The
general way to think about these things is that you should test all data for
validity at public interfaces. Then if you have internal functions you don't
have to test for validity (as you will slow down to repeated
testing). Its a bit like testing messages at a firewall before they
enter the dmz. However,
it is still a wise decision to check argument validity in all functions in
debugging mode e.g. with assert as this will catch errors early

as to the to lower it just gives a bit more generality if you don'
have to worry
about case

also you asked about using > and <.  I personally much prefer big and
little they are much more obvious and intuitive </> are open to interpretation

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.

yep exceptions ;-)

Edward





regards gary



Related Messages


Powered by MHonArc, Updated Tue Nov 28 04:40:50 2006