0

why is this thread marked as solved D:
this isn't solved until this function is complete:

def __BIT(big,signed,byte_size,value):
    if type(value)==str:
        if value=='': #Read
            p=__POS()
            strval=f.read(byte_size)
            if len(strval)==byte_size: #check for EOF
                sv=(reversed(strval) if big else strval)
                val=0
                for i,v in enumerate(sv): val=val|(int(v.encode('hex'),16)<<(i*8)) #int
                if signed == 1: val=(val-pow(256,byte_size) if val>(pow(256,byte_size)/2) else val) #signed
                if signed == 2: #float (IEEE)
                    e=((byte_size*8)-1)//(byte_size+1)+(byte_size>2)*byte_size//2; m,b=((byte_size*8)-(1+e)),int('1'*(e-1),2)
                    S,E,M=[(val>>((byte_size*8)-1))&1,(val>>m)&int('1'*e,2),val&int('1'*m,2)] #<- added brackets (faster processing)
                    if E == int('1'*e,2): val=(float('NaN') if M!=0 else (float('+inf') if S else float('-inf')))
                    else: val=((pow(-1,S)*(2**(E-b-m)*((1<<m)+M))) if E else pow(-1,S)*(2**(1-b-m)*M))
                    #credit to pyTony for simplifying the formula of 'e' and fixing the return values
                __LOG(p+': read 0x'+strval.encode('hex')+' as '+str(val))
                return val
    elif type(value)==int: #write int
        if signed==1: value=(value+pow(256,byte_size) if value<0 else value)
        Bytes=[chr((value>>(8*i))&255) for i in range(byte_size)]
        f.write(''.join(reversed(Bytes)) if big else ''.join(Bytes))
    elif type(value)==float: #write float
        #----------------------------------------
        #TODO: need float2hex conversion aglorithm
        from struct import pack
        if byte_size==4: f.write(pack(('<f' if big else '>f'), value)[0:4])
        if byte_size==8: f.write(pack(('<d' if big else '>d'), value)[0:4])
        #----------------------------------------
    elif type(value)==list: return list(__BIT(big,signed,byte_size,Lval) for Lval in value)
    elif type(value)==tuple: return tuple(__BIT(big,signed,byte_size,Tval) for Tval in value)
    elif type(value)==bool: return (__BIT(big,signed,byte_size,int(value)))

@ Gribouillis: what I mean is the returned length of the float from __BIT() is greater than that from struct.unpack()

btw, that function does everything from reading and writing ints, signed-ints, and floats to/from the file
(of any specified byte length)

if anyone has any speedups or anything, it would be much appreciated. :)

Edited by DarkPikachu

0

I think there are many possible speedups, for example on my computer, ~(~0 << e) is ten times faster than int('1'*e, 2)

>>> from timeit import Timer
>>> t = Timer("~(~0 << 5)")
>>> t.timeit()
0.027177095413208008 # microseconds
>>> t = Timer("int('1' * 5, 2)")
>>> t.timeit()
0.2893860340118408

In the same way, 1 << 8*8 is ten times faster than pow(256, 8)

Edited by Gribouillis

0

ok thanx, and cool
that'll greatly help in processing time.

but my main problem is that for loop...
( for i,v in enumerate(sv): val=val|(int(v.encode('hex'),16)<<(i*8)) )
IK there's a faster way to compute a variable unsigned int,
but I just can't think of it >_<

EDIT:
hey, think you could fill in the blank area in my function?? (writing a float value)
I've tried to understand your nice class, but I just don't get it >_<
I need something simple to follow...

EDIT2:
btw, I forgot to mention I lost net back home...
so that's why I havn't been on. :|

Edited by DarkPikachu

0

umm...
that (1<< 8 * 8 ) deal you got there,
would I implament that as (1<< 8 * byte_size )??

Edited by DarkPikachu

0

Yes, or even (1 << (byte_size << 3)), perhaps a nanosecond better.

I think the for i,v in enumerate(sv): val=val|(int(v.encode('hex'),16)<<(i*8)) can be replaced with

val = reduce(lambda a, b: (a << 8) | b, (ord(x) for x in reversed(sv)))

which is much faster. You can also pull the lambda out of BIT's body.

Edited by Gribouillis

0

well this is my code as of now:

def __BIT(big,signed,byte_size,value):
    #credit to Gribouillis for speedups
    if type(value)==str:
        if value=='': #Read
            p=__POS()
            strval=f.read(byte_size)
            if len(strval)==byte_size: #check for EOF
                sv=(reversed(strval) if big else strval)
                val = reduce(a, b: (a << 8) | b, (ord(x) for x in reversed(sv))) #int
                if signed == 1: val=(val-(1<<(byte_size<<3)) if val>(1<<(byte_size<<3)/2) else val) #signed
                if signed == 2: #float (IEEE)
                    e=((byte_size*8)-1)//(byte_size+1)+(byte_size>2)*byte_size//2; m,b=((byte_size*8)-(1+e)), ~(~0 << e-1)
                    S,E,M=[(val>>((byte_size*8)-1))&1,(val>>m)&~(~0 << e),val&~(~0 << m)] #<- added brackets (faster processing)
                    if E == int('1'*e,2): val=(float('NaN') if M!=0 else (float('+inf') if S else float('-inf')))
                    else: val=((pow(-1,S)*(2**(E-b-m)*((1<<m)+M))) if E else pow(-1,S)*(2**(1-b-m)*M))
                    #credit to pyTony for simplifying the formula of 'e' and fixing the return values
                __LOG(p+': read 0x'+strval.encode('hex')+' as '+str(val))
                return val
            #TODO: throw EOF error
    elif type(value)==int: #write int
        if signed==1: value=(value+pow(256,byte_size) if value<0 else value)
        Bytes=[chr((value>>(8*i))&255) for i in range(byte_size)]
        f.write(''.join(reversed(Bytes)) if big else ''.join(Bytes))
    elif type(value)==float: #write float

        #----------------------------------------
        #TODO: need float2hex conversion aglorithm
        from struct import pack
        if byte_size==4: f.write(pack(('<f' if big else '>f'), value)[0:4])
        if byte_size==8: f.write(pack(('<d' if big else '>d'), value)[0:4]) #doesn't work (logs 32bit)
        #----------------------------------------

    elif type(value)==list: return list(__BIT(big,signed,byte_size,Lval) for Lval in value)
    elif type(value)==tuple: return tuple(__BIT(big,signed,byte_size,Tval) for Tval in value)
    elif type(value)==bool: return (__BIT(big,signed,byte_size,int(value)))

thanx :)

so using for loops as generators is faster.
that was a Q I wanted to know. XD

0

so using for loops as generators is faster.

Not necessarily, but ord(v) is faster than int(v.encode('hex'),16). Also reduce is good here.
You can still gain speed. For example the values e, m, b computed at line 12 could be stored in an external array indexed on byte_size. When you're reading a float, the byte size will be small, so you're always computing the same values. At line 8 and 9, in the big case, you're reversing twice. This could be avoided. There are still some int('1'*e,2) and pow(256,...).

Edited by Gribouillis

0

ok...
m and b I could fit into a list, but I'm not sure about e,
since it's used by m and b...

and you're right * facepalm's *
I could compute the e, m, and b when the function read mode is called >.<
can't believe I missed that... heh

and I can get rid of sv...
for reversing twice, I can invert the big-endian process, and get rid of that second reverse >_>

and I think I'm overlooking the other int('1'*e,2) >_>
IK I missed a pow()... but that's for write mode...
(more concerned with reading atm)

0

there we go:

def __BIT(big,signed,byte_size,value):
    #credit to Gribouillis for speedups
    if type(value)==str:
        if value=='': #Read
            p=__POS() #get file position
            e=((byte_size*8)-1)//(byte_size+1)+(byte_size>2)*byte_size//2; m,b=[((byte_size*8)-(1+e)), ~(~0 << e-1)]
            strval=f.read(byte_size)
            if len(strval)==byte_size: #check for EOF
                val = reduce(a, b: (a << 8) | b,(ord(x) for x in (strval if big else reversed(strval)))) #int
                if signed == 1: val=(val-(1<<(byte_size<<3)) if val>(1<<(byte_size<<3)/2) else val) #signed
                if signed == 2: #float (IEEE)
                    S,E,M=[(val>>((byte_size*8)-1))&1,(val>>m)&~(~0 << e),val&~(~0 << m)] #<- added brackets (faster processing)
                    if E == int('1'*e,2): val=(float('NaN') if M!=0 else (float('+inf') if S else float('-inf')))
                    else: val=((pow(-1,S)*(2**(E-b-m)*((1<<m)+M))) if E else pow(-1,S)*(2**(1-b-m)*M))
                    #credit to pyTony for simplifying the formula of 'e' and fixing the return values
                __LOG(p+': read 0x'+strval.encode('hex')+' as '+str(val))
                return val
            #TODO: throw EOF error
    elif type(value)==int: #write int
        if signed==1: value=(value+pow(256,byte_size) if value<0 else value)
        Bytes=[chr((value>>(8*i))&255) for i in range(byte_size)]
        f.write(''.join(reversed(Bytes)) if big else ''.join(Bytes))
    elif type(value)==float: #write float

        #----------------------------------------
        #TODO: need float2hex conversion aglorithm
        from struct import pack
        if byte_size==4: f.write(pack(('<f' if big else '>f'), value)[0:4])
        if byte_size==8: f.write(pack(('<d' if big else '>d'), value)[0:4]) #doesn't work (logs 32bit)
        #----------------------------------------

    elif type(value)==list: return list(__BIT(big,signed,byte_size,Lval) for Lval in value)
    elif type(value)==tuple: return tuple(__BIT(big,signed,byte_size,Tval) for Tval in value)
    elif type(value)==bool: return (__BIT(big,signed,byte_size,int(value)))
0

never thought I'd need to dust off this old thread... heh

nearly 4 years now and I've finally found a bug with the code.
the bug's farely small though so it should be an easy fix...

http://stackoverflow.com/questions/1592158/convert-hex-to-float/21617990#21617990
(my comment on this part)

but I think I might have a more primitive approach for the fix...
what would be your approach?? (before I state mine)

also, if you're wondering...
don't worry about the write code.
that's already done, and works with any byte-size ;)

0

I do not think you need the del statements for class local function variables, what is motivation for those?

0

saving memory...

I'm trying to crack down on the dev5 update of UMC.
dev4 was a memory hog, and one reason was from not deleting unused data.

EDIT:
so I may not need THAT many, since those variables ARE re-used in time,
but each int created basically creates a new instance right??
so in my thinkng it would be good to delete THAT instance BEFORE a new one gets created... >_>

Edited by DarkPikachu

0

This is little far ago, difficult to remind it without much study.

I did reformat little your/our code to help little in understanding it. It does not cost to be clear noticably, as Python turns everything to byte code anyway, right?

My prints did come up different values than yours in comments, not the one you stated as problem though. I eliminated the dot operation from the formulas inside the if, maybe it speed things little.

class variable_float(object):
    def __init__(self, value=0, byte_size=4):
        if value: # speedy check (before performing any calculations)
            Fe=((byte_size*8)-1)//(byte_size+1)+(byte_size>2)*byte_size//2+(byte_size==3)
            Fm,Fb,Fie=(((byte_size*8)-(1+Fe)), ~(~0<<Fe-1), (1<<Fe)-1)
            FS,FE,FM=((value>>((byte_size*8)-1))&1,(value>>Fm)&Fie,value&~(~0 << Fm))
            if FE == Fie:
                self.value=(float('NaN') if FM!=0 else (float('+inf') if FS else float('-inf')))
            else:
                self.value=((pow(-1,FS)*(2**(FE-Fb-Fm)*((1<<Fm)+FM))) if FE else pow(-1,FS)*(2**(1-Fb-Fm)*FM))
        else:
            self.value = 0.0

    def __str__(self):
        return str(self.value)

print variable_float(0x41973333) # >>> 18.899999618530273
print variable_float(0x41995C29) # >>> 19.170000076293945
print variable_float(0x470FC614) # >>> 36806.078125
print variable_float(0x00800000) # >>> 1.1754943508222875e-38 (minimum float value)
print variable_float(0x7F7FFFFF) # >>> 340282346638528859811704183484516925440L (maximum float value)
# looks like I've found a small bug o.o
# the code still works though (the numbers are properly formatted)
# the result SHOULD be: 3.4028234663852886e+38 (rounded)
print variable_float(0x3f80000000, 5) # >>> 1.0

""" My print:
18.8999996185
19.1700000763
36806.078125
1.17549435082e-38
340282346638528859811704183484516925440
1.0
"""

Edited by pyTony

1

There is still no bug in my code

from anyfloat import anyfloat

_size = { 4 : (8, 23), 5 : (8, 31)}

def variable_float(n, bytes = 4):
    return float(anyfloat.from_ieee(n, _size[bytes]))

print repr(variable_float(0x41973333))
print repr(variable_float(0x41995C29))
print repr(variable_float(0x470FC614))
print repr(variable_float(0x00800000))
print repr(variable_float(0x7F7FFFFF))
print repr(variable_float(0x3f80000000, 5))

""" my output -->
18.899999618530273
19.170000076293945
36806.078125
1.1754943508222875e-38
3.4028234663852886e+38
1.0
"""

See here.

Votes + Comments
Power of modular programming
0

I still have your src...

it's just that all these garbed up conversion methods between anyfloat and ieee confuse me... heh

I just need a simple conversive interface to convert an int to an IEEE, IBM, or Borland float.
(the other 2 will come in time, as I've been intending to support them)

IBM is the same as IEEE, except the bit-widths are slightly different.
I'm not so sure about Borland

also PyTony, I tried your code...
I get the same results as your prints... heh
(a little less accurate for the sake of speed)
^ I only need that for the interface's GL transfer (if that)...
as for conversion, I need more accracy. ;)

also... I'm worried about RAM, as UMC is more like Blender with it's data.
(everything gets stored internally)

I have looked into an extension that can compress data in the RAM...
and I forget why I'm not using it. >_<

anyways...
if python deletes those extra instances automatically,
then I'd say I wouldn't need those del statements.
(I do know about the garbage collector)

something I've found out if you want to save memory:

f = open(file, 'rb')
d = f.read()
f.close()
# f is still an object here
del f
# now f is no longer in memory

so I'd thought to apply the same thing to unused ints and such.
(since python ints are really just classes)
^ and to my knowledge, classes use a good chunk of memory, even though it's small

keep in mind I still use Py2x

This question has already been answered. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.