| // Copyright 2017 The Wuffs Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| // 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.set_quirk_enabled!(quirk: base.u32, enabled: base.bool) { |
| } |
| |
| pub func hasher.update_u32!(x: slice base.u8) base.u32 { |
| 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) |
| return this.state |
| } |
| |
| pri func hasher.up!(x: slice 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 : slice base.u8 |
| var p : slice 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) |
| } |