aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2011-06-08 09:10:01 -0700
committerRobert Griesemer <gri@golang.org>2011-06-08 09:10:01 -0700
commit21032ebebd164aaf2c128304ff116859096449d4 (patch)
tree482ba70dfbe3a1a2d36ce295d478e9466e7e16c2
parent6c746328f79d4767deb212ebc12fe06d90eb7ecb (diff)
downloadgo-21032ebebd164aaf2c128304ff116859096449d4.tar.gz
go-21032ebebd164aaf2c128304ff116859096449d4.zip
big: gobs for big rats
Fixes #1926. R=r CC=golang-dev https://golang.org/cl/4550122
-rwxr-xr-xsrc/pkg/big/int.go8
-rwxr-xr-xsrc/pkg/big/int_test.go6
-rw-r--r--src/pkg/big/rat.go43
-rw-r--r--src/pkg/big/rat_test.go34
4 files changed, 85 insertions, 6 deletions
diff --git a/src/pkg/big/int.go b/src/pkg/big/int.go
index e66c34a836..22bdf8d2f8 100755
--- a/src/pkg/big/int.go
+++ b/src/pkg/big/int.go
@@ -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
diff --git a/src/pkg/big/int_test.go b/src/pkg/big/int_test.go
index 1a492925b8..58a55030d5 100755
--- a/src/pkg/big/int_test.go
+++ b/src/pkg/big/int_test.go
@@ -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
diff --git a/src/pkg/big/rat.go b/src/pkg/big/rat.go
index b2e93f2a45..1fbf8c4596 100644
--- a/src/pkg/big/rat.go
+++ b/src/pkg/big/rat.go
@@ -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
+}
diff --git a/src/pkg/big/rat_test.go b/src/pkg/big/rat_test.go
index 4effbf8eac..e64505ea3c 100644
--- a/src/pkg/big/rat_test.go
+++ b/src/pkg/big/rat_test.go
@@ -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)
+ }
+ }
+ }
+}