codekingpro/portable-devtools
114k
1// Copyright 2015 The Go Authors. All rights reserved.2// Use of this source code is governed by a BSD-style3// license that can be found in the LICENSE file.4 5// This file implements encoding/decoding of Floats.6 7package big8 9import (10 "errors"11 "fmt"12 "internal/byteorder"13)14 15// Gob codec version. Permits backward-compatible changes to the encoding.16const floatGobVersion byte = 117 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, nil24 }25 26 // determine max. space (bytes) required for encoding27 sz := 1 + 1 + 4 // version + mode|acc|form|neg (3+2+2+1bit) + prec28 n := 0 // number of mantissa words29 if x.form == finite {30 // add space for mantissa and exponent31 n = int((x.prec + (_W - 1)) / _W) // required mantissa length in words for given precision32 // actual mantissa slice could be shorter (trailing 0's) or longer (unused bits):33 // - if shorter, only encode the words present34 // - if longer, cut off unused words when encoding in bytes35 // (in practice, this should never happen since rounding36 // 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) >= n41 sz += 4 + n*_S // exp + mant42 }43 buf := make([]byte, sz)44 45 buf[0] = floatGobVersion46 b := byte(x.mode&7)<<5 | byte((x.acc+1)&3)<<3 | byte(x.form&3)<<147 if x.neg {48 b |= 149 }50 buf[1] = b51 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 words56 }57 58 return buf, nil59}60 61// GobDecode implements the [encoding/gob.GobDecoder] interface.62// The result is rounded per the precision and rounding mode of63// z unless z's precision is 0, in which case z is set exactly64// 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 nil70 }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.prec80 oldMode := z.mode81 82 b := buf[1]83 z.mode = RoundingMode((b >> 5) & 7)84 z.acc = Accuracy((b>>3)&3) - 185 z.form = form((b >> 1) & 3)86 z.neg = b&1 != 087 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 = oldMode99 z.SetPrec(uint(oldPrec))100 }101 102 if msg := z.validate0(); msg != "" {103 return errors.New("Float.GobDecode: " + msg)104 }105 106 return nil107}108 109// AppendText implements the [encoding.TextAppender] interface.110// Only the [Float] value is marshaled (in full precision), other111// attributes such as precision or accuracy are ignored.112func (x *Float) AppendText(b []byte) ([]byte, error) {113 if x == nil {114 return append(b, "<nil>"...), nil115 }116 return x.Append(b, 'g', -1), nil117}118 119// MarshalText implements the [encoding.TextMarshaler] interface.120// Only the [Float] value is marshaled (in full precision), other121// attributes such as precision or accuracy are ignored.122func (x *Float) MarshalText() (text []byte, err error) {123 return x.AppendText(nil)124}125 126// UnmarshalText implements the [encoding.TextUnmarshaler] interface.127// The result is rounded per the precision and rounding mode of z.128// If z's precision is 0, it is changed to 64 before rounding takes129// effect.130func (z *Float) UnmarshalText(text []byte) error {131 // TODO(gri): get rid of the []byte/string conversion132 _, _, err := z.Parse(string(text), 0)133 if err != nil {134 err = fmt.Errorf("math/big: cannot unmarshal %q into a *big.Float (%v)", text, err)135 }136 return err137}138 