Commit 658ca498 authored by Tom Szymanski's avatar Tom Szymanski

Make adler32 cleaner.

R=rsc
APPROVED=rsc
DELTA=22  (9 added, 6 deleted, 7 changed)
OCL=26498
CL=26500
parent bdbb3b45
...@@ -13,44 +13,46 @@ package adler32 ...@@ -13,44 +13,46 @@ package adler32
import "os" import "os"
const (
mod = 65521;
)
// Digest represents the partial evaluation of a checksum. // Digest represents the partial evaluation of a checksum.
type Digest struct { type Digest struct {
// invariant: (a < mod && b < mod) || a <= b
// invariant: a + b + 255 <= 0xffffffff
a, b uint32; a, b uint32;
n int;
} }
const (
mod = 65521;
maxIter = 5552; // max mod-free iterations before would overflow uint32
)
// NewDigest creates a new Digest. // NewDigest creates a new Digest.
func NewDigest() *Digest { func NewDigest() *Digest {
return &Digest{1, 0, 0}; return &Digest{1, 0};
} }
// Write updates the Digest with the incremental checksum generated by p. // Write updates the Digest with the incremental checksum generated by p.
// It returns the number of bytes written; err is always nil. // It returns the number of bytes written; err is always nil.
func (d *Digest) Write(p []byte) (nn int, err *os.Error) { func (d *Digest) Write(p []byte) (nn int, err *os.Error) {
a, b, n := d.a, d.b, d.n; a, b := d.a, d.b;
for i := 0; i < len(p); i++ { for i := 0; i < len(p); i++ {
a += uint32(p[i]); a += uint32(p[i]);
b += a; b += a;
n++; // invariant: a <= b
if n == maxIter { if b > (0xffffffff - 255) / 2 {
a %= mod; a %= mod;
b %= mod; b %= mod;
n = 0; // invariant: a < mod && b < mod
} else {
// invariant: a + b + 255 <= 2 * b + 255 <= 0xffffffff
} }
} }
d.a, d.b, d.n = a, b, n; d.a, d.b = a, b;
return len(p), nil return len(p), nil
} }
// Sum32 returns the 32-bit Adler-32 checksum of the data written to the Digest. // Sum32 returns the 32-bit Adler-32 checksum of the data written to the Digest.
func (d *Digest) Sum32() uint32 { func (d *Digest) Sum32() uint32 {
a, b := d.a, d.b; a, b := d.a, d.b;
if a >= mod || b >= mod { if b >= mod {
a %= mod; a %= mod;
b %= mod; b %= mod;
} }
......
...@@ -47,6 +47,7 @@ var golden = []_Adler32Test { ...@@ -47,6 +47,7 @@ var golden = []_Adler32Test {
_Adler32Test{ 0x39111dd0, "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley" }, _Adler32Test{ 0x39111dd0, "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley" },
_Adler32Test{ 0x91dd304f, "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule" }, _Adler32Test{ 0x91dd304f, "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule" },
_Adler32Test{ 0x2e5d1316, "How can you write a big system without C++? -Paul Glick" }, _Adler32Test{ 0x2e5d1316, "How can you write a big system without C++? -Paul Glick" },
_Adler32Test{ 0xd0201df6, "'Invariant assertions' is the most elegant programming technique! -Tom Szymanski" },
} }
func TestGolden(t *testing.T) { func TestGolden(t *testing.T) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment