blob: 423647515b259a8465eb1efa29457923a8b9ddcf [file] [log] [blame]
// Copyright 2020 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.
pri func decoder.filter_1!(curr: slice base.u8) {
var filter_distance : base.u64[..= 8]
var fa : base.u8
var i_start : base.u64
var i : base.u64
filter_distance = this.filter_distance as base.u64
i_start = 0
while i_start < filter_distance {
assert i_start < 8 via "a < b: a < c; c <= b"(c: filter_distance)
fa = 0
i = i_start
while i < args.curr.length(),
inv i_start < 8,
{
args.curr[i] ~mod+= fa
fa = args.curr[i]
i ~mod+= filter_distance
} endwhile
i_start += 1
} endwhile
}
pri func decoder.filter_2!(curr: slice base.u8, prev: slice base.u8) {
var i : base.u64
i = 0
while (i < args.curr.length()) and (i < args.prev.length()) {
assert i < 0xFFFF_FFFF_FFFF_FFFF via "a < b: a < c; c <= b"(c: args.curr.length())
args.curr[i] ~mod+= args.prev[i]
i += 1
} endwhile
}
pri func decoder.filter_3!(curr: slice base.u8, prev: slice base.u8) {
var filter_distance : base.u64[..= 8]
var i : base.u64
filter_distance = this.filter_distance as base.u64
if args.prev.length() == 0 {
i = filter_distance
while i < args.curr.length() {
assert i < 0xFFFF_FFFF_FFFF_FFFF via "a < b: a < c; c <= b"(c: args.curr.length())
if i >= filter_distance {
if (i - filter_distance) < args.curr.length() {
args.curr[i] ~mod+= args.curr[i - filter_distance] / 2
}
}
i += 1
} endwhile
} else {
i = 0
while (i < args.curr.length()) and (i < args.prev.length()) {
assert i < 0xFFFF_FFFF_FFFF_FFFF via "a < b: a < c; c <= b"(c: args.curr.length())
if i >= filter_distance {
if (i - filter_distance) < args.curr.length() {
args.curr[i] ~mod+= ((
(args.curr[i - filter_distance] as base.u32) +
(args.prev[i] as base.u32)) / 2) as base.u8
}
} else {
args.curr[i] ~mod+= args.prev[i] / 2
}
i += 1
} endwhile
}
}
pri func decoder.filter_4!(curr: slice base.u8, prev: slice base.u8) {
var filter_distance : base.u64[..= 8]
var i : base.u64
var fa : base.u32
var fb : base.u32
var fc : base.u32
var pp : base.u32
var pa : base.u32
var pb : base.u32
var pc : base.u32
filter_distance = this.filter_distance as base.u64
i = 0
while (i < args.curr.length()) and (i < args.prev.length()) {
assert i < 0xFFFF_FFFF_FFFF_FFFF via "a < b: a < c; c <= b"(c: args.curr.length())
if i < filter_distance {
args.curr[i] ~mod+= args.prev[i]
} else {
if ((i - filter_distance) < args.curr.length()) and
((i - filter_distance) < args.prev.length()) {
fa = args.curr[i - filter_distance] as base.u32
fb = args.prev[i] as base.u32
fc = args.prev[i - filter_distance] as base.u32
pp = (fa ~mod+ fb) ~mod- fc
pa = pp ~mod- fa
if pa >= 0x8000_0000 {
pa = 0 ~mod- pa
}
pb = pp ~mod- fb
if pb >= 0x8000_0000 {
pb = 0 ~mod- pb
}
pc = pp ~mod- fc
if pc >= 0x8000_0000 {
pc = 0 ~mod- pc
}
if (pa <= pb) and (pa <= pc) {
args.curr[i] ~mod+= (fa & 0xFF) as base.u8
} else if pb <= pc {
args.curr[i] ~mod+= (fb & 0xFF) as base.u8
} else {
args.curr[i] ~mod+= (fc & 0xFF) as base.u8
}
}
}
i += 1
} endwhile
}