Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(846)

Side by Side Diff: src/pkg/hash/adler32/adler32.go

Issue 6251044: code review 6251044: hash/adler32: optimize. (Closed)
Patch Set: diff -r e2e4e44b1804 https://go.googlecode.com/hg/ Created 11 years, 10 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/pkg/hash/adler32/adler32_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // Package adler32 implements the Adler-32 checksum. 5 // Package adler32 implements the Adler-32 checksum.
6 // Defined in RFC 1950: 6 //
7 // It is defined in RFC 1950:
7 // Adler-32 is composed of two sums accumulated per byte: s1 is 8 // Adler-32 is composed of two sums accumulated per byte: s1 is
8 // the sum of all bytes, s2 is the sum of all s1 values. Both sums 9 // the sum of all bytes, s2 is the sum of all s1 values. Both sums
9 // are done modulo 65521. s1 is initialized to 1, s2 to zero. The 10 // are done modulo 65521. s1 is initialized to 1, s2 to zero. The
10 // Adler-32 checksum is stored as s2*65536 + s1 in most- 11 // Adler-32 checksum is stored as s2*65536 + s1 in most-
11 // significant-byte first (network) order. 12 // significant-byte first (network) order.
12 package adler32 13 package adler32
13 14
14 import "hash" 15 import "hash"
15 16
16 const ( 17 const (
18 // mod is the largest prime that is less than 65536.
17 mod = 65521 19 mod = 65521
20 // nmax is the largest n such that
21 // 255 * n * (n+1) / 2 + (n+1) * (mod-1) <= 2^32-1.
22 // It is mentioned in RFC 1950 (search for "5552").
23 nmax = 5552
18 ) 24 )
19 25
20 // The size of an Adler-32 checksum in bytes. 26 // The size of an Adler-32 checksum in bytes.
21 const Size = 4 27 const Size = 4
22 28
23 // digest represents the partial evaluation of a checksum. 29 // digest represents the partial evaluation of a checksum.
24 type digest struct { 30 // The low 16 bits are s1, the high 16 bits are s2.
25 » // invariant: (a < mod && b < mod) || a <= b 31 type digest uint32
26 » // invariant: a + b + 255 <= 0xffffffff
27 » a, b uint32
28 }
29 32
30 func (d *digest) Reset() { d.a, d.b = 1, 0 } 33 func (d *digest) Reset() { *d = 1 }
31 34
32 // New returns a new hash.Hash32 computing the Adler-32 checksum. 35 // New returns a new hash.Hash32 computing the Adler-32 checksum.
33 func New() hash.Hash32 { 36 func New() hash.Hash32 {
34 d := new(digest) 37 d := new(digest)
35 d.Reset() 38 d.Reset()
36 return d 39 return d
37 } 40 }
38 41
39 func (d *digest) Size() int { return Size } 42 func (d *digest) Size() int { return Size }
40 43
41 func (d *digest) BlockSize() int { return 1 } 44 func (d *digest) BlockSize() int { return 1 }
42 45
43 // Add p to the running checksum a, b. 46 // Add p to the running checksum d.
44 func update(a, b uint32, p []byte) (aa, bb uint32) { 47 func update(d digest, p []byte) digest {
45 » for _, pi := range p { 48 » s1, s2 := uint32(d&0xffff), uint32(d>>16)
46 » » a += uint32(pi) 49 » for len(p) > 0 {
47 » » b += a 50 » » var q []byte
48 » » // invariant: a <= b 51 » » if len(p) > nmax {
49 » » if b > (0xffffffff-255)/2 { 52 » » » p, q = p[:nmax], p[nmax:]
50 » » » a %= mod
51 » » » b %= mod
52 » » » // invariant: a < mod && b < mod
53 » » } else {
54 » » » // invariant: a + b + 255 <= 2 * b + 255 <= 0xffffffff
55 } 53 }
54 for _, x := range p {
55 s1 += uint32(x)
56 s2 += s1
57 }
58 s1 %= mod
59 s2 %= mod
60 p = q
56 } 61 }
57 » return a, b 62 » return digest(s2<<16 | s1)
58 }
59
60 // Return the 32-bit checksum corresponding to a, b.
61 func finish(a, b uint32) uint32 {
62 » if b >= mod {
63 » » a %= mod
64 » » b %= mod
65 » }
66 » return b<<16 | a
67 } 63 }
68 64
69 func (d *digest) Write(p []byte) (nn int, err error) { 65 func (d *digest) Write(p []byte) (nn int, err error) {
70 » d.a, d.b = update(d.a, d.b, p) 66 » *d = update(*d, p)
71 return len(p), nil 67 return len(p), nil
72 } 68 }
73 69
74 func (d *digest) Sum32() uint32 { return finish(d.a, d.b) } 70 func (d *digest) Sum32() uint32 { return uint32(*d) }
75 71
76 func (d *digest) Sum(in []byte) []byte { 72 func (d *digest) Sum(in []byte) []byte {
77 » s := d.Sum32() 73 » s := uint32(*d)
78 return append(in, byte(s>>24), byte(s>>16), byte(s>>8), byte(s)) 74 return append(in, byte(s>>24), byte(s>>16), byte(s>>8), byte(s))
79 } 75 }
80 76
81 // Checksum returns the Adler-32 checksum of data. 77 // Checksum returns the Adler-32 checksum of data.
82 func Checksum(data []byte) uint32 { return finish(update(1, 0, data)) } 78 func Checksum(data []byte) uint32 { return uint32(update(1, data)) }
OLDNEW
« no previous file with comments | « no previous file | src/pkg/hash/adler32/adler32_test.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b