mirror of
https://github.com/golang/go
synced 2024-11-19 16:44:43 -07:00
big: gobs for big rats
Fixes #1926. R=r CC=golang-dev https://golang.org/cl/4550122
This commit is contained in:
parent
6c746328f7
commit
21032ebebd
@ -816,13 +816,13 @@ func (z *Int) Not(x *Int) *Int {
|
||||
|
||||
|
||||
// Gob codec version. Permits backward-compatible changes to the encoding.
|
||||
const version byte = 1
|
||||
const intGobVersion byte = 1
|
||||
|
||||
// GobEncode implements the gob.GobEncoder interface.
|
||||
func (z *Int) GobEncode() ([]byte, os.Error) {
|
||||
buf := make([]byte, len(z.abs)*_S+1) // extra byte for version and sign bit
|
||||
buf := make([]byte, 1+len(z.abs)*_S) // extra byte for version and sign bit
|
||||
i := z.abs.bytes(buf) - 1 // i >= 0
|
||||
b := version << 1 // make space for sign bit
|
||||
b := intGobVersion << 1 // make space for sign bit
|
||||
if z.neg {
|
||||
b |= 1
|
||||
}
|
||||
@ -837,7 +837,7 @@ func (z *Int) GobDecode(buf []byte) os.Error {
|
||||
return os.ErrorString("Int.GobDecode: no data")
|
||||
}
|
||||
b := buf[0]
|
||||
if b>>1 != version {
|
||||
if b>>1 != intGobVersion {
|
||||
return os.ErrorString(fmt.Sprintf("Int.GobDecode: encoding version %d not supported", b>>1))
|
||||
}
|
||||
z.neg = b&1 != 0
|
||||
|
@ -1303,6 +1303,7 @@ func TestModInverse(t *testing.T) {
|
||||
}
|
||||
|
||||
|
||||
// used by TestIntGobEncoding and TestRatGobEncoding
|
||||
var gobEncodingTests = []string{
|
||||
"0",
|
||||
"1",
|
||||
@ -1313,7 +1314,7 @@ var gobEncodingTests = []string{
|
||||
"298472983472983471903246121093472394872319615612417471234712061",
|
||||
}
|
||||
|
||||
func TestGobEncoding(t *testing.T) {
|
||||
func TestIntGobEncoding(t *testing.T) {
|
||||
var medium bytes.Buffer
|
||||
enc := gob.NewEncoder(&medium)
|
||||
dec := gob.NewDecoder(&medium)
|
||||
@ -1321,7 +1322,8 @@ func TestGobEncoding(t *testing.T) {
|
||||
for j := 0; j < 2; j++ {
|
||||
medium.Reset() // empty buffer for each test case (in case of failures)
|
||||
stest := test
|
||||
if j == 0 {
|
||||
if j != 0 {
|
||||
// negative numbers
|
||||
stest = "-" + test
|
||||
}
|
||||
var tx Int
|
||||
|
@ -7,6 +7,7 @@
|
||||
package big
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
@ -354,3 +355,45 @@ func (z *Rat) FloatString(prec int) string {
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
|
||||
// Gob codec version. Permits backward-compatible changes to the encoding.
|
||||
const ratGobVersion byte = 1
|
||||
|
||||
// GobEncode implements the gob.GobEncoder interface.
|
||||
func (z *Rat) GobEncode() ([]byte, os.Error) {
|
||||
buf := make([]byte, 1+4+(len(z.a.abs)+len(z.b))*_S) // extra bytes for version and sign bit (1), and numerator length (4)
|
||||
i := z.b.bytes(buf)
|
||||
j := z.a.abs.bytes(buf[0:i])
|
||||
n := i - j
|
||||
if int(uint32(n)) != n {
|
||||
// this should never happen
|
||||
return nil, os.ErrorString("Rat.GobEncode: numerator too large")
|
||||
}
|
||||
binary.BigEndian.PutUint32(buf[j-4:j], uint32(n))
|
||||
j -= 1 + 4
|
||||
b := ratGobVersion << 1 // make space for sign bit
|
||||
if z.a.neg {
|
||||
b |= 1
|
||||
}
|
||||
buf[j] = b
|
||||
return buf[j:], nil
|
||||
}
|
||||
|
||||
|
||||
// GobDecode implements the gob.GobDecoder interface.
|
||||
func (z *Rat) GobDecode(buf []byte) os.Error {
|
||||
if len(buf) == 0 {
|
||||
return os.ErrorString("Rat.GobDecode: no data")
|
||||
}
|
||||
b := buf[0]
|
||||
if b>>1 != ratGobVersion {
|
||||
return os.ErrorString(fmt.Sprintf("Rat.GobDecode: encoding version %d not supported", b>>1))
|
||||
}
|
||||
const j = 1 + 4
|
||||
i := j + binary.BigEndian.Uint32(buf[j-4:j])
|
||||
z.a.neg = b&1 != 0
|
||||
z.a.abs = z.a.abs.setBytes(buf[j:i])
|
||||
z.b = z.b.setBytes(buf[i:])
|
||||
return nil
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ package big
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"gob"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@ -308,3 +309,36 @@ func TestRatSetFrac64Rat(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func TestRatGobEncoding(t *testing.T) {
|
||||
var medium bytes.Buffer
|
||||
enc := gob.NewEncoder(&medium)
|
||||
dec := gob.NewDecoder(&medium)
|
||||
for i, test := range gobEncodingTests {
|
||||
for j := 0; j < 4; j++ {
|
||||
medium.Reset() // empty buffer for each test case (in case of failures)
|
||||
stest := test
|
||||
if j&1 != 0 {
|
||||
// negative numbers
|
||||
stest = "-" + test
|
||||
}
|
||||
if j%2 != 0 {
|
||||
// fractions
|
||||
stest = stest + "." + test
|
||||
}
|
||||
var tx Rat
|
||||
tx.SetString(stest)
|
||||
if err := enc.Encode(&tx); err != nil {
|
||||
t.Errorf("#%d%c: encoding failed: %s", i, 'a'+j, err)
|
||||
}
|
||||
var rx Rat
|
||||
if err := dec.Decode(&rx); err != nil {
|
||||
t.Errorf("#%d%c: decoding failed: %s", i, 'a'+j, err)
|
||||
}
|
||||
if rx.Cmp(&tx) != 0 {
|
||||
t.Errorf("#%d%c: transmission failed: got %s want %s", i, 'a'+j, &rx, &tx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user