blob: f3b8a7fc4bea9fbf3a52c2c80adae69b19c03d15 [file] [log] [blame]
// Copyright 2017 The Wuffs Authors.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
// SPDX-License-Identifier: Apache-2.0 OR MIT
// TODO: drop the '?' but still generate wuffs_adler32__hasher__initialize?
pub struct hasher? implements base.hasher_u32(
state : base.u32,
started : base.bool,
)
pub func hasher.get_quirk(key: base.u32) base.u64 {
return 0
}
pub func hasher.set_quirk!(key: base.u32, value: base.u64) base.status {
return base."#unsupported option"
}
pub func hasher.update!(x: roslice base.u8) {
if not this.started {
this.started = true
this.state = 1
// There used to be an up_x86_avx2 implementation too, but while it
// made the std/adler32 micro-benchmarks better, it also made the
// std/zlib and std/png micro-benchmarks worse. See commit baec831f
// "Add std/adler32 hasher.up_x86_avx2".
choose up = [
up_arm_neon,
up_x86_sse42]
}
this.up!(x: args.x)
}
pub func hasher.update_u32!(x: roslice base.u8) base.u32 {
this.update!(x: args.x)
return this.state
}
pri func hasher.up!(x: roslice base.u8),
choosy,
{
// The Adler-32 checksum's magic 65521 and 5552 numbers are discussed in
// this package's README.md.
var s1 : base.u32
var s2 : base.u32
var remaining : roslice base.u8
var p : roslice base.u8
s1 = this.state.low_bits(n: 16)
s2 = this.state.high_bits(n: 16)
while args.x.length() > 0 {
remaining = args.x[.. 0]
if args.x.length() > 5552 {
remaining = args.x[5552 ..]
args.x = args.x[.. 5552]
}
// The SIMD versions of this function replace this simple iterate loop.
iterate (p = args.x)(length: 1, advance: 1, unroll: 8) {
s1 ~mod+= p[0] as base.u32
s2 ~mod+= s1
}
s1 %= 65521
s2 %= 65521
args.x = remaining
} endwhile
this.state = ((s2 & 0xFFFF) << 16) | (s1 & 0xFFFF)
}
pub func hasher.checksum_u32() base.u32 {
return this.state
}