mirror of
https://github.com/golang/go
synced 2024-11-21 23:24:41 -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.
|
// Gob codec version. Permits backward-compatible changes to the encoding.
|
||||||
const version byte = 1
|
const intGobVersion byte = 1
|
||||||
|
|
||||||
// GobEncode implements the gob.GobEncoder interface.
|
// GobEncode implements the gob.GobEncoder interface.
|
||||||
func (z *Int) GobEncode() ([]byte, os.Error) {
|
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
|
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 {
|
if z.neg {
|
||||||
b |= 1
|
b |= 1
|
||||||
}
|
}
|
||||||
@ -837,7 +837,7 @@ func (z *Int) GobDecode(buf []byte) os.Error {
|
|||||||
return os.ErrorString("Int.GobDecode: no data")
|
return os.ErrorString("Int.GobDecode: no data")
|
||||||
}
|
}
|
||||||
b := buf[0]
|
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))
|
return os.ErrorString(fmt.Sprintf("Int.GobDecode: encoding version %d not supported", b>>1))
|
||||||
}
|
}
|
||||||
z.neg = b&1 != 0
|
z.neg = b&1 != 0
|
||||||
|
@ -1303,6 +1303,7 @@ func TestModInverse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// used by TestIntGobEncoding and TestRatGobEncoding
|
||||||
var gobEncodingTests = []string{
|
var gobEncodingTests = []string{
|
||||||
"0",
|
"0",
|
||||||
"1",
|
"1",
|
||||||
@ -1313,7 +1314,7 @@ var gobEncodingTests = []string{
|
|||||||
"298472983472983471903246121093472394872319615612417471234712061",
|
"298472983472983471903246121093472394872319615612417471234712061",
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGobEncoding(t *testing.T) {
|
func TestIntGobEncoding(t *testing.T) {
|
||||||
var medium bytes.Buffer
|
var medium bytes.Buffer
|
||||||
enc := gob.NewEncoder(&medium)
|
enc := gob.NewEncoder(&medium)
|
||||||
dec := gob.NewDecoder(&medium)
|
dec := gob.NewDecoder(&medium)
|
||||||
@ -1321,7 +1322,8 @@ func TestGobEncoding(t *testing.T) {
|
|||||||
for j := 0; j < 2; j++ {
|
for j := 0; j < 2; j++ {
|
||||||
medium.Reset() // empty buffer for each test case (in case of failures)
|
medium.Reset() // empty buffer for each test case (in case of failures)
|
||||||
stest := test
|
stest := test
|
||||||
if j == 0 {
|
if j != 0 {
|
||||||
|
// negative numbers
|
||||||
stest = "-" + test
|
stest = "-" + test
|
||||||
}
|
}
|
||||||
var tx Int
|
var tx Int
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
package big
|
package big
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
@ -354,3 +355,45 @@ func (z *Rat) FloatString(prec int) string {
|
|||||||
|
|
||||||
return s
|
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 (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"gob"
|
||||||
"testing"
|
"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