github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/math/big/floatmarsh.go (about) 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 7 package big 8 9 import ( 10 "encoding/binary" 11 "errors" 12 "fmt" 13 ) 14 15 // Gob codec version. Permits backward-compatible changes to the encoding. 16 const 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. 21 func (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 binary.BigEndian.PutUint32(buf[2:], x.prec) 52 53 if x.form == finite { 54 binary.BigEndian.PutUint32(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. 65 func (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 = binary.BigEndian.Uint32(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(binary.BigEndian.Uint32(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. 112 func (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. 124 func (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 }