简体   繁体   中英

Implement a basic datatype in BinData

I am trying to implement binary16 encoding for a half-precision floating point type.

The code is working except for one detail: It returns an object with the three properties (sign, exponent, fraction), but I would like it to return the float. Right now, I have to call to_f to get to the float. I would like this to work the way the integrated int and float classes work.

Here's my code:

require 'bindata'
class Binary16Be < BinData::Record
  # naming based on https://en.wikipedia.org/wiki/Half-precision_floating-point_format
  bit1 :sign_bit
  bit5 :exponent
  bit10 :fraction

  def sign
    sign_bit.zero? ? 1 : -1
  end

  def to_f
    if exponent == 31 # special value in binary16 - all exponent bits are 1
      return fraction.zero? ? (sign * Float::INFINITY) : Float::NAN
    end
    sign * 2**(exponent - 15) * (1.0 + fraction.to_f / 1024)
  end
end

What I would like:

Binary16Be.read("\x3C\x00")
=> 1.0

What happens right now:

Binary16Be.read("\x3C\x00")
{:sign_bit=>0, :exponent=>15, :fraction=>0}

(this is not actually my own answer, I received this from the gem's author. Made slight alterations to his answer to fit this Q&A format a little better.)

The procedure is described in the bindata Wiki / Primitive Types

In your case:

  1. Subclass Primitive instead of Record
  2. Rename #to_f to #get
  3. Implement #set

The converted code

class Binary16Be < BinData::Primitive
  # naming based on
  # https://en.wikipedia.org/wiki/Half-precision_floating-point_format
  bit1 :sign_bit
  bit5 :exponent
  bit10 :fraction

  def sign
    sign_bit.zero? ? 1 : -1
  end

  def get
    if exponent == 31 # special value in binary16 - all exponent bits are 1
      return fraction.zero? ? (sign * Float::INFINITY) : Float::NAN
    end
    sign * 2**(exponent - 15) * (1.0 + fraction.to_f / 1024)
  end

  def set(val)
    self.sign = (val >= 0.0)
    self.fraction = ... # TODO implement
    self.exponent = ... # TODO implement
  end
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM