gitee.com/quant1x/gox@v1.7.6/encoding/binary/struc/custom_float16.go (about)

     1  package struc
     2  
     3  import (
     4  	"encoding/binary"
     5  	"io"
     6  	"math"
     7  	"strconv"
     8  )
     9  
    10  type Float16 float64
    11  
    12  func (f *Float16) Pack(p []byte, opt *Options) (int, error) {
    13  	order := opt.Order
    14  	if order == nil {
    15  		order = binary.BigEndian
    16  	}
    17  	sign := uint16(0)
    18  	if *f < 0 {
    19  		sign = 1
    20  	}
    21  	var frac, exp uint16
    22  	if math.IsInf(float64(*f), 0) {
    23  		exp = 0x1f
    24  		frac = 0
    25  	} else if math.IsNaN(float64(*f)) {
    26  		exp = 0x1f
    27  		frac = 1
    28  	} else {
    29  		bits := math.Float64bits(float64(*f))
    30  		exp64 := (bits >> 52) & 0x7ff
    31  		if exp64 != 0 {
    32  			exp = uint16((exp64 - 1023 + 15) & 0x1f)
    33  		}
    34  		frac = uint16((bits >> 42) & 0x3ff)
    35  	}
    36  	var out uint16
    37  	out |= sign << 15
    38  	out |= exp << 10
    39  	out |= frac & 0x3ff
    40  	order.PutUint16(p, out)
    41  	return 2, nil
    42  }
    43  func (f *Float16) Unpack(r io.Reader, length int, opt *Options) error {
    44  	order := opt.Order
    45  	if order == nil {
    46  		order = binary.BigEndian
    47  	}
    48  	var tmp [2]byte
    49  	if _, err := r.Read(tmp[:]); err != nil {
    50  		return err
    51  	}
    52  	val := order.Uint16(tmp[:2])
    53  	sign := (val >> 15) & 1
    54  	exp := int16((val >> 10) & 0x1f)
    55  	frac := val & 0x3ff
    56  	if exp == 0x1f {
    57  		if frac != 0 {
    58  			*f = Float16(math.NaN())
    59  		} else {
    60  			*f = Float16(math.Inf(int(sign)*-2 + 1))
    61  		}
    62  	} else {
    63  		var bits uint64
    64  		bits |= uint64(sign) << 63
    65  		bits |= uint64(frac) << 42
    66  		if exp > 0 {
    67  			bits |= uint64(exp-15+1023) << 52
    68  		}
    69  		*f = Float16(math.Float64frombits(bits))
    70  	}
    71  	return nil
    72  }
    73  func (f *Float16) Size(opt *Options) int {
    74  	return 2
    75  }
    76  func (f *Float16) String() string {
    77  	return strconv.FormatFloat(float64(*f), 'g', -1, 32)
    78  }