1 Jan 2012

Golang: read IBM 32-bit floating point in Go, and compare with python

Since I'm learning Go, so rewrote reading IBM 32bit floating point as in last post in GO:

package ibmtools

import "math"

const p24 = 2 << 23
func Ibm32frombits(b [4]byte) float64 {
 ui := uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
 sign := 1 - 2*float64(ui>>31&0x01)
 exponent := math.Pow(16.0, float64(ui>>24&0x7f)-64.0)
 mantissa := float64(ui&0x00ffffff) / float64(p24)
 return math.Copysign(mantissa*exponent, sign)
}

You can go to https://github.com/jackielii/ibmtools to view the full source or use gointall to install it.

I also did some speed tests:

Python:

p24 = pow(2, 24)
def ibm2ieee(ibm):
    """ read an IBM floating point number. """
    sign = ibm >> 31 & 0x01
    exponent = ibm >> 24 & 0x7f
    mantissa = ibm & 0x00ffffff
    mantissa = (mantissa * 1.0) / p24
    ieee = (1 - 2 * sign) * mantissa * pow(16, exponent - 64)
    return ieee

And run it using:

nemo@EliteBook:~/workspace$ python -m timeit "from testibm import ibm2ieee" "ibm2ieee(0b11000010011101101010000000000000)"
1000000 loops, best of 3: 1.62 usec per loop

Test Go using:

package ibmtools

import (
 "testing"
 // "strconv"
)

var (
 bit = "11000010011101101010000000000000"
 by  = [4]byte{194, 118, 160, 0}
)

func BenchmarkIbm2ieee(b *testing.B) {
 for i := 0; i < b.N; i++ {
  Ibm32frombits(by)
 }
}
nemo@EliteBook:~/workspace/ibmtools$ gomake bench
gotest -test.bench=. -test.run="Do not run tests"
rm -f _test/ibmtools.a
6g   -p ibmtools -o _gotest_.6 ebcdic.go ibmfloat.go  ibmtools_test.go
rm -f _test/ibmtools.a
gopack grc _test/ibmtools.a _gotest_.6 
PASS
ibmtools.BenchmarkIbm2ieee 20000000         90.3 ns/op

Result: Python 1.62 us = 1620 ns, and Go 90.3 ns. Go is around 17 times faster.

I know it's not a fair comparison, but it's illustrative.

No comments: