initial commit
[govpp.git] / vendor / github.com / lunixbochs / struc / custom_float16.go
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 }