1// Copyright 2015 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// This file implements encoding/decoding of Floats. 6 7package big 8 9import ( 10 "errors" 11 "fmt" 12 "internal/byteorder" 13) 14 15// Gob codec version. Permits backward-compatible changes to the encoding. 16const floatGobVersion byte = 1 17 18// GobEncode implements the [encoding/gob.GobEncoder] interface. 19// The [Float] value and all its attributes (precision, 20// rounding mode, accuracy) are marshaled. 21func (x *Float) GobEncode() ([]byte, error) { 22 if x == nil { 23 return nil, nil 24 } 25 26 // determine max. space (bytes) required for encoding 27 sz := 1 + 1 + 4 // version + mode|acc|form|neg (3+2+2+1bit) + prec 28 n := 0 // number of mantissa words 29 if x.form == finite { 30 // add space for mantissa and exponent 31 n = int((x.prec + (_W - 1)) / _W) // required mantissa length in words for given precision 32 // actual mantissa slice could be shorter (trailing 0's) or longer (unused bits): 33 // - if shorter, only encode the words present 34 // - if longer, cut off unused words when encoding in bytes 35 // (in practice, this should never happen since rounding 36 // takes care of it, but be safe and do it always) 37 if len(x.mant) < n { 38 n = len(x.mant) 39 } 40 // len(x.mant) >= n 41 sz += 4 + n*_S // exp + mant 42 } 43 buf := make([]byte, sz) 44 45 buf[0] = floatGobVersion 46 b := byte(x.mode&7)<<5 | byte((x.acc+1)&3)<<3 | byte(x.form&3)<<1 47 if x.neg { 48 b |= 1 49 } 50 buf[1] = b 51 byteorder.BePutUint32(buf[2:], x.prec) 52 53 if x.form == finite { 54 byteorder.BePutUint32(buf[6:], uint32(x.exp)) 55 x.mant[len(x.mant)-n:].bytes(buf[10:]) // cut off unused trailing words 56 } 57 58 return buf, nil 59} 60 61// GobDecode implements the [encoding/gob.GobDecoder] interface. 62// The result is rounded per the precision and rounding mode of 63// z unless z's precision is 0, in which case z is set exactly 64// to the decoded value. 65func (z *Float) GobDecode(buf []byte) error { 66 if len(buf) == 0 { 67 // Other side sent a nil or default value. 68 *z = Float{} 69 return nil 70 } 71 if len(buf) < 6 { 72 return errors.New("Float.GobDecode: buffer too small") 73 } 74 75 if buf[0] != floatGobVersion { 76 return fmt.Errorf("Float.GobDecode: encoding version %d not supported", buf[0]) 77 } 78 79 oldPrec := z.prec 80 oldMode := z.mode 81 82 b := buf[1] 83 z.mode = RoundingMode((b >> 5) & 7) 84 z.acc = Accuracy((b>>3)&3) - 1 85 z.form = form((b >> 1) & 3) 86 z.neg = b&1 != 0 87 z.prec = byteorder.BeUint32(buf[2:]) 88 89 if z.form == finite { 90 if len(buf) < 10 { 91 return errors.New("Float.GobDecode: buffer too small for finite form float") 92 } 93 z.exp = int32(byteorder.BeUint32(buf[6:])) 94 z.mant = z.mant.setBytes(buf[10:]) 95 } 96 97 if oldPrec != 0 { 98 z.mode = oldMode 99 z.SetPrec(uint(oldPrec)) 100 } 101 102 if msg := z.validate0(); msg != "" { 103 return errors.New("Float.GobDecode: " + msg) 104 } 105 106 return nil 107} 108 109// MarshalText implements the [encoding.TextMarshaler] interface. 110// Only the [Float] value is marshaled (in full precision), other 111// attributes such as precision or accuracy are ignored. 112func (x *Float) MarshalText() (text []byte, err error) { 113 if x == nil { 114 return []byte("<nil>"), nil 115 } 116 var buf []byte 117 return x.Append(buf, 'g', -1), nil 118} 119 120// UnmarshalText implements the [encoding.TextUnmarshaler] interface. 121// The result is rounded per the precision and rounding mode of z. 122// If z's precision is 0, it is changed to 64 before rounding takes 123// effect. 124func (z *Float) UnmarshalText(text []byte) error { 125 // TODO(gri): get rid of the []byte/string conversion 126 _, _, err := z.Parse(string(text), 0) 127 if err != nil { 128 err = fmt.Errorf("math/big: cannot unmarshal %q into a *big.Float (%v)", text, err) 129 } 130 return err 131} 132